diff options
Diffstat (limited to 'deps/v8/src/torque/csa-generator.cc')
-rw-r--r-- | deps/v8/src/torque/csa-generator.cc | 463 |
1 files changed, 351 insertions, 112 deletions
diff --git a/deps/v8/src/torque/csa-generator.cc b/deps/v8/src/torque/csa-generator.cc index 902b1b7f4a..68bb170863 100644 --- a/deps/v8/src/torque/csa-generator.cc +++ b/deps/v8/src/torque/csa-generator.cc @@ -14,11 +14,11 @@ namespace torque { base::Optional<Stack<std::string>> CSAGenerator::EmitGraph( Stack<std::string> parameters) { for (Block* block : cfg_.blocks()) { - out_ << " PLabel<"; + out_ << " compiler::CodeAssemblerParameterizedLabel<"; PrintCommaSeparatedList(out_, block->InputTypes(), [](const Type* t) { return t->GetGeneratedTNodeTypeName(); }); - out_ << "> " << BlockName(block) << "(this, compiler::CodeAssemblerLabel::" + out_ << "> " << BlockName(block) << "(&ca_, compiler::CodeAssemblerLabel::" << (block->IsDeferred() ? "kDeferred" : "kNonDeferred") << ");\n"; } @@ -40,10 +40,10 @@ Stack<std::string> CSAGenerator::EmitBlock(const Block* block) { Stack<std::string> stack; for (const Type* t : block->InputTypes()) { stack.Push(FreshNodeName()); - out_ << " TNode<" << t->GetGeneratedTNodeTypeName() << "> " + out_ << " compiler::TNode<" << t->GetGeneratedTNodeTypeName() << "> " << stack.Top() << ";\n"; } - out_ << " Bind(&" << BlockName(block); + out_ << " ca_.Bind(&" << BlockName(block); for (const std::string& name : stack) { out_ << ", &" << name; } @@ -87,27 +87,27 @@ void CSAGenerator::EmitInstruction( // TODO(tebbi): This can trigger an error in CSA if it is used. Instead, we // should prevent usage of uninitialized in the type system. This // requires "if constexpr" being evaluated at Torque time. - stack->Push("Uninitialized<" + instruction.type->GetGeneratedTNodeTypeName() + - ">()"); + stack->Push("ca_.Uninitialized<" + + instruction.type->GetGeneratedTNodeTypeName() + ">()"); } void CSAGenerator::EmitInstruction( - const PushCodePointerInstruction& instruction, Stack<std::string>* stack) { - stack->Push( - "UncheckedCast<Code>(HeapConstant(Builtins::CallableFor(isolate(), " - "Builtins::k" + - instruction.external_name + ").code()))"); + const PushBuiltinPointerInstruction& instruction, + Stack<std::string>* stack) { + stack->Push("ca_.UncheckedCast<BuiltinPtr>(ca_.SmiConstant(Builtins::k" + + instruction.external_name + "))"); } -void CSAGenerator::EmitInstruction(const ModuleConstantInstruction& instruction, - Stack<std::string>* stack) { +void CSAGenerator::EmitInstruction( + const NamespaceConstantInstruction& instruction, + Stack<std::string>* stack) { const Type* type = instruction.constant->type(); std::vector<std::string> results; for (const Type* lowered : LowerType(type)) { results.push_back(FreshNodeName()); stack->Push(results.back()); - out_ << " TNode<" << lowered->GetGeneratedTNodeTypeName() << "> " - << stack->Top() << ";\n"; + out_ << " compiler::TNode<" << lowered->GetGeneratedTNodeTypeName() + << "> " << stack->Top() << ";\n"; out_ << " USE(" << stack->Top() << ");\n"; } out_ << " "; @@ -118,7 +118,8 @@ void CSAGenerator::EmitInstruction(const ModuleConstantInstruction& instruction, } else if (results.size() == 1) { out_ << results[0] << " = "; } - out_ << instruction.constant->constant_name() << "()"; + out_ << instruction.constant->ExternalAssemblerName() << "(state_)." + << instruction.constant->constant_name() << "()"; if (type->IsStructType()) { out_ << ".Flatten();\n"; } else { @@ -126,39 +127,152 @@ void CSAGenerator::EmitInstruction(const ModuleConstantInstruction& instruction, } } -void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, - Stack<std::string>* stack) { - std::vector<std::string> constexpr_arguments = - instruction.constexpr_arguments; - std::vector<std::string> args; - TypeVector parameter_types = - instruction.macro->signature().parameter_types.types; +void CSAGenerator::ProcessArgumentsCommon( + const TypeVector& parameter_types, std::vector<std::string>* args, + std::vector<std::string>* constexpr_arguments, Stack<std::string>* stack) { for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) { const Type* type = *it; VisitResult arg; if (type->IsConstexpr()) { - args.push_back(std::move(constexpr_arguments.back())); - constexpr_arguments.pop_back(); + args->push_back(std::move(constexpr_arguments->back())); + constexpr_arguments->pop_back(); } else { std::stringstream s; size_t slot_count = LoweredSlotCount(type); VisitResult arg = VisitResult(type, stack->TopRange(slot_count)); EmitCSAValue(arg, *stack, s); - args.push_back(s.str()); + args->push_back(s.str()); stack->PopMany(slot_count); } } - std::reverse(args.begin(), args.end()); + std::reverse(args->begin(), args->end()); +} + +void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, + Stack<std::string>* stack) { + std::vector<std::string> constexpr_arguments = + instruction.constexpr_arguments; + std::vector<std::string> args; + TypeVector parameter_types = + instruction.intrinsic->signature().parameter_types.types; + ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack); + + Stack<std::string> pre_call_stack = *stack; + const Type* return_type = instruction.intrinsic->signature().return_type; + std::vector<std::string> results; + for (const Type* type : LowerType(return_type)) { + results.push_back(FreshNodeName()); + stack->Push(results.back()); + out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> " + << stack->Top() << ";\n"; + out_ << " USE(" << stack->Top() << ");\n"; + } + out_ << " "; + + if (return_type->IsStructType()) { + out_ << "std::tie("; + PrintCommaSeparatedList(out_, results); + out_ << ") = "; + } else { + if (results.size() == 1) { + out_ << results[0] << " = "; + } + } + + if (instruction.intrinsic->ExternalName() == "%RawObjectCast") { + if (parameter_types.size() != 1) { + ReportError("%RawObjectCast must take a single parameter"); + } + if (return_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { + if (return_type->GetGeneratedTNodeTypeName() != + parameter_types[0]->GetGeneratedTNodeTypeName()) { + out_ << "TORQUE_CAST"; + } + } else { + std::stringstream s; + s << "%RawObjectCast must cast to subtype of Tagged (" << *return_type + << " is not)"; + ReportError(s.str()); + } + } else if (instruction.intrinsic->ExternalName() == "%RawPointerCast") { + if (parameter_types.size() != 1) { + ReportError("%RawPointerCast must take a single parameter"); + } + if (!return_type->IsSubtypeOf(TypeOracle::GetRawPtrType())) { + std::stringstream s; + s << "%RawObjectCast must cast to subtype of RawPtr (" << *return_type + << " is not)"; + ReportError(s.str()); + } + } else if (instruction.intrinsic->ExternalName() == "%FromConstexpr") { + if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) { + ReportError( + "%FromConstexpr must take a single parameter with constexpr " + "type"); + } + if (return_type->IsConstexpr()) { + ReportError("%FromConstexpr must return a non-constexpr type"); + } + if (return_type->IsSubtypeOf(TypeOracle::GetSmiType())) { + out_ << "ca_.SmiConstant"; + } else if (return_type->IsSubtypeOf(TypeOracle::GetNumberType())) { + out_ << "ca_.NumberConstant"; + } else if (return_type->IsSubtypeOf(TypeOracle::GetStringType())) { + out_ << "ca_.StringConstant"; + } else if (return_type->IsSubtypeOf(TypeOracle::GetObjectType())) { + ReportError( + "%FromConstexpr cannot cast to subclass of HeapObject unless it's a " + "String or Number"); + } else if (return_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) { + out_ << "ca_.IntPtrConstant"; + } else if (return_type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) { + out_ << "ca_.UintPtrConstant"; + } else if (return_type->IsSubtypeOf(TypeOracle::GetInt32Type())) { + out_ << "ca_.Int32Constant"; + } else { + std::stringstream s; + s << "%FromConstexpr does not support return type " << *return_type; + ReportError(s.str()); + } + } else if (instruction.intrinsic->ExternalName() == "%Allocate") { + out_ << "ca_.UncheckedCast<" << return_type->GetGeneratedTNodeTypeName() + << ">(CodeStubAssembler(state_).Allocate"; + } else { + ReportError("no built in intrinsic with name " + + instruction.intrinsic->ExternalName()); + } + out_ << "("; + PrintCommaSeparatedList(out_, args); + if (instruction.intrinsic->ExternalName() == "%Allocate") out_ << ")"; + if (return_type->IsStructType()) { + out_ << ").Flatten();\n"; + } else { + out_ << ");\n"; + } +} + +void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, + Stack<std::string>* stack) { + std::vector<std::string> constexpr_arguments = + instruction.constexpr_arguments; + std::vector<std::string> args; + TypeVector parameter_types = + instruction.macro->signature().parameter_types.types; + ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack); + + Stack<std::string> pre_call_stack = *stack; const Type* return_type = instruction.macro->signature().return_type; std::vector<std::string> results; for (const Type* type : LowerType(return_type)) { results.push_back(FreshNodeName()); stack->Push(results.back()); - out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> " + out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> " << stack->Top() << ";\n"; out_ << " USE(" << stack->Top() << ");\n"; } + std::string catch_name = + PreCallableExceptionPreparation(instruction.catch_block); out_ << " "; if (return_type->IsStructType()) { out_ << "std::tie("; @@ -166,11 +280,12 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, out_ << ") = "; } else { if (results.size() == 1) { - out_ << results[0] << " = UncheckedCast<" + out_ << results[0] << " = ca_.UncheckedCast<" << return_type->GetGeneratedTNodeTypeName() << ">("; } } - out_ << instruction.macro->name() << "("; + out_ << instruction.macro->external_assembler_name() << "(state_)." + << instruction.macro->ExternalName() << "("; PrintCommaSeparatedList(out_, args); if (return_type->IsStructType()) { out_ << ").Flatten();\n"; @@ -178,6 +293,8 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, if (results.size() == 1) out_ << ")"; out_ << ");\n"; } + PostCallableExceptionPreparation(catch_name, return_type, + instruction.catch_block, &pre_call_stack); } void CSAGenerator::EmitInstruction( @@ -188,31 +305,17 @@ void CSAGenerator::EmitInstruction( std::vector<std::string> args; TypeVector parameter_types = instruction.macro->signature().parameter_types.types; - for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) { - const Type* type = *it; - VisitResult arg; - if (type->IsConstexpr()) { - args.push_back(std::move(constexpr_arguments.back())); - constexpr_arguments.pop_back(); - } else { - std::stringstream s; - size_t slot_count = LoweredSlotCount(type); - VisitResult arg = VisitResult(type, stack->TopRange(slot_count)); - EmitCSAValue(arg, *stack, s); - args.push_back(s.str()); - stack->PopMany(slot_count); - } - } - std::reverse(args.begin(), args.end()); + ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack); + Stack<std::string> pre_call_stack = *stack; std::vector<std::string> results; const Type* return_type = instruction.macro->signature().return_type; if (return_type != TypeOracle::GetNeverType()) { for (const Type* type : LowerType(instruction.macro->signature().return_type)) { results.push_back(FreshNodeName()); - out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> " - << results.back() << ";\n"; + out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() + << "> " << results.back() << ";\n"; out_ << " USE(" << results.back() << ");\n"; } } @@ -228,13 +331,16 @@ void CSAGenerator::EmitInstruction( for (size_t j = 0; j < label_parameters.size(); ++j) { var_names[i].push_back("result_" + std::to_string(i) + "_" + std::to_string(j)); - out_ << " TVariable<" + out_ << " compiler::TypedCodeAssemblerVariable<" << label_parameters[j]->GetGeneratedTNodeTypeName() << "> " - << var_names[i][j] << "(this);\n"; + << var_names[i][j] << "(&ca_);\n"; } - out_ << " Label " << label_names[i] << "(this);\n"; + out_ << " compiler::CodeAssemblerLabel " << label_names[i] + << "(&ca_);\n"; } + std::string catch_name = + PreCallableExceptionPreparation(instruction.catch_block); out_ << " "; if (results.size() == 1) { out_ << results[0] << " = "; @@ -243,7 +349,8 @@ void CSAGenerator::EmitInstruction( PrintCommaSeparatedList(out_, results); out_ << ") = "; } - out_ << instruction.macro->name() << "("; + out_ << instruction.macro->external_assembler_name() << "(state_)." + << instruction.macro->ExternalName() << "("; PrintCommaSeparatedList(out_, args); bool first = args.empty(); for (size_t i = 0; i < label_names.size(); ++i) { @@ -254,9 +361,17 @@ void CSAGenerator::EmitInstruction( out_ << ", &" << var_names[i][j]; } } - out_ << ");\n"; + if (return_type->IsStructType()) { + out_ << ").Flatten();\n"; + } else { + out_ << ");\n"; + } + + PostCallableExceptionPreparation(catch_name, return_type, + instruction.catch_block, &pre_call_stack); + if (instruction.return_continuation) { - out_ << " Goto(&" << BlockName(*instruction.return_continuation); + out_ << " ca_.Goto(&" << BlockName(*instruction.return_continuation); for (const std::string& value : *stack) { out_ << ", " << value; } @@ -267,8 +382,8 @@ void CSAGenerator::EmitInstruction( } for (size_t i = 0; i < label_names.size(); ++i) { out_ << " if (" << label_names[i] << ".is_used()) {\n"; - out_ << " Bind(&" << label_names[i] << ");\n"; - out_ << " Goto(&" << BlockName(instruction.label_blocks[i]); + out_ << " ca_.Bind(&" << label_names[i] << ");\n"; + out_ << " ca_.Goto(&" << BlockName(instruction.label_blocks[i]); for (const std::string& value : *stack) { out_ << ", " << value; } @@ -287,30 +402,44 @@ void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction, std::vector<const Type*> result_types = LowerType(instruction.builtin->signature().return_type); if (instruction.is_tailcall) { - out_ << " TailCallBuiltin(Builtins::k" << instruction.builtin->name() - << ", "; + out_ << " CodeStubAssembler(state_).TailCallBuiltin(Builtins::k" + << instruction.builtin->ExternalName() << ", "; PrintCommaSeparatedList(out_, arguments); out_ << ");\n"; } else { + std::string result_name = FreshNodeName(); + if (result_types.size() == 1) { + out_ << " compiler::TNode<" + << result_types[0]->GetGeneratedTNodeTypeName() << "> " + << result_name << ";\n"; + } + std::string catch_name = + PreCallableExceptionPreparation(instruction.catch_block); + Stack<std::string> pre_call_stack = *stack; if (result_types.size() == 1) { std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName(); - stack->Push(FreshNodeName()); - out_ << " TNode<" << generated_type << "> " << stack->Top() << " = "; - if (generated_type != "Object") out_ << "CAST("; - out_ << "CallBuiltin(Builtins::k" << instruction.builtin->name() << ", "; + stack->Push(result_name); + out_ << " " << result_name << " = "; + if (generated_type != "Object") out_ << "TORQUE_CAST("; + out_ << "CodeStubAssembler(state_).CallBuiltin(Builtins::k" + << instruction.builtin->ExternalName() << ", "; PrintCommaSeparatedList(out_, arguments); if (generated_type != "Object") out_ << ")"; out_ << ");\n"; - out_ << " USE(" << stack->Top() << ");\n"; + out_ << " USE(" << result_name << ");\n"; } else { DCHECK_EQ(0, result_types.size()); // TODO(tebbi): Actually, builtins have to return a value, so we should // not have to handle this case. - out_ << " CallBuiltin(Builtins::k" << instruction.builtin->name() - << ", "; + out_ << " CodeStubAssembler(state_).CallBuiltin(Builtins::k" + << instruction.builtin->ExternalName() << ", "; PrintCommaSeparatedList(out_, arguments); out_ << ");\n"; } + PostCallableExceptionPreparation( + catch_name, + result_types.size() == 0 ? TypeOracle::GetVoidType() : result_types[0], + instruction.catch_block, &pre_call_stack); } } @@ -320,67 +449,127 @@ void CSAGenerator::EmitInstruction( std::vector<std::string> function_and_arguments = stack->PopMany(1 + instruction.argc); std::vector<const Type*> result_types = - LowerType(instruction.example_builtin->signature().return_type); + LowerType(instruction.type->return_type()); if (result_types.size() != 1) { ReportError("builtins must have exactly one result"); } if (instruction.is_tailcall) { - out_ << " Tail (Builtins::CallableFor(isolate(), Builtins::k" - << instruction.example_builtin->name() << ").descriptor(), "; - PrintCommaSeparatedList(out_, function_and_arguments); - out_ << ");\n"; - } else { - stack->Push(FreshNodeName()); - std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName(); - out_ << " TNode<" << generated_type << "> " << stack->Top() << " = "; - if (generated_type != "Object") out_ << "CAST("; - out_ << "CallStub(Builtins::CallableFor(isolate(), Builtins::k" - << instruction.example_builtin->name() << ").descriptor(), "; - PrintCommaSeparatedList(out_, function_and_arguments); - out_ << ")"; - if (generated_type != "Object") out_ << ")"; - out_ << "; \n"; - out_ << " USE(" << stack->Top() << ");\n"; + ReportError("tail-calls to builtin pointers are not supported"); + } + + stack->Push(FreshNodeName()); + std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName(); + out_ << " compiler::TNode<" << generated_type << "> " << stack->Top() + << " = "; + if (generated_type != "Object") out_ << "TORQUE_CAST("; + out_ << "CodeStubAssembler(state_).CallBuiltinPointer(Builtins::" + "CallableFor(ca_." + "isolate()," + "ExampleBuiltinForTorqueFunctionPointerType(" + << instruction.type->function_pointer_type_id() << ")).descriptor(), "; + PrintCommaSeparatedList(out_, function_and_arguments); + out_ << ")"; + if (generated_type != "Object") out_ << ")"; + out_ << "; \n"; + out_ << " USE(" << stack->Top() << ");\n"; +} + +std::string CSAGenerator::PreCallableExceptionPreparation( + base::Optional<Block*> catch_block) { + std::string catch_name; + if (catch_block) { + catch_name = FreshCatchName(); + out_ << " compiler::CodeAssemblerExceptionHandlerLabel " << catch_name + << "_label(&ca_, compiler::CodeAssemblerLabel::kDeferred);\n"; + out_ << " { compiler::CodeAssemblerScopedExceptionHandler s(&ca_, &" + << catch_name << "_label);\n"; + } + return catch_name; +} + +void CSAGenerator::PostCallableExceptionPreparation( + const std::string& catch_name, const Type* return_type, + base::Optional<Block*> catch_block, Stack<std::string>* stack) { + if (catch_block) { + std::string block_name = BlockName(*catch_block); + out_ << " }\n"; + out_ << " if (" << catch_name << "_label.is_used()) {\n"; + out_ << " compiler::CodeAssemblerLabel " << catch_name + << "_skip(&ca_);\n"; + if (!return_type->IsNever()) { + out_ << " ca_.Goto(&" << catch_name << "_skip);\n"; + } + out_ << " compiler::TNode<Object> " << catch_name + << "_exception_object;\n"; + out_ << " ca_.Bind(&" << catch_name << "_label, &" << catch_name + << "_exception_object);\n"; + out_ << " ca_.Goto(&" << block_name; + for (size_t i = 0; i < stack->Size(); ++i) { + out_ << ", " << stack->begin()[i]; + } + out_ << ", " << catch_name << "_exception_object);\n"; + if (!return_type->IsNever()) { + out_ << " ca_.Bind(&" << catch_name << "_skip);\n"; + } + out_ << " }\n"; } } void CSAGenerator::EmitInstruction(const CallRuntimeInstruction& instruction, Stack<std::string>* stack) { std::vector<std::string> arguments = stack->PopMany(instruction.argc); - std::vector<const Type*> result_types = - LowerType(instruction.runtime_function->signature().return_type); + const Type* return_type = + instruction.runtime_function->signature().return_type; + std::vector<const Type*> result_types; + if (return_type != TypeOracle::GetNeverType()) { + result_types = LowerType(return_type); + } if (result_types.size() > 1) { ReportError("runtime function must have at most one result"); } if (instruction.is_tailcall) { - out_ << " TailCallRuntime(Runtime::k" - << instruction.runtime_function->name() << ", "; + out_ << " CodeStubAssembler(state_).TailCallRuntime(Runtime::k" + << instruction.runtime_function->ExternalName() << ", "; PrintCommaSeparatedList(out_, arguments); out_ << ");\n"; } else { + std::string result_name = FreshNodeName(); + if (result_types.size() == 1) { + out_ << " compiler::TNode<" + << result_types[0]->GetGeneratedTNodeTypeName() << "> " + << result_name << ";\n"; + } + std::string catch_name = + PreCallableExceptionPreparation(instruction.catch_block); + Stack<std::string> pre_call_stack = *stack; if (result_types.size() == 1) { - stack->Push(FreshNodeName()); - out_ << " TNode<" << result_types[0]->GetGeneratedTNodeTypeName() - << "> " << stack->Top() << " = CAST(CallRuntime(Runtime::k" - << instruction.runtime_function->name() << ", "; + stack->Push(result_name); + out_ << " " << result_name + << " = TORQUE_CAST(CodeStubAssembler(state_).CallRuntime(Runtime::k" + << instruction.runtime_function->ExternalName() << ", "; PrintCommaSeparatedList(out_, arguments); out_ << "));\n"; - out_ << " USE(" << stack->Top() << ");\n"; + out_ << " USE(" << result_name << ");\n"; } else { DCHECK_EQ(0, result_types.size()); - // TODO(tebbi): Actually, runtime functions have to return a value, so we - // should not have to handle this case. - out_ << " CallRuntime(Runtime::k" - << instruction.runtime_function->name() << ", "; + out_ << " CodeStubAssembler(state_).CallRuntime(Runtime::k" + << instruction.runtime_function->ExternalName() << ", "; PrintCommaSeparatedList(out_, arguments); out_ << ");\n"; + if (return_type == TypeOracle::GetNeverType()) { + out_ << " CodeStubAssembler(state_).Unreachable();\n"; + } else { + DCHECK(return_type == TypeOracle::GetVoidType()); + } } + PostCallableExceptionPreparation(catch_name, return_type, + instruction.catch_block, &pre_call_stack); } } void CSAGenerator::EmitInstruction(const BranchInstruction& instruction, Stack<std::string>* stack) { - out_ << " Branch(" << stack->Pop() << ", &" + out_ << " ca_.Branch(" << stack->Pop() << ", &" << BlockName(instruction.if_true) << ", &" << BlockName(instruction.if_false); for (const std::string& value : *stack) { @@ -392,13 +581,13 @@ void CSAGenerator::EmitInstruction(const BranchInstruction& instruction, void CSAGenerator::EmitInstruction( const ConstexprBranchInstruction& instruction, Stack<std::string>* stack) { out_ << " if (" << instruction.condition << ") {\n"; - out_ << " Goto(&" << BlockName(instruction.if_true); + out_ << " ca_.Goto(&" << BlockName(instruction.if_true); for (const std::string& value : *stack) { out_ << ", " << value; } out_ << ");\n"; out_ << " } else {\n"; - out_ << " Goto(&" << BlockName(instruction.if_false); + out_ << " ca_.Goto(&" << BlockName(instruction.if_false); for (const std::string& value : *stack) { out_ << ", " << value; } @@ -409,7 +598,7 @@ void CSAGenerator::EmitInstruction( void CSAGenerator::EmitInstruction(const GotoInstruction& instruction, Stack<std::string>* stack) { - out_ << " Goto(&" << BlockName(instruction.destination); + out_ << " ca_.Goto(&" << BlockName(instruction.destination); for (const std::string& value : *stack) { out_ << ", " << value; } @@ -422,7 +611,7 @@ void CSAGenerator::EmitInstruction(const GotoExternalInstruction& instruction, it != instruction.variable_names.rend(); ++it) { out_ << " *" << *it << " = " << stack->Pop() << ";\n"; } - out_ << " Goto(" << instruction.destination << ");\n"; + out_ << " ca_.Goto(" << instruction.destination << ");\n"; } void CSAGenerator::EmitInstruction(const ReturnInstruction& instruction, @@ -430,7 +619,7 @@ void CSAGenerator::EmitInstruction(const ReturnInstruction& instruction, if (*linkage_ == Builtin::kVarArgsJavaScript) { out_ << " " << ARGUMENTS_VARIABLE_STRING << "->PopAndReturn("; } else { - out_ << " Return("; + out_ << " CodeStubAssembler(state_).Return("; } out_ << stack->Pop() << ");\n"; } @@ -438,26 +627,75 @@ void CSAGenerator::EmitInstruction(const ReturnInstruction& instruction, void CSAGenerator::EmitInstruction( const PrintConstantStringInstruction& instruction, Stack<std::string>* stack) { - out_ << " Print(" << StringLiteralQuote(instruction.message) << ");\n"; + out_ << " CodeStubAssembler(state_).Print(" + << StringLiteralQuote(instruction.message) << ");\n"; } -void CSAGenerator::EmitInstruction(const DebugBreakInstruction& instruction, +void CSAGenerator::EmitInstruction(const AbortInstruction& instruction, Stack<std::string>* stack) { - if (instruction.never_continues) { - out_ << " Unreachable();\n"; - } else { - out_ << " DebugBreak();\n"; + switch (instruction.kind) { + case AbortInstruction::Kind::kUnreachable: + DCHECK(instruction.message.empty()); + out_ << " CodeStubAssembler(state_).Unreachable();\n"; + break; + case AbortInstruction::Kind::kDebugBreak: + DCHECK(instruction.message.empty()); + out_ << " CodeStubAssembler(state_).DebugBreak();\n"; + break; + case AbortInstruction::Kind::kAssertionFailure: { + std::string file = + StringLiteralQuote(SourceFileMap::GetSource(instruction.pos.source)); + out_ << " CodeStubAssembler(state_).FailAssert(" + << StringLiteralQuote(instruction.message) << ", " << file << ", " + << instruction.pos.line + 1 << ");\n"; + break; + } } } void CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction, Stack<std::string>* stack) { stack->Poke(stack->AboveTop() - 1, - "UncheckedCast<" + + "ca_.UncheckedCast<" + instruction.destination_type->GetGeneratedTNodeTypeName() + ">(" + stack->Top() + ")"); } +void CSAGenerator::EmitInstruction( + const LoadObjectFieldInstruction& instruction, Stack<std::string>* stack) { + const Field& field = + instruction.class_type->LookupField(instruction.field_name); + std::string result_name = FreshNodeName(); + std::string type_string = + field.name_and_type.type->IsSubtypeOf(TypeOracle::GetSmiType()) + ? "MachineType::TaggedSigned()" + : "MachineType::AnyTagged()"; + out_ << field.name_and_type.type->GetGeneratedTypeName() << " " << result_name + << " = " + << "ca_.UncheckedCast<" + << field.name_and_type.type->GetGeneratedTNodeTypeName() + << ">(CodeStubAssembler(state_).LoadObjectField(" + << stack->Top() + ", " + std::to_string(field.offset) + ", " + << type_string + "));\n"; + stack->Poke(stack->AboveTop() - 1, result_name); +} + +void CSAGenerator::EmitInstruction( + const StoreObjectFieldInstruction& instruction, Stack<std::string>* stack) { + auto value = stack->Pop(); + auto object = stack->Pop(); + stack->Push(value); + const Field& field = + instruction.class_type->LookupField(instruction.field_name); + if (field.offset == 0) { + out_ << " CodeStubAssembler(state_).StoreMap(" + object + ", " + value + + ");\n"; + } else { + out_ << " CodeStubAssembler(state_).StoreObjectField(" + object + ", " + + std::to_string(field.offset) + ", " + value + ");\n"; + } +} + // static void CSAGenerator::EmitCSAValue(VisitResult result, const Stack<std::string>& values, @@ -465,20 +703,21 @@ void CSAGenerator::EmitCSAValue(VisitResult result, if (!result.IsOnStack()) { out << result.constexpr_value(); } else if (auto* struct_type = StructType::DynamicCast(result.type())) { - out << struct_type->name() << "{"; + out << struct_type->GetGeneratedTypeName() << "{"; bool first = true; for (auto& field : struct_type->fields()) { if (!first) { out << ", "; } first = false; - EmitCSAValue(ProjectStructField(result, field.name), values, out); + EmitCSAValue(ProjectStructField(result, field.name_and_type.name), values, + out); } out << "}"; } else { DCHECK_EQ(1, result.stack_range().Size()); - out << "TNode<" << result.type()->GetGeneratedTNodeTypeName() << ">{" - << values.Peek(result.stack_range().begin()) << "}"; + out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName() + << ">{" << values.Peek(result.stack_range().begin()) << "}"; } } |