11cb0ef41Sopenharmony_ci// Copyright 2020 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/cc-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>> CCGenerator::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 // Redirect the output of non-declarations into a buffer and only output 251cb0ef41Sopenharmony_ci // declarations right away. 261cb0ef41Sopenharmony_ci std::stringstream out_buffer; 271cb0ef41Sopenharmony_ci std::ostream* old_out = out_; 281cb0ef41Sopenharmony_ci out_ = &out_buffer; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci EmitInstruction(GotoInstruction{cfg_.start()}, ¶meters); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci for (Block* block : cfg_.blocks()) { 331cb0ef41Sopenharmony_ci if (cfg_.end() && *cfg_.end() == block) continue; 341cb0ef41Sopenharmony_ci if (block->IsDead()) continue; 351cb0ef41Sopenharmony_ci EmitBlock(block); 361cb0ef41Sopenharmony_ci } 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci base::Optional<Stack<std::string>> result; 391cb0ef41Sopenharmony_ci if (cfg_.end()) { 401cb0ef41Sopenharmony_ci result = EmitBlock(*cfg_.end()); 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci // All declarations have been printed now, so we can append the buffered 441cb0ef41Sopenharmony_ci // output and redirect back to the original output stream. 451cb0ef41Sopenharmony_ci out_ = old_out; 461cb0ef41Sopenharmony_ci out() << out_buffer.str(); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci return result; 491cb0ef41Sopenharmony_ci} 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ciStack<std::string> CCGenerator::EmitBlock(const Block* block) { 521cb0ef41Sopenharmony_ci out() << "\n"; 531cb0ef41Sopenharmony_ci out() << " " << BlockName(block) << ":\n"; 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci Stack<std::string> stack; 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < block->InputTypes().AboveTop(); ++i) { 581cb0ef41Sopenharmony_ci const auto& def = block->InputDefinitions().Peek(i); 591cb0ef41Sopenharmony_ci stack.Push(DefinitionToVariable(def)); 601cb0ef41Sopenharmony_ci if (def.IsPhiFromBlock(block)) { 611cb0ef41Sopenharmony_ci decls() << " " 621cb0ef41Sopenharmony_ci << (is_cc_debug_ ? block->InputTypes().Peek(i)->GetDebugType() 631cb0ef41Sopenharmony_ci : block->InputTypes().Peek(i)->GetRuntimeType()) 641cb0ef41Sopenharmony_ci << " " << stack.Top() << "{}; USE(" << stack.Top() << ");\n"; 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci for (const Instruction& instruction : block->instructions()) { 691cb0ef41Sopenharmony_ci TorqueCodeGenerator::EmitInstruction(instruction, &stack); 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci return stack; 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_civoid CCGenerator::EmitSourcePosition(SourcePosition pos, bool always_emit) { 751cb0ef41Sopenharmony_ci const std::string& file = SourceFileMap::AbsolutePath(pos.source); 761cb0ef41Sopenharmony_ci if (always_emit || !previous_position_.CompareStartIgnoreColumn(pos)) { 771cb0ef41Sopenharmony_ci // Lines in Torque SourcePositions are zero-based, while the 781cb0ef41Sopenharmony_ci // CodeStubAssembler and downwind systems are one-based. 791cb0ef41Sopenharmony_ci out() << " // " << file << ":" << (pos.start.line + 1) << "\n"; 801cb0ef41Sopenharmony_ci previous_position_ = pos; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci} 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction( 851cb0ef41Sopenharmony_ci const PushUninitializedInstruction& instruction, 861cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 871cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: PushUninitialized"); 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction( 911cb0ef41Sopenharmony_ci const PushBuiltinPointerInstruction& instruction, 921cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 931cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: PushBuiltinPointer"); 941cb0ef41Sopenharmony_ci} 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction( 971cb0ef41Sopenharmony_ci const NamespaceConstantInstruction& instruction, 981cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 991cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: NamespaceConstantInstruction"); 1001cb0ef41Sopenharmony_ci} 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_cistd::vector<std::string> CCGenerator::ProcessArgumentsCommon( 1031cb0ef41Sopenharmony_ci const TypeVector& parameter_types, 1041cb0ef41Sopenharmony_ci std::vector<std::string> constexpr_arguments, Stack<std::string>* stack) { 1051cb0ef41Sopenharmony_ci std::vector<std::string> args; 1061cb0ef41Sopenharmony_ci for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) { 1071cb0ef41Sopenharmony_ci const Type* type = *it; 1081cb0ef41Sopenharmony_ci if (type->IsConstexpr()) { 1091cb0ef41Sopenharmony_ci args.push_back(std::move(constexpr_arguments.back())); 1101cb0ef41Sopenharmony_ci constexpr_arguments.pop_back(); 1111cb0ef41Sopenharmony_ci } else { 1121cb0ef41Sopenharmony_ci std::stringstream s; 1131cb0ef41Sopenharmony_ci size_t slot_count = LoweredSlotCount(type); 1141cb0ef41Sopenharmony_ci VisitResult arg = VisitResult(type, stack->TopRange(slot_count)); 1151cb0ef41Sopenharmony_ci EmitCCValue(arg, *stack, s); 1161cb0ef41Sopenharmony_ci args.push_back(s.str()); 1171cb0ef41Sopenharmony_ci stack->PopMany(slot_count); 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci std::reverse(args.begin(), args.end()); 1211cb0ef41Sopenharmony_ci return args; 1221cb0ef41Sopenharmony_ci} 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, 1251cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 1261cb0ef41Sopenharmony_ci TypeVector parameter_types = 1271cb0ef41Sopenharmony_ci instruction.intrinsic->signature().parameter_types.types; 1281cb0ef41Sopenharmony_ci std::vector<std::string> args = ProcessArgumentsCommon( 1291cb0ef41Sopenharmony_ci parameter_types, instruction.constexpr_arguments, stack); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci Stack<std::string> pre_call_stack = *stack; 1321cb0ef41Sopenharmony_ci const Type* return_type = instruction.intrinsic->signature().return_type; 1331cb0ef41Sopenharmony_ci std::vector<std::string> results; 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci const auto lowered = LowerType(return_type); 1361cb0ef41Sopenharmony_ci for (std::size_t i = 0; i < lowered.size(); ++i) { 1371cb0ef41Sopenharmony_ci results.push_back(DefinitionToVariable(instruction.GetValueDefinition(i))); 1381cb0ef41Sopenharmony_ci stack->Push(results.back()); 1391cb0ef41Sopenharmony_ci decls() << " " 1401cb0ef41Sopenharmony_ci << (is_cc_debug_ ? lowered[i]->GetDebugType() 1411cb0ef41Sopenharmony_ci : lowered[i]->GetRuntimeType()) 1421cb0ef41Sopenharmony_ci << " " << stack->Top() << "{}; USE(" << stack->Top() << ");\n"; 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci out() << " "; 1461cb0ef41Sopenharmony_ci if (return_type->StructSupertype()) { 1471cb0ef41Sopenharmony_ci out() << "std::tie("; 1481cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), results); 1491cb0ef41Sopenharmony_ci out() << ") = "; 1501cb0ef41Sopenharmony_ci } else { 1511cb0ef41Sopenharmony_ci if (results.size() == 1) { 1521cb0ef41Sopenharmony_ci out() << results[0] << " = "; 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci if (instruction.intrinsic->ExternalName() == "%RawDownCast") { 1571cb0ef41Sopenharmony_ci if (parameter_types.size() != 1) { 1581cb0ef41Sopenharmony_ci ReportError("%RawDownCast must take a single parameter"); 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci const Type* original_type = parameter_types[0]; 1611cb0ef41Sopenharmony_ci bool is_subtype = 1621cb0ef41Sopenharmony_ci return_type->IsSubtypeOf(original_type) || 1631cb0ef41Sopenharmony_ci (original_type == TypeOracle::GetUninitializedHeapObjectType() && 1641cb0ef41Sopenharmony_ci return_type->IsSubtypeOf(TypeOracle::GetHeapObjectType())); 1651cb0ef41Sopenharmony_ci if (!is_subtype) { 1661cb0ef41Sopenharmony_ci ReportError("%RawDownCast error: ", *return_type, " is not a subtype of ", 1671cb0ef41Sopenharmony_ci *original_type); 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci if (!original_type->StructSupertype() && 1701cb0ef41Sopenharmony_ci return_type->GetRuntimeType() != original_type->GetRuntimeType()) { 1711cb0ef41Sopenharmony_ci out() << "static_cast<" << return_type->GetRuntimeType() << ">"; 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci } else if (instruction.intrinsic->ExternalName() == "%GetClassMapConstant") { 1741cb0ef41Sopenharmony_ci ReportError("C++ generator doesn't yet support %GetClassMapConstant"); 1751cb0ef41Sopenharmony_ci } else if (instruction.intrinsic->ExternalName() == "%FromConstexpr") { 1761cb0ef41Sopenharmony_ci if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) { 1771cb0ef41Sopenharmony_ci ReportError( 1781cb0ef41Sopenharmony_ci "%FromConstexpr must take a single parameter with constexpr " 1791cb0ef41Sopenharmony_ci "type"); 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci if (return_type->IsConstexpr()) { 1821cb0ef41Sopenharmony_ci ReportError("%FromConstexpr must return a non-constexpr type"); 1831cb0ef41Sopenharmony_ci } 1841cb0ef41Sopenharmony_ci if (return_type->IsSubtypeOf(TypeOracle::GetSmiType())) { 1851cb0ef41Sopenharmony_ci if (is_cc_debug_) { 1861cb0ef41Sopenharmony_ci out() << "Internals::IntToSmi"; 1871cb0ef41Sopenharmony_ci } else { 1881cb0ef41Sopenharmony_ci out() << "Smi::FromInt"; 1891cb0ef41Sopenharmony_ci } 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci // Wrap the raw constexpr value in a static_cast to ensure that 1921cb0ef41Sopenharmony_ci // enums get properly casted to their backing integral value. 1931cb0ef41Sopenharmony_ci out() << "(CastToUnderlyingTypeIfEnum"; 1941cb0ef41Sopenharmony_ci } else { 1951cb0ef41Sopenharmony_ci ReportError("no built in intrinsic with name " + 1961cb0ef41Sopenharmony_ci instruction.intrinsic->ExternalName()); 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci out() << "("; 2001cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), args); 2011cb0ef41Sopenharmony_ci if (instruction.intrinsic->ExternalName() == "%FromConstexpr") { 2021cb0ef41Sopenharmony_ci out() << ")"; 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci out() << ");\n"; 2051cb0ef41Sopenharmony_ci} 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, 2081cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2091cb0ef41Sopenharmony_ci TypeVector parameter_types = 2101cb0ef41Sopenharmony_ci instruction.macro->signature().parameter_types.types; 2111cb0ef41Sopenharmony_ci std::vector<std::string> args = ProcessArgumentsCommon( 2121cb0ef41Sopenharmony_ci parameter_types, instruction.constexpr_arguments, stack); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci Stack<std::string> pre_call_stack = *stack; 2151cb0ef41Sopenharmony_ci const Type* return_type = instruction.macro->signature().return_type; 2161cb0ef41Sopenharmony_ci std::vector<std::string> results; 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci const auto lowered = LowerType(return_type); 2191cb0ef41Sopenharmony_ci for (std::size_t i = 0; i < lowered.size(); ++i) { 2201cb0ef41Sopenharmony_ci results.push_back(DefinitionToVariable(instruction.GetValueDefinition(i))); 2211cb0ef41Sopenharmony_ci stack->Push(results.back()); 2221cb0ef41Sopenharmony_ci decls() << " " 2231cb0ef41Sopenharmony_ci << (is_cc_debug_ ? lowered[i]->GetDebugType() 2241cb0ef41Sopenharmony_ci : lowered[i]->GetRuntimeType()) 2251cb0ef41Sopenharmony_ci << " " << stack->Top() << "{}; USE(" << stack->Top() << ");\n"; 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci // We should have inlined any calls requiring complex control flow. 2291cb0ef41Sopenharmony_ci CHECK(!instruction.catch_block); 2301cb0ef41Sopenharmony_ci out() << (is_cc_debug_ ? " ASSIGN_OR_RETURN(" : " "); 2311cb0ef41Sopenharmony_ci if (return_type->StructSupertype().has_value()) { 2321cb0ef41Sopenharmony_ci out() << "std::tie("; 2331cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), results); 2341cb0ef41Sopenharmony_ci out() << (is_cc_debug_ ? "), " : ") = "); 2351cb0ef41Sopenharmony_ci } else { 2361cb0ef41Sopenharmony_ci if (results.size() == 1) { 2371cb0ef41Sopenharmony_ci out() << results[0] << (is_cc_debug_ ? ", " : " = "); 2381cb0ef41Sopenharmony_ci } else { 2391cb0ef41Sopenharmony_ci DCHECK_EQ(0, results.size()); 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci } 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci if (is_cc_debug_) { 2441cb0ef41Sopenharmony_ci out() << instruction.macro->CCDebugName() << "(accessor"; 2451cb0ef41Sopenharmony_ci if (!args.empty()) out() << ", "; 2461cb0ef41Sopenharmony_ci } else { 2471cb0ef41Sopenharmony_ci out() << instruction.macro->CCName() << "("; 2481cb0ef41Sopenharmony_ci } 2491cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out(), args); 2501cb0ef41Sopenharmony_ci if (is_cc_debug_) { 2511cb0ef41Sopenharmony_ci out() << "));\n"; 2521cb0ef41Sopenharmony_ci } else { 2531cb0ef41Sopenharmony_ci out() << ");\n"; 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci} 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction( 2581cb0ef41Sopenharmony_ci const CallCsaMacroAndBranchInstruction& instruction, 2591cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2601cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: CallCsaMacroAndBranch"); 2611cb0ef41Sopenharmony_ci} 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const MakeLazyNodeInstruction& instruction, 2641cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2651cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: MakeLazyNode"); 2661cb0ef41Sopenharmony_ci} 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const CallBuiltinInstruction& instruction, 2691cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2701cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: CallBuiltin"); 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction( 2741cb0ef41Sopenharmony_ci const CallBuiltinPointerInstruction& instruction, 2751cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2761cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: CallBuiltinPointer"); 2771cb0ef41Sopenharmony_ci} 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const CallRuntimeInstruction& instruction, 2801cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2811cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: CallRuntime"); 2821cb0ef41Sopenharmony_ci} 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const BranchInstruction& instruction, 2851cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2861cb0ef41Sopenharmony_ci out() << " if (" << stack->Pop() << ") {\n"; 2871cb0ef41Sopenharmony_ci EmitGoto(instruction.if_true, stack, " "); 2881cb0ef41Sopenharmony_ci out() << " } else {\n"; 2891cb0ef41Sopenharmony_ci EmitGoto(instruction.if_false, stack, " "); 2901cb0ef41Sopenharmony_ci out() << " }\n"; 2911cb0ef41Sopenharmony_ci} 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const ConstexprBranchInstruction& instruction, 2941cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 2951cb0ef41Sopenharmony_ci out() << " if ((" << instruction.condition << ")) {\n"; 2961cb0ef41Sopenharmony_ci EmitGoto(instruction.if_true, stack, " "); 2971cb0ef41Sopenharmony_ci out() << " } else {\n"; 2981cb0ef41Sopenharmony_ci EmitGoto(instruction.if_false, stack, " "); 2991cb0ef41Sopenharmony_ci out() << " }\n"; 3001cb0ef41Sopenharmony_ci} 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_civoid CCGenerator::EmitGoto(const Block* destination, Stack<std::string>* stack, 3031cb0ef41Sopenharmony_ci std::string indentation) { 3041cb0ef41Sopenharmony_ci const auto& destination_definitions = destination->InputDefinitions(); 3051cb0ef41Sopenharmony_ci DCHECK_EQ(stack->Size(), destination_definitions.Size()); 3061cb0ef41Sopenharmony_ci for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { 3071cb0ef41Sopenharmony_ci DefinitionLocation def = destination_definitions.Peek(i); 3081cb0ef41Sopenharmony_ci if (def.IsPhiFromBlock(destination)) { 3091cb0ef41Sopenharmony_ci out() << indentation << DefinitionToVariable(def) << " = " 3101cb0ef41Sopenharmony_ci << stack->Peek(i) << ";\n"; 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci out() << indentation << "goto " << BlockName(destination) << ";\n"; 3141cb0ef41Sopenharmony_ci} 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const GotoInstruction& instruction, 3171cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3181cb0ef41Sopenharmony_ci EmitGoto(instruction.destination, stack, " "); 3191cb0ef41Sopenharmony_ci} 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const GotoExternalInstruction& instruction, 3221cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3231cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: GotoExternal"); 3241cb0ef41Sopenharmony_ci} 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const ReturnInstruction& instruction, 3271cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3281cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: Return"); 3291cb0ef41Sopenharmony_ci} 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction( 3321cb0ef41Sopenharmony_ci const PrintConstantStringInstruction& instruction, 3331cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3341cb0ef41Sopenharmony_ci out() << " std::cout << " << StringLiteralQuote(instruction.message) 3351cb0ef41Sopenharmony_ci << ";\n"; 3361cb0ef41Sopenharmony_ci} 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const AbortInstruction& instruction, 3391cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3401cb0ef41Sopenharmony_ci switch (instruction.kind) { 3411cb0ef41Sopenharmony_ci case AbortInstruction::Kind::kUnreachable: 3421cb0ef41Sopenharmony_ci DCHECK(instruction.message.empty()); 3431cb0ef41Sopenharmony_ci out() << " UNREACHABLE();\n"; 3441cb0ef41Sopenharmony_ci break; 3451cb0ef41Sopenharmony_ci case AbortInstruction::Kind::kDebugBreak: 3461cb0ef41Sopenharmony_ci DCHECK(instruction.message.empty()); 3471cb0ef41Sopenharmony_ci out() << " base::OS::DebugBreak();\n"; 3481cb0ef41Sopenharmony_ci break; 3491cb0ef41Sopenharmony_ci case AbortInstruction::Kind::kAssertionFailure: { 3501cb0ef41Sopenharmony_ci std::string file = StringLiteralQuote( 3511cb0ef41Sopenharmony_ci SourceFileMap::PathFromV8Root(instruction.pos.source)); 3521cb0ef41Sopenharmony_ci out() << " CHECK(false, \"Failed Torque assertion: '\"" 3531cb0ef41Sopenharmony_ci << StringLiteralQuote(instruction.message) << "\"' at \"" << file 3541cb0ef41Sopenharmony_ci << "\":\"" 3551cb0ef41Sopenharmony_ci << StringLiteralQuote( 3561cb0ef41Sopenharmony_ci std::to_string(instruction.pos.start.line + 1)) 3571cb0ef41Sopenharmony_ci << ");\n"; 3581cb0ef41Sopenharmony_ci break; 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci} 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const UnsafeCastInstruction& instruction, 3641cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3651cb0ef41Sopenharmony_ci const std::string str = "static_cast<" + 3661cb0ef41Sopenharmony_ci instruction.destination_type->GetRuntimeType() + 3671cb0ef41Sopenharmony_ci ">(" + stack->Top() + ")"; 3681cb0ef41Sopenharmony_ci stack->Poke(stack->AboveTop() - 1, str); 3691cb0ef41Sopenharmony_ci SetDefinitionVariable(instruction.GetValueDefinition(), str); 3701cb0ef41Sopenharmony_ci} 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const LoadReferenceInstruction& instruction, 3731cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 3741cb0ef41Sopenharmony_ci std::string result_name = 3751cb0ef41Sopenharmony_ci DefinitionToVariable(instruction.GetValueDefinition()); 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_ci std::string offset = stack->Pop(); 3781cb0ef41Sopenharmony_ci std::string object = stack->Pop(); 3791cb0ef41Sopenharmony_ci stack->Push(result_name); 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci if (!is_cc_debug_) { 3821cb0ef41Sopenharmony_ci std::string result_type = instruction.type->GetRuntimeType(); 3831cb0ef41Sopenharmony_ci decls() << " " << result_type << " " << result_name << "{}; USE(" 3841cb0ef41Sopenharmony_ci << result_name << ");\n"; 3851cb0ef41Sopenharmony_ci out() << " " << result_name << " = "; 3861cb0ef41Sopenharmony_ci if (instruction.type->IsSubtypeOf(TypeOracle::GetTaggedType())) { 3871cb0ef41Sopenharmony_ci // Currently, all of the tagged loads we emit are for smi values, so there 3881cb0ef41Sopenharmony_ci // is no point in providing an PtrComprCageBase. If at some point we start 3891cb0ef41Sopenharmony_ci // emitting loads for tagged fields which might be HeapObjects, then we 3901cb0ef41Sopenharmony_ci // should plumb an PtrComprCageBase through the generated functions that 3911cb0ef41Sopenharmony_ci // need it. 3921cb0ef41Sopenharmony_ci if (!instruction.type->IsSubtypeOf(TypeOracle::GetSmiType())) { 3931cb0ef41Sopenharmony_ci Error( 3941cb0ef41Sopenharmony_ci "Not supported in C++ output: LoadReference on non-smi tagged " 3951cb0ef41Sopenharmony_ci "value"); 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci // References and slices can cause some values to have the Torque type 3991cb0ef41Sopenharmony_ci // HeapObject|TaggedZeroPattern, which is output as "Object". TaggedField 4001cb0ef41Sopenharmony_ci // requires HeapObject, so we need a cast. 4011cb0ef41Sopenharmony_ci out() << "TaggedField<" << result_type 4021cb0ef41Sopenharmony_ci << ">::load(*static_cast<HeapObject*>(&" << object 4031cb0ef41Sopenharmony_ci << "), static_cast<int>(" << offset << "));\n"; 4041cb0ef41Sopenharmony_ci } else { 4051cb0ef41Sopenharmony_ci out() << "(" << object << ").ReadField<" << result_type << ">(" << offset 4061cb0ef41Sopenharmony_ci << ");\n"; 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci } else { 4091cb0ef41Sopenharmony_ci std::string result_type = instruction.type->GetDebugType(); 4101cb0ef41Sopenharmony_ci decls() << " " << result_type << " " << result_name << "{}; USE(" 4111cb0ef41Sopenharmony_ci << result_name << ");\n"; 4121cb0ef41Sopenharmony_ci if (instruction.type->IsSubtypeOf(TypeOracle::GetTaggedType())) { 4131cb0ef41Sopenharmony_ci out() << " READ_TAGGED_FIELD_OR_FAIL(" << result_name << ", accessor, " 4141cb0ef41Sopenharmony_ci << object << ", static_cast<int>(" << offset << "));\n"; 4151cb0ef41Sopenharmony_ci } else { 4161cb0ef41Sopenharmony_ci out() << " READ_FIELD_OR_FAIL(" << result_type << ", " << result_name 4171cb0ef41Sopenharmony_ci << ", accessor, " << object << ", " << offset << ");\n"; 4181cb0ef41Sopenharmony_ci } 4191cb0ef41Sopenharmony_ci } 4201cb0ef41Sopenharmony_ci} 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const StoreReferenceInstruction& instruction, 4231cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 4241cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: StoreReference"); 4251cb0ef41Sopenharmony_ci} 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_cinamespace { 4281cb0ef41Sopenharmony_cistd::string GetBitFieldSpecialization(const Type* container, 4291cb0ef41Sopenharmony_ci const BitField& field) { 4301cb0ef41Sopenharmony_ci std::stringstream stream; 4311cb0ef41Sopenharmony_ci stream << "base::BitField<" 4321cb0ef41Sopenharmony_ci << field.name_and_type.type->GetConstexprGeneratedTypeName() << ", " 4331cb0ef41Sopenharmony_ci << field.offset << ", " << field.num_bits << ", " 4341cb0ef41Sopenharmony_ci << container->GetConstexprGeneratedTypeName() << ">"; 4351cb0ef41Sopenharmony_ci return stream.str(); 4361cb0ef41Sopenharmony_ci} 4371cb0ef41Sopenharmony_ci} // namespace 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const LoadBitFieldInstruction& instruction, 4401cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 4411cb0ef41Sopenharmony_ci std::string result_name = 4421cb0ef41Sopenharmony_ci DefinitionToVariable(instruction.GetValueDefinition()); 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci std::string bit_field_struct = stack->Pop(); 4451cb0ef41Sopenharmony_ci stack->Push(result_name); 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_ci const Type* struct_type = instruction.bit_field_struct_type; 4481cb0ef41Sopenharmony_ci 4491cb0ef41Sopenharmony_ci decls() << " " << instruction.bit_field.name_and_type.type->GetRuntimeType() 4501cb0ef41Sopenharmony_ci << " " << result_name << "{}; USE(" << result_name << ");\n"; 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci base::Optional<const Type*> smi_tagged_type = 4531cb0ef41Sopenharmony_ci Type::MatchUnaryGeneric(struct_type, TypeOracle::GetSmiTaggedGeneric()); 4541cb0ef41Sopenharmony_ci if (smi_tagged_type) { 4551cb0ef41Sopenharmony_ci // Get the untagged value and its type. 4561cb0ef41Sopenharmony_ci if (is_cc_debug_) { 4571cb0ef41Sopenharmony_ci bit_field_struct = "Internals::SmiValue(" + bit_field_struct + ")"; 4581cb0ef41Sopenharmony_ci } else { 4591cb0ef41Sopenharmony_ci bit_field_struct = bit_field_struct + ".value()"; 4601cb0ef41Sopenharmony_ci } 4611cb0ef41Sopenharmony_ci struct_type = *smi_tagged_type; 4621cb0ef41Sopenharmony_ci } 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci out() << " " << result_name << " = CastToUnderlyingTypeIfEnum(" 4651cb0ef41Sopenharmony_ci << GetBitFieldSpecialization(struct_type, instruction.bit_field) 4661cb0ef41Sopenharmony_ci << "::decode(" << bit_field_struct << "));\n"; 4671cb0ef41Sopenharmony_ci} 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_civoid CCGenerator::EmitInstruction(const StoreBitFieldInstruction& instruction, 4701cb0ef41Sopenharmony_ci Stack<std::string>* stack) { 4711cb0ef41Sopenharmony_ci ReportError("Not supported in C++ output: StoreBitField"); 4721cb0ef41Sopenharmony_ci} 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_cinamespace { 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_civoid CollectAllFields(const VisitResult& result, 4771cb0ef41Sopenharmony_ci const Stack<std::string>& values, 4781cb0ef41Sopenharmony_ci std::vector<std::string>& all_fields) { 4791cb0ef41Sopenharmony_ci if (!result.IsOnStack()) { 4801cb0ef41Sopenharmony_ci all_fields.push_back(result.constexpr_value()); 4811cb0ef41Sopenharmony_ci } else if (auto struct_type = result.type()->StructSupertype()) { 4821cb0ef41Sopenharmony_ci for (const Field& field : (*struct_type)->fields()) { 4831cb0ef41Sopenharmony_ci CollectAllFields(ProjectStructField(result, field.name_and_type.name), 4841cb0ef41Sopenharmony_ci values, all_fields); 4851cb0ef41Sopenharmony_ci } 4861cb0ef41Sopenharmony_ci } else { 4871cb0ef41Sopenharmony_ci DCHECK_EQ(1, result.stack_range().Size()); 4881cb0ef41Sopenharmony_ci all_fields.push_back(values.Peek(result.stack_range().begin())); 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci} 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ci} // namespace 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci// static 4951cb0ef41Sopenharmony_civoid CCGenerator::EmitCCValue(VisitResult result, 4961cb0ef41Sopenharmony_ci const Stack<std::string>& values, 4971cb0ef41Sopenharmony_ci std::ostream& out) { 4981cb0ef41Sopenharmony_ci std::vector<std::string> all_fields; 4991cb0ef41Sopenharmony_ci CollectAllFields(result, values, all_fields); 5001cb0ef41Sopenharmony_ci if (all_fields.size() == 1) { 5011cb0ef41Sopenharmony_ci out << all_fields[0]; 5021cb0ef41Sopenharmony_ci } else { 5031cb0ef41Sopenharmony_ci out << "std::make_tuple("; 5041cb0ef41Sopenharmony_ci PrintCommaSeparatedList(out, all_fields); 5051cb0ef41Sopenharmony_ci out << ")"; 5061cb0ef41Sopenharmony_ci } 5071cb0ef41Sopenharmony_ci} 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci} // namespace torque 5101cb0ef41Sopenharmony_ci} // namespace internal 5111cb0ef41Sopenharmony_ci} // namespace v8 512