11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/torque/csa-generator.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/common/globals.h" 81cb0ef41Sopenharmony_ci#include "src/torque/global-context.h" 91cb0ef41Sopenharmony_ci#include "src/torque/type-oracle.h" 101cb0ef41Sopenharmony_ci#include "src/torque/types.h" 111cb0ef41Sopenharmony_ci#include "src/torque/utils.h" 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cinamespace v8 { 141cb0ef41Sopenharmony_cinamespace internal { 151cb0ef41Sopenharmony_cinamespace torque { 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_cibase::Optional<Stack<std::string>> CSAGenerator::EmitGraph( 181cb0ef41Sopenharmony_ci Stack<std::string> parameters) { 191cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < parameters.AboveTop(); ++i) { 201cb0ef41Sopenharmony_ci SetDefinitionVariable(DefinitionLocation::Parameter(i.offset), 211cb0ef41Sopenharmony_ci parameters.Peek(i)); 221cb0ef41Sopenharmony_ci } 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci for (Block* block : cfg_.blocks()) { 251cb0ef41Sopenharmony_ci if (block->IsDead()) continue; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci out() << " compiler::CodeAssemblerParameterizedLabel<"; 281cb0ef41Sopenharmony_ci bool first = true; 291cb0ef41Sopenharmony_ci DCHECK_EQ(block->InputTypes().Size(), block->InputDefinitions().Size()); 301cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < block->InputTypes().AboveTop(); ++i) { 311cb0ef41Sopenharmony_ci if (block->InputDefinitions().Peek(i).IsPhiFromBlock(block)) { 321cb0ef41Sopenharmony_ci if (!first) out() << ", "; 331cb0ef41Sopenharmony_ci out() << block->InputTypes().Peek(i)->GetGeneratedTNodeTypeName(); 341cb0ef41Sopenharmony_ci first = false; 351cb0ef41Sopenharmony_ci } 361cb0ef41Sopenharmony_ci } 371cb0ef41Sopenharmony_ci out() << "> " << BlockName(block) << "(&ca_, compiler::CodeAssemblerLabel::" 381cb0ef41Sopenharmony_ci << (block->IsDeferred() ? "kDeferred" : "kNonDeferred") << ");\n"; 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci EmitInstruction(GotoInstruction{cfg_.start()}, ¶meters); 421cb0ef41Sopenharmony_ci for (Block* block : cfg_.blocks()) { 431cb0ef41Sopenharmony_ci if (cfg_.end() && *cfg_.end() == block) continue; 441cb0ef41Sopenharmony_ci if (block->IsDead()) continue; 451cb0ef41Sopenharmony_ci out() << "\n"; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci // Redirect the output of non-declarations into a buffer and only output 481cb0ef41Sopenharmony_ci // declarations right away. 491cb0ef41Sopenharmony_ci std::stringstream out_buffer; 501cb0ef41Sopenharmony_ci std::ostream* old_out = out_; 511cb0ef41Sopenharmony_ci out_ = &out_buffer; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci out() << " if (" << BlockName(block) << ".is_used()) {\n"; 541cb0ef41Sopenharmony_ci EmitBlock(block); 551cb0ef41Sopenharmony_ci out() << " }\n"; 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci // All declarations have been printed now, so we can append the buffered 581cb0ef41Sopenharmony_ci // output and redirect back to the original output stream. 591cb0ef41Sopenharmony_ci out_ = old_out; 601cb0ef41Sopenharmony_ci out() << out_buffer.str(); 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci if (cfg_.end()) { 631cb0ef41Sopenharmony_ci out() << "\n"; 641cb0ef41Sopenharmony_ci return EmitBlock(*cfg_.end()); 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci return base::nullopt; 671cb0ef41Sopenharmony_ci} 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ciStack<std::string> CSAGenerator::EmitBlock(const Block* block) { 701cb0ef41Sopenharmony_ci Stack<std::string> stack; 711cb0ef41Sopenharmony_ci std::stringstream phi_names; 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < block->InputTypes().AboveTop(); ++i) { 741cb0ef41Sopenharmony_ci const auto& def = block->InputDefinitions().Peek(i); 751cb0ef41Sopenharmony_ci stack.Push(DefinitionToVariable(def)); 761cb0ef41Sopenharmony_ci if (def.IsPhiFromBlock(block)) { 771cb0ef41Sopenharmony_ci decls() << " TNode<" 781cb0ef41Sopenharmony_ci << block->InputTypes().Peek(i)->GetGeneratedTNodeTypeName() 791cb0ef41Sopenharmony_ci << "> " << stack.Top() << ";\n"; 801cb0ef41Sopenharmony_ci phi_names << ", &" << stack.Top(); 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci out() << " ca_.Bind(&" << BlockName(block) << phi_names.str() << ");\n"; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci for (const Instruction& instruction : block->instructions()) { 861cb0ef41Sopenharmony_ci TorqueCodeGenerator::EmitInstruction(instruction, &stack); 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci return stack; 891cb0ef41Sopenharmony_ci} 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_civoid CSAGenerator::EmitSourcePosition(SourcePosition pos, bool always_emit) { 921cb0ef41Sopenharmony_ci const std::string& file = SourceFileMap::AbsolutePath(pos.source); 931cb0ef41Sopenharmony_ci if (always_emit || !previous_position_.CompareStartIgnoreColumn(pos)) { 941cb0ef41Sopenharmony_ci // Lines in Torque SourcePositions are zero-based, while the 951cb0ef41Sopenharmony_ci // CodeStubAssembler and downwind systems are one-based. 961cb0ef41Sopenharmony_ci out() << " ca_.SetSourcePosition(\"" << file << "\", " 971cb0ef41Sopenharmony_ci << (pos.start.line + 1) << ");\n"; 981cb0ef41Sopenharmony_ci previous_position_ = pos; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci} 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction( 1031cb0ef41Sopenharmony_ci const PushUninitializedInstruction& instruction, 1041cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 1051cb0ef41Sopenharmony_ci // TODO(turbofan): This can trigger an error in CSA if it is used. Instead, we 1061cb0ef41Sopenharmony_ci // should prevent usage of uninitialized in the type system. This 1071cb0ef41Sopenharmony_ci // requires "if constexpr" being evaluated at Torque time. 1081cb0ef41Sopenharmony_ci const std::string str = "ca_.Uninitialized<" + 1091cb0ef41Sopenharmony_ci instruction.type->GetGeneratedTNodeTypeName() + ">()"; 1101cb0ef41Sopenharmony_ci stack->Push(str); 1111cb0ef41Sopenharmony_ci SetDefinitionVariable(instruction.GetValueDefinition(), str); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction( 1151cb0ef41Sopenharmony_ci const PushBuiltinPointerInstruction& instruction, 1161cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 1171cb0ef41Sopenharmony_ci const std::string str = 1181cb0ef41Sopenharmony_ci "ca_.UncheckedCast<BuiltinPtr>(ca_.SmiConstant(Builtin::k" + 1191cb0ef41Sopenharmony_ci instruction.external_name + "))"; 1201cb0ef41Sopenharmony_ci stack->Push(str); 1211cb0ef41Sopenharmony_ci SetDefinitionVariable(instruction.GetValueDefinition(), str); 1221cb0ef41Sopenharmony_ci} 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction( 1251cb0ef41Sopenharmony_ci const NamespaceConstantInstruction& instruction, 1261cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 1271cb0ef41Sopenharmony_ci const Type* type = instruction.constant->type(); 1281cb0ef41Sopenharmony_ci std::vector<std::string> results; 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci const auto lowered = LowerType(type); 1311cb0ef41Sopenharmony_ci for (std::size_t i = 0; i < lowered.size(); ++i) { 1321cb0ef41Sopenharmony_ci results.push_back(DefinitionToVariable(instruction.GetValueDefinition(i))); 1331cb0ef41Sopenharmony_ci stack->Push(results.back()); 1341cb0ef41Sopenharmony_ci decls() << " TNode<" << lowered[i]->GetGeneratedTNodeTypeName() << "> " 1351cb0ef41Sopenharmony_ci << stack->Top() << ";\n"; 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci out() << " "; 1391cb0ef41Sopenharmony_ci if (type->StructSupertype()) { 1401cb0ef41Sopenharmony_ci out() << "std::tie("; 1411cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), results); 1421cb0ef41Sopenharmony_ci out() << ") = "; 1431cb0ef41Sopenharmony_ci } else if (results.size() == 1) { 1441cb0ef41Sopenharmony_ci out() << results[0] << " = "; 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci out() << instruction.constant->external_name() << "(state_)"; 1471cb0ef41Sopenharmony_ci if (type->StructSupertype()) { 1481cb0ef41Sopenharmony_ci out() << ".Flatten();\n"; 1491cb0ef41Sopenharmony_ci } else { 1501cb0ef41Sopenharmony_ci out() << ";\n"; 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci} 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_cistd::vector<std::string> CSAGenerator::ProcessArgumentsCommon( 1551cb0ef41Sopenharmony_ci const TypeVector& parameter_types, 1561cb0ef41Sopenharmony_ci std::vector<std::string> constexpr_arguments, Stack<std::string>* stack) { 1571cb0ef41Sopenharmony_ci std::vector<std::string> args; 1581cb0ef41Sopenharmony_ci for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) { 1591cb0ef41Sopenharmony_ci const Type* type = *it; 1601cb0ef41Sopenharmony_ci if (type->IsConstexpr()) { 1611cb0ef41Sopenharmony_ci args.push_back(std::move(constexpr_arguments.back())); 1621cb0ef41Sopenharmony_ci constexpr_arguments.pop_back(); 1631cb0ef41Sopenharmony_ci } else { 1641cb0ef41Sopenharmony_ci std::stringstream s; 1651cb0ef41Sopenharmony_ci size_t slot_count = LoweredSlotCount(type); 1661cb0ef41Sopenharmony_ci VisitResult arg = VisitResult(type, stack->TopRange(slot_count)); 1671cb0ef41Sopenharmony_ci EmitCSAValue(arg, *stack, s); 1681cb0ef41Sopenharmony_ci args.push_back(s.str()); 1691cb0ef41Sopenharmony_ci stack->PopMany(slot_count); 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci } 1721cb0ef41Sopenharmony_ci std::reverse(args.begin(), args.end()); 1731cb0ef41Sopenharmony_ci return args; 1741cb0ef41Sopenharmony_ci} 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, 1771cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 1781cb0ef41Sopenharmony_ci TypeVector parameter_types = 1791cb0ef41Sopenharmony_ci instruction.intrinsic->signature().parameter_types.types; 1801cb0ef41Sopenharmony_ci std::vector<std::string> args = ProcessArgumentsCommon( 1811cb0ef41Sopenharmony_ci parameter_types, instruction.constexpr_arguments, stack); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci Stack<std::string> pre_call_stack = *stack; 1841cb0ef41Sopenharmony_ci const Type* return_type = instruction.intrinsic->signature().return_type; 1851cb0ef41Sopenharmony_ci std::vector<std::string> results; 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci const auto lowered = LowerType(return_type); 1881cb0ef41Sopenharmony_ci for (std::size_t i = 0; i < lowered.size(); ++i) { 1891cb0ef41Sopenharmony_ci results.push_back(DefinitionToVariable(instruction.GetValueDefinition(i))); 1901cb0ef41Sopenharmony_ci stack->Push(results.back()); 1911cb0ef41Sopenharmony_ci decls() << " TNode<" << lowered[i]->GetGeneratedTNodeTypeName() << "> " 1921cb0ef41Sopenharmony_ci << stack->Top() << ";\n"; 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci out() << " "; 1961cb0ef41Sopenharmony_ci if (return_type->StructSupertype()) { 1971cb0ef41Sopenharmony_ci out() << "std::tie("; 1981cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), results); 1991cb0ef41Sopenharmony_ci out() << ") = "; 2001cb0ef41Sopenharmony_ci } else { 2011cb0ef41Sopenharmony_ci if (results.size() == 1) { 2021cb0ef41Sopenharmony_ci out() << results[0] << " = "; 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci if (instruction.intrinsic->ExternalName() == "%RawDownCast") { 2071cb0ef41Sopenharmony_ci if (parameter_types.size() != 1) { 2081cb0ef41Sopenharmony_ci ReportError("%RawDownCast must take a single parameter"); 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci const Type* original_type = parameter_types[0]; 2111cb0ef41Sopenharmony_ci bool is_subtype = 2121cb0ef41Sopenharmony_ci return_type->IsSubtypeOf(original_type) || 2131cb0ef41Sopenharmony_ci (original_type == TypeOracle::GetUninitializedHeapObjectType() && 2141cb0ef41Sopenharmony_ci return_type->IsSubtypeOf(TypeOracle::GetHeapObjectType())); 2151cb0ef41Sopenharmony_ci if (!is_subtype) { 2161cb0ef41Sopenharmony_ci ReportError("%RawDownCast error: ", *return_type, " is not a subtype of ", 2171cb0ef41Sopenharmony_ci *original_type); 2181cb0ef41Sopenharmony_ci } 2191cb0ef41Sopenharmony_ci if (!original_type->StructSupertype() && 2201cb0ef41Sopenharmony_ci return_type->GetGeneratedTNodeTypeName() != 2211cb0ef41Sopenharmony_ci original_type->GetGeneratedTNodeTypeName()) { 2221cb0ef41Sopenharmony_ci if (return_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { 2231cb0ef41Sopenharmony_ci out() << "TORQUE_CAST"; 2241cb0ef41Sopenharmony_ci } else { 2251cb0ef41Sopenharmony_ci out() << "ca_.UncheckedCast<" 2261cb0ef41Sopenharmony_ci << return_type->GetGeneratedTNodeTypeName() << ">"; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci } else if (instruction.intrinsic->ExternalName() == "%GetClassMapConstant") { 2301cb0ef41Sopenharmony_ci if (parameter_types.size() != 0) { 2311cb0ef41Sopenharmony_ci ReportError("%GetClassMapConstant must not take parameters"); 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci if (instruction.specialization_types.size() != 1) { 2341cb0ef41Sopenharmony_ci ReportError( 2351cb0ef41Sopenharmony_ci "%GetClassMapConstant must take a single class as specialization " 2361cb0ef41Sopenharmony_ci "parameter"); 2371cb0ef41Sopenharmony_ci } 2381cb0ef41Sopenharmony_ci const ClassType* class_type = 2391cb0ef41Sopenharmony_ci ClassType::DynamicCast(instruction.specialization_types[0]); 2401cb0ef41Sopenharmony_ci if (!class_type) { 2411cb0ef41Sopenharmony_ci ReportError("%GetClassMapConstant must take a class type parameter"); 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci // If the class isn't actually used as the parameter to a TNode, 2441cb0ef41Sopenharmony_ci // then we can't rely on the class existing in C++ or being of the same 2451cb0ef41Sopenharmony_ci // type (e.g. it could be a template), so don't use the template CSA 2461cb0ef41Sopenharmony_ci // machinery for accessing the class' map. 2471cb0ef41Sopenharmony_ci std::string class_name = 2481cb0ef41Sopenharmony_ci class_type->name() != class_type->GetGeneratedTNodeTypeName() 2491cb0ef41Sopenharmony_ci ? std::string("void") 2501cb0ef41Sopenharmony_ci : class_type->name(); 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci out() << std::string("CodeStubAssembler(state_).GetClassMapConstant<") + 2531cb0ef41Sopenharmony_ci class_name + ">"; 2541cb0ef41Sopenharmony_ci } else if (instruction.intrinsic->ExternalName() == "%FromConstexpr") { 2551cb0ef41Sopenharmony_ci if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) { 2561cb0ef41Sopenharmony_ci ReportError( 2571cb0ef41Sopenharmony_ci "%FromConstexpr must take a single parameter with constexpr " 2581cb0ef41Sopenharmony_ci "type"); 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci if (return_type->IsConstexpr()) { 2611cb0ef41Sopenharmony_ci ReportError("%FromConstexpr must return a non-constexpr type"); 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci if (return_type->IsSubtypeOf(TypeOracle::GetSmiType())) { 2641cb0ef41Sopenharmony_ci out() << "ca_.SmiConstant"; 2651cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetNumberType())) { 2661cb0ef41Sopenharmony_ci out() << "ca_.NumberConstant"; 2671cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetStringType())) { 2681cb0ef41Sopenharmony_ci out() << "ca_.StringConstant"; 2691cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetObjectType())) { 2701cb0ef41Sopenharmony_ci ReportError( 2711cb0ef41Sopenharmony_ci "%FromConstexpr cannot cast to subclass of HeapObject unless it's a " 2721cb0ef41Sopenharmony_ci "String or Number"); 2731cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) { 2741cb0ef41Sopenharmony_ci out() << "ca_.IntPtrConstant"; 2751cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) { 2761cb0ef41Sopenharmony_ci out() << "ca_.UintPtrConstant"; 2771cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetInt32Type())) { 2781cb0ef41Sopenharmony_ci out() << "ca_.Int32Constant"; 2791cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetUint32Type())) { 2801cb0ef41Sopenharmony_ci out() << "ca_.Uint32Constant"; 2811cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetInt64Type())) { 2821cb0ef41Sopenharmony_ci out() << "ca_.Int64Constant"; 2831cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetUint64Type())) { 2841cb0ef41Sopenharmony_ci out() << "ca_.Uint64Constant"; 2851cb0ef41Sopenharmony_ci } else if (return_type->IsSubtypeOf(TypeOracle::GetBoolType())) { 2861cb0ef41Sopenharmony_ci out() << "ca_.BoolConstant"; 2871cb0ef41Sopenharmony_ci } else { 2881cb0ef41Sopenharmony_ci std::stringstream s; 2891cb0ef41Sopenharmony_ci s << "%FromConstexpr does not support return type " << *return_type; 2901cb0ef41Sopenharmony_ci ReportError(s.str()); 2911cb0ef41Sopenharmony_ci } 2921cb0ef41Sopenharmony_ci // Wrap the raw constexpr value in a static_cast to ensure that 2931cb0ef41Sopenharmony_ci // enums get properly casted to their backing integral value. 2941cb0ef41Sopenharmony_ci out() << "(CastToUnderlyingTypeIfEnum"; 2951cb0ef41Sopenharmony_ci } else { 2961cb0ef41Sopenharmony_ci ReportError("no built in intrinsic with name " + 2971cb0ef41Sopenharmony_ci instruction.intrinsic->ExternalName()); 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci out() << "("; 3011cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), args); 3021cb0ef41Sopenharmony_ci if (instruction.intrinsic->ExternalName() == "%FromConstexpr") { 3031cb0ef41Sopenharmony_ci out() << ")"; 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci if (return_type->StructSupertype()) { 3061cb0ef41Sopenharmony_ci out() << ").Flatten();\n"; 3071cb0ef41Sopenharmony_ci } else { 3081cb0ef41Sopenharmony_ci out() << ");\n"; 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci} 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, 3131cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3141cb0ef41Sopenharmony_ci TypeVector parameter_types = 3151cb0ef41Sopenharmony_ci instruction.macro->signature().parameter_types.types; 3161cb0ef41Sopenharmony_ci std::vector<std::string> args = ProcessArgumentsCommon( 3171cb0ef41Sopenharmony_ci parameter_types, instruction.constexpr_arguments, stack); 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci Stack<std::string> pre_call_stack = *stack; 3201cb0ef41Sopenharmony_ci const Type* return_type = instruction.macro->signature().return_type; 3211cb0ef41Sopenharmony_ci std::vector<std::string> results; 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci const auto lowered = LowerType(return_type); 3241cb0ef41Sopenharmony_ci for (std::size_t i = 0; i < lowered.size(); ++i) { 3251cb0ef41Sopenharmony_ci results.push_back(DefinitionToVariable(instruction.GetValueDefinition(i))); 3261cb0ef41Sopenharmony_ci stack->Push(results.back()); 3271cb0ef41Sopenharmony_ci decls() << " TNode<" << lowered[i]->GetGeneratedTNodeTypeName() << "> " 3281cb0ef41Sopenharmony_ci << stack->Top() << ";\n"; 3291cb0ef41Sopenharmony_ci } 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci std::string catch_name = 3321cb0ef41Sopenharmony_ci PreCallableExceptionPreparation(instruction.catch_block); 3331cb0ef41Sopenharmony_ci out() << " "; 3341cb0ef41Sopenharmony_ci bool needs_flattening = return_type->StructSupertype().has_value(); 3351cb0ef41Sopenharmony_ci if (needs_flattening) { 3361cb0ef41Sopenharmony_ci out() << "std::tie("; 3371cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), results); 3381cb0ef41Sopenharmony_ci out() << ") = "; 3391cb0ef41Sopenharmony_ci } else { 3401cb0ef41Sopenharmony_ci if (results.size() == 1) { 3411cb0ef41Sopenharmony_ci out() << results[0] << " = "; 3421cb0ef41Sopenharmony_ci } else { 3431cb0ef41Sopenharmony_ci DCHECK_EQ(0, results.size()); 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci if (ExternMacro* extern_macro = ExternMacro::DynamicCast(instruction.macro)) { 3471cb0ef41Sopenharmony_ci out() << extern_macro->external_assembler_name() << "(state_)."; 3481cb0ef41Sopenharmony_ci } else { 3491cb0ef41Sopenharmony_ci args.insert(args.begin(), "state_"); 3501cb0ef41Sopenharmony_ci } 3511cb0ef41Sopenharmony_ci out() << instruction.macro->ExternalName() << "("; 3521cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), args); 3531cb0ef41Sopenharmony_ci if (needs_flattening) { 3541cb0ef41Sopenharmony_ci out() << ").Flatten();\n"; 3551cb0ef41Sopenharmony_ci } else { 3561cb0ef41Sopenharmony_ci out() << ");\n"; 3571cb0ef41Sopenharmony_ci } 3581cb0ef41Sopenharmony_ci PostCallableExceptionPreparation(catch_name, return_type, 3591cb0ef41Sopenharmony_ci instruction.catch_block, &pre_call_stack, 3601cb0ef41Sopenharmony_ci instruction.GetExceptionObjectDefinition()); 3611cb0ef41Sopenharmony_ci} 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction( 3641cb0ef41Sopenharmony_ci const CallCsaMacroAndBranchInstruction& instruction, 3651cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3661cb0ef41Sopenharmony_ci TypeVector parameter_types = 3671cb0ef41Sopenharmony_ci instruction.macro->signature().parameter_types.types; 3681cb0ef41Sopenharmony_ci std::vector<std::string> args = ProcessArgumentsCommon( 3691cb0ef41Sopenharmony_ci parameter_types, instruction.constexpr_arguments, stack); 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci Stack<std::string> pre_call_stack = *stack; 3721cb0ef41Sopenharmony_ci std::vector<std::string> results; 3731cb0ef41Sopenharmony_ci const Type* return_type = instruction.macro->signature().return_type; 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci if (return_type != TypeOracle::GetNeverType()) { 3761cb0ef41Sopenharmony_ci const auto lowered = LowerType(return_type); 3771cb0ef41Sopenharmony_ci for (std::size_t i = 0; i < lowered.size(); ++i) { 3781cb0ef41Sopenharmony_ci results.push_back( 3791cb0ef41Sopenharmony_ci DefinitionToVariable(instruction.GetValueDefinition(i))); 3801cb0ef41Sopenharmony_ci decls() << " TNode<" << lowered[i]->GetGeneratedTNodeTypeName() << "> " 3811cb0ef41Sopenharmony_ci << results.back() << ";\n"; 3821cb0ef41Sopenharmony_ci } 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci std::vector<std::string> label_names; 3861cb0ef41Sopenharmony_ci std::vector<std::vector<std::string>> var_names; 3871cb0ef41Sopenharmony_ci const LabelDeclarationVector& labels = instruction.macro->signature().labels; 3881cb0ef41Sopenharmony_ci DCHECK_EQ(labels.size(), instruction.label_blocks.size()); 3891cb0ef41Sopenharmony_ci for (size_t i = 0; i < labels.size(); ++i) { 3901cb0ef41Sopenharmony_ci TypeVector label_parameters = labels[i].types; 3911cb0ef41Sopenharmony_ci label_names.push_back(FreshLabelName()); 3921cb0ef41Sopenharmony_ci var_names.push_back({}); 3931cb0ef41Sopenharmony_ci for (size_t j = 0; j < label_parameters.size(); ++j) { 3941cb0ef41Sopenharmony_ci var_names[i].push_back(FreshNodeName()); 3951cb0ef41Sopenharmony_ci const auto def = instruction.GetLabelValueDefinition(i, j); 3961cb0ef41Sopenharmony_ci SetDefinitionVariable(def, var_names[i].back() + ".value()"); 3971cb0ef41Sopenharmony_ci decls() << " compiler::TypedCodeAssemblerVariable<" 3981cb0ef41Sopenharmony_ci << label_parameters[j]->GetGeneratedTNodeTypeName() << "> " 3991cb0ef41Sopenharmony_ci << var_names[i][j] << "(&ca_);\n"; 4001cb0ef41Sopenharmony_ci } 4011cb0ef41Sopenharmony_ci out() << " compiler::CodeAssemblerLabel " << label_names[i] 4021cb0ef41Sopenharmony_ci << "(&ca_);\n"; 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci std::string catch_name = 4061cb0ef41Sopenharmony_ci PreCallableExceptionPreparation(instruction.catch_block); 4071cb0ef41Sopenharmony_ci out() << " "; 4081cb0ef41Sopenharmony_ci if (results.size() == 1) { 4091cb0ef41Sopenharmony_ci out() << results[0] << " = "; 4101cb0ef41Sopenharmony_ci } else if (results.size() > 1) { 4111cb0ef41Sopenharmony_ci out() << "std::tie("; 4121cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), results); 4131cb0ef41Sopenharmony_ci out() << ") = "; 4141cb0ef41Sopenharmony_ci } 4151cb0ef41Sopenharmony_ci if (ExternMacro* extern_macro = ExternMacro::DynamicCast(instruction.macro)) { 4161cb0ef41Sopenharmony_ci out() << extern_macro->external_assembler_name() << "(state_)."; 4171cb0ef41Sopenharmony_ci } else { 4181cb0ef41Sopenharmony_ci args.insert(args.begin(), "state_"); 4191cb0ef41Sopenharmony_ci } 4201cb0ef41Sopenharmony_ci out() << instruction.macro->ExternalName() << "("; 4211cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), args); 4221cb0ef41Sopenharmony_ci bool first = args.empty(); 4231cb0ef41Sopenharmony_ci for (size_t i = 0; i < label_names.size(); ++i) { 4241cb0ef41Sopenharmony_ci if (!first) out() << ", "; 4251cb0ef41Sopenharmony_ci out() << "&" << label_names[i]; 4261cb0ef41Sopenharmony_ci first = false; 4271cb0ef41Sopenharmony_ci for (size_t j = 0; j < var_names[i].size(); ++j) { 4281cb0ef41Sopenharmony_ci out() << ", &" << var_names[i][j]; 4291cb0ef41Sopenharmony_ci } 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci if (return_type->StructSupertype()) { 4321cb0ef41Sopenharmony_ci out() << ").Flatten();\n"; 4331cb0ef41Sopenharmony_ci } else { 4341cb0ef41Sopenharmony_ci out() << ");\n"; 4351cb0ef41Sopenharmony_ci } 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci PostCallableExceptionPreparation(catch_name, return_type, 4381cb0ef41Sopenharmony_ci instruction.catch_block, &pre_call_stack, 4391cb0ef41Sopenharmony_ci instruction.GetExceptionObjectDefinition()); 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci if (instruction.return_continuation) { 4421cb0ef41Sopenharmony_ci out() << " ca_.Goto(&" << BlockName(*instruction.return_continuation); 4431cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size() + results.size(), 4441cb0ef41Sopenharmony_ci (*instruction.return_continuation)->InputDefinitions().Size()); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci const auto& input_definitions = 4471cb0ef41Sopenharmony_ci (*instruction.return_continuation)->InputDefinitions(); 4481cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < input_definitions.AboveTop(); ++i) { 4491cb0ef41Sopenharmony_ci if (input_definitions.Peek(i).IsPhiFromBlock( 4501cb0ef41Sopenharmony_ci *instruction.return_continuation)) { 4511cb0ef41Sopenharmony_ci out() << ", " 4521cb0ef41Sopenharmony_ci << (i < stack->AboveTop() ? stack->Peek(i) : results[i.offset]); 4531cb0ef41Sopenharmony_ci } 4541cb0ef41Sopenharmony_ci } 4551cb0ef41Sopenharmony_ci out() << ");\n"; 4561cb0ef41Sopenharmony_ci } 4571cb0ef41Sopenharmony_ci for (size_t l = 0; l < label_names.size(); ++l) { 4581cb0ef41Sopenharmony_ci out() << " if (" << label_names[l] << ".is_used()) {\n"; 4591cb0ef41Sopenharmony_ci out() << " ca_.Bind(&" << label_names[l] << ");\n"; 4601cb0ef41Sopenharmony_ci out() << " ca_.Goto(&" << BlockName(instruction.label_blocks[l]); 4611cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size() + var_names[l].size(), 4621cb0ef41Sopenharmony_ci instruction.label_blocks[l]->InputDefinitions().Size()); 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci const auto& label_definitions = 4651cb0ef41Sopenharmony_ci instruction.label_blocks[l]->InputDefinitions(); 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci BottomOffset i = {0}; 4681cb0ef41Sopenharmony_ci for (; i < stack->AboveTop(); ++i) { 4691cb0ef41Sopenharmony_ci if (label_definitions.Peek(i).IsPhiFromBlock( 4701cb0ef41Sopenharmony_ci instruction.label_blocks[l])) { 4711cb0ef41Sopenharmony_ci out() << ", " << stack->Peek(i); 4721cb0ef41Sopenharmony_ci } 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci for (std::size_t k = 0; k < var_names[l].size(); ++k, ++i) { 4751cb0ef41Sopenharmony_ci if (label_definitions.Peek(i).IsPhiFromBlock( 4761cb0ef41Sopenharmony_ci instruction.label_blocks[l])) { 4771cb0ef41Sopenharmony_ci out() << ", " << var_names[l][k] << ".value()"; 4781cb0ef41Sopenharmony_ci } 4791cb0ef41Sopenharmony_ci } 4801cb0ef41Sopenharmony_ci out() << ");\n"; 4811cb0ef41Sopenharmony_ci out() << " }\n"; 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci} 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const MakeLazyNodeInstruction& instruction, 4861cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 4871cb0ef41Sopenharmony_ci TypeVector parameter_types = 4881cb0ef41Sopenharmony_ci instruction.macro->signature().parameter_types.types; 4891cb0ef41Sopenharmony_ci std::vector<std::string> args = ProcessArgumentsCommon( 4901cb0ef41Sopenharmony_ci parameter_types, instruction.constexpr_arguments, stack); 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ci std::string result_name = 4931cb0ef41Sopenharmony_ci DefinitionToVariable(instruction.GetValueDefinition()); 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci stack->Push(result_name); 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci decls() << " " << instruction.result_type->GetGeneratedTypeName() << " " 4981cb0ef41Sopenharmony_ci << result_name << ";\n"; 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci // We assume here that the CodeAssemblerState will outlive any usage of 5011cb0ef41Sopenharmony_ci // the generated std::function that binds it. Likewise, copies of TNode values 5021cb0ef41Sopenharmony_ci // are only valid during generation of the current builtin. 5031cb0ef41Sopenharmony_ci out() << " " << result_name << " = [=] () { return "; 5041cb0ef41Sopenharmony_ci bool first = true; 5051cb0ef41Sopenharmony_ci if (const ExternMacro* extern_macro = 5061cb0ef41Sopenharmony_ci ExternMacro::DynamicCast(instruction.macro)) { 5071cb0ef41Sopenharmony_ci out() << extern_macro->external_assembler_name() << "(state_)." 5081cb0ef41Sopenharmony_ci << extern_macro->ExternalName() << "("; 5091cb0ef41Sopenharmony_ci } else { 5101cb0ef41Sopenharmony_ci out() << instruction.macro->ExternalName() << "(state_"; 5111cb0ef41Sopenharmony_ci first = false; 5121cb0ef41Sopenharmony_ci } 5131cb0ef41Sopenharmony_ci if (!args.empty()) { 5141cb0ef41Sopenharmony_ci if (!first) out() << ", "; 5151cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), args); 5161cb0ef41Sopenharmony_ci } 5171cb0ef41Sopenharmony_ci out() << "); };\n"; 5181cb0ef41Sopenharmony_ci} 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction, 5211cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 5221cb0ef41Sopenharmony_ci std::vector<std::string> arguments = stack->PopMany(instruction.argc); 5231cb0ef41Sopenharmony_ci std::vector<const Type*> result_types = 5241cb0ef41Sopenharmony_ci LowerType(instruction.builtin->signature().return_type); 5251cb0ef41Sopenharmony_ci if (instruction.is_tailcall) { 5261cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).TailCallBuiltin(Builtin::k" 5271cb0ef41Sopenharmony_ci << instruction.builtin->ExternalName(); 5281cb0ef41Sopenharmony_ci if (!instruction.builtin->signature().HasContextParameter()) { 5291cb0ef41Sopenharmony_ci // Add dummy context parameter to satisfy the TailCallBuiltin signature. 5301cb0ef41Sopenharmony_ci out() << ", TNode<Object>()"; 5311cb0ef41Sopenharmony_ci } 5321cb0ef41Sopenharmony_ci for (const std::string& argument : arguments) { 5331cb0ef41Sopenharmony_ci out() << ", " << argument; 5341cb0ef41Sopenharmony_ci } 5351cb0ef41Sopenharmony_ci out() << ");\n"; 5361cb0ef41Sopenharmony_ci } else { 5371cb0ef41Sopenharmony_ci std::vector<std::string> result_names(result_types.size()); 5381cb0ef41Sopenharmony_ci for (size_t i = 0; i < result_types.size(); ++i) { 5391cb0ef41Sopenharmony_ci result_names[i] = DefinitionToVariable(instruction.GetValueDefinition(i)); 5401cb0ef41Sopenharmony_ci decls() << " TNode<" << result_types[i]->GetGeneratedTNodeTypeName() 5411cb0ef41Sopenharmony_ci << "> " << result_names[i] << ";\n"; 5421cb0ef41Sopenharmony_ci } 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_ci std::string lhs_name; 5451cb0ef41Sopenharmony_ci std::string lhs_type; 5461cb0ef41Sopenharmony_ci switch (result_types.size()) { 5471cb0ef41Sopenharmony_ci case 1: 5481cb0ef41Sopenharmony_ci lhs_name = result_names[0]; 5491cb0ef41Sopenharmony_ci lhs_type = result_types[0]->GetGeneratedTNodeTypeName(); 5501cb0ef41Sopenharmony_ci break; 5511cb0ef41Sopenharmony_ci case 2: 5521cb0ef41Sopenharmony_ci // If a builtin returns two values, the return type is represented as a 5531cb0ef41Sopenharmony_ci // TNode containing a pair. We need a temporary place to store that 5541cb0ef41Sopenharmony_ci // result so we can unpack it into separate TNodes. 5551cb0ef41Sopenharmony_ci lhs_name = result_names[0] + "_and_" + result_names[1]; 5561cb0ef41Sopenharmony_ci lhs_type = "PairT<" + result_types[0]->GetGeneratedTNodeTypeName() + 5571cb0ef41Sopenharmony_ci ", " + result_types[1]->GetGeneratedTNodeTypeName() + ">"; 5581cb0ef41Sopenharmony_ci decls() << " TNode<" << lhs_type << "> " << lhs_name << ";\n"; 5591cb0ef41Sopenharmony_ci break; 5601cb0ef41Sopenharmony_ci default: 5611cb0ef41Sopenharmony_ci ReportError( 5621cb0ef41Sopenharmony_ci "Torque can only call builtins that return one or two values, not ", 5631cb0ef41Sopenharmony_ci result_types.size()); 5641cb0ef41Sopenharmony_ci } 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ci std::string catch_name = 5671cb0ef41Sopenharmony_ci PreCallableExceptionPreparation(instruction.catch_block); 5681cb0ef41Sopenharmony_ci Stack<std::string> pre_call_stack = *stack; 5691cb0ef41Sopenharmony_ci 5701cb0ef41Sopenharmony_ci std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName(); 5711cb0ef41Sopenharmony_ci for (const std::string& name : result_names) { 5721cb0ef41Sopenharmony_ci stack->Push(name); 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci out() << " " << lhs_name << " = "; 5751cb0ef41Sopenharmony_ci out() << "ca_.CallStub<" << lhs_type 5761cb0ef41Sopenharmony_ci << ">(Builtins::CallableFor(ca_.isolate(), Builtin::k" 5771cb0ef41Sopenharmony_ci << instruction.builtin->ExternalName() << ")"; 5781cb0ef41Sopenharmony_ci if (!instruction.builtin->signature().HasContextParameter()) { 5791cb0ef41Sopenharmony_ci // Add dummy context parameter to satisfy the CallBuiltin signature. 5801cb0ef41Sopenharmony_ci out() << ", TNode<Object>()"; 5811cb0ef41Sopenharmony_ci } 5821cb0ef41Sopenharmony_ci for (const std::string& argument : arguments) { 5831cb0ef41Sopenharmony_ci out() << ", " << argument; 5841cb0ef41Sopenharmony_ci } 5851cb0ef41Sopenharmony_ci out() << ");\n"; 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci if (result_types.size() > 1) { 5881cb0ef41Sopenharmony_ci for (size_t i = 0; i < result_types.size(); ++i) { 5891cb0ef41Sopenharmony_ci out() << " " << result_names[i] << " = ca_.Projection<" << i << ">(" 5901cb0ef41Sopenharmony_ci << lhs_name << ");\n"; 5911cb0ef41Sopenharmony_ci } 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_ci PostCallableExceptionPreparation( 5951cb0ef41Sopenharmony_ci catch_name, 5961cb0ef41Sopenharmony_ci result_types.size() == 0 ? TypeOracle::GetVoidType() : result_types[0], 5971cb0ef41Sopenharmony_ci instruction.catch_block, &pre_call_stack, 5981cb0ef41Sopenharmony_ci instruction.GetExceptionObjectDefinition()); 5991cb0ef41Sopenharmony_ci } 6001cb0ef41Sopenharmony_ci} 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction( 6031cb0ef41Sopenharmony_ci const CallBuiltinPointerInstruction& instruction, 6041cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 6051cb0ef41Sopenharmony_ci std::vector<std::string> arguments = stack->PopMany(instruction.argc); 6061cb0ef41Sopenharmony_ci std::string function = stack->Pop(); 6071cb0ef41Sopenharmony_ci std::vector<const Type*> result_types = 6081cb0ef41Sopenharmony_ci LowerType(instruction.type->return_type()); 6091cb0ef41Sopenharmony_ci if (result_types.size() != 1) { 6101cb0ef41Sopenharmony_ci ReportError("builtins must have exactly one result"); 6111cb0ef41Sopenharmony_ci } 6121cb0ef41Sopenharmony_ci if (instruction.is_tailcall) { 6131cb0ef41Sopenharmony_ci ReportError("tail-calls to builtin pointers are not supported"); 6141cb0ef41Sopenharmony_ci } 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci DCHECK_EQ(1, instruction.GetValueDefinitionCount()); 6171cb0ef41Sopenharmony_ci stack->Push(DefinitionToVariable(instruction.GetValueDefinition(0))); 6181cb0ef41Sopenharmony_ci std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName(); 6191cb0ef41Sopenharmony_ci decls() << " TNode<" << generated_type << "> " << stack->Top() << ";\n"; 6201cb0ef41Sopenharmony_ci out() << stack->Top() << " = "; 6211cb0ef41Sopenharmony_ci if (generated_type != "Object") out() << "TORQUE_CAST("; 6221cb0ef41Sopenharmony_ci out() << "CodeStubAssembler(state_).CallBuiltinPointer(Builtins::" 6231cb0ef41Sopenharmony_ci "CallableFor(ca_." 6241cb0ef41Sopenharmony_ci "isolate()," 6251cb0ef41Sopenharmony_ci "ExampleBuiltinForTorqueFunctionPointerType(" 6261cb0ef41Sopenharmony_ci << instruction.type->function_pointer_type_id() << ")).descriptor(), " 6271cb0ef41Sopenharmony_ci << function; 6281cb0ef41Sopenharmony_ci if (!instruction.type->HasContextParameter()) { 6291cb0ef41Sopenharmony_ci // Add dummy context parameter to satisfy the CallBuiltinPointer signature. 6301cb0ef41Sopenharmony_ci out() << ", TNode<Object>()"; 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci for (const std::string& argument : arguments) { 6331cb0ef41Sopenharmony_ci out() << ", " << argument; 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci out() << ")"; 6361cb0ef41Sopenharmony_ci if (generated_type != "Object") out() << ")"; 6371cb0ef41Sopenharmony_ci out() << ";\n"; 6381cb0ef41Sopenharmony_ci} 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_cistd::string CSAGenerator::PreCallableExceptionPreparation( 6411cb0ef41Sopenharmony_ci base::Optional<Block*> catch_block) { 6421cb0ef41Sopenharmony_ci std::string catch_name; 6431cb0ef41Sopenharmony_ci if (catch_block) { 6441cb0ef41Sopenharmony_ci catch_name = FreshCatchName(); 6451cb0ef41Sopenharmony_ci out() << " compiler::CodeAssemblerExceptionHandlerLabel " << catch_name 6461cb0ef41Sopenharmony_ci << "__label(&ca_, compiler::CodeAssemblerLabel::kDeferred);\n"; 6471cb0ef41Sopenharmony_ci out() << " { compiler::ScopedExceptionHandler s(&ca_, &" << catch_name 6481cb0ef41Sopenharmony_ci << "__label);\n"; 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci return catch_name; 6511cb0ef41Sopenharmony_ci} 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_civoid CSAGenerator::PostCallableExceptionPreparation( 6541cb0ef41Sopenharmony_ci const std::string& catch_name, const Type* return_type, 6551cb0ef41Sopenharmony_ci base::Optional<Block*> catch_block, Stack<std::string>* stack, 6561cb0ef41Sopenharmony_ci const base::Optional<DefinitionLocation>& exception_object_definition) { 6571cb0ef41Sopenharmony_ci if (catch_block) { 6581cb0ef41Sopenharmony_ci DCHECK(exception_object_definition); 6591cb0ef41Sopenharmony_ci std::string block_name = BlockName(*catch_block); 6601cb0ef41Sopenharmony_ci out() << " }\n"; 6611cb0ef41Sopenharmony_ci out() << " if (" << catch_name << "__label.is_used()) {\n"; 6621cb0ef41Sopenharmony_ci out() << " compiler::CodeAssemblerLabel " << catch_name 6631cb0ef41Sopenharmony_ci << "_skip(&ca_);\n"; 6641cb0ef41Sopenharmony_ci if (!return_type->IsNever()) { 6651cb0ef41Sopenharmony_ci out() << " ca_.Goto(&" << catch_name << "_skip);\n"; 6661cb0ef41Sopenharmony_ci } 6671cb0ef41Sopenharmony_ci decls() << " TNode<Object> " 6681cb0ef41Sopenharmony_ci << DefinitionToVariable(*exception_object_definition) << ";\n"; 6691cb0ef41Sopenharmony_ci out() << " ca_.Bind(&" << catch_name << "__label, &" 6701cb0ef41Sopenharmony_ci << DefinitionToVariable(*exception_object_definition) << ");\n"; 6711cb0ef41Sopenharmony_ci out() << " ca_.Goto(&" << block_name; 6721cb0ef41Sopenharmony_ci 6731cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size() + 1, (*catch_block)->InputDefinitions().Size()); 6741cb0ef41Sopenharmony_ci const auto& input_definitions = (*catch_block)->InputDefinitions(); 6751cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < input_definitions.AboveTop(); ++i) { 6761cb0ef41Sopenharmony_ci if (input_definitions.Peek(i).IsPhiFromBlock(*catch_block)) { 6771cb0ef41Sopenharmony_ci if (i < stack->AboveTop()) { 6781cb0ef41Sopenharmony_ci out() << ", " << stack->Peek(i); 6791cb0ef41Sopenharmony_ci } else { 6801cb0ef41Sopenharmony_ci DCHECK_EQ(i, stack->AboveTop()); 6811cb0ef41Sopenharmony_ci out() << ", " << DefinitionToVariable(*exception_object_definition); 6821cb0ef41Sopenharmony_ci } 6831cb0ef41Sopenharmony_ci } 6841cb0ef41Sopenharmony_ci } 6851cb0ef41Sopenharmony_ci out() << ");\n"; 6861cb0ef41Sopenharmony_ci 6871cb0ef41Sopenharmony_ci if (!return_type->IsNever()) { 6881cb0ef41Sopenharmony_ci out() << " ca_.Bind(&" << catch_name << "_skip);\n"; 6891cb0ef41Sopenharmony_ci } 6901cb0ef41Sopenharmony_ci out() << " }\n"; 6911cb0ef41Sopenharmony_ci } 6921cb0ef41Sopenharmony_ci} 6931cb0ef41Sopenharmony_ci 6941cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const CallRuntimeInstruction& instruction, 6951cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 6961cb0ef41Sopenharmony_ci std::vector<std::string> arguments = stack->PopMany(instruction.argc); 6971cb0ef41Sopenharmony_ci const Type* return_type = 6981cb0ef41Sopenharmony_ci instruction.runtime_function->signature().return_type; 6991cb0ef41Sopenharmony_ci std::vector<const Type*> result_types; 7001cb0ef41Sopenharmony_ci if (return_type != TypeOracle::GetNeverType()) { 7011cb0ef41Sopenharmony_ci result_types = LowerType(return_type); 7021cb0ef41Sopenharmony_ci } 7031cb0ef41Sopenharmony_ci if (result_types.size() > 1) { 7041cb0ef41Sopenharmony_ci ReportError("runtime function must have at most one result"); 7051cb0ef41Sopenharmony_ci } 7061cb0ef41Sopenharmony_ci if (instruction.is_tailcall) { 7071cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).TailCallRuntime(Runtime::k" 7081cb0ef41Sopenharmony_ci << instruction.runtime_function->ExternalName() << ", "; 7091cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), arguments); 7101cb0ef41Sopenharmony_ci out() << ");\n"; 7111cb0ef41Sopenharmony_ci } else { 7121cb0ef41Sopenharmony_ci std::string result_name; 7131cb0ef41Sopenharmony_ci if (result_types.size() == 1) { 7141cb0ef41Sopenharmony_ci result_name = DefinitionToVariable(instruction.GetValueDefinition(0)); 7151cb0ef41Sopenharmony_ci decls() << " TNode<" << result_types[0]->GetGeneratedTNodeTypeName() 7161cb0ef41Sopenharmony_ci << "> " << result_name << ";\n"; 7171cb0ef41Sopenharmony_ci } 7181cb0ef41Sopenharmony_ci std::string catch_name = 7191cb0ef41Sopenharmony_ci PreCallableExceptionPreparation(instruction.catch_block); 7201cb0ef41Sopenharmony_ci Stack<std::string> pre_call_stack = *stack; 7211cb0ef41Sopenharmony_ci if (result_types.size() == 1) { 7221cb0ef41Sopenharmony_ci std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName(); 7231cb0ef41Sopenharmony_ci stack->Push(result_name); 7241cb0ef41Sopenharmony_ci out() << " " << result_name << " = "; 7251cb0ef41Sopenharmony_ci if (generated_type != "Object") out() << "TORQUE_CAST("; 7261cb0ef41Sopenharmony_ci out() << "CodeStubAssembler(state_).CallRuntime(Runtime::k" 7271cb0ef41Sopenharmony_ci << instruction.runtime_function->ExternalName() << ", "; 7281cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), arguments); 7291cb0ef41Sopenharmony_ci out() << ")"; 7301cb0ef41Sopenharmony_ci if (generated_type != "Object") out() << ")"; 7311cb0ef41Sopenharmony_ci out() << "; \n"; 7321cb0ef41Sopenharmony_ci } else { 7331cb0ef41Sopenharmony_ci DCHECK_EQ(0, result_types.size()); 7341cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).CallRuntime(Runtime::k" 7351cb0ef41Sopenharmony_ci << instruction.runtime_function->ExternalName() << ", "; 7361cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), arguments); 7371cb0ef41Sopenharmony_ci out() << ");\n"; 7381cb0ef41Sopenharmony_ci if (return_type == TypeOracle::GetNeverType()) { 7391cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).Unreachable();\n"; 7401cb0ef41Sopenharmony_ci } else { 7411cb0ef41Sopenharmony_ci DCHECK(return_type == TypeOracle::GetVoidType()); 7421cb0ef41Sopenharmony_ci } 7431cb0ef41Sopenharmony_ci } 7441cb0ef41Sopenharmony_ci PostCallableExceptionPreparation( 7451cb0ef41Sopenharmony_ci catch_name, return_type, instruction.catch_block, &pre_call_stack, 7461cb0ef41Sopenharmony_ci instruction.GetExceptionObjectDefinition()); 7471cb0ef41Sopenharmony_ci } 7481cb0ef41Sopenharmony_ci} 7491cb0ef41Sopenharmony_ci 7501cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const BranchInstruction& instruction, 7511cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 7521cb0ef41Sopenharmony_ci out() << " ca_.Branch(" << stack->Pop() << ", &" 7531cb0ef41Sopenharmony_ci << BlockName(instruction.if_true) << ", std::vector<compiler::Node*>{"; 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_ci const auto& true_definitions = instruction.if_true->InputDefinitions(); 7561cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size(), true_definitions.Size()); 7571cb0ef41Sopenharmony_ci bool first = true; 7581cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { 7591cb0ef41Sopenharmony_ci if (true_definitions.Peek(i).IsPhiFromBlock(instruction.if_true)) { 7601cb0ef41Sopenharmony_ci if (!first) out() << ", "; 7611cb0ef41Sopenharmony_ci out() << stack->Peek(i); 7621cb0ef41Sopenharmony_ci first = false; 7631cb0ef41Sopenharmony_ci } 7641cb0ef41Sopenharmony_ci } 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci out() << "}, &" << BlockName(instruction.if_false) 7671cb0ef41Sopenharmony_ci << ", std::vector<compiler::Node*>{"; 7681cb0ef41Sopenharmony_ci 7691cb0ef41Sopenharmony_ci const auto& false_definitions = instruction.if_false->InputDefinitions(); 7701cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size(), false_definitions.Size()); 7711cb0ef41Sopenharmony_ci first = true; 7721cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { 7731cb0ef41Sopenharmony_ci if (false_definitions.Peek(i).IsPhiFromBlock(instruction.if_false)) { 7741cb0ef41Sopenharmony_ci if (!first) out() << ", "; 7751cb0ef41Sopenharmony_ci out() << stack->Peek(i); 7761cb0ef41Sopenharmony_ci first = false; 7771cb0ef41Sopenharmony_ci } 7781cb0ef41Sopenharmony_ci } 7791cb0ef41Sopenharmony_ci 7801cb0ef41Sopenharmony_ci out() << "});\n"; 7811cb0ef41Sopenharmony_ci} 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction( 7841cb0ef41Sopenharmony_ci const ConstexprBranchInstruction& instruction, Stack<std::string>* stack) { 7851cb0ef41Sopenharmony_ci out() << " if ((" << instruction.condition << ")) {\n"; 7861cb0ef41Sopenharmony_ci out() << " ca_.Goto(&" << BlockName(instruction.if_true); 7871cb0ef41Sopenharmony_ci 7881cb0ef41Sopenharmony_ci const auto& true_definitions = instruction.if_true->InputDefinitions(); 7891cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size(), true_definitions.Size()); 7901cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { 7911cb0ef41Sopenharmony_ci if (true_definitions.Peek(i).IsPhiFromBlock(instruction.if_true)) { 7921cb0ef41Sopenharmony_ci out() << ", " << stack->Peek(i); 7931cb0ef41Sopenharmony_ci } 7941cb0ef41Sopenharmony_ci } 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_ci out() << ");\n"; 7971cb0ef41Sopenharmony_ci out() << " } else {\n"; 7981cb0ef41Sopenharmony_ci out() << " ca_.Goto(&" << BlockName(instruction.if_false); 7991cb0ef41Sopenharmony_ci 8001cb0ef41Sopenharmony_ci const auto& false_definitions = instruction.if_false->InputDefinitions(); 8011cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size(), false_definitions.Size()); 8021cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { 8031cb0ef41Sopenharmony_ci if (false_definitions.Peek(i).IsPhiFromBlock(instruction.if_false)) { 8041cb0ef41Sopenharmony_ci out() << ", " << stack->Peek(i); 8051cb0ef41Sopenharmony_ci } 8061cb0ef41Sopenharmony_ci } 8071cb0ef41Sopenharmony_ci 8081cb0ef41Sopenharmony_ci out() << ");\n"; 8091cb0ef41Sopenharmony_ci out() << " }\n"; 8101cb0ef41Sopenharmony_ci} 8111cb0ef41Sopenharmony_ci 8121cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const GotoInstruction& instruction, 8131cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 8141cb0ef41Sopenharmony_ci out() << " ca_.Goto(&" << BlockName(instruction.destination); 8151cb0ef41Sopenharmony_ci const auto& destination_definitions = 8161cb0ef41Sopenharmony_ci instruction.destination->InputDefinitions(); 8171cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size(), destination_definitions.Size()); 8181cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { 8191cb0ef41Sopenharmony_ci if (destination_definitions.Peek(i).IsPhiFromBlock( 8201cb0ef41Sopenharmony_ci instruction.destination)) { 8211cb0ef41Sopenharmony_ci out() << ", " << stack->Peek(i); 8221cb0ef41Sopenharmony_ci } 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci out() << ");\n"; 8251cb0ef41Sopenharmony_ci} 8261cb0ef41Sopenharmony_ci 8271cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const GotoExternalInstruction& instruction, 8281cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 8291cb0ef41Sopenharmony_ci for (auto it = instruction.variable_names.rbegin(); 8301cb0ef41Sopenharmony_ci it != instruction.variable_names.rend(); ++it) { 8311cb0ef41Sopenharmony_ci out() << " *" << *it << " = " << stack->Pop() << ";\n"; 8321cb0ef41Sopenharmony_ci } 8331cb0ef41Sopenharmony_ci out() << " ca_.Goto(" << instruction.destination << ");\n"; 8341cb0ef41Sopenharmony_ci} 8351cb0ef41Sopenharmony_ci 8361cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const ReturnInstruction& instruction, 8371cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 8381cb0ef41Sopenharmony_ci if (*linkage_ == Builtin::kVarArgsJavaScript) { 8391cb0ef41Sopenharmony_ci out() << " " << ARGUMENTS_VARIABLE_STRING << ".PopAndReturn("; 8401cb0ef41Sopenharmony_ci } else { 8411cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).Return("; 8421cb0ef41Sopenharmony_ci } 8431cb0ef41Sopenharmony_ci std::vector<std::string> values = stack->PopMany(instruction.count); 8441cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), values); 8451cb0ef41Sopenharmony_ci out() << ");\n"; 8461cb0ef41Sopenharmony_ci} 8471cb0ef41Sopenharmony_ci 8481cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction( 8491cb0ef41Sopenharmony_ci const PrintConstantStringInstruction& instruction, 8501cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 8511cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).Print(" 8521cb0ef41Sopenharmony_ci << StringLiteralQuote(instruction.message) << ");\n"; 8531cb0ef41Sopenharmony_ci} 8541cb0ef41Sopenharmony_ci 8551cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const AbortInstruction& instruction, 8561cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 8571cb0ef41Sopenharmony_ci switch (instruction.kind) { 8581cb0ef41Sopenharmony_ci case AbortInstruction::Kind::kUnreachable: 8591cb0ef41Sopenharmony_ci DCHECK(instruction.message.empty()); 8601cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).Unreachable();\n"; 8611cb0ef41Sopenharmony_ci break; 8621cb0ef41Sopenharmony_ci case AbortInstruction::Kind::kDebugBreak: 8631cb0ef41Sopenharmony_ci DCHECK(instruction.message.empty()); 8641cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).DebugBreak();\n"; 8651cb0ef41Sopenharmony_ci break; 8661cb0ef41Sopenharmony_ci case AbortInstruction::Kind::kAssertionFailure: { 8671cb0ef41Sopenharmony_ci std::string file = StringLiteralQuote( 8681cb0ef41Sopenharmony_ci SourceFileMap::PathFromV8Root(instruction.pos.source)); 8691cb0ef41Sopenharmony_ci out() << " {\n"; 8701cb0ef41Sopenharmony_ci out() << " auto pos_stack = ca_.GetMacroSourcePositionStack();\n"; 8711cb0ef41Sopenharmony_ci out() << " pos_stack.push_back({" << file << ", " 8721cb0ef41Sopenharmony_ci << instruction.pos.start.line + 1 << "});\n"; 8731cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).FailAssert(" 8741cb0ef41Sopenharmony_ci << StringLiteralQuote(instruction.message) << ", pos_stack);\n"; 8751cb0ef41Sopenharmony_ci out() << " }\n"; 8761cb0ef41Sopenharmony_ci break; 8771cb0ef41Sopenharmony_ci } 8781cb0ef41Sopenharmony_ci } 8791cb0ef41Sopenharmony_ci} 8801cb0ef41Sopenharmony_ci 8811cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction, 8821cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 8831cb0ef41Sopenharmony_ci const std::string str = 8841cb0ef41Sopenharmony_ci "ca_.UncheckedCast<" + 8851cb0ef41Sopenharmony_ci instruction.destination_type->GetGeneratedTNodeTypeName() + ">(" + 8861cb0ef41Sopenharmony_ci stack->Top() + ")"; 8871cb0ef41Sopenharmony_ci stack->Poke(stack->AboveTop() - 1, str); 8881cb0ef41Sopenharmony_ci SetDefinitionVariable(instruction.GetValueDefinition(), str); 8891cb0ef41Sopenharmony_ci} 8901cb0ef41Sopenharmony_ci 8911cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const LoadReferenceInstruction& instruction, 8921cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 8931cb0ef41Sopenharmony_ci std::string result_name = 8941cb0ef41Sopenharmony_ci DefinitionToVariable(instruction.GetValueDefinition()); 8951cb0ef41Sopenharmony_ci 8961cb0ef41Sopenharmony_ci std::string offset = stack->Pop(); 8971cb0ef41Sopenharmony_ci std::string object = stack->Pop(); 8981cb0ef41Sopenharmony_ci stack->Push(result_name); 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci decls() << " " << instruction.type->GetGeneratedTypeName() << " " 9011cb0ef41Sopenharmony_ci << result_name << ";\n"; 9021cb0ef41Sopenharmony_ci out() << " " << result_name 9031cb0ef41Sopenharmony_ci << " = CodeStubAssembler(state_).LoadReference<" 9041cb0ef41Sopenharmony_ci << instruction.type->GetGeneratedTNodeTypeName() 9051cb0ef41Sopenharmony_ci << ">(CodeStubAssembler::Reference{" << object << ", " << offset 9061cb0ef41Sopenharmony_ci << "});\n"; 9071cb0ef41Sopenharmony_ci} 9081cb0ef41Sopenharmony_ci 9091cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const StoreReferenceInstruction& instruction, 9101cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 9111cb0ef41Sopenharmony_ci std::string value = stack->Pop(); 9121cb0ef41Sopenharmony_ci std::string offset = stack->Pop(); 9131cb0ef41Sopenharmony_ci std::string object = stack->Pop(); 9141cb0ef41Sopenharmony_ci 9151cb0ef41Sopenharmony_ci out() << " CodeStubAssembler(state_).StoreReference<" 9161cb0ef41Sopenharmony_ci << instruction.type->GetGeneratedTNodeTypeName() 9171cb0ef41Sopenharmony_ci << ">(CodeStubAssembler::" 9181cb0ef41Sopenharmony_ci "Reference{" 9191cb0ef41Sopenharmony_ci << object << ", " << offset << "}, " << value << ");\n"; 9201cb0ef41Sopenharmony_ci} 9211cb0ef41Sopenharmony_ci 9221cb0ef41Sopenharmony_cinamespace { 9231cb0ef41Sopenharmony_cistd::string GetBitFieldSpecialization(const Type* container, 9241cb0ef41Sopenharmony_ci const BitField& field) { 9251cb0ef41Sopenharmony_ci auto smi_tagged_type = 9261cb0ef41Sopenharmony_ci Type::MatchUnaryGeneric(container, TypeOracle::GetSmiTaggedGeneric()); 9271cb0ef41Sopenharmony_ci std::string container_type = smi_tagged_type 9281cb0ef41Sopenharmony_ci ? "uintptr_t" 9291cb0ef41Sopenharmony_ci : container->GetConstexprGeneratedTypeName(); 9301cb0ef41Sopenharmony_ci int offset = smi_tagged_type 9311cb0ef41Sopenharmony_ci ? field.offset + TargetArchitecture::SmiTagAndShiftSize() 9321cb0ef41Sopenharmony_ci : field.offset; 9331cb0ef41Sopenharmony_ci std::stringstream stream; 9341cb0ef41Sopenharmony_ci stream << "base::BitField<" 9351cb0ef41Sopenharmony_ci << field.name_and_type.type->GetConstexprGeneratedTypeName() << ", " 9361cb0ef41Sopenharmony_ci << offset << ", " << field.num_bits << ", " << container_type << ">"; 9371cb0ef41Sopenharmony_ci return stream.str(); 9381cb0ef41Sopenharmony_ci} 9391cb0ef41Sopenharmony_ci} // namespace 9401cb0ef41Sopenharmony_ci 9411cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const LoadBitFieldInstruction& instruction, 9421cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 9431cb0ef41Sopenharmony_ci std::string result_name = 9441cb0ef41Sopenharmony_ci DefinitionToVariable(instruction.GetValueDefinition()); 9451cb0ef41Sopenharmony_ci 9461cb0ef41Sopenharmony_ci std::string bit_field_struct = stack->Pop(); 9471cb0ef41Sopenharmony_ci stack->Push(result_name); 9481cb0ef41Sopenharmony_ci 9491cb0ef41Sopenharmony_ci const Type* struct_type = instruction.bit_field_struct_type; 9501cb0ef41Sopenharmony_ci const Type* field_type = instruction.bit_field.name_and_type.type; 9511cb0ef41Sopenharmony_ci auto smi_tagged_type = 9521cb0ef41Sopenharmony_ci Type::MatchUnaryGeneric(struct_type, TypeOracle::GetSmiTaggedGeneric()); 9531cb0ef41Sopenharmony_ci bool struct_is_pointer_size = 9541cb0ef41Sopenharmony_ci IsPointerSizeIntegralType(struct_type) || smi_tagged_type; 9551cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!struct_is_pointer_size, Is32BitIntegralType(struct_type)); 9561cb0ef41Sopenharmony_ci bool field_is_pointer_size = IsPointerSizeIntegralType(field_type); 9571cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!field_is_pointer_size, Is32BitIntegralType(field_type)); 9581cb0ef41Sopenharmony_ci std::string struct_word_type = struct_is_pointer_size ? "WordT" : "Word32T"; 9591cb0ef41Sopenharmony_ci std::string decoder = 9601cb0ef41Sopenharmony_ci struct_is_pointer_size 9611cb0ef41Sopenharmony_ci ? (field_is_pointer_size ? "DecodeWord" : "DecodeWord32FromWord") 9621cb0ef41Sopenharmony_ci : (field_is_pointer_size ? "DecodeWordFromWord32" : "DecodeWord32"); 9631cb0ef41Sopenharmony_ci 9641cb0ef41Sopenharmony_ci decls() << " " << field_type->GetGeneratedTypeName() << " " << result_name 9651cb0ef41Sopenharmony_ci << ";\n"; 9661cb0ef41Sopenharmony_ci 9671cb0ef41Sopenharmony_ci if (smi_tagged_type) { 9681cb0ef41Sopenharmony_ci // If the container is a SMI, then UncheckedCast is insufficient and we must 9691cb0ef41Sopenharmony_ci // use a bit cast. 9701cb0ef41Sopenharmony_ci bit_field_struct = 9711cb0ef41Sopenharmony_ci "ca_.BitcastTaggedToWordForTagAndSmiBits(" + bit_field_struct + ")"; 9721cb0ef41Sopenharmony_ci } 9731cb0ef41Sopenharmony_ci 9741cb0ef41Sopenharmony_ci out() << " " << result_name << " = ca_.UncheckedCast<" 9751cb0ef41Sopenharmony_ci << field_type->GetGeneratedTNodeTypeName() 9761cb0ef41Sopenharmony_ci << ">(CodeStubAssembler(state_)." << decoder << "<" 9771cb0ef41Sopenharmony_ci << GetBitFieldSpecialization(struct_type, instruction.bit_field) 9781cb0ef41Sopenharmony_ci << ">(ca_.UncheckedCast<" << struct_word_type << ">(" 9791cb0ef41Sopenharmony_ci << bit_field_struct << ")));\n"; 9801cb0ef41Sopenharmony_ci} 9811cb0ef41Sopenharmony_ci 9821cb0ef41Sopenharmony_civoid CSAGenerator::EmitInstruction(const StoreBitFieldInstruction& instruction, 9831cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 9841cb0ef41Sopenharmony_ci std::string result_name = 9851cb0ef41Sopenharmony_ci DefinitionToVariable(instruction.GetValueDefinition()); 9861cb0ef41Sopenharmony_ci 9871cb0ef41Sopenharmony_ci std::string value = stack->Pop(); 9881cb0ef41Sopenharmony_ci std::string bit_field_struct = stack->Pop(); 9891cb0ef41Sopenharmony_ci stack->Push(result_name); 9901cb0ef41Sopenharmony_ci 9911cb0ef41Sopenharmony_ci const Type* struct_type = instruction.bit_field_struct_type; 9921cb0ef41Sopenharmony_ci const Type* field_type = instruction.bit_field.name_and_type.type; 9931cb0ef41Sopenharmony_ci auto smi_tagged_type = 9941cb0ef41Sopenharmony_ci Type::MatchUnaryGeneric(struct_type, TypeOracle::GetSmiTaggedGeneric()); 9951cb0ef41Sopenharmony_ci bool struct_is_pointer_size = 9961cb0ef41Sopenharmony_ci IsPointerSizeIntegralType(struct_type) || smi_tagged_type; 9971cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!struct_is_pointer_size, Is32BitIntegralType(struct_type)); 9981cb0ef41Sopenharmony_ci bool field_is_pointer_size = IsPointerSizeIntegralType(field_type); 9991cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!field_is_pointer_size, Is32BitIntegralType(field_type)); 10001cb0ef41Sopenharmony_ci std::string struct_word_type = struct_is_pointer_size ? "WordT" : "Word32T"; 10011cb0ef41Sopenharmony_ci std::string field_word_type = field_is_pointer_size ? "UintPtrT" : "Uint32T"; 10021cb0ef41Sopenharmony_ci std::string encoder = 10031cb0ef41Sopenharmony_ci struct_is_pointer_size 10041cb0ef41Sopenharmony_ci ? (field_is_pointer_size ? "UpdateWord" : "UpdateWord32InWord") 10051cb0ef41Sopenharmony_ci : (field_is_pointer_size ? "UpdateWordInWord32" : "UpdateWord32"); 10061cb0ef41Sopenharmony_ci 10071cb0ef41Sopenharmony_ci decls() << " " << struct_type->GetGeneratedTypeName() << " " << result_name 10081cb0ef41Sopenharmony_ci << ";\n"; 10091cb0ef41Sopenharmony_ci 10101cb0ef41Sopenharmony_ci if (smi_tagged_type) { 10111cb0ef41Sopenharmony_ci // If the container is a SMI, then UncheckedCast is insufficient and we must 10121cb0ef41Sopenharmony_ci // use a bit cast. 10131cb0ef41Sopenharmony_ci bit_field_struct = 10141cb0ef41Sopenharmony_ci "ca_.BitcastTaggedToWordForTagAndSmiBits(" + bit_field_struct + ")"; 10151cb0ef41Sopenharmony_ci } 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci std::string result_expression = 10181cb0ef41Sopenharmony_ci "CodeStubAssembler(state_)." + encoder + "<" + 10191cb0ef41Sopenharmony_ci GetBitFieldSpecialization(struct_type, instruction.bit_field) + 10201cb0ef41Sopenharmony_ci ">(ca_.UncheckedCast<" + struct_word_type + ">(" + bit_field_struct + 10211cb0ef41Sopenharmony_ci "), ca_.UncheckedCast<" + field_word_type + ">(" + value + ")" + 10221cb0ef41Sopenharmony_ci (instruction.starts_as_zero ? ", true" : "") + ")"; 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_ci if (smi_tagged_type) { 10251cb0ef41Sopenharmony_ci result_expression = 10261cb0ef41Sopenharmony_ci "ca_.BitcastWordToTaggedSigned(" + result_expression + ")"; 10271cb0ef41Sopenharmony_ci } 10281cb0ef41Sopenharmony_ci 10291cb0ef41Sopenharmony_ci out() << " " << result_name << " = ca_.UncheckedCast<" 10301cb0ef41Sopenharmony_ci << struct_type->GetGeneratedTNodeTypeName() << ">(" << result_expression 10311cb0ef41Sopenharmony_ci << ");\n"; 10321cb0ef41Sopenharmony_ci} 10331cb0ef41Sopenharmony_ci 10341cb0ef41Sopenharmony_ci// static 10351cb0ef41Sopenharmony_civoid CSAGenerator::EmitCSAValue(VisitResult result, 10361cb0ef41Sopenharmony_ci const Stack<std::string>& values, 10371cb0ef41Sopenharmony_ci std::ostream& out) { 10381cb0ef41Sopenharmony_ci if (!result.IsOnStack()) { 10391cb0ef41Sopenharmony_ci out << result.constexpr_value(); 10401cb0ef41Sopenharmony_ci } else if (auto struct_type = result.type()->StructSupertype()) { 10411cb0ef41Sopenharmony_ci out << (*struct_type)->GetGeneratedTypeName() << "{"; 10421cb0ef41Sopenharmony_ci bool first = true; 10431cb0ef41Sopenharmony_ci for (auto& field : (*struct_type)->fields()) { 10441cb0ef41Sopenharmony_ci if (!first) { 10451cb0ef41Sopenharmony_ci out << ", "; 10461cb0ef41Sopenharmony_ci } 10471cb0ef41Sopenharmony_ci first = false; 10481cb0ef41Sopenharmony_ci EmitCSAValue(ProjectStructField(result, field.name_and_type.name), values, 10491cb0ef41Sopenharmony_ci out); 10501cb0ef41Sopenharmony_ci } 10511cb0ef41Sopenharmony_ci out << "}"; 10521cb0ef41Sopenharmony_ci } else { 10531cb0ef41Sopenharmony_ci DCHECK_EQ(1, result.stack_range().Size()); 10541cb0ef41Sopenharmony_ci out << result.type()->GetGeneratedTypeName() << "{" 10551cb0ef41Sopenharmony_ci << values.Peek(result.stack_range().begin()) << "}"; 10561cb0ef41Sopenharmony_ci } 10571cb0ef41Sopenharmony_ci} 10581cb0ef41Sopenharmony_ci 10591cb0ef41Sopenharmony_ci} // namespace torque 10601cb0ef41Sopenharmony_ci} // namespace internal 10611cb0ef41Sopenharmony_ci} // namespace v8 1062