LCOV - code coverage report
Current view: top level - src/torque - csa-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 429 470 91.3 %
Date: 2019-01-20 Functions: 29 31 93.5 %

          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/torque/type-oracle.h"
       8             : #include "src/torque/utils.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : namespace torque {
      13             : 
      14         594 : base::Optional<Stack<std::string>> CSAGenerator::EmitGraph(
      15             :     Stack<std::string> parameters) {
      16       10558 :   for (Block* block : cfg_.blocks()) {
      17        4388 :     out_ << "  compiler::CodeAssemblerParameterizedLabel<";
      18        4388 :     PrintCommaSeparatedList(out_, block->InputTypes(), [](const Type* t) {
      19       27205 :       return t->GetGeneratedTNodeTypeName();
      20       31593 :     });
      21       13164 :     out_ << "> " << BlockName(block) << "(&ca_, compiler::CodeAssemblerLabel::"
      22        8776 :          << (block->IsDeferred() ? "kDeferred" : "kNonDeferred") << ");\n";
      23             :   }
      24             : 
      25        1782 :   EmitInstruction(GotoInstruction{cfg_.start()}, &parameters);
      26        5576 :   for (Block* block : cfg_.blocks()) {
      27       12159 :     if (cfg_.end() && *cfg_.end() == block) continue;
      28       11799 :     out_ << "\n  if (" << BlockName(block) << ".is_used()) {\n";
      29        7866 :     EmitBlock(block);
      30        3933 :     out_ << "  }\n";
      31             :   }
      32        1188 :   if (cfg_.end()) {
      33         455 :     out_ << "\n";
      34        1365 :     return EmitBlock(*cfg_.end());
      35             :   }
      36             :   return base::nullopt;
      37             : }
      38             : 
      39        4388 : Stack<std::string> CSAGenerator::EmitBlock(const Block* block) {
      40             :   Stack<std::string> stack;
      41       31593 :   for (const Type* t : block->InputTypes()) {
      42       54410 :     stack.Push(FreshNodeName());
      43       81615 :     out_ << "    compiler::TNode<" << t->GetGeneratedTNodeTypeName() << "> "
      44       54410 :          << stack.Top() << ";\n";
      45             :   }
      46        8776 :   out_ << "    ca_.Bind(&" << BlockName(block);
      47       31593 :   for (const std::string& name : stack) {
      48       27205 :     out_ << ", &" << name;
      49             :   }
      50        4388 :   out_ << ");\n";
      51       36004 :   for (const Instruction& instruction : block->instructions()) {
      52       27228 :     EmitInstruction(instruction, &stack);
      53             :   }
      54        4388 :   return stack;
      55             : }
      56             : 
      57       27228 : void CSAGenerator::EmitInstruction(const Instruction& instruction,
      58             :                                    Stack<std::string>* stack) {
      59       27228 :   switch (instruction.kind()) {
      60             : #define ENUM_ITEM(T)          \
      61             :   case InstructionKind::k##T: \
      62             :     return EmitInstruction(instruction.Cast<T>(), stack);
      63       20998 :     TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
      64             : #undef ENUM_ITEM
      65             :   }
      66             : }
      67             : 
      68       12423 : void CSAGenerator::EmitInstruction(const PeekInstruction& instruction,
      69             :                                    Stack<std::string>* stack) {
      70       24846 :   stack->Push(stack->Peek(instruction.slot));
      71       12423 : }
      72             : 
      73         467 : void CSAGenerator::EmitInstruction(const PokeInstruction& instruction,
      74             :                                    Stack<std::string>* stack) {
      75         934 :   stack->Poke(instruction.slot, stack->Top());
      76         934 :   stack->Pop();
      77         467 : }
      78             : 
      79           0 : void CSAGenerator::EmitInstruction(const DeleteRangeInstruction& instruction,
      80             :                                    Stack<std::string>* stack) {
      81        6230 :   stack->DeleteRange(instruction.range);
      82           0 : }
      83             : 
      84          77 : void CSAGenerator::EmitInstruction(
      85             :     const PushUninitializedInstruction& instruction,
      86             :     Stack<std::string>* stack) {
      87             :   // TODO(tebbi): This can trigger an error in CSA if it is used. Instead, we
      88             :   // should prevent usage of uninitialized in the type system. This
      89             :   // requires "if constexpr" being evaluated at Torque time.
      90         231 :   stack->Push("ca_.Uninitialized<" +
      91         154 :               instruction.type->GetGeneratedTNodeTypeName() + ">()");
      92          77 : }
      93             : 
      94          63 : void CSAGenerator::EmitInstruction(
      95             :     const PushBuiltinPointerInstruction& instruction,
      96             :     Stack<std::string>* stack) {
      97         126 :   stack->Push("ca_.UncheckedCast<BuiltinPtr>(ca_.SmiConstant(Builtins::k" +
      98          63 :               instruction.external_name + "))");
      99          63 : }
     100             : 
     101         245 : void CSAGenerator::EmitInstruction(
     102             :     const NamespaceConstantInstruction& instruction,
     103             :     Stack<std::string>* stack) {
     104         245 :   const Type* type = instruction.constant->type();
     105             :   std::vector<std::string> results;
     106         980 :   for (const Type* lowered : LowerType(type)) {
     107         490 :     results.push_back(FreshNodeName());
     108         490 :     stack->Push(results.back());
     109         490 :     out_ << "    compiler::TNode<" << lowered->GetGeneratedTNodeTypeName()
     110         735 :          << "> " << stack->Top() << ";\n";
     111         490 :     out_ << "    USE(" << stack->Top() << ");\n";
     112             :   }
     113         245 :   out_ << "    ";
     114         245 :   if (type->IsStructType()) {
     115           0 :     out_ << "std::tie(";
     116           0 :     PrintCommaSeparatedList(out_, results);
     117           0 :     out_ << ") = ";
     118         490 :   } else if (results.size() == 1) {
     119         490 :     out_ << results[0] << " = ";
     120             :   }
     121         735 :   out_ << instruction.constant->ExternalAssemblerName() << "(state_)."
     122         490 :        << instruction.constant->constant_name() << "()";
     123         245 :   if (type->IsStructType()) {
     124           0 :     out_ << ".Flatten();\n";
     125             :   } else {
     126         245 :     out_ << ";\n";
     127         245 :   }
     128         245 : }
     129             : 
     130        4022 : void CSAGenerator::ProcessArgumentsCommon(
     131             :     const TypeVector& parameter_types, std::vector<std::string>* args,
     132             :     std::vector<std::string>* constexpr_arguments, Stack<std::string>* stack) {
     133       11194 :   for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) {
     134        7172 :     const Type* type = *it;
     135             :     VisitResult arg;
     136        7172 :     if (type->IsConstexpr()) {
     137        1604 :       args->push_back(std::move(constexpr_arguments->back()));
     138             :       constexpr_arguments->pop_back();
     139             :     } else {
     140        5568 :       std::stringstream s;
     141        5568 :       size_t slot_count = LoweredSlotCount(type);
     142             :       VisitResult arg = VisitResult(type, stack->TopRange(slot_count));
     143       11136 :       EmitCSAValue(arg, *stack, s);
     144        5568 :       args->push_back(s.str());
     145       11136 :       stack->PopMany(slot_count);
     146             :     }
     147             :   }
     148             :   std::reverse(args->begin(), args->end());
     149        4022 : }
     150             : 
     151          61 : void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
     152             :                                    Stack<std::string>* stack) {
     153             :   std::vector<std::string> constexpr_arguments =
     154          61 :       instruction.constexpr_arguments;
     155          61 :   std::vector<std::string> args;
     156             :   TypeVector parameter_types =
     157          61 :       instruction.intrinsic->signature().parameter_types.types;
     158          61 :   ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
     159             : 
     160             :   Stack<std::string> pre_call_stack = *stack;
     161          61 :   const Type* return_type = instruction.intrinsic->signature().return_type;
     162          61 :   std::vector<std::string> results;
     163         244 :   for (const Type* type : LowerType(return_type)) {
     164         122 :     results.push_back(FreshNodeName());
     165         122 :     stack->Push(results.back());
     166         183 :     out_ << "    compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
     167         122 :          << stack->Top() << ";\n";
     168         122 :     out_ << "    USE(" << stack->Top() << ");\n";
     169             :   }
     170          61 :   out_ << "    ";
     171             : 
     172          61 :   if (return_type->IsStructType()) {
     173           0 :     out_ << "std::tie(";
     174           0 :     PrintCommaSeparatedList(out_, results);
     175           0 :     out_ << ") = ";
     176             :   } else {
     177         122 :     if (results.size() == 1) {
     178         122 :       out_ << results[0] << " = ";
     179             :     }
     180             :   }
     181             : 
     182         122 :   if (instruction.intrinsic->ExternalName() == "%RawObjectCast") {
     183          86 :     if (parameter_types.size() != 1) {
     184           0 :       ReportError("%RawObjectCast must take a single parameter");
     185             :     }
     186          43 :     if (return_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
     187         172 :       if (return_type->GetGeneratedTNodeTypeName() !=
     188          86 :           parameter_types[0]->GetGeneratedTNodeTypeName()) {
     189          42 :         out_ << "TORQUE_CAST";
     190             :       }
     191             :     } else {
     192           0 :       std::stringstream s;
     193           0 :       s << "%RawObjectCast must cast to subtype of Tagged (" << *return_type
     194           0 :         << " is not)";
     195           0 :       ReportError(s.str());
     196             :     }
     197          36 :   } else if (instruction.intrinsic->ExternalName() == "%RawPointerCast") {
     198           6 :     if (parameter_types.size() != 1) {
     199           0 :       ReportError("%RawPointerCast must take a single parameter");
     200             :     }
     201           3 :     if (!return_type->IsSubtypeOf(TypeOracle::GetRawPtrType())) {
     202           0 :       std::stringstream s;
     203           0 :       s << "%RawObjectCast must cast to subtype of RawPtr (" << *return_type
     204           0 :         << " is not)";
     205           0 :       ReportError(s.str());
     206             :     }
     207          30 :   } else if (instruction.intrinsic->ExternalName() == "%FromConstexpr") {
     208          28 :     if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) {
     209             :       ReportError(
     210             :           "%FromConstexpr must take a single parameter with constexpr "
     211           0 :           "type");
     212             :     }
     213          14 :     if (return_type->IsConstexpr()) {
     214           0 :       ReportError("%FromConstexpr must return a non-constexpr type");
     215             :     }
     216          14 :     if (return_type->IsSubtypeOf(TypeOracle::GetSmiType())) {
     217           2 :       out_ << "ca_.SmiConstant";
     218          12 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetNumberType())) {
     219           4 :       out_ << "ca_.NumberConstant";
     220           8 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetStringType())) {
     221           1 :       out_ << "ca_.StringConstant";
     222           7 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
     223             :       ReportError(
     224             :           "%FromConstexpr cannot cast to subclass of HeapObject unless it's a "
     225           0 :           "String or Number");
     226           7 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) {
     227           3 :       out_ << "ca_.IntPtrConstant";
     228           4 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) {
     229           1 :       out_ << "ca_.UintPtrConstant";
     230           3 :     } else if (return_type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
     231           3 :       out_ << "ca_.Int32Constant";
     232             :     } else {
     233           0 :       std::stringstream s;
     234           0 :       s << "%FromConstexpr does not support return type " << *return_type;
     235           0 :       ReportError(s.str());
     236             :     }
     237           2 :   } else if (instruction.intrinsic->ExternalName() == "%Allocate") {
     238           2 :     out_ << "ca_.UncheckedCast<" << return_type->GetGeneratedTNodeTypeName()
     239           1 :          << ">(CodeStubAssembler(state_).Allocate";
     240             :   } else {
     241           0 :     ReportError("no built in intrinsic with name " +
     242           0 :                 instruction.intrinsic->ExternalName());
     243             :   }
     244             : 
     245          61 :   out_ << "(";
     246          61 :   PrintCommaSeparatedList(out_, args);
     247         122 :   if (instruction.intrinsic->ExternalName() == "%Allocate") out_ << ")";
     248          61 :   if (return_type->IsStructType()) {
     249           0 :     out_ << ").Flatten();\n";
     250             :   } else {
     251          61 :     out_ << ");\n";
     252          61 :   }
     253          61 : }
     254             : 
     255        3541 : void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
     256             :                                    Stack<std::string>* stack) {
     257             :   std::vector<std::string> constexpr_arguments =
     258        3541 :       instruction.constexpr_arguments;
     259        3541 :   std::vector<std::string> args;
     260             :   TypeVector parameter_types =
     261        3541 :       instruction.macro->signature().parameter_types.types;
     262        3541 :   ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
     263             : 
     264             :   Stack<std::string> pre_call_stack = *stack;
     265        3541 :   const Type* return_type = instruction.macro->signature().return_type;
     266        3541 :   std::vector<std::string> results;
     267       14012 :   for (const Type* type : LowerType(return_type)) {
     268        6778 :     results.push_back(FreshNodeName());
     269        6778 :     stack->Push(results.back());
     270       10167 :     out_ << "    compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
     271        6778 :          << stack->Top() << ";\n";
     272        6778 :     out_ << "    USE(" << stack->Top() << ");\n";
     273             :   }
     274             :   std::string catch_name =
     275        3541 :       PreCallableExceptionPreparation(instruction.catch_block);
     276        3541 :   out_ << "    ";
     277        3541 :   if (return_type->IsStructType()) {
     278          21 :     out_ << "std::tie(";
     279          21 :     PrintCommaSeparatedList(out_, results);
     280          21 :     out_ << ") = ";
     281             :   } else {
     282        7040 :     if (results.size() == 1) {
     283        6656 :       out_ << results[0] << " = ca_.UncheckedCast<"
     284        9984 :            << return_type->GetGeneratedTNodeTypeName() << ">(";
     285             :     }
     286             :   }
     287        7082 :   out_ << instruction.macro->external_assembler_name() << "(state_)."
     288        7082 :        << instruction.macro->ExternalName() << "(";
     289        3541 :   PrintCommaSeparatedList(out_, args);
     290        3541 :   if (return_type->IsStructType()) {
     291          21 :     out_ << ").Flatten();\n";
     292             :   } else {
     293        7040 :     if (results.size() == 1) out_ << ")";
     294        3520 :     out_ << ");\n";
     295             :   }
     296             :   PostCallableExceptionPreparation(catch_name, return_type,
     297        7082 :                                    instruction.catch_block, &pre_call_stack);
     298        3541 : }
     299             : 
     300         420 : void CSAGenerator::EmitInstruction(
     301             :     const CallCsaMacroAndBranchInstruction& instruction,
     302             :     Stack<std::string>* stack) {
     303             :   std::vector<std::string> constexpr_arguments =
     304         420 :       instruction.constexpr_arguments;
     305         420 :   std::vector<std::string> args;
     306             :   TypeVector parameter_types =
     307         420 :       instruction.macro->signature().parameter_types.types;
     308         420 :   ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
     309             : 
     310             :   Stack<std::string> pre_call_stack = *stack;
     311         420 :   std::vector<std::string> results;
     312         420 :   const Type* return_type = instruction.macro->signature().return_type;
     313         420 :   if (return_type != TypeOracle::GetNeverType()) {
     314         877 :     for (const Type* type :
     315         564 :          LowerType(instruction.macro->signature().return_type)) {
     316         502 :       results.push_back(FreshNodeName());
     317         502 :       out_ << "    compiler::TNode<" << type->GetGeneratedTNodeTypeName()
     318         502 :            << "> " << results.back() << ";\n";
     319         502 :       out_ << "    USE(" << results.back() << ");\n";
     320             :     }
     321             :   }
     322             : 
     323         420 :   std::vector<std::string> label_names;
     324         420 :   std::vector<std::vector<std::string>> var_names;
     325        1306 :   const LabelDeclarationVector& labels = instruction.macro->signature().labels;
     326             :   DCHECK_EQ(labels.size(), instruction.label_blocks.size());
     327        1772 :   for (size_t i = 0; i < labels.size(); ++i) {
     328         466 :     TypeVector label_parameters = labels[i].types;
     329         932 :     label_names.push_back("label" + std::to_string(i));
     330         466 :     var_names.push_back({});
     331         960 :     for (size_t j = 0; j < label_parameters.size(); ++j) {
     332          84 :       var_names[i].push_back("result_" + std::to_string(i) + "_" +
     333             :                              std::to_string(j));
     334          14 :       out_ << "    compiler::TypedCodeAssemblerVariable<"
     335          56 :            << label_parameters[j]->GetGeneratedTNodeTypeName() << "> "
     336          42 :            << var_names[i][j] << "(&ca_);\n";
     337             :     }
     338         932 :     out_ << "    compiler::CodeAssemblerLabel " << label_names[i]
     339         466 :          << "(&ca_);\n";
     340             :   }
     341             : 
     342             :   std::string catch_name =
     343         420 :       PreCallableExceptionPreparation(instruction.catch_block);
     344         420 :   out_ << "    ";
     345         840 :   if (results.size() == 1) {
     346         494 :     out_ << results[0] << " = ";
     347         173 :   } else if (results.size() > 1) {
     348           2 :     out_ << "std::tie(";
     349           2 :     PrintCommaSeparatedList(out_, results);
     350           2 :     out_ << ") = ";
     351             :   }
     352         840 :   out_ << instruction.macro->external_assembler_name() << "(state_)."
     353         840 :        << instruction.macro->ExternalName() << "(";
     354         420 :   PrintCommaSeparatedList(out_, args);
     355             :   bool first = args.empty();
     356        1772 :   for (size_t i = 0; i < label_names.size(); ++i) {
     357         466 :     if (!first) out_ << ", ";
     358         932 :     out_ << "&" << label_names[i];
     359             :     first = false;
     360        1440 :     for (size_t j = 0; j < var_names[i].size(); ++j) {
     361          14 :       out_ << ", &" << var_names[i][j];
     362             :     }
     363             :   }
     364         420 :   if (return_type->IsStructType()) {
     365           2 :     out_ << ").Flatten();\n";
     366             :   } else {
     367         418 :     out_ << ");\n";
     368             :   }
     369             : 
     370             :   PostCallableExceptionPreparation(catch_name, return_type,
     371         420 :                                    instruction.catch_block, &pre_call_stack);
     372             : 
     373         420 :   if (instruction.return_continuation) {
     374         626 :     out_ << "    ca_.Goto(&" << BlockName(*instruction.return_continuation);
     375        3631 :     for (const std::string& value : *stack) {
     376        3318 :       out_ << ", " << value;
     377             :     }
     378         877 :     for (const std::string& result : results) {
     379         251 :       out_ << ", " << result;
     380             :     }
     381         313 :     out_ << ");\n";
     382             :   }
     383        1352 :   for (size_t i = 0; i < label_names.size(); ++i) {
     384         932 :     out_ << "    if (" << label_names[i] << ".is_used()) {\n";
     385        1398 :     out_ << "      ca_.Bind(&" << label_names[i] << ");\n";
     386        1398 :     out_ << "      ca_.Goto(&" << BlockName(instruction.label_blocks[i]);
     387        5339 :     for (const std::string& value : *stack) {
     388        4873 :       out_ << ", " << value;
     389             :     }
     390        1412 :     for (const std::string& var : var_names[i]) {
     391          28 :       out_ << ", " << var << ".value()";
     392             :     }
     393         466 :     out_ << ");\n";
     394             : 
     395         466 :     out_ << "    }\n";
     396         420 :   }
     397         420 : }
     398             : 
     399          71 : void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction,
     400             :                                    Stack<std::string>* stack) {
     401          71 :   std::vector<std::string> arguments = stack->PopMany(instruction.argc);
     402             :   std::vector<const Type*> result_types =
     403          71 :       LowerType(instruction.builtin->signature().return_type);
     404          71 :   if (instruction.is_tailcall) {
     405           1 :     out_ << "   CodeStubAssembler(state_).TailCallBuiltin(Builtins::k"
     406           2 :          << instruction.builtin->ExternalName() << ", ";
     407           1 :     PrintCommaSeparatedList(out_, arguments);
     408           1 :     out_ << ");\n";
     409             :   } else {
     410          70 :     std::string result_name = FreshNodeName();
     411         140 :     if (result_types.size() == 1) {
     412          48 :       out_ << "    compiler::TNode<"
     413         144 :            << result_types[0]->GetGeneratedTNodeTypeName() << "> "
     414          48 :            << result_name << ";\n";
     415             :     }
     416             :     std::string catch_name =
     417          70 :         PreCallableExceptionPreparation(instruction.catch_block);
     418             :     Stack<std::string> pre_call_stack = *stack;
     419         140 :     if (result_types.size() == 1) {
     420          48 :       std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
     421          96 :       stack->Push(result_name);
     422          96 :       out_ << "    " << result_name << " = ";
     423          48 :       if (generated_type != "Object") out_ << "TORQUE_CAST(";
     424          48 :       out_ << "CodeStubAssembler(state_).CallBuiltin(Builtins::k"
     425          96 :            << instruction.builtin->ExternalName() << ", ";
     426          48 :       PrintCommaSeparatedList(out_, arguments);
     427          48 :       if (generated_type != "Object") out_ << ")";
     428          48 :       out_ << ");\n";
     429          96 :       out_ << "    USE(" << result_name << ");\n";
     430             :     } else {
     431             :       DCHECK_EQ(0, result_types.size());
     432             :       // TODO(tebbi): Actually, builtins have to return a value, so we should
     433             :       // not have to handle this case.
     434          22 :       out_ << "    CodeStubAssembler(state_).CallBuiltin(Builtins::k"
     435          44 :            << instruction.builtin->ExternalName() << ", ";
     436          22 :       PrintCommaSeparatedList(out_, arguments);
     437          22 :       out_ << ");\n";
     438             :     }
     439             :     PostCallableExceptionPreparation(
     440             :         catch_name,
     441          70 :         result_types.size() == 0 ? TypeOracle::GetVoidType() : result_types[0],
     442          70 :         instruction.catch_block, &pre_call_stack);
     443          71 :   }
     444          71 : }
     445             : 
     446          36 : void CSAGenerator::EmitInstruction(
     447             :     const CallBuiltinPointerInstruction& instruction,
     448             :     Stack<std::string>* stack) {
     449             :   std::vector<std::string> function_and_arguments =
     450          36 :       stack->PopMany(1 + instruction.argc);
     451             :   std::vector<const Type*> result_types =
     452          72 :       LowerType(instruction.type->return_type());
     453          72 :   if (result_types.size() != 1) {
     454           0 :     ReportError("builtins must have exactly one result");
     455             :   }
     456          36 :   if (instruction.is_tailcall) {
     457           0 :     ReportError("tail-calls to builtin pointers are not supported");
     458             :   }
     459             : 
     460          72 :   stack->Push(FreshNodeName());
     461          36 :   std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
     462          72 :   out_ << "    compiler::TNode<" << generated_type << "> " << stack->Top()
     463          36 :        << " = ";
     464          36 :   if (generated_type != "Object") out_ << "TORQUE_CAST(";
     465             :   out_ << "CodeStubAssembler(state_).CallBuiltinPointer(Builtins::"
     466             :           "CallableFor(ca_."
     467             :           "isolate(),"
     468          36 :           "ExampleBuiltinForTorqueFunctionPointerType("
     469          72 :        << instruction.type->function_pointer_type_id() << ")).descriptor(), ";
     470          36 :   PrintCommaSeparatedList(out_, function_and_arguments);
     471          36 :   out_ << ")";
     472          36 :   if (generated_type != "Object") out_ << ")";
     473          36 :   out_ << "; \n";
     474         108 :   out_ << "    USE(" << stack->Top() << ");\n";
     475          36 : }
     476             : 
     477        4051 : std::string CSAGenerator::PreCallableExceptionPreparation(
     478        4051 :     base::Optional<Block*> catch_block) {
     479             :   std::string catch_name;
     480        4051 :   if (catch_block) {
     481          44 :     catch_name = FreshCatchName();
     482          22 :     out_ << "    compiler::CodeAssemblerExceptionHandlerLabel " << catch_name
     483          22 :          << "_label(&ca_, compiler::CodeAssemblerLabel::kDeferred);\n";
     484          22 :     out_ << "    { compiler::CodeAssemblerScopedExceptionHandler s(&ca_, &"
     485          22 :          << catch_name << "_label);\n";
     486             :   }
     487        4051 :   return catch_name;
     488             : }
     489             : 
     490        4051 : void CSAGenerator::PostCallableExceptionPreparation(
     491             :     const std::string& catch_name, const Type* return_type,
     492        4051 :     base::Optional<Block*> catch_block, Stack<std::string>* stack) {
     493        4051 :   if (catch_block) {
     494          22 :     std::string block_name = BlockName(*catch_block);
     495          22 :     out_ << "    }\n";
     496          44 :     out_ << "    if (" << catch_name << "_label.is_used()) {\n";
     497          22 :     out_ << "      compiler::CodeAssemblerLabel " << catch_name
     498          22 :          << "_skip(&ca_);\n";
     499          22 :     if (!return_type->IsNever()) {
     500          38 :       out_ << "      ca_.Goto(&" << catch_name << "_skip);\n";
     501             :     }
     502          22 :     out_ << "      compiler::TNode<Object> " << catch_name
     503          22 :          << "_exception_object;\n";
     504          44 :     out_ << "      ca_.Bind(&" << catch_name << "_label, &" << catch_name
     505          22 :          << "_exception_object);\n";
     506          22 :     out_ << "      ca_.Goto(&" << block_name;
     507         370 :     for (size_t i = 0; i < stack->Size(); ++i) {
     508         163 :       out_ << ", " << stack->begin()[i];
     509             :     }
     510          44 :     out_ << ", " << catch_name << "_exception_object);\n";
     511          22 :     if (!return_type->IsNever()) {
     512          38 :       out_ << "      ca_.Bind(&" << catch_name << "_skip);\n";
     513             :     }
     514          22 :     out_ << "    }\n";
     515             :   }
     516        4051 : }
     517             : 
     518          20 : void CSAGenerator::EmitInstruction(const CallRuntimeInstruction& instruction,
     519             :                                    Stack<std::string>* stack) {
     520          20 :   std::vector<std::string> arguments = stack->PopMany(instruction.argc);
     521             :   const Type* return_type =
     522          20 :       instruction.runtime_function->signature().return_type;
     523             :   std::vector<const Type*> result_types;
     524          20 :   if (return_type != TypeOracle::GetNeverType()) {
     525          30 :     result_types = LowerType(return_type);
     526             :   }
     527          40 :   if (result_types.size() > 1) {
     528           0 :     ReportError("runtime function must have at most one result");
     529             :   }
     530          20 :   if (instruction.is_tailcall) {
     531           0 :     out_ << "    CodeStubAssembler(state_).TailCallRuntime(Runtime::k"
     532           0 :          << instruction.runtime_function->ExternalName() << ", ";
     533           0 :     PrintCommaSeparatedList(out_, arguments);
     534           0 :     out_ << ");\n";
     535             :   } else {
     536          20 :     std::string result_name = FreshNodeName();
     537          40 :     if (result_types.size() == 1) {
     538           5 :       out_ << "    compiler::TNode<"
     539          15 :            << result_types[0]->GetGeneratedTNodeTypeName() << "> "
     540           5 :            << result_name << ";\n";
     541             :     }
     542             :     std::string catch_name =
     543          20 :         PreCallableExceptionPreparation(instruction.catch_block);
     544             :     Stack<std::string> pre_call_stack = *stack;
     545          40 :     if (result_types.size() == 1) {
     546          10 :       stack->Push(result_name);
     547           5 :       out_ << "    " << result_name
     548           5 :            << " = TORQUE_CAST(CodeStubAssembler(state_).CallRuntime(Runtime::k"
     549          10 :            << instruction.runtime_function->ExternalName() << ", ";
     550           5 :       PrintCommaSeparatedList(out_, arguments);
     551           5 :       out_ << "));\n";
     552          10 :       out_ << "    USE(" << result_name << ");\n";
     553             :     } else {
     554             :       DCHECK_EQ(0, result_types.size());
     555          15 :       out_ << "    CodeStubAssembler(state_).CallRuntime(Runtime::k"
     556          30 :            << instruction.runtime_function->ExternalName() << ", ";
     557          15 :       PrintCommaSeparatedList(out_, arguments);
     558          15 :       out_ << ");\n";
     559          15 :       if (return_type == TypeOracle::GetNeverType()) {
     560           5 :         out_ << "    CodeStubAssembler(state_).Unreachable();\n";
     561             :       } else {
     562             :         DCHECK(return_type == TypeOracle::GetVoidType());
     563             :       }
     564             :     }
     565             :     PostCallableExceptionPreparation(catch_name, return_type,
     566          20 :                                      instruction.catch_block, &pre_call_stack);
     567          20 :   }
     568          20 : }
     569             : 
     570         577 : void CSAGenerator::EmitInstruction(const BranchInstruction& instruction,
     571             :                                    Stack<std::string>* stack) {
     572        1731 :   out_ << "    ca_.Branch(" << stack->Pop() << ", &"
     573        1731 :        << BlockName(instruction.if_true) << ", &"
     574        1154 :        << BlockName(instruction.if_false);
     575        4496 :   for (const std::string& value : *stack) {
     576        3919 :     out_ << ", " << value;
     577             :   }
     578         577 :   out_ << ");\n";
     579         577 : }
     580             : 
     581          49 : void CSAGenerator::EmitInstruction(
     582             :     const ConstexprBranchInstruction& instruction, Stack<std::string>* stack) {
     583          98 :   out_ << "    if (" << instruction.condition << ") {\n";
     584          98 :   out_ << "      ca_.Goto(&" << BlockName(instruction.if_true);
     585         379 :   for (const std::string& value : *stack) {
     586         330 :     out_ << ", " << value;
     587             :   }
     588          49 :   out_ << ");\n";
     589          49 :   out_ << "    } else {\n";
     590          98 :   out_ << "      ca_.Goto(&" << BlockName(instruction.if_false);
     591         379 :   for (const std::string& value : *stack) {
     592         330 :     out_ << ", " << value;
     593             :   }
     594          49 :   out_ << ");\n";
     595             : 
     596          49 :   out_ << "    }\n";
     597          49 : }
     598             : 
     599        3010 : void CSAGenerator::EmitInstruction(const GotoInstruction& instruction,
     600             :                                    Stack<std::string>* stack) {
     601        6020 :   out_ << "    ca_.Goto(&" << BlockName(instruction.destination);
     602       17543 :   for (const std::string& value : *stack) {
     603       14533 :     out_ << ", " << value;
     604             :   }
     605        3010 :   out_ << ");\n";
     606        3010 : }
     607             : 
     608         129 : void CSAGenerator::EmitInstruction(const GotoExternalInstruction& instruction,
     609             :                                    Stack<std::string>* stack) {
     610         141 :   for (auto it = instruction.variable_names.rbegin();
     611             :        it != instruction.variable_names.rend(); ++it) {
     612          48 :     out_ << "    *" << *it << " = " << stack->Pop() << ";\n";
     613             :   }
     614         258 :   out_ << "    ca_.Goto(" << instruction.destination << ");\n";
     615         129 : }
     616             : 
     617         163 : void CSAGenerator::EmitInstruction(const ReturnInstruction& instruction,
     618             :                                    Stack<std::string>* stack) {
     619         163 :   if (*linkage_ == Builtin::kVarArgsJavaScript) {
     620          58 :     out_ << "    " << ARGUMENTS_VARIABLE_STRING << "->PopAndReturn(";
     621             :   } else {
     622         105 :     out_ << "    CodeStubAssembler(state_).Return(";
     623             :   }
     624         489 :   out_ << stack->Pop() << ");\n";
     625         163 : }
     626             : 
     627           0 : void CSAGenerator::EmitInstruction(
     628             :     const PrintConstantStringInstruction& instruction,
     629             :     Stack<std::string>* stack) {
     630           0 :   out_ << "    CodeStubAssembler(state_).Print("
     631           0 :        << StringLiteralQuote(instruction.message) << ");\n";
     632           0 : }
     633             : 
     634         173 : void CSAGenerator::EmitInstruction(const AbortInstruction& instruction,
     635             :                                    Stack<std::string>* stack) {
     636         173 :   switch (instruction.kind) {
     637             :     case AbortInstruction::Kind::kUnreachable:
     638             :       DCHECK(instruction.message.empty());
     639          67 :       out_ << "    CodeStubAssembler(state_).Unreachable();\n";
     640          67 :       break;
     641             :     case AbortInstruction::Kind::kDebugBreak:
     642             :       DCHECK(instruction.message.empty());
     643           0 :       out_ << "    CodeStubAssembler(state_).DebugBreak();\n";
     644           0 :       break;
     645             :     case AbortInstruction::Kind::kAssertionFailure: {
     646             :       std::string file =
     647         106 :           StringLiteralQuote(SourceFileMap::GetSource(instruction.pos.source));
     648         106 :       out_ << "    CodeStubAssembler(state_).FailAssert("
     649         424 :            << StringLiteralQuote(instruction.message) << ", " << file << ", "
     650         212 :            << instruction.pos.line + 1 << ");\n";
     651             :       break;
     652             :     }
     653             :   }
     654         173 : }
     655             : 
     656          29 : void CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction,
     657             :                                    Stack<std::string>* stack) {
     658             :   stack->Poke(stack->AboveTop() - 1,
     659          87 :               "ca_.UncheckedCast<" +
     660          58 :                   instruction.destination_type->GetGeneratedTNodeTypeName() +
     661         116 :                   ">(" + stack->Top() + ")");
     662          29 : }
     663             : 
     664          13 : void CSAGenerator::EmitInstruction(
     665             :     const LoadObjectFieldInstruction& instruction, Stack<std::string>* stack) {
     666             :   const Field& field =
     667          13 :       instruction.class_type->LookupField(instruction.field_name);
     668          13 :   std::string result_name = FreshNodeName();
     669             :   std::string type_string =
     670          13 :       field.name_and_type.type->IsSubtypeOf(TypeOracle::GetSmiType())
     671             :           ? "MachineType::TaggedSigned()"
     672          13 :           : "MachineType::AnyTagged()";
     673          39 :   out_ << field.name_and_type.type->GetGeneratedTypeName() << " " << result_name
     674          13 :        << " = "
     675          13 :        << "ca_.UncheckedCast<"
     676          26 :        << field.name_and_type.type->GetGeneratedTNodeTypeName()
     677          13 :        << ">(CodeStubAssembler(state_).LoadObjectField("
     678          78 :        << stack->Top() + ", " + std::to_string(field.offset) + ", "
     679          13 :        << type_string + "));\n";
     680          39 :   stack->Poke(stack->AboveTop() - 1, result_name);
     681          13 : }
     682             : 
     683          25 : void CSAGenerator::EmitInstruction(
     684             :     const StoreObjectFieldInstruction& instruction, Stack<std::string>* stack) {
     685          25 :   auto value = stack->Pop();
     686          25 :   auto object = stack->Pop();
     687          50 :   stack->Push(value);
     688             :   const Field& field =
     689          25 :       instruction.class_type->LookupField(instruction.field_name);
     690          25 :   if (field.offset == 0) {
     691           8 :     out_ << "    CodeStubAssembler(state_).StoreMap(" + object + ", " + value +
     692           2 :                 ");\n";
     693             :   } else {
     694         138 :     out_ << "    CodeStubAssembler(state_).StoreObjectField(" + object + ", " +
     695          69 :                 std::to_string(field.offset) + ", " + value + ");\n";
     696             :   }
     697          25 : }
     698             : 
     699             : // static
     700       11977 : void CSAGenerator::EmitCSAValue(VisitResult result,
     701             :                                 const Stack<std::string>& values,
     702             :                                 std::ostream& out) {
     703        6006 :   if (!result.IsOnStack()) {
     704             :     out << result.constexpr_value();
     705        5971 :   } else if (auto* struct_type = StructType::DynamicCast(result.type())) {
     706          93 :     out << struct_type->GetGeneratedTypeName() << "{";
     707             :     bool first = true;
     708         150 :     for (auto& field : struct_type->fields()) {
     709          88 :       if (!first) {
     710          57 :         out << ", ";
     711             :       }
     712             :       first = false;
     713             :       EmitCSAValue(ProjectStructField(result, field.name_and_type.name), values,
     714         264 :                    out);
     715             :     }
     716          31 :     out << "}";
     717             :   } else {
     718             :     DCHECK_EQ(1, result.stack_range().Size());
     719       11880 :     out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName()
     720       11880 :         << ">{" << values.Peek(result.stack_range().begin()) << "}";
     721             :   }
     722        6006 : }
     723             : 
     724             : }  // namespace torque
     725             : }  // namespace internal
     726        9078 : }  // namespace v8

Generated by: LCOV version 1.10