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()}, &parameters);
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