LCOV - code coverage report
Current view: top level - src/torque - csa-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 455 490 92.9 %
Date: 2019-04-17 Functions: 30 32 93.8 %

          Line data    Source code
       1             : // Copyright 2018 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/torque/csa-generator.h"
       6             : 
       7             : #include "src/globals.h"
       8             : #include "src/torque/type-oracle.h"
       9             : #include "src/torque/utils.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : namespace torque {
      14             : 
      15        1337 : base::Optional<Stack<std::string>> CSAGenerator::EmitGraph(
      16             :     Stack<std::string> parameters) {
      17        1337 :   for (Block* block : cfg_.blocks()) {
      18        7757 :     out_ << "  compiler::CodeAssemblerParameterizedLabel<";
      19        7757 :     PrintCommaSeparatedList(out_, block->InputTypes(), [](const Type* t) {
      20             :       return t->GetGeneratedTNodeTypeName();
      21       53130 :     });
      22       15514 :     out_ << "> " << BlockName(block) << "(&ca_, compiler::CodeAssemblerLabel::"
      23       15514 :          << (block->IsDeferred() ? "kDeferred" : "kNonDeferred") << ");\n";
      24             :   }
      25             : 
      26        4011 :   EmitInstruction(GotoInstruction{cfg_.start()}, &parameters);
      27        1337 :   for (Block* block : cfg_.blocks()) {
      28       21517 :     if (cfg_.end() && *cfg_.end() == block) continue;
      29       19881 :     out_ << "\n  if (" << BlockName(block) << ".is_used()) {\n";
      30       13254 :     EmitBlock(block);
      31        6627 :     out_ << "  }\n";
      32             :   }
      33        2674 :   if (cfg_.end()) {
      34        1130 :     out_ << "\n";
      35        3390 :     return EmitBlock(*cfg_.end());
      36             :   }
      37             :   return base::nullopt;
      38             : }
      39             : 
      40        7757 : Stack<std::string> CSAGenerator::EmitBlock(const Block* block) {
      41             :   Stack<std::string> stack;
      42       98503 :   for (const Type* t : block->InputTypes()) {
      43       90746 :     stack.Push(FreshNodeName());
      44       90746 :     out_ << "    compiler::TNode<" << t->GetGeneratedTNodeTypeName() << "> "
      45       90746 :          << stack.Top() << ";\n";
      46             :   }
      47       15514 :   out_ << "    ca_.Bind(&" << BlockName(block);
      48       98503 :   for (const std::string& name : stack) {
      49       45373 :     out_ << ", &" << name;
      50             :   }
      51        7757 :   out_ << ");\n";
      52       52429 :   for (const Instruction& instruction : block->instructions()) {
      53       44672 :     EmitInstruction(instruction, &stack);
      54             :   }
      55        7757 :   return stack;
      56             : }
      57             : 
      58       44672 : void CSAGenerator::EmitSourcePosition(SourcePosition pos, bool always_emit) {
      59       44672 :   const std::string& file = SourceFileMap::GetSource(pos.source);
      60       89344 :   if (always_emit || !previous_position_.CompareStartIgnoreColumn(pos)) {
      61             :     // Lines in Torque SourcePositions are zero-based, while the
      62             :     // CodeStubAssembler and downwind systems are one-based.
      63        6276 :     out_ << "    ca_.SetSourcePosition(\"" << file << "\", "
      64       12552 :          << (pos.start.line + 1) << ");\n";
      65        6276 :     previous_position_ = pos;
      66             :   }
      67       44672 : }
      68             : 
      69       44672 : void CSAGenerator::EmitInstruction(const Instruction& instruction,
      70             :                                    Stack<std::string>* stack) {
      71       44672 :   EmitSourcePosition(instruction->pos);
      72       44672 :   switch (instruction.kind()) {
      73             : #define ENUM_ITEM(T)          \
      74             :   case InstructionKind::k##T: \
      75             :     return EmitInstruction(instruction.Cast<T>(), stack);
      76       34963 :     TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
      77             : #undef ENUM_ITEM
      78             :   }
      79             : }
      80             : 
      81       20515 : void CSAGenerator::EmitInstruction(const PeekInstruction& instruction,
      82             :                                    Stack<std::string>* stack) {
      83       20515 :   stack->Push(stack->Peek(instruction.slot));
      84       20515 : }
      85             : 
      86         598 : void CSAGenerator::EmitInstruction(const PokeInstruction& instruction,
      87             :                                    Stack<std::string>* stack) {
      88        1794 :   stack->Poke(instruction.slot, stack->Top());
      89        1196 :   stack->Pop();
      90         598 : }
      91             : 
      92           0 : void CSAGenerator::EmitInstruction(const DeleteRangeInstruction& instruction,
      93             :                                    Stack<std::string>* stack) {
      94        9709 :   stack->DeleteRange(instruction.range);
      95           0 : }
      96             : 
      97          94 : void CSAGenerator::EmitInstruction(
      98             :     const PushUninitializedInstruction& instruction,
      99             :     Stack<std::string>* stack) {
     100             :   // TODO(tebbi): This can trigger an error in CSA if it is used. Instead, we
     101             :   // should prevent usage of uninitialized in the type system. This
     102             :   // requires "if constexpr" being evaluated at Torque time.
     103         188 :   stack->Push("ca_.Uninitialized<" +
     104         376 :               instruction.type->GetGeneratedTNodeTypeName() + ">()");
     105          94 : }
     106             : 
     107          74 : void CSAGenerator::EmitInstruction(
     108             :     const PushBuiltinPointerInstruction& instruction,
     109             :     Stack<std::string>* stack) {
     110         148 :   stack->Push("ca_.UncheckedCast<BuiltinPtr>(ca_.SmiConstant(Builtins::k" +
     111         148 :               instruction.external_name + "))");
     112          74 : }
     113             : 
     114         363 : void CSAGenerator::EmitInstruction(
     115             :     const NamespaceConstantInstruction& instruction,
     116             :     Stack<std::string>* stack) {
     117         363 :   const Type* type = instruction.constant->type();
     118         363 :   std::vector<std::string> results;
     119        1089 :   for (const Type* lowered : LowerType(type)) {
     120         726 :     results.push_back(FreshNodeName());
     121         363 :     stack->Push(results.back());
     122         726 :     out_ << "    compiler::TNode<" << lowered->GetGeneratedTNodeTypeName()
     123         726 :          << "> " << stack->Top() << ";\n";
     124         726 :     out_ << "    USE(" << stack->Top() << ");\n";
     125             :   }
     126         363 :   out_ << "    ";
     127         363 :   if (type->IsStructType()) {
     128           0 :     out_ << "std::tie(";
     129           0 :     PrintCommaSeparatedList(out_, results);
     130           0 :     out_ << ") = ";
     131         363 :   } else if (results.size() == 1) {
     132         726 :     out_ << results[0] << " = ";
     133             :   }
     134         726 :   out_ << instruction.constant->ExternalAssemblerName() << "(state_)."
     135         726 :        << instruction.constant->name()->value << "()";
     136         363 :   if (type->IsStructType()) {
     137           0 :     out_ << ".Flatten();\n";
     138             :   } else {
     139         363 :     out_ << ";\n";
     140             :   }
     141         363 : }
     142             : 
     143        5140 : void CSAGenerator::ProcessArgumentsCommon(
     144             :     const TypeVector& parameter_types, std::vector<std::string>* args,
     145             :     std::vector<std::string>* constexpr_arguments, Stack<std::string>* stack) {
     146       14111 :   for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) {
     147        8971 :     const Type* type = *it;
     148        8971 :     VisitResult arg;
     149        8971 :     if (type->IsConstexpr()) {
     150             :       args->push_back(std::move(constexpr_arguments->back()));
     151             :       constexpr_arguments->pop_back();
     152             :     } else {
     153       14160 :       std::stringstream s;
     154        7080 :       size_t slot_count = LoweredSlotCount(type);
     155             :       VisitResult arg = VisitResult(type, stack->TopRange(slot_count));
     156       14160 :       EmitCSAValue(arg, *stack, s);
     157        7080 :       args->push_back(s.str());
     158        7080 :       stack->PopMany(slot_count);
     159             :     }
     160             :   }
     161             :   std::reverse(args->begin(), args->end());
     162        5140 : }
     163             : 
     164         104 : void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
     165             :                                    Stack<std::string>* stack) {
     166             :   std::vector<std::string> constexpr_arguments =
     167         208 :       instruction.constexpr_arguments;
     168         104 :   std::vector<std::string> args;
     169             :   TypeVector parameter_types =
     170         104 :       instruction.intrinsic->signature().parameter_types.types;
     171         104 :   ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
     172             : 
     173             :   Stack<std::string> pre_call_stack = *stack;
     174         104 :   const Type* return_type = instruction.intrinsic->signature().return_type;
     175         104 :   std::vector<std::string> results;
     176         312 :   for (const Type* type : LowerType(return_type)) {
     177         208 :     results.push_back(FreshNodeName());
     178         104 :     stack->Push(results.back());
     179         208 :     out_ << "    compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
     180         208 :          << stack->Top() << ";\n";
     181         208 :     out_ << "    USE(" << stack->Top() << ");\n";
     182             :   }
     183         104 :   out_ << "    ";
     184             : 
     185         104 :   if (return_type->IsStructType()) {
     186           0 :     out_ << "std::tie(";
     187           0 :     PrintCommaSeparatedList(out_, results);
     188           0 :     out_ << ") = ";
     189             :   } else {
     190         104 :     if (results.size() == 1) {
     191         208 :       out_ << results[0] << " = ";
     192             :     }
     193             :   }
     194             : 
     195         208 :   if (instruction.intrinsic->ExternalName() == "%RawDownCast") {
     196          68 :     if (parameter_types.size() != 1) {
     197           0 :       ReportError("%RawDownCast must take a single parameter");
     198             :     }
     199          68 :     if (!return_type->IsSubtypeOf(parameter_types[0])) {
     200           0 :       ReportError("%RawDownCast error: ", *return_type, " is not a subtype of ",
     201           0 :                   *parameter_types[0]);
     202             :     }
     203          68 :     if (return_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
     204         195 :       if (return_type->GetGeneratedTNodeTypeName() !=
     205         130 :           parameter_types[0]->GetGeneratedTNodeTypeName()) {
     206          39 :         out_ << "TORQUE_CAST";
     207             :       }
     208             :     }
     209          72 :   } else if (instruction.intrinsic->ExternalName() == "%FromConstexpr") {
     210          15 :     if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) {
     211             :       ReportError(
     212             :           "%FromConstexpr must take a single parameter with constexpr "
     213           0 :           "type");
     214             :     }
     215          15 :     if (return_type->IsConstexpr()) {
     216           0 :       ReportError("%FromConstexpr must return a non-constexpr type");
     217             :     }
     218          15 :     if (return_type->IsSubtypeOf(TypeOracle::GetSmiType())) {
     219           3 :       out_ << "ca_.SmiConstant";
     220          12 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetNumberType())) {
     221           4 :       out_ << "ca_.NumberConstant";
     222           8 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetStringType())) {
     223           1 :       out_ << "ca_.StringConstant";
     224           7 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
     225             :       ReportError(
     226             :           "%FromConstexpr cannot cast to subclass of HeapObject unless it's a "
     227           0 :           "String or Number");
     228           7 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) {
     229           3 :       out_ << "ca_.IntPtrConstant";
     230           4 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) {
     231           1 :       out_ << "ca_.UintPtrConstant";
     232           3 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
     233           3 :       out_ << "ca_.Int32Constant";
     234             :     } else {
     235           0 :       std::stringstream s;
     236           0 :       s << "%FromConstexpr does not support return type " << *return_type;
     237           0 :       ReportError(s.str());
     238             :     }
     239          42 :   } else if (instruction.intrinsic->ExternalName() ==
     240             :              "%GetAllocationBaseSize") {
     241           9 :     if (instruction.specialization_types.size() != 1) {
     242             :       ReportError(
     243             :           "incorrect number of specialization classes for "
     244           0 :           "%GetAllocationBaseSize (should be one)");
     245             :     }
     246             :     const ClassType* class_type =
     247           9 :         ClassType::cast(instruction.specialization_types[0]);
     248             :     // Special case classes that may not always have a fixed size (e.g.
     249             :     // JSObjects). Their size must be fetched from the map.
     250           9 :     if (class_type != TypeOracle::GetJSObjectType()) {
     251           7 :       out_ << "CodeStubAssembler(state_).IntPtrConstant((";
     252           7 :       args[0] = std::to_string(class_type->size());
     253             :     } else {
     254           2 :       out_ << "CodeStubAssembler(state_).TimesTaggedSize(CodeStubAssembler("
     255           2 :               "state_).LoadMapInstanceSizeInWords(";
     256             :     }
     257          24 :   } else if (instruction.intrinsic->ExternalName() == "%Allocate") {
     258          18 :     out_ << "ca_.UncheckedCast<" << return_type->GetGeneratedTNodeTypeName()
     259           9 :          << ">(CodeStubAssembler(state_).Allocate";
     260           6 :   } else if (instruction.intrinsic->ExternalName() ==
     261             :              "%AllocateInternalClass") {
     262           3 :     out_ << "CodeStubAssembler(state_).AllocateUninitializedFixedArray";
     263             :   } else {
     264           0 :     ReportError("no built in intrinsic with name " +
     265           0 :                 instruction.intrinsic->ExternalName());
     266             :   }
     267             : 
     268         104 :   out_ << "(";
     269         104 :   PrintCommaSeparatedList(out_, args);
     270         208 :   if (instruction.intrinsic->ExternalName() == "%Allocate") out_ << ")";
     271         208 :   if (instruction.intrinsic->ExternalName() == "%GetAllocationBaseSize")
     272           9 :     out_ << "))";
     273         104 :   if (return_type->IsStructType()) {
     274           0 :     out_ << ").Flatten();\n";
     275             :   } else {
     276         104 :     out_ << ");\n";
     277             :   }
     278         208 :   if (instruction.intrinsic->ExternalName() == "%Allocate") {
     279           9 :     out_ << "    CodeStubAssembler(state_).InitializeFieldsWithRoot("
     280           9 :          << results[0] << ", ";
     281           9 :     out_ << "CodeStubAssembler(state_).IntPtrConstant("
     282          18 :          << std::to_string(ClassType::cast(return_type)->size()) << "), ";
     283           9 :     PrintCommaSeparatedList(out_, args);
     284           9 :     out_ << ", RootIndex::kUndefinedValue);\n";
     285             :   }
     286         104 : }
     287             : 
     288        4438 : void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
     289             :                                    Stack<std::string>* stack) {
     290             :   std::vector<std::string> constexpr_arguments =
     291        8876 :       instruction.constexpr_arguments;
     292        4438 :   std::vector<std::string> args;
     293             :   TypeVector parameter_types =
     294        4438 :       instruction.macro->signature().parameter_types.types;
     295        4438 :   ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
     296             : 
     297             :   Stack<std::string> pre_call_stack = *stack;
     298        4438 :   const Type* return_type = instruction.macro->signature().return_type;
     299        4438 :   std::vector<std::string> results;
     300       13200 :   for (const Type* type : LowerType(return_type)) {
     301        8648 :     results.push_back(FreshNodeName());
     302        4324 :     stack->Push(results.back());
     303        8648 :     out_ << "    compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
     304        8648 :          << stack->Top() << ";\n";
     305        8648 :     out_ << "    USE(" << stack->Top() << ");\n";
     306             :   }
     307             :   std::string catch_name =
     308        4438 :       PreCallableExceptionPreparation(instruction.catch_block);
     309        4438 :   out_ << "    ";
     310             :   bool needs_flattening =
     311        4438 :       return_type->IsStructType() || return_type->IsReferenceType();
     312        4438 :   if (needs_flattening) {
     313          36 :     out_ << "std::tie(";
     314          36 :     PrintCommaSeparatedList(out_, results);
     315          36 :     out_ << ") = ";
     316             :   } else {
     317        4402 :     if (results.size() == 1) {
     318        4184 :       out_ << results[0] << " = ca_.UncheckedCast<"
     319       12552 :            << return_type->GetGeneratedTNodeTypeName() << ">(";
     320             :     } else {
     321             :       DCHECK_EQ(0, results.size());
     322             :     }
     323             :   }
     324        4438 :   out_ << instruction.macro->external_assembler_name() << "(state_)."
     325        8876 :        << instruction.macro->ExternalName() << "(";
     326        4438 :   PrintCommaSeparatedList(out_, args);
     327        4438 :   if (needs_flattening) {
     328          36 :     out_ << ").Flatten();\n";
     329             :   } else {
     330        4402 :     if (results.size() == 1) out_ << ")";
     331        4402 :     out_ << ");\n";
     332             :   }
     333             :   PostCallableExceptionPreparation(catch_name, return_type,
     334        4438 :                                    instruction.catch_block, &pre_call_stack);
     335        4438 : }
     336             : 
     337         598 : void CSAGenerator::EmitInstruction(
     338             :     const CallCsaMacroAndBranchInstruction& instruction,
     339             :     Stack<std::string>* stack) {
     340             :   std::vector<std::string> constexpr_arguments =
     341        1196 :       instruction.constexpr_arguments;
     342         598 :   std::vector<std::string> args;
     343             :   TypeVector parameter_types =
     344         598 :       instruction.macro->signature().parameter_types.types;
     345         598 :   ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
     346             : 
     347             :   Stack<std::string> pre_call_stack = *stack;
     348         598 :   std::vector<std::string> results;
     349         598 :   const Type* return_type = instruction.macro->signature().return_type;
     350         598 :   if (return_type != TypeOracle::GetNeverType()) {
     351         803 :     for (const Type* type :
     352         803 :          LowerType(instruction.macro->signature().return_type)) {
     353         778 :       results.push_back(FreshNodeName());
     354         778 :       out_ << "    compiler::TNode<" << type->GetGeneratedTNodeTypeName()
     355         389 :            << "> " << results.back() << ";\n";
     356         778 :       out_ << "    USE(" << results.back() << ");\n";
     357             :     }
     358             :   }
     359             : 
     360         598 :   std::vector<std::string> label_names;
     361         598 :   std::vector<std::vector<std::string>> var_names;
     362         598 :   const LabelDeclarationVector& labels = instruction.macro->signature().labels;
     363             :   DCHECK_EQ(labels.size(), instruction.label_blocks.size());
     364        1758 :   for (size_t i = 0; i < labels.size(); ++i) {
     365         580 :     TypeVector label_parameters = labels[i].types;
     366        1740 :     label_names.push_back("label" + std::to_string(i));
     367         580 :     var_names.push_back({});
     368         630 :     for (size_t j = 0; j < label_parameters.size(); ++j) {
     369         125 :       var_names[i].push_back("result_" + std::to_string(i) + "_" +
     370          25 :                              std::to_string(j));
     371          25 :       out_ << "    compiler::TypedCodeAssemblerVariable<"
     372          50 :            << label_parameters[j]->GetGeneratedTNodeTypeName() << "> "
     373          25 :            << var_names[i][j] << "(&ca_);\n";
     374             :     }
     375         580 :     out_ << "    compiler::CodeAssemblerLabel " << label_names[i]
     376         580 :          << "(&ca_);\n";
     377             :   }
     378             : 
     379             :   std::string catch_name =
     380         598 :       PreCallableExceptionPreparation(instruction.catch_block);
     381         598 :   out_ << "    ";
     382         598 :   if (results.size() == 1) {
     383         770 :     out_ << results[0] << " = ";
     384         213 :   } else if (results.size() > 1) {
     385           2 :     out_ << "std::tie(";
     386           2 :     PrintCommaSeparatedList(out_, results);
     387           2 :     out_ << ") = ";
     388             :   }
     389         598 :   out_ << instruction.macro->external_assembler_name() << "(state_)."
     390        1196 :        << instruction.macro->ExternalName() << "(";
     391         598 :   PrintCommaSeparatedList(out_, args);
     392             :   bool first = args.empty();
     393        1758 :   for (size_t i = 0; i < label_names.size(); ++i) {
     394         580 :     if (!first) out_ << ", ";
     395         580 :     out_ << "&" << label_names[i];
     396             :     first = false;
     397         630 :     for (size_t j = 0; j < var_names[i].size(); ++j) {
     398          25 :       out_ << ", &" << var_names[i][j];
     399             :     }
     400             :   }
     401         598 :   if (return_type->IsStructType()) {
     402           2 :     out_ << ").Flatten();\n";
     403             :   } else {
     404         596 :     out_ << ");\n";
     405             :   }
     406             : 
     407             :   PostCallableExceptionPreparation(catch_name, return_type,
     408         598 :                                    instruction.catch_block, &pre_call_stack);
     409             : 
     410         598 :   if (instruction.return_continuation) {
     411         828 :     out_ << "    ca_.Goto(&" << BlockName(*instruction.return_continuation);
     412        7726 :     for (const std::string& value : *stack) {
     413        3656 :       out_ << ", " << value;
     414             :     }
     415         803 :     for (const std::string& result : results) {
     416         389 :       out_ << ", " << result;
     417             :     }
     418         414 :     out_ << ");\n";
     419             :   }
     420        1758 :   for (size_t i = 0; i < label_names.size(); ++i) {
     421        1160 :     out_ << "    if (" << label_names[i] << ".is_used()) {\n";
     422        1160 :     out_ << "      ca_.Bind(&" << label_names[i] << ");\n";
     423        1160 :     out_ << "      ca_.Goto(&" << BlockName(instruction.label_blocks[i]);
     424       11186 :     for (const std::string& value : *stack) {
     425        5303 :       out_ << ", " << value;
     426             :     }
     427         605 :     for (const std::string& var : var_names[i]) {
     428          50 :       out_ << ", " << var << ".value()";
     429             :     }
     430         580 :     out_ << ");\n";
     431             : 
     432         580 :     out_ << "    }\n";
     433             :   }
     434         598 : }
     435             : 
     436         143 : void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction,
     437             :                                    Stack<std::string>* stack) {
     438         286 :   std::vector<std::string> arguments = stack->PopMany(instruction.argc);
     439             :   std::vector<const Type*> result_types =
     440         143 :       LowerType(instruction.builtin->signature().return_type);
     441         143 :   if (instruction.is_tailcall) {
     442           2 :     out_ << "   CodeStubAssembler(state_).TailCallBuiltin(Builtins::k"
     443           4 :          << instruction.builtin->ExternalName() << ", ";
     444           2 :     PrintCommaSeparatedList(out_, arguments);
     445           2 :     out_ << ");\n";
     446             :   } else {
     447         141 :     std::string result_name = FreshNodeName();
     448         141 :     if (result_types.size() == 1) {
     449         114 :       out_ << "    compiler::TNode<"
     450         228 :            << result_types[0]->GetGeneratedTNodeTypeName() << "> "
     451         114 :            << result_name << ";\n";
     452             :     }
     453             :     std::string catch_name =
     454         141 :         PreCallableExceptionPreparation(instruction.catch_block);
     455             :     Stack<std::string> pre_call_stack = *stack;
     456         141 :     if (result_types.size() == 1) {
     457         114 :       std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
     458         114 :       stack->Push(result_name);
     459         228 :       out_ << "    " << result_name << " = ";
     460         114 :       if (generated_type != "Object") out_ << "TORQUE_CAST(";
     461         114 :       out_ << "CodeStubAssembler(state_).CallBuiltin(Builtins::k"
     462         228 :            << instruction.builtin->ExternalName() << ", ";
     463         114 :       PrintCommaSeparatedList(out_, arguments);
     464         114 :       if (generated_type != "Object") out_ << ")";
     465         114 :       out_ << ");\n";
     466         228 :       out_ << "    USE(" << result_name << ");\n";
     467             :     } else {
     468             :       DCHECK_EQ(0, result_types.size());
     469             :       // TODO(tebbi): Actually, builtins have to return a value, so we should
     470             :       // not have to handle this case.
     471          27 :       out_ << "    CodeStubAssembler(state_).CallBuiltin(Builtins::k"
     472          54 :            << instruction.builtin->ExternalName() << ", ";
     473          27 :       PrintCommaSeparatedList(out_, arguments);
     474          27 :       out_ << ");\n";
     475             :     }
     476         141 :     PostCallableExceptionPreparation(
     477             :         catch_name,
     478             :         result_types.size() == 0 ? TypeOracle::GetVoidType() : result_types[0],
     479         141 :         instruction.catch_block, &pre_call_stack);
     480             :   }
     481         143 : }
     482             : 
     483          23 : void CSAGenerator::EmitInstruction(
     484             :     const CallBuiltinPointerInstruction& instruction,
     485             :     Stack<std::string>* stack) {
     486             :   std::vector<std::string> function_and_arguments =
     487          46 :       stack->PopMany(1 + instruction.argc);
     488             :   std::vector<const Type*> result_types =
     489          23 :       LowerType(instruction.type->return_type());
     490          23 :   if (result_types.size() != 1) {
     491           0 :     ReportError("builtins must have exactly one result");
     492             :   }
     493          23 :   if (instruction.is_tailcall) {
     494           0 :     ReportError("tail-calls to builtin pointers are not supported");
     495             :   }
     496             : 
     497          46 :   stack->Push(FreshNodeName());
     498          23 :   std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
     499          23 :   out_ << "    compiler::TNode<" << generated_type << "> " << stack->Top()
     500          23 :        << " = ";
     501          23 :   if (generated_type != "Object") out_ << "TORQUE_CAST(";
     502          23 :   out_ << "CodeStubAssembler(state_).CallBuiltinPointer(Builtins::"
     503             :           "CallableFor(ca_."
     504             :           "isolate(),"
     505             :           "ExampleBuiltinForTorqueFunctionPointerType("
     506          46 :        << instruction.type->function_pointer_type_id() << ")).descriptor(), ";
     507          23 :   PrintCommaSeparatedList(out_, function_and_arguments);
     508          23 :   out_ << ")";
     509          23 :   if (generated_type != "Object") out_ << ")";
     510          23 :   out_ << "; \n";
     511          46 :   out_ << "    USE(" << stack->Top() << ");\n";
     512          23 : }
     513             : 
     514        5204 : std::string CSAGenerator::PreCallableExceptionPreparation(
     515             :     base::Optional<Block*> catch_block) {
     516             :   std::string catch_name;
     517        5204 :   if (catch_block) {
     518          26 :     catch_name = FreshCatchName();
     519          13 :     out_ << "    compiler::CodeAssemblerExceptionHandlerLabel " << catch_name
     520          13 :          << "_label(&ca_, compiler::CodeAssemblerLabel::kDeferred);\n";
     521          13 :     out_ << "    { compiler::CodeAssemblerScopedExceptionHandler s(&ca_, &"
     522          13 :          << catch_name << "_label);\n";
     523             :   }
     524        5204 :   return catch_name;
     525             : }
     526             : 
     527        5204 : void CSAGenerator::PostCallableExceptionPreparation(
     528             :     const std::string& catch_name, const Type* return_type,
     529             :     base::Optional<Block*> catch_block, Stack<std::string>* stack) {
     530        5204 :   if (catch_block) {
     531          13 :     std::string block_name = BlockName(*catch_block);
     532          13 :     out_ << "    }\n";
     533          26 :     out_ << "    if (" << catch_name << "_label.is_used()) {\n";
     534          13 :     out_ << "      compiler::CodeAssemblerLabel " << catch_name
     535          13 :          << "_skip(&ca_);\n";
     536          13 :     if (!return_type->IsNever()) {
     537          20 :       out_ << "      ca_.Goto(&" << catch_name << "_skip);\n";
     538             :     }
     539          13 :     out_ << "      compiler::TNode<Object> " << catch_name
     540          13 :          << "_exception_object;\n";
     541          13 :     out_ << "      ca_.Bind(&" << catch_name << "_label, &" << catch_name
     542          13 :          << "_exception_object);\n";
     543          13 :     out_ << "      ca_.Goto(&" << block_name;
     544         245 :     for (size_t i = 0; i < stack->Size(); ++i) {
     545         116 :       out_ << ", " << stack->begin()[i];
     546             :     }
     547          26 :     out_ << ", " << catch_name << "_exception_object);\n";
     548          13 :     if (!return_type->IsNever()) {
     549          20 :       out_ << "      ca_.Bind(&" << catch_name << "_skip);\n";
     550             :     }
     551          13 :     out_ << "    }\n";
     552             :   }
     553        5204 : }
     554             : 
     555          27 : void CSAGenerator::EmitInstruction(const CallRuntimeInstruction& instruction,
     556             :                                    Stack<std::string>* stack) {
     557          54 :   std::vector<std::string> arguments = stack->PopMany(instruction.argc);
     558             :   const Type* return_type =
     559          27 :       instruction.runtime_function->signature().return_type;
     560             :   std::vector<const Type*> result_types;
     561          27 :   if (return_type != TypeOracle::GetNeverType()) {
     562          30 :     result_types = LowerType(return_type);
     563             :   }
     564          27 :   if (result_types.size() > 1) {
     565           0 :     ReportError("runtime function must have at most one result");
     566             :   }
     567          27 :   if (instruction.is_tailcall) {
     568           0 :     out_ << "    CodeStubAssembler(state_).TailCallRuntime(Runtime::k"
     569           0 :          << instruction.runtime_function->ExternalName() << ", ";
     570           0 :     PrintCommaSeparatedList(out_, arguments);
     571           0 :     out_ << ");\n";
     572             :   } else {
     573          27 :     std::string result_name = FreshNodeName();
     574          27 :     if (result_types.size() == 1) {
     575          11 :       out_ << "    compiler::TNode<"
     576          22 :            << result_types[0]->GetGeneratedTNodeTypeName() << "> "
     577          11 :            << result_name << ";\n";
     578             :     }
     579             :     std::string catch_name =
     580          27 :         PreCallableExceptionPreparation(instruction.catch_block);
     581             :     Stack<std::string> pre_call_stack = *stack;
     582          27 :     if (result_types.size() == 1) {
     583          11 :       stack->Push(result_name);
     584          11 :       out_ << "    " << result_name
     585             :            << " = TORQUE_CAST(CodeStubAssembler(state_).CallRuntime(Runtime::k"
     586          22 :            << instruction.runtime_function->ExternalName() << ", ";
     587          11 :       PrintCommaSeparatedList(out_, arguments);
     588          11 :       out_ << "));\n";
     589          22 :       out_ << "    USE(" << result_name << ");\n";
     590             :     } else {
     591             :       DCHECK_EQ(0, result_types.size());
     592          16 :       out_ << "    CodeStubAssembler(state_).CallRuntime(Runtime::k"
     593          32 :            << instruction.runtime_function->ExternalName() << ", ";
     594          16 :       PrintCommaSeparatedList(out_, arguments);
     595          16 :       out_ << ");\n";
     596          16 :       if (return_type == TypeOracle::GetNeverType()) {
     597          12 :         out_ << "    CodeStubAssembler(state_).Unreachable();\n";
     598             :       } else {
     599             :         DCHECK(return_type == TypeOracle::GetVoidType());
     600             :       }
     601             :     }
     602             :     PostCallableExceptionPreparation(catch_name, return_type,
     603          27 :                                      instruction.catch_block, &pre_call_stack);
     604             :   }
     605          27 : }
     606             : 
     607         836 : void CSAGenerator::EmitInstruction(const BranchInstruction& instruction,
     608             :                                    Stack<std::string>* stack) {
     609        1672 :   out_ << "    ca_.Branch(" << stack->Pop() << ", &"
     610        1672 :        << BlockName(instruction.if_true) << ", &"
     611        1672 :        << BlockName(instruction.if_false);
     612       15270 :   for (const std::string& value : *stack) {
     613        7217 :     out_ << ", " << value;
     614             :   }
     615         836 :   out_ << ");\n";
     616         836 : }
     617             : 
     618          53 : void CSAGenerator::EmitInstruction(
     619             :     const ConstexprBranchInstruction& instruction, Stack<std::string>* stack) {
     620         106 :   out_ << "    if ((" << instruction.condition << ")) {\n";
     621         106 :   out_ << "      ca_.Goto(&" << BlockName(instruction.if_true);
     622         793 :   for (const std::string& value : *stack) {
     623         370 :     out_ << ", " << value;
     624             :   }
     625          53 :   out_ << ");\n";
     626          53 :   out_ << "    } else {\n";
     627         106 :   out_ << "      ca_.Goto(&" << BlockName(instruction.if_false);
     628         793 :   for (const std::string& value : *stack) {
     629         370 :     out_ << ", " << value;
     630             :   }
     631          53 :   out_ << ");\n";
     632             : 
     633          53 :   out_ << "    }\n";
     634          53 : }
     635             : 
     636        5846 : void CSAGenerator::EmitInstruction(const GotoInstruction& instruction,
     637             :                                    Stack<std::string>* stack) {
     638       11692 :   out_ << "    ca_.Goto(&" << BlockName(instruction.destination);
     639       62332 :   for (const std::string& value : *stack) {
     640       28243 :     out_ << ", " << value;
     641             :   }
     642        5846 :   out_ << ");\n";
     643        5846 : }
     644             : 
     645         136 : void CSAGenerator::EmitInstruction(const GotoExternalInstruction& instruction,
     646             :                                    Stack<std::string>* stack) {
     647         164 :   for (auto it = instruction.variable_names.rbegin();
     648             :        it != instruction.variable_names.rend(); ++it) {
     649          84 :     out_ << "    *" << *it << " = " << stack->Pop() << ";\n";
     650             :   }
     651         272 :   out_ << "    ca_.Goto(" << instruction.destination << ");\n";
     652         136 : }
     653             : 
     654         243 : void CSAGenerator::EmitInstruction(const ReturnInstruction& instruction,
     655             :                                    Stack<std::string>* stack) {
     656         243 :   if (*linkage_ == Builtin::kVarArgsJavaScript) {
     657         214 :     out_ << "    " << ARGUMENTS_VARIABLE_STRING << ".PopAndReturn(";
     658             :   } else {
     659         136 :     out_ << "    CodeStubAssembler(state_).Return(";
     660             :   }
     661         729 :   out_ << stack->Pop() << ");\n";
     662         243 : }
     663             : 
     664           0 : void CSAGenerator::EmitInstruction(
     665             :     const PrintConstantStringInstruction& instruction,
     666             :     Stack<std::string>* stack) {
     667           0 :   out_ << "    CodeStubAssembler(state_).Print("
     668           0 :        << StringLiteralQuote(instruction.message) << ");\n";
     669           0 : }
     670             : 
     671         238 : void CSAGenerator::EmitInstruction(const AbortInstruction& instruction,
     672             :                                    Stack<std::string>* stack) {
     673         238 :   switch (instruction.kind) {
     674             :     case AbortInstruction::Kind::kUnreachable:
     675             :       DCHECK(instruction.message.empty());
     676         127 :       out_ << "    CodeStubAssembler(state_).Unreachable();\n";
     677         127 :       break;
     678             :     case AbortInstruction::Kind::kDebugBreak:
     679             :       DCHECK(instruction.message.empty());
     680           0 :       out_ << "    CodeStubAssembler(state_).DebugBreak();\n";
     681           0 :       break;
     682             :     case AbortInstruction::Kind::kAssertionFailure: {
     683             :       std::string file =
     684         111 :           StringLiteralQuote(SourceFileMap::GetSource(instruction.pos.source));
     685         111 :       out_ << "    CodeStubAssembler(state_).FailAssert("
     686         222 :            << StringLiteralQuote(instruction.message) << ", " << file << ", "
     687         222 :            << instruction.pos.start.line + 1 << ");\n";
     688             :       break;
     689             :     }
     690             :   }
     691         238 : }
     692             : 
     693          42 : void CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction,
     694             :                                    Stack<std::string>* stack) {
     695             :   stack->Poke(stack->AboveTop() - 1,
     696          84 :               "ca_.UncheckedCast<" +
     697         168 :                   instruction.destination_type->GetGeneratedTNodeTypeName() +
     698         210 :                   ">(" + stack->Top() + ")");
     699          42 : }
     700             : 
     701         962 : void CSAGenerator::EmitInstruction(
     702             :     const CreateFieldReferenceInstruction& instruction,
     703             :     Stack<std::string>* stack) {
     704             :   const Field& field =
     705         962 :       instruction.class_type->LookupField(instruction.field_name);
     706         962 :   std::string offset_name = FreshNodeName();
     707         962 :   stack->Push(offset_name);
     708             : 
     709         962 :   out_ << "    compiler::TNode<IntPtrT> " << offset_name
     710         962 :        << " = ca_.IntPtrConstant(";
     711         962 :   if (instruction.class_type->IsExtern()) {
     712        1696 :     out_ << field.aggregate->GetGeneratedTNodeTypeName() << "::k"
     713        2544 :          << CamelifyString(field.name_and_type.name) << "Offset";
     714             :   } else {
     715         114 :     out_ << "FixedArray::kHeaderSize + " << field.offset;
     716             :   }
     717         962 :   out_ << ");\n"
     718        1924 :        << "    USE(" << stack->Top() << ");\n";
     719         962 : }
     720             : 
     721         547 : void CSAGenerator::EmitInstruction(const LoadReferenceInstruction& instruction,
     722             :                                    Stack<std::string>* stack) {
     723         547 :   std::string result_name = FreshNodeName();
     724             : 
     725         547 :   std::string offset = stack->Pop();
     726         547 :   std::string object = stack->Pop();
     727         547 :   stack->Push(result_name);
     728             : 
     729        1094 :   out_ << "    " << instruction.type->GetGeneratedTypeName() << result_name
     730             :        << " = CodeStubAssembler(state_).LoadReference<"
     731        1094 :        << instruction.type->GetGeneratedTNodeTypeName()
     732             :        << ">(CodeStubAssembler::Reference{" << object << ", " << offset
     733         547 :        << "});\n";
     734         547 : }
     735             : 
     736         420 : void CSAGenerator::EmitInstruction(const StoreReferenceInstruction& instruction,
     737             :                                    Stack<std::string>* stack) {
     738         420 :   std::string value = stack->Pop();
     739         420 :   std::string offset = stack->Pop();
     740         420 :   std::string object = stack->Pop();
     741             : 
     742         420 :   out_ << "    CodeStubAssembler(state_).StoreReference(CodeStubAssembler::"
     743             :           "Reference{"
     744         420 :        << object << ", " << offset << "}, " << value << ");\n";
     745         420 : }
     746             : 
     747             : // static
     748        8310 : void CSAGenerator::EmitCSAValue(VisitResult result,
     749             :                                 const Stack<std::string>& values,
     750             :                                 std::ostream& out) {
     751        8310 :   if (!result.IsOnStack()) {
     752             :     out << result.constexpr_value();
     753        8279 :   } else if (auto* struct_type = StructType::DynamicCast(result.type())) {
     754         528 :     out << struct_type->GetGeneratedTypeName() << "{";
     755             :     bool first = true;
     756         703 :     for (auto& field : struct_type->fields()) {
     757         527 :       if (!first) {
     758         351 :         out << ", ";
     759             :       }
     760             :       first = false;
     761        2108 :       EmitCSAValue(ProjectStructField(result, field.name_and_type.name), values,
     762         527 :                    out);
     763             :     }
     764         176 :     out << "}";
     765        8103 :   } else if (result.type()->IsReferenceType()) {
     766             :     DCHECK_EQ(2, result.stack_range().Size());
     767             :     size_t offset = result.stack_range().begin().offset;
     768             :     out << "CodeStubAssembler::Reference{" << values.Peek(BottomOffset{offset})
     769           6 :         << ", " << values.Peek(BottomOffset{offset + 1}) << "}";
     770             :   } else {
     771             :     DCHECK_EQ(1, result.stack_range().Size());
     772       16200 :     out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName()
     773        8100 :         << ">{" << values.Peek(result.stack_range().begin()) << "}";
     774             :   }
     775        8310 : }
     776             : 
     777             : }  // namespace torque
     778             : }  // namespace internal
     779       59456 : }  // namespace v8

Generated by: LCOV version 1.10