diff options
Diffstat (limited to 'deps/v8/src/torque/implementation-visitor.cc')
-rw-r--r-- | deps/v8/src/torque/implementation-visitor.cc | 1589 |
1 files changed, 781 insertions, 808 deletions
diff --git a/deps/v8/src/torque/implementation-visitor.cc b/deps/v8/src/torque/implementation-visitor.cc index 5044d914db..89c0c70416 100644 --- a/deps/v8/src/torque/implementation-visitor.cc +++ b/deps/v8/src/torque/implementation-visitor.cc @@ -4,6 +4,7 @@ #include <algorithm> +#include "src/torque/csa-generator.h" #include "src/torque/implementation-visitor.h" #include "src/torque/parameter-difference.h" @@ -26,19 +27,20 @@ VisitResult ImplementationVisitor::Visit(Expression* expr) { const Type* ImplementationVisitor::Visit(Statement* stmt) { CurrentSourcePosition::Scope scope(stmt->pos); - GenerateIndent(); - source_out() << "// " << CurrentPositionAsString() << "\n"; + const Type* result; switch (stmt->kind) { -#define ENUM_ITEM(name) \ - case AstNode::Kind::k##name: \ - return Visit(name::cast(stmt)); +#define ENUM_ITEM(name) \ + case AstNode::Kind::k##name: \ + result = Visit(name::cast(stmt)); \ + break; AST_STATEMENT_NODE_KIND_LIST(ENUM_ITEM) #undef ENUM_ITEM default: - UNIMPLEMENTED(); + UNREACHABLE(); } - UNREACHABLE(); - return nullptr; + DCHECK_EQ(result == TypeOracle::GetNeverType(), + assembler().CurrentBlockIsComplete()); + return result; } void ImplementationVisitor::Visit(Declaration* decl) { @@ -72,12 +74,13 @@ void ImplementationVisitor::BeginModuleFile(Module* module) { std::ostream& header = module->header_stream(); if (module->IsDefault()) { - source << "#include \"src/code-stub-assembler.h\""; + source << "#include \"src/torque-assembler.h\""; } else { source << "#include \"src/builtins/builtins-" + DashifyString(module->name()) + "-gen.h\""; } source << "\n"; + source << "#include \"src/objects/arguments.h\"\n"; source << "#include \"src/builtins/builtins-utils-gen.h\"\n"; source << "#include \"src/builtins/builtins.h\"\n"; source << "#include \"src/code-factory.h\"\n"; @@ -103,7 +106,7 @@ void ImplementationVisitor::BeginModuleFile(Module* module) { header << "#ifndef " << headerDefine << "\n"; header << "#define " << headerDefine << "\n\n"; if (module->IsDefault()) { - header << "#include \"src/code-stub-assembler.h\""; + header << "#include \"src/torque-assembler.h\""; } else { header << "#include \"src/builtins/builtins-" + DashifyString(module->name()) + "-gen.h\"\n"; @@ -176,12 +179,20 @@ void ImplementationVisitor::Visit(ConstDeclaration* decl) { DCHECK(!signature.return_type->IsVoidOrNever()); + assembler_ = CfgAssembler(Stack<const Type*>{}); + VisitResult expression_result = Visit(decl->expression); VisitResult return_result = GenerateImplicitConvert(signature.return_type, expression_result); - GenerateIndent(); - source_out() << "return " << return_result.RValue() << ";\n"; + CSAGenerator csa_generator{assembler().Result(), source_out()}; + Stack<std::string> values = *csa_generator.EmitGraph(Stack<std::string>{}); + + assembler_ = base::nullopt; + + source_out() << "return "; + CSAGenerator::EmitCSAValue(return_result, values, source_out()); + source_out() << ";\n"; source_out() << "}\n\n"; } @@ -193,13 +204,41 @@ void ImplementationVisitor::Visit(StructDeclaration* decl) { header_out() << " " << field.type->GetGeneratedTypeName(); header_out() << " " << field.name << ";\n"; } - header_out() << " } " - << ";\n"; + header_out() << "\n std::tuple<"; + bool first = true; + for (const Type* type : LowerType(struct_type)) { + if (!first) { + header_out() << ", "; + } + first = false; + header_out() << type->GetGeneratedTypeName(); + } + header_out() << "> Flatten() const {\n" + << " return std::tuple_cat("; + first = true; + for (auto& field : struct_type->fields()) { + if (!first) { + header_out() << ", "; + } + first = false; + if (field.type->IsStructType()) { + header_out() << field.name << ".Flatten()"; + } else { + header_out() << "std::make_tuple(" << field.name << ")"; + } + } + header_out() << ");\n"; + header_out() << " }\n"; + header_out() << " };\n"; } void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl, const Signature& sig, Statement* body) { Signature signature = MakeSignature(decl->signature.get()); + const Type* return_type = signature.return_type; + bool can_return = return_type != TypeOracle::GetNeverType(); + bool has_return_value = + can_return && return_type != TypeOracle::GetVoidType(); std::string name = GetGeneratedCallableName( decl->name, declarations()->GetCurrentSpecializationTypeNamesVector()); const TypeVector& list = signature.types(); @@ -216,15 +255,43 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl, source_out(), GetDSLAssemblerName(CurrentModule()) + "::", macro); source_out() << " {\n"; - const Variable* result_var = nullptr; - if (macro->HasReturnValue()) { - result_var = - GeneratePredeclaredVariableDeclaration(kReturnValueVariable, {}); + Stack<std::string> lowered_parameters; + Stack<const Type*> lowered_parameter_types; + + for (const std::string& name : macro->parameter_names()) { + Parameter* parameter = Parameter::cast(declarations()->LookupValue(name)); + const Type* type = parameter->type(); + if (type->IsConstexpr()) { + parameter->set_value( + VisitResult(parameter->type(), parameter->external_name())); + } else { + LowerParameter(type, parameter->external_name(), &lowered_parameters); + StackRange range = lowered_parameter_types.PushMany(LowerType(type)); + parameter->set_value(VisitResult(type, range)); + } + } + + DCHECK_EQ(lowered_parameters.Size(), lowered_parameter_types.Size()); + assembler_ = CfgAssembler(lowered_parameter_types); + + for (const LabelDeclaration& label_info : sig.labels) { + Label* label = declarations()->LookupLabel(label_info.name); + Stack<const Type*> label_input_stack; + for (Variable* v : label->GetParameters()) { + label_input_stack.PushMany(LowerType(v->type())); + } + CreateBlockForLabel(label, label_input_stack); } + Label* macro_end = declarations()->DeclareLabel("macro_end"); - GenerateLabelDefinition(macro_end, decl); + if (can_return) { + Stack<const Type*> result_stack; + CreateBlockForLabel(macro_end, + Stack<const Type*>{LowerType(signature.return_type)}); + } const Type* result = Visit(body); + if (result->IsNever()) { if (!macro->signature().return_type->IsNever() && !macro->HasReturns()) { std::stringstream s; @@ -246,23 +313,54 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl, ReportError(s.str()); } } - if (macro->HasReturns()) { - if (!result->IsNever()) { - GenerateLabelGoto(macro_end); + if (!result->IsNever()) { + GenerateLabelGoto(macro_end); + } + + for (const LabelDeclaration& label_info : sig.labels) { + Label* label = declarations()->LookupLabel(label_info.name); + GenerateLabelBind(label); + std::vector<std::string> label_parameter_variables; + for (size_t i = 0; i < label->GetParameterCount(); ++i) { + label_parameter_variables.push_back( + ExternalLabelParameterName(label, i)); } + assembler().Emit(GotoExternalInstruction{label->external_label_name(), + label_parameter_variables}); + } + + if (macro->HasReturns() || !result->IsNever()) { GenerateLabelBind(macro_end); } - if (result_var != nullptr) { - GenerateIndent(); - source_out() << "return " - << RValueFlattenStructs( - VisitResult(result_var->type(), result_var)) - << ";\n"; + + CSAGenerator csa_generator{assembler().Result(), source_out()}; + base::Optional<Stack<std::string>> values = + csa_generator.EmitGraph(lowered_parameters); + + assembler_ = base::nullopt; + + if (has_return_value) { + source_out() << " return "; + CSAGenerator::EmitCSAValue(GetAndClearReturnValue(), *values, + source_out()); + source_out() << ";\n"; } source_out() << "}\n\n"; } } +namespace { +std::string AddParameter(Value* parameter, size_t i, + Stack<std::string>* parameters, + Stack<const Type*>* parameter_types) { + std::string name = "parameter" + std::to_string(i); + parameters->Push(name); + StackRange range = parameter_types->PushMany(LowerType(parameter->type())); + parameter->set_value(VisitResult(parameter->type(), range)); + return name; +} +} // namespace + void ImplementationVisitor::Visit(TorqueBuiltinDeclaration* decl, const Signature& signature, Statement* body) { std::string name = GetGeneratedCallableName( @@ -272,15 +370,17 @@ void ImplementationVisitor::Visit(TorqueBuiltinDeclaration* decl, Builtin* builtin = declarations()->LookupBuiltin(name); CurrentCallableActivator activator(global_context_, builtin, decl); + Stack<const Type*> parameter_types; + Stack<std::string> parameters; + // Context - const Value* val = + Value* val = declarations()->LookupValue(decl->signature->parameters.names[0]); - GenerateIndent(); - source_out() << "TNode<Context> " << val->value() + std::string parameter0 = AddParameter(val, 0, ¶meters, ¶meter_types); + source_out() << " TNode<Context> " << parameter0 << " = UncheckedCast<Context>(Parameter(" << "Descriptor::kContext));\n"; - GenerateIndent(); - source_out() << "USE(" << val->value() << ");\n"; + source_out() << " USE(" << parameter0 << ");\n"; size_t first = 1; if (builtin->IsVarArgsJavaScript()) { @@ -288,41 +388,82 @@ void ImplementationVisitor::Visit(TorqueBuiltinDeclaration* decl, ExternConstant* arguments = ExternConstant::cast(declarations()->LookupValue( decl->signature->parameters.arguments_variable)); - std::string arguments_name = arguments->value(); - GenerateIndent(); + std::string arguments_name = arguments->value().constexpr_value(); source_out() - << "Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);\n"; - GenerateIndent(); - source_out() << "CodeStubArguments arguments_impl(this, " + << " Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);\n"; + source_out() << " CodeStubArguments arguments_impl(this, " "ChangeInt32ToIntPtr(argc));\n"; - const Value* receiver = + Value* receiver = declarations()->LookupValue(decl->signature->parameters.names[1]); - GenerateIndent(); - source_out() << "TNode<Object> " << receiver->value() + std::string parameter1 = + AddParameter(receiver, 1, ¶meters, ¶meter_types); + + source_out() << " TNode<Object> " << parameter1 << " = arguments_impl.GetReceiver();\n"; - GenerateIndent(); - source_out() << "auto arguments = &arguments_impl;\n"; - GenerateIndent(); + source_out() << "auto " << CSAGenerator::ARGUMENTS_VARIABLE_STRING + << " = &arguments_impl;\n"; source_out() << "USE(arguments);\n"; - GenerateIndent(); - source_out() << "USE(" << receiver->value() << ");\n"; + source_out() << "USE(" << parameter1 << ");\n"; first = 2; } - GenerateParameterList(decl->signature->parameters.names, first); - Visit(body); + for (size_t i = 0; i < decl->signature->parameters.names.size(); ++i) { + if (i < first) continue; + const std::string& parameter_name = decl->signature->parameters.names[i]; + Value* parameter = declarations()->LookupValue(parameter_name); + std::string var = AddParameter(parameter, i, ¶meters, ¶meter_types); + source_out() << " " << parameter->type()->GetGeneratedTypeName() << " " + << var << " = " + << "UncheckedCast<" + << parameter->type()->GetGeneratedTNodeTypeName() + << ">(Parameter(Descriptor::k" + << CamelifyString(parameter_name) << "));\n"; + source_out() << " USE(" << var << ");\n"; + } + + assembler_ = CfgAssembler(parameter_types); + const Type* body_result = Visit(body); + if (body_result != TypeOracle::GetNeverType()) { + ReportError("control reaches end of builtin, expected return of a value"); + } + CSAGenerator csa_generator{assembler().Result(), source_out(), + builtin->kind()}; + csa_generator.EmitGraph(parameters); + assembler_ = base::nullopt; source_out() << "}\n\n"; } const Type* ImplementationVisitor::Visit(VarDeclarationStatement* stmt) { + base::Optional<const Type*> type; + if (stmt->type) type = declarations()->GetType(*stmt->type); base::Optional<VisitResult> init_result; if (stmt->initializer) { + StackScope scope(this); init_result = Visit(*stmt->initializer); + if (type) { + init_result = GenerateImplicitConvert(*type, *init_result); + } + init_result = scope.Yield(*init_result); + } else { + DCHECK(type.has_value()); + if ((*type)->IsConstexpr()) { + ReportError("constexpr variables need an initializer"); + } + TypeVector lowered_types = LowerType(*type); + for (const Type* type : lowered_types) { + assembler().Emit(PushUninitializedInstruction{type}); + } + init_result = + VisitResult(*type, assembler().TopRange(lowered_types.size())); } - base::Optional<const Type*> type; - if (stmt->type) type = declarations()->GetType(*stmt->type); - GenerateVariableDeclaration(stmt, stmt->name, stmt->const_qualified, type, - init_result); + Variable* var; + if (stmt->const_qualified) { + var = declarations()->DeclareVariable(stmt->name, init_result->type(), + stmt->const_qualified); + } else { + var = Variable::cast(declarations()->LookupValue(stmt->name)); + } + var->set_value(*init_result); return TypeOracle::GetVoidType(); } @@ -331,72 +472,61 @@ const Type* ImplementationVisitor::Visit(TailCallStatement* stmt) { } VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) { - std::string f1 = NewTempVariable(); - std::string f2 = NewTempVariable(); - - // The code for both paths of the conditional need to be generated first in - // lambdas before evaluating the conditional expression because the common - // type of the result of both the true and false of the condition needs to be - // known when declaring the variable to hold the result of the conditional. - VisitResult left, right; - GenerateIndent(); - source_out() << "auto " << f1 << " = [=]() "; - { - ScopedIndent indent(this, false); - source_out() << "\n"; - left = Visit(expr->if_true); - GenerateIndent(); - source_out() << "return " << RValueFlattenStructs(left) << ";\n"; - } - source_out() << ";\n"; - GenerateIndent(); - source_out() << "auto " << f2 << " = [=]() "; + Label* true_label; + Label* false_label; + Block* done_block = assembler().NewBlock(); + Block* true_conversion_block = assembler().NewBlock(); { - ScopedIndent indent(this, false); - source_out() << "\n"; - right = Visit(expr->if_false); - GenerateIndent(); - source_out() << "return " << RValueFlattenStructs(right) << ";\n"; + Declarations::NodeScopeActivator scope(declarations(), expr->condition); + + true_label = declarations()->LookupLabel(kTrueLabelName); + CreateBlockForLabel(true_label, assembler().CurrentStack()); + false_label = declarations()->LookupLabel(kFalseLabelName); + CreateBlockForLabel(false_label, assembler().CurrentStack()); + done_block = assembler().NewBlock(); + + { + StackScope condition_scope(this); + VisitResult condition_result = Visit(expr->condition); + if (!condition_result.type()->IsNever()) { + condition_result = condition_scope.Yield(GenerateImplicitConvert( + TypeOracle::GetBoolType(), condition_result)); + assembler().Branch(true_label->block(), false_label->block()); + } + } } - source_out() << ";\n"; - const Type* common_type = GetCommonType(left.type(), right.type()); - std::string result_var = NewTempVariable(); - Variable* result = - GenerateVariableDeclaration(expr, result_var, false, common_type); + VisitResult left; + VisitResult right; { - ScopedIndent indent(this); - Declarations::NodeScopeActivator scope(declarations(), expr->condition); - - Label* true_label = declarations()->LookupLabel(kTrueLabelName); - GenerateLabelDefinition(true_label); - Label* false_label = declarations()->LookupLabel(kFalseLabelName); - GenerateLabelDefinition(false_label); - Label* done_label = declarations()->DeclarePrivateLabel(kDoneLabelName); - GenerateLabelDefinition(done_label, expr); + // The code for both paths of the conditional need to be generated first + // before evaluating the conditional expression because the common type of + // the result of both the true and false of the condition needs to be known + // to convert both branches to a common type. + assembler().Bind(true_label->block()); + StackScope left_scope(this); + left = Visit(expr->if_true); + assembler().Goto(true_conversion_block); - VisitResult condition_result = Visit(expr->condition); - if (!condition_result.type()->IsNever()) { - condition_result = - GenerateImplicitConvert(TypeOracle::GetBoolType(), condition_result); - GenerateBranch(condition_result, true_label, false_label); + const Type* common_type; + { + assembler().Bind(false_label->block()); + StackScope right_scope(this); + right = Visit(expr->if_false); + common_type = GetCommonType(left.type(), right.type()); + right = right_scope.Yield(GenerateImplicitConvert(common_type, right)); + assembler().Goto(done_block); } - GenerateLabelBind(true_label); - GenerateIndent(); - VisitResult left_result = {right.type(), f1 + "()"}; - GenerateAssignToVariable(result, left_result); - GenerateLabelGoto(done_label); - GenerateLabelBind(false_label); - GenerateIndent(); - VisitResult right_result = {right.type(), f2 + "()"}; - GenerateAssignToVariable(result, right_result); - GenerateLabelGoto(done_label); - - GenerateLabelBind(done_label); + assembler().Bind(true_conversion_block); + left = left_scope.Yield(GenerateImplicitConvert(common_type, left)); + assembler().Goto(done_block); } - return VisitResult(common_type, result); + + assembler().Bind(done_block); + CHECK_EQ(left, right); + return left; } VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) { @@ -404,32 +534,44 @@ VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) { { Declarations::NodeScopeActivator scope(declarations(), expr->left); Label* false_label = declarations()->LookupLabel(kFalseLabelName); - GenerateLabelDefinition(false_label); + CreateBlockForLabel(false_label, assembler().CurrentStack()); left_result = Visit(expr->left); if (left_result.type()->IsBool()) { Label* true_label = declarations()->LookupLabel(kTrueLabelName); - GenerateIndent(); - source_out() << "GotoIf(" << RValueFlattenStructs(left_result) << ", " - << true_label->generated() << ");\n"; + assembler().Branch(true_label->block(), false_label->block()); + assembler().Bind(false_label->block()); + } else if (left_result.type()->IsNever()) { + assembler().Bind(false_label->block()); } else if (!left_result.type()->IsConstexprBool()) { - GenerateLabelBind(false_label); + ReportError( + "expected type bool, constexpr bool, or never on left-hand side of " + "operator ||"); } } - VisitResult right_result = Visit(expr->right); - if (right_result.type() != left_result.type()) { - std::stringstream stream; - stream << "types of left and right expression of logical OR don't match (\"" - << *left_result.type() << "\" vs. \"" << *right_result.type() - << "\")"; - ReportError(stream.str()); - } + if (left_result.type()->IsConstexprBool()) { - return VisitResult(left_result.type(), - std::string("(") + RValueFlattenStructs(left_result) + - " || " + RValueFlattenStructs(right_result) + ")"); - } else { - return right_result; + VisitResult right_result = Visit(expr->right); + if (!right_result.type()->IsConstexprBool()) { + ReportError( + "expected type constexpr bool on right-hand side of operator " + "||"); + } + return VisitResult(TypeOracle::GetConstexprBoolType(), + std::string("(") + left_result.constexpr_value() + + " || " + right_result.constexpr_value() + ")"); } + + VisitResult right_result = Visit(expr->right); + if (right_result.type()->IsBool()) { + Label* true_label = declarations()->LookupLabel(kTrueLabelName); + Label* false_label = declarations()->LookupLabel(kFalseLabelName); + assembler().Branch(true_label->block(), false_label->block()); + return VisitResult::NeverResult(); + } else if (!right_result.type()->IsNever()) { + ReportError( + "expected type bool or never on right-hand side of operator ||"); + } + return right_result; } VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) { @@ -437,67 +579,75 @@ VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) { { Declarations::NodeScopeActivator scope(declarations(), expr->left); Label* true_label = declarations()->LookupLabel(kTrueLabelName); - GenerateLabelDefinition(true_label); + CreateBlockForLabel(true_label, assembler().CurrentStack()); left_result = Visit(expr->left); if (left_result.type()->IsBool()) { Label* false_label = declarations()->LookupLabel(kFalseLabelName); - GenerateIndent(); - source_out() << "GotoIfNot(" << RValueFlattenStructs(left_result) << ", " - << false_label->generated() << ");\n"; + assembler().Branch(true_label->block(), false_label->block()); + assembler().Bind(true_label->block()); + } else if (left_result.type()->IsNever()) { + assembler().Bind(true_label->block()); } else if (!left_result.type()->IsConstexprBool()) { - GenerateLabelBind(true_label); + ReportError( + "expected type bool, constexpr bool, or never on left-hand side of " + "operator &&"); } } - VisitResult right_result = Visit(expr->right); - if (right_result.type() != left_result.type()) { - std::stringstream stream; - stream - << "types of left and right expression of logical AND don't match (\"" - << *left_result.type() << "\" vs. \"" << *right_result.type() << "\")"; - ReportError(stream.str()); - } + if (left_result.type()->IsConstexprBool()) { - return VisitResult(left_result.type(), - std::string("(") + RValueFlattenStructs(left_result) + - " && " + RValueFlattenStructs(right_result) + ")"); - } else { - return right_result; + VisitResult right_result = Visit(expr->right); + if (!right_result.type()->IsConstexprBool()) { + ReportError( + "expected type constexpr bool on right-hand side of operator " + "&&"); + } + return VisitResult(TypeOracle::GetConstexprBoolType(), + std::string("(") + left_result.constexpr_value() + + " && " + right_result.constexpr_value() + ")"); + } + + VisitResult right_result = Visit(expr->right); + if (right_result.type()->IsBool()) { + Label* true_label = declarations()->LookupLabel(kTrueLabelName); + Label* false_label = declarations()->LookupLabel(kFalseLabelName); + assembler().Branch(true_label->block(), false_label->block()); + return VisitResult::NeverResult(); + } else if (!right_result.type()->IsNever()) { + ReportError( + "expected type bool or never on right-hand side of operator &&"); } + return right_result; } VisitResult ImplementationVisitor::Visit(IncrementDecrementExpression* expr) { - VisitResult value_copy; - auto location_ref = GetLocationReference(expr->location); - VisitResult current_value = - GenerateFetchFromLocation(expr->location, location_ref); - if (expr->postfix) { - value_copy = GenerateCopy(current_value); - } + StackScope scope(this); + LocationReference location_ref = GetLocationReference(expr->location); + VisitResult current_value = GenerateFetchFromLocation(location_ref); VisitResult one = {TypeOracle::GetConstInt31Type(), "1"}; Arguments args; args.parameters = {current_value, one}; VisitResult assignment_value = GenerateCall( expr->op == IncrementDecrementOperator::kIncrement ? "+" : "-", args); - GenerateAssignToLocation(expr->location, location_ref, assignment_value); - return expr->postfix ? value_copy : assignment_value; + GenerateAssignToLocation(location_ref, assignment_value); + return scope.Yield(expr->postfix ? current_value : assignment_value); } VisitResult ImplementationVisitor::Visit(AssignmentExpression* expr) { + StackScope scope(this); LocationReference location_ref = GetLocationReference(expr->location); VisitResult assignment_value; if (expr->op) { - VisitResult location_value = - GenerateFetchFromLocation(expr->location, location_ref); + VisitResult location_value = GenerateFetchFromLocation(location_ref); assignment_value = Visit(expr->value); Arguments args; args.parameters = {location_value, assignment_value}; assignment_value = GenerateCall(*expr->op, args); - GenerateAssignToLocation(expr->location, location_ref, assignment_value); + GenerateAssignToLocation(location_ref, assignment_value); } else { assignment_value = Visit(expr->value); - GenerateAssignToLocation(expr->location, location_ref, assignment_value); + GenerateAssignToLocation(location_ref, assignment_value); } - return assignment_value; + return scope.Yield(assignment_value); } VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) { @@ -513,9 +663,7 @@ VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) { result_type = declarations()->LookupType(CONST_INT32_TYPE_STRING); } } - std::string temp = GenerateNewTempVariable(result_type); - source_out() << expr->number << ";\n"; - return VisitResult{result_type, temp}; + return VisitResult{result_type, expr->number}; } VisitResult ImplementationVisitor::Visit(AssumeTypeImpossibleExpression* expr) { @@ -525,16 +673,16 @@ VisitResult ImplementationVisitor::Visit(AssumeTypeImpossibleExpression* expr) { if (result_type->IsNever()) { ReportError("unreachable code"); } - return VisitResult{result_type, "UncheckedCast<" + - result_type->GetGeneratedTNodeTypeName() + - ">(" + result.RValue() + ")"}; + CHECK_EQ(LowerType(result_type), TypeVector{result_type}); + assembler().Emit(UnsafeCastInstruction{result_type}); + result.SetType(result_type); + return result; } VisitResult ImplementationVisitor::Visit(StringLiteralExpression* expr) { - std::string temp = GenerateNewTempVariable(TypeOracle::GetConstStringType()); - source_out() << "\"" << expr->literal.substr(1, expr->literal.size() - 2) - << "\";\n"; - return VisitResult{TypeOracle::GetConstStringType(), temp}; + return VisitResult{ + TypeOracle::GetConstStringType(), + "\"" + expr->literal.substr(1, expr->literal.size() - 2) + "\""}; } VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) { @@ -546,13 +694,12 @@ VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) { const Type* type = TypeOracle::GetFunctionPointerType( builtin->signature().parameter_types.types, builtin->signature().return_type); - std::string code = - "HeapConstant(Builtins::CallableFor(isolate(), Builtins::k" + - builtin->name() + ").code())"; - return VisitResult(type, code); + assembler().Emit(PushCodePointerInstruction{builtin->name(), type}); + return VisitResult(type, assembler().TopRange(1)); } VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) { + StackScope scope(this); std::string name = expr->name; if (expr->generic_arguments.size() != 0) { GenericList* generic_list = declarations()->LookupGeneric(expr->name); @@ -567,10 +714,10 @@ VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) { } if (Builtin* builtin = Builtin::DynamicCast(declarations()->Lookup(name))) { - return GetBuiltinCode(builtin); + return scope.Yield(GetBuiltinCode(builtin)); } - return GenerateFetchFromLocation(expr, GetLocationReference(expr)); + return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr))); } const Type* ImplementationVisitor::Visit(GotoStatement* stmt) { @@ -585,20 +732,21 @@ const Type* ImplementationVisitor::Visit(GotoStatement* stmt) { } size_t i = 0; + StackRange arguments = assembler().TopRange(0); for (Expression* e : stmt->arguments) { + StackScope scope(this); VisitResult result = Visit(e); Variable* var = label->GetParameter(i++); - GenerateAssignToVariable(var, result); + result = GenerateImplicitConvert(var->type(), result); + arguments.Extend(scope.Yield(result).stack_range()); } - GenerateLabelGoto(label); + GenerateLabelGoto(label, arguments); label->MarkUsed(); return TypeOracle::GetNeverType(); } const Type* ImplementationVisitor::Visit(IfStatement* stmt) { - ScopedIndent indent(this); - bool has_else = stmt->if_false.has_value(); if (stmt->is_constexpr) { @@ -611,23 +759,33 @@ const Type* ImplementationVisitor::Visit(IfStatement* stmt) { ReportError(stream.str()); } + Block* true_block = assembler().NewBlock(); + Block* false_block = assembler().NewBlock(); + Block* done_block = assembler().NewBlock(); + + assembler().Emit(ConstexprBranchInstruction{ + expression_result.constexpr_value(), true_block, false_block}); + + assembler().Bind(true_block); const Type* left_result; - const Type* right_result = TypeOracle::GetVoidType(); { - GenerateIndent(); - source_out() << "if ((" << RValueFlattenStructs(expression_result) - << ")) "; - ScopedIndent indent(this, false); - source_out() << "\n"; + StackScope stack_scope(this); left_result = Visit(stmt->if_true); } + if (left_result == TypeOracle::GetVoidType()) { + assembler().Goto(done_block); + } + assembler().Bind(false_block); + const Type* right_result = TypeOracle::GetVoidType(); if (has_else) { - source_out() << " else "; - ScopedIndent indent(this, false); - source_out() << "\n"; + StackScope stack_scope(this); right_result = Visit(*stmt->if_false); } + if (right_result == TypeOracle::GetVoidType()) { + assembler().Goto(done_block); + } + if (left_result->IsNever() != right_result->IsNever()) { std::stringstream stream; stream << "either both or neither branches in a constexpr if statement " @@ -636,8 +794,9 @@ const Type* ImplementationVisitor::Visit(IfStatement* stmt) { ReportError(stream.str()); } - source_out() << "\n"; - + if (left_result != TypeOracle::GetNeverType()) { + assembler().Bind(done_block); + } return left_result; } else { Label* true_label = nullptr; @@ -645,56 +804,54 @@ const Type* ImplementationVisitor::Visit(IfStatement* stmt) { { Declarations::NodeScopeActivator scope(declarations(), &*stmt->condition); true_label = declarations()->LookupLabel(kTrueLabelName); - GenerateLabelDefinition(true_label); + CreateBlockForLabel(true_label, assembler().CurrentStack()); false_label = declarations()->LookupLabel(kFalseLabelName); - GenerateLabelDefinition(false_label, !has_else ? stmt : nullptr); + CreateBlockForLabel(false_label, assembler().CurrentStack()); } - Label* done_label = nullptr; + Block* done_block; bool live = false; if (has_else) { - done_label = declarations()->DeclarePrivateLabel("if_done_label"); - GenerateLabelDefinition(done_label, stmt); + done_block = assembler().NewBlock(); } else { - done_label = false_label; + done_block = false_label->block(); live = true; } std::vector<Statement*> blocks = {stmt->if_true}; std::vector<Label*> labels = {true_label, false_label}; if (has_else) blocks.push_back(*stmt->if_false); - if (GenerateExpressionBranch(stmt->condition, labels, blocks, done_label)) { + if (GenerateExpressionBranch(stmt->condition, labels, blocks, done_block)) { live = true; } if (live) { - GenerateLabelBind(done_label); + assembler().Bind(done_block); } return live ? TypeOracle::GetVoidType() : TypeOracle::GetNeverType(); } } const Type* ImplementationVisitor::Visit(WhileStatement* stmt) { - ScopedIndent indent(this); - Label* body_label = nullptr; Label* exit_label = nullptr; { Declarations::NodeScopeActivator scope(declarations(), stmt->condition); body_label = declarations()->LookupLabel(kTrueLabelName); - GenerateLabelDefinition(body_label); + CreateBlockForLabel(body_label, assembler().CurrentStack()); exit_label = declarations()->LookupLabel(kFalseLabelName); - GenerateLabelDefinition(exit_label); + CreateBlockForLabel(exit_label, assembler().CurrentStack()); } - Label* header_label = declarations()->DeclarePrivateLabel("header"); - GenerateLabelDefinition(header_label, stmt); - GenerateLabelGoto(header_label); - GenerateLabelBind(header_label); + Block* header_block = assembler().NewBlock(); + assembler().Goto(header_block); + + assembler().Bind(header_block); Declarations::NodeScopeActivator scope(declarations(), stmt->body); - BreakContinueActivator activator(global_context_, exit_label, header_label); + BreakContinueActivator activator(global_context_, exit_label->block(), + header_block); GenerateExpressionBranch(stmt->condition, {body_label, exit_label}, - {stmt->body}, header_label); + {stmt->body}, header_block); GenerateLabelBind(exit_label); return TypeOracle::GetVoidType(); @@ -702,7 +859,6 @@ const Type* ImplementationVisitor::Visit(WhileStatement* stmt) { const Type* ImplementationVisitor::Visit(BlockStatement* block) { Declarations::NodeScopeActivator scope(declarations(), block); - ScopedIndent indent(this); const Type* type = TypeOracle::GetVoidType(); for (Statement* s : block->statements) { if (type->IsNever()) { @@ -717,17 +873,14 @@ const Type* ImplementationVisitor::Visit(BlockStatement* block) { const Type* ImplementationVisitor::Visit(DebugStatement* stmt) { #if defined(DEBUG) - GenerateIndent(); - source_out() << "Print(\"" - << "halting because of '" << stmt->reason << "' at " - << PositionAsString(stmt->pos) << "\");\n"; + assembler().Emit(PrintConstantStringInstruction{"halting because of '" + + stmt->reason + "' at " + + PositionAsString(stmt->pos)}); #endif - GenerateIndent(); + assembler().Emit(DebugBreakInstruction{stmt->never_continues}); if (stmt->never_continues) { - source_out() << "Unreachable();\n"; return TypeOracle::GetNeverType(); } else { - source_out() << "DebugBreak();\n"; return TypeOracle::GetVoidType(); } } @@ -769,9 +922,9 @@ const Type* ImplementationVisitor::Visit(AssertStatement* stmt) { Label* false_label = nullptr; Declarations::NodeScopeActivator scope(declarations(), stmt->expression); true_label = declarations()->LookupLabel(kTrueLabelName); - GenerateLabelDefinition(true_label); + CreateBlockForLabel(true_label, assembler().CurrentStack()); false_label = declarations()->LookupLabel(kFalseLabelName); - GenerateLabelDefinition(false_label); + CreateBlockForLabel(false_label, assembler().CurrentStack()); VisitResult expression_result = Visit(stmt->expression); if (expression_result.type() == TypeOracle::GetBoolType()) { @@ -786,12 +939,10 @@ const Type* ImplementationVisitor::Visit(AssertStatement* stmt) { } GenerateLabelBind(false_label); - GenerateIndent(); - source_out() << "Print(\"" - << "assert '" << FormatAssertSource(stmt->source) - << "' failed at " << PositionAsString(stmt->pos) << "\");\n"; - GenerateIndent(); - source_out() << "Unreachable();\n"; + assembler().Emit(PrintConstantStringInstruction{ + "assert '" + FormatAssertSource(stmt->source) + "' failed at " + + PositionAsString(stmt->pos)}); + assembler().Emit(DebugBreakInstruction{true}); GenerateLabelBind(true_label); } @@ -824,20 +975,16 @@ const Type* ImplementationVisitor::Visit(ReturnStatement* stmt) { VisitResult return_result = GenerateImplicitConvert( current_callable->signature().return_type, expression_result); if (current_callable->IsMacro()) { - Variable* var = - Variable::cast(declarations()->LookupValue(kReturnValueVariable)); - GenerateAssignToVariable(var, return_result); - GenerateLabelGoto(end); - } else if (current_callable->IsBuiltin()) { - if (Builtin::cast(current_callable)->IsVarArgsJavaScript()) { - GenerateIndent(); - source_out() << "arguments->PopAndReturn(" - << RValueFlattenStructs(return_result) << ");\n"; + if (return_result.IsOnStack()) { + StackRange return_value_range = + GenerateLabelGoto(end, return_result.stack_range()); + SetReturnValue(VisitResult(return_result.type(), return_value_range)); } else { - GenerateIndent(); - source_out() << "Return(" << RValueFlattenStructs(return_result) - << ");\n"; + GenerateLabelGoto(end); + SetReturnValue(return_result); } + } else if (current_callable->IsBuiltin()) { + assembler().Emit(ReturnInstruction{}); } else { UNREACHABLE(); } @@ -856,6 +1003,7 @@ const Type* ImplementationVisitor::Visit(ReturnStatement* stmt) { const Type* ImplementationVisitor::Visit(ForOfLoopStatement* stmt) { Declarations::NodeScopeActivator scope(declarations(), stmt); + StackScope stack_scope(this); VisitResult expression_result = Visit(stmt->iterable); VisitResult begin = stmt->begin @@ -866,194 +1014,207 @@ const Type* ImplementationVisitor::Visit(ForOfLoopStatement* stmt) { ? Visit(*stmt->end) : GenerateCall(".length", {{expression_result}, {}}); - Label* body_label = declarations()->DeclarePrivateLabel("body"); - GenerateLabelDefinition(body_label); - Label* increment_label = declarations()->DeclarePrivateLabel("increment"); - GenerateLabelDefinition(increment_label); - Label* exit_label = declarations()->DeclarePrivateLabel("exit"); - GenerateLabelDefinition(exit_label); - const Type* common_type = GetCommonType(begin.type(), end.type()); - Variable* index_var = GenerateVariableDeclaration( - stmt, std::string(kForIndexValueVariable) + "_" + NewTempVariable(), - false, common_type, begin); + VisitResult index = GenerateImplicitConvert(common_type, begin); - VisitResult index_for_read = {index_var->type(), index_var}; + Block* body_block = assembler().NewBlock(); + Block* increment_block = assembler().NewBlock(assembler().CurrentStack()); + Block* exit_block = assembler().NewBlock(assembler().CurrentStack()); - Label* header_label = declarations()->DeclarePrivateLabel("header"); - GenerateLabelDefinition(header_label, stmt); + Block* header_block = assembler().NewBlock(); - GenerateLabelGoto(header_label); + assembler().Goto(header_block); - GenerateLabelBind(header_label); + assembler().Bind(header_block); - BreakContinueActivator activator(global_context_, exit_label, - increment_label); + BreakContinueActivator activator(global_context_, exit_block, + increment_block); - VisitResult result = GenerateCall("<", {{index_for_read, end}, {}}); - GenerateBranch(result, body_label, exit_label); + { + StackScope comparison_scope(this); + VisitResult result = GenerateCall("<", {{index, end}, {}}); + if (result.type() != TypeOracle::GetBoolType()) { + ReportError("operator < with arguments(", *index.type(), ", ", + *end.type(), + ") used in for-of loop has to return type bool, but " + "returned type ", + *result.type()); + } + comparison_scope.Yield(result); + } + assembler().Branch(body_block, exit_block); - GenerateLabelBind(body_label); - VisitResult element_result = - GenerateCall("[]", {{expression_result, index_for_read}, {}}); - base::Optional<const Type*> declared_type; - if (stmt->var_declaration->type) - declared_type = declarations()->GetType(*stmt->var_declaration->type); - GenerateVariableDeclaration( - stmt->var_declaration, stmt->var_declaration->name, - stmt->var_declaration->const_qualified, declared_type, element_result); - Visit(stmt->body); - GenerateLabelGoto(increment_label); + assembler().Bind(body_block); + { + StackScope body_scope(this); - GenerateLabelBind(increment_label); - Arguments increment_args; - increment_args.parameters = {index_for_read, - {TypeOracle::GetConstInt31Type(), "1"}}; - VisitResult increment_result = GenerateCall("+", increment_args); + VisitResult element_result; + { + StackScope element_scope(this); + VisitResult result = GenerateCall("[]", {{expression_result, index}, {}}); + if (stmt->var_declaration->type) { + const Type* declared_type = + declarations()->GetType(*stmt->var_declaration->type); + result = GenerateImplicitConvert(declared_type, result); + } + element_result = element_scope.Yield(result); + } + Variable* element_var = Variable::cast( + declarations()->LookupValue(stmt->var_declaration->name)); + element_var->set_value(element_result); + Visit(stmt->body); + } + assembler().Goto(increment_block); + + assembler().Bind(increment_block); + { + Arguments increment_args; + increment_args.parameters = {index, {TypeOracle::GetConstInt31Type(), "1"}}; + VisitResult increment_result = GenerateCall("+", increment_args); - GenerateAssignToVariable(index_var, increment_result); + GenerateAssignToLocation(LocationReference::VariableAccess(index), + increment_result); + } - GenerateLabelGoto(header_label); + assembler().Goto(header_block); - GenerateLabelBind(exit_label); + assembler().Bind(exit_block); return TypeOracle::GetVoidType(); } -const Type* ImplementationVisitor::Visit(TryLabelStatement* stmt) { - ScopedIndent indent(this); - Label* try_done = declarations()->DeclarePrivateLabel("try_done"); - GenerateLabelDefinition(try_done); - const Type* try_result = TypeOracle::GetNeverType(); - std::vector<Label*> labels; +VisitResult ImplementationVisitor::Visit(TryLabelExpression* expr) { + Block* done_block = assembler().NewBlock(); + VisitResult try_result; + Label* label = nullptr; // Output labels for the goto handlers and for the merge after the try. { // Activate a new scope to see handler labels - Declarations::NodeScopeActivator scope(declarations(), stmt); - for (LabelBlock* block : stmt->label_blocks) { - CurrentSourcePosition::Scope scope(block->pos); - Label* label = declarations()->LookupLabel(block->label); - labels.push_back(label); - GenerateLabelDefinition(label); - } - - size_t i = 0; - for (auto label : labels) { - Declarations::NodeScopeActivator scope(declarations(), - stmt->label_blocks[i]->body); - for (auto& v : label->GetParameters()) { - GenerateVariableDeclaration(stmt, v->name(), false, v->type()); + Declarations::NodeScopeActivator scope(declarations(), expr); + { + LabelBlock* block = expr->label_block; + CurrentSourcePosition::Scope source_position(block->pos); + label = declarations()->LookupLabel(block->label); + + Declarations::NodeScopeActivator scope(declarations(), block->body); + Stack<const Type*> label_input_stack = assembler().CurrentStack(); + for (Variable* v : label->GetParameters()) { + StackRange range = label_input_stack.PushMany(LowerType(v->type())); + v->set_value(VisitResult(v->type(), range)); v->Define(); } - ++i; + CreateBlockForLabel(label, label_input_stack); } - Label* try_begin_label = declarations()->DeclarePrivateLabel("try_begin"); - GenerateLabelDefinition(try_begin_label); - GenerateLabelGoto(try_begin_label); - // Visit try - if (GenerateLabeledStatementBlocks({stmt->try_block}, - std::vector<Label*>({try_begin_label}), - try_done)) { - try_result = TypeOracle::GetVoidType(); + { + StackScope stack_scope(this); + try_result = Visit(expr->try_expression); + if (try_result.type() != TypeOracle::GetNeverType()) { + try_result = stack_scope.Yield(try_result); + assembler().Goto(done_block); + } } } - // Make sure that each label clause is actually used. It's not just a friendly - // thing to do, it will cause problems downstream in the compiler if there are - // bound labels that are never jumped to. - auto label_iterator = stmt->label_blocks.begin(); - for (auto label : labels) { - CurrentSourcePosition::Scope scope((*label_iterator)->pos); - if (!label->IsUsed()) { - std::stringstream s; - s << "label "; - s << (*label_iterator)->label; - s << " has a handler block but is never referred to in try block"; - ReportError(s.str()); + if (label->IsUsed()) { + // Visit and output the code for the label block. If the label block falls + // through, then the try must not return a value. Also, if the try doesn't + // fall through, but the label does, then overall the try-label block + // returns type void. + GenerateLabelBind(label); + const Type* label_result; + { + StackScope stack_scope(this); + label_result = Visit(expr->label_block->body); + } + if (!try_result.type()->IsVoidOrNever() && label_result->IsVoid()) { + ReportError( + "otherwise clauses cannot fall through in a non-void expression"); + } + if (label_result != TypeOracle::GetNeverType()) { + assembler().Goto(done_block); + } + if (label_result->IsVoid() && try_result.type()->IsNever()) { + try_result = + VisitResult(TypeOracle::GetVoidType(), try_result.stack_range()); } - label_iterator++; - } - - // Visit and output the code for each catch block, one-by-one. - std::vector<Statement*> bodies; - for (LabelBlock* block : stmt->label_blocks) bodies.push_back(block->body); - if (GenerateLabeledStatementBlocks(bodies, labels, try_done)) { - try_result = TypeOracle::GetVoidType(); } - if (!try_result->IsNever()) { - GenerateLabelBind(try_done); + if (!try_result.type()->IsNever()) { + assembler().Bind(done_block); } return try_result; } +VisitResult ImplementationVisitor::Visit(StatementExpression* expr) { + return VisitResult{Visit(expr->statement), assembler().TopRange(0)}; +} + const Type* ImplementationVisitor::Visit(BreakStatement* stmt) { - Label* break_label = global_context_.GetCurrentBreak(); - if (break_label == nullptr) { + Block* break_block = global_context_.GetCurrentBreak(); + if (break_block == nullptr) { ReportError("break used outside of loop"); } - GenerateLabelGoto(break_label); + assembler().Goto(break_block); return TypeOracle::GetNeverType(); } const Type* ImplementationVisitor::Visit(ContinueStatement* stmt) { - Label* continue_label = global_context_.GetCurrentContinue(); - if (continue_label == nullptr) { + Block* continue_block = global_context_.GetCurrentContinue(); + if (continue_block == nullptr) { ReportError("continue used outside of loop"); } - GenerateLabelGoto(continue_label); + assembler().Goto(continue_block); return TypeOracle::GetNeverType(); } const Type* ImplementationVisitor::Visit(ForLoopStatement* stmt) { Declarations::NodeScopeActivator scope(declarations(), stmt); + StackScope stack_scope(this); if (stmt->var_declaration) Visit(*stmt->var_declaration); Label* body_label = declarations()->LookupLabel(kTrueLabelName); - GenerateLabelDefinition(body_label); + CreateBlockForLabel(body_label, assembler().CurrentStack()); Label* exit_label = declarations()->LookupLabel(kFalseLabelName); - GenerateLabelDefinition(exit_label); + CreateBlockForLabel(exit_label, assembler().CurrentStack()); - Label* header_label = declarations()->DeclarePrivateLabel("header"); - GenerateLabelDefinition(header_label, stmt); - GenerateLabelGoto(header_label); - GenerateLabelBind(header_label); + Block* header_block = assembler().NewBlock(); + assembler().Goto(header_block); + assembler().Bind(header_block); // The continue label is where "continue" statements jump to. If no action // expression is provided, we jump directly to the header. - Label* continue_label = header_label; + Block* continue_block = header_block; // The action label is only needed when an action expression was provided. - Label* action_label = nullptr; + Block* action_block = nullptr; if (stmt->action) { - action_label = declarations()->DeclarePrivateLabel("action"); - GenerateLabelDefinition(action_label); + action_block = assembler().NewBlock(); // The action expression needs to be executed on a continue. - continue_label = action_label; + continue_block = action_block; } - BreakContinueActivator activator(global_context_, exit_label, continue_label); + BreakContinueActivator activator(global_context_, exit_label->block(), + continue_block); std::vector<Label*> labels = {body_label, exit_label}; bool generate_action = true; if (stmt->test) { generate_action = GenerateExpressionBranch(*stmt->test, labels, - {stmt->body}, continue_label); + {stmt->body}, continue_block); } else { GenerateLabelGoto(body_label); generate_action = - GenerateLabeledStatementBlocks({stmt->body}, labels, continue_label); + GenerateLabeledStatementBlocks({stmt->body}, labels, continue_block); } if (generate_action && stmt->action) { - ScopedIndent indent(this); - GenerateLabelBind(action_label); + assembler().Bind(action_block); Visit(*stmt->action); - GenerateLabelGoto(header_label); + assembler().Goto(header_block); } GenerateLabelBind(exit_label); @@ -1075,7 +1236,7 @@ void ImplementationVisitor::GenerateImplementation(const std::string& dir, std::string ImplementationVisitor::GetBaseAssemblerName(Module* module) { if (module == global_context_.GetDefaultModule()) { - return "CodeStubAssembler"; + return "TorqueAssembler"; } else { std::string assembler_name(CamelifyString(module->name()) + "BuiltinsAssembler"); @@ -1089,12 +1250,6 @@ std::string ImplementationVisitor::GetDSLAssemblerName(Module* module) { return assembler_name; } -void ImplementationVisitor::GenerateIndent() { - for (size_t i = 0; i <= indent_; ++i) { - source_out() << " "; - } -} - void ImplementationVisitor::GenerateMacroFunctionDeclaration( std::ostream& o, const std::string& macro_prefix, Macro* macro) { GenerateFunctionDeclaration(o, macro_prefix, macro->name(), @@ -1128,11 +1283,12 @@ void ImplementationVisitor::GenerateFunctionDeclaration( if (!first) { o << ", "; } - const Value* parameter = declarations()->LookupValue(name); + const Parameter* parameter = + Parameter::cast(declarations()->LookupValue(name)); const Type* parameter_type = *type_iterator; const std::string& generated_type_name = parameter_type->GetGeneratedTypeName(); - o << generated_type_name << " " << parameter->value(); + o << generated_type_name << " " << parameter->external_name(); type_iterator++; first = false; } @@ -1142,13 +1298,15 @@ void ImplementationVisitor::GenerateFunctionDeclaration( if (!first) { o << ", "; } - o << "Label* " << label->generated(); + o << "Label* " << label->external_label_name(); + size_t i = 0; for (Variable* var : label->GetParameters()) { std::string generated_type_name("TVariable<"); generated_type_name += var->type()->GetGeneratedTNodeTypeName(); generated_type_name += ">*"; o << ", "; - o << generated_type_name << " " << var->value(); + o << generated_type_name << " " << ExternalLabelParameterName(label, i); + ++i; } } @@ -1280,43 +1438,6 @@ Callable* ImplementationVisitor::LookupCall( return result; } -void ImplementationVisitor::GetFlattenedStructsVars( - const Variable* base, std::set<const Variable*>* vars) { - const Type* type = base->type(); - if (base->IsConst()) return; - if (type->IsStructType()) { - const StructType* struct_type = StructType::cast(type); - for (auto& field : struct_type->fields()) { - std::string field_var_name = base->name() + "." + field.name; - GetFlattenedStructsVars( - Variable::cast(declarations()->LookupValue(field_var_name)), vars); - } - } else { - vars->insert(base); - } -} - -void ImplementationVisitor::GenerateChangedVarsFromControlSplit(AstNode* node) { - const std::set<const Variable*>& changed_vars = - global_context_.GetControlSplitChangedVariables( - node, declarations()->GetCurrentSpecializationTypeNamesVector()); - std::set<const Variable*> flattened_vars; - for (auto v : changed_vars) { - GetFlattenedStructsVars(v, &flattened_vars); - } - std::vector<const Variable*> flattened_vars_sorted(flattened_vars.begin(), - flattened_vars.end()); - auto compare_variables = [](const Variable* a, const Variable* b) { - return a->value() < b->value(); - }; - std::sort(flattened_vars_sorted.begin(), flattened_vars_sorted.end(), - compare_variables); - source_out() << "{"; - PrintCommaSeparatedList(source_out(), flattened_vars_sorted, - [](const Variable* v) { return v->value(); }); - source_out() << "}"; -} - const Type* ImplementationVisitor::GetCommonType(const Type* left, const Type* right) { const Type* common_type; @@ -1332,11 +1453,11 @@ const Type* ImplementationVisitor::GetCommonType(const Type* left, } VisitResult ImplementationVisitor::GenerateCopy(const VisitResult& to_copy) { - std::string temp = GenerateNewTempVariable(to_copy.type()); - source_out() << RValueFlattenStructs(to_copy) << ";\n"; - GenerateIndent(); - source_out() << "USE(" << temp << ");\n"; - return VisitResult(to_copy.type(), temp); + if (to_copy.IsOnStack()) { + return VisitResult(to_copy.type(), + assembler().Peek(to_copy.stack_range(), to_copy.type())); + } + return to_copy; } VisitResult ImplementationVisitor::Visit(StructExpression* decl) { @@ -1354,23 +1475,19 @@ VisitResult ImplementationVisitor::Visit(StructExpression* decl) { << ")"; ReportError(s.str()); } - std::vector<VisitResult> expression_results; - for (auto& field : struct_type->fields()) { - VisitResult value = Visit(decl->expressions[expression_results.size()]); + StackRange stack_range = assembler().TopRange(0); + for (size_t i = 0; i < struct_type->fields().size(); ++i) { + const NameAndType& field = struct_type->fields()[i]; + StackScope scope(this); + VisitResult value = Visit(decl->expressions[i]); value = GenerateImplicitConvert(field.type, value); - expression_results.push_back(value); + stack_range.Extend(scope.Yield(value).stack_range()); } - std::string result_var_name = GenerateNewTempVariable(struct_type); - source_out() << "{"; - PrintCommaSeparatedList( - source_out(), expression_results, - [&](const VisitResult& result) { return RValueFlattenStructs(result); }); - source_out() << "};\n"; - return VisitResult(struct_type, result_var_name); + return VisitResult(struct_type, stack_range); } LocationReference ImplementationVisitor::GetLocationReference( - LocationExpression* location) { + Expression* location) { switch (location->kind) { case AstNode::Kind::kIdentifierExpression: return GetLocationReference(static_cast<IdentifierExpression*>(location)); @@ -1381,231 +1498,92 @@ LocationReference ImplementationVisitor::GetLocationReference( return GetLocationReference( static_cast<ElementAccessExpression*>(location)); default: - UNREACHABLE(); + return LocationReference::Temporary(Visit(location), "expression"); } } LocationReference ImplementationVisitor::GetLocationReference( FieldAccessExpression* expr) { - VisitResult result = Visit(expr->object); - if (result.type()->IsStructType()) { - if (result.declarable()) { - return LocationReference( - declarations()->LookupValue((*result.declarable())->name() + "." + - expr->field), - {}, {}); - } + LocationReference reference = GetLocationReference(expr->object); + if (reference.IsVariableAccess() && + reference.variable().type()->IsStructType()) { + return LocationReference::VariableAccess( + ProjectStructField(reference.variable(), expr->field)); } - return LocationReference(nullptr, result, {}); -} - -std::string ImplementationVisitor::RValueFlattenStructs(VisitResult result) { - if (result.declarable()) { - const Value* value = *result.declarable(); - const Type* type = value->type(); - if (const StructType* struct_type = StructType::DynamicCast(type)) { - std::stringstream s; - s << struct_type->name() << "{"; - PrintCommaSeparatedList( - s, struct_type->fields(), [&](const NameAndType& field) { - std::string field_declaration = value->name() + "." + field.name; - Variable* field_variable = - Variable::cast(declarations()->LookupValue(field_declaration)); - return RValueFlattenStructs( - VisitResult(field_variable->type(), field_variable)); - }); - s << "}"; - return s.str(); - } + if (reference.IsTemporary() && reference.temporary().type()->IsStructType()) { + return LocationReference::Temporary( + ProjectStructField(reference.temporary(), expr->field), + reference.temporary_description()); } - return result.RValue(); + return LocationReference::FieldAccess(GenerateFetchFromLocation(reference), + expr->field); } -VisitResult ImplementationVisitor::GenerateFetchFromLocation( - LocationExpression* location, LocationReference reference) { - switch (location->kind) { - case AstNode::Kind::kIdentifierExpression: - return GenerateFetchFromLocation( - static_cast<IdentifierExpression*>(location), reference); - case AstNode::Kind::kFieldAccessExpression: - return GenerateFetchFromLocation( - static_cast<FieldAccessExpression*>(location), reference); - case AstNode::Kind::kElementAccessExpression: - return GenerateFetchFromLocation( - static_cast<ElementAccessExpression*>(location), reference); - default: - UNREACHABLE(); - } -} - -VisitResult ImplementationVisitor::GenerateFetchFromLocation( - FieldAccessExpression* expr, LocationReference reference) { - if (reference.value != nullptr) { - return GenerateFetchFromLocation(reference); - } - const Type* type = reference.base.type(); - if (const StructType* struct_type = StructType::DynamicCast(type)) { - return VisitResult(struct_type->GetFieldType(expr->field), - reference.base.RValue() + "." + expr->field); - } else { - Arguments arguments; - arguments.parameters = {reference.base}; - return GenerateCall(std::string(".") + expr->field, arguments); - } +LocationReference ImplementationVisitor::GetLocationReference( + ElementAccessExpression* expr) { + VisitResult array = Visit(expr->array); + VisitResult index = Visit(expr->index); + return LocationReference::ArrayAccess(array, index); } -void ImplementationVisitor::GenerateAssignToVariable(Variable* var, - VisitResult value) { - if (var->type()->IsStructType()) { - if (value.type() != var->type()) { - std::stringstream s; - s << "incompatable assignment from type " << *value.type() << " to " - << *var->type(); - ReportError(s.str()); - } - const StructType* struct_type = StructType::cast(var->type()); - for (auto& field : struct_type->fields()) { - std::string field_declaration = var->name() + "." + field.name; - Variable* field_variable = - Variable::cast(declarations()->LookupValue(field_declaration)); - if (value.declarable() && (*value.declarable())->IsVariable()) { - Variable* source_field = Variable::cast(declarations()->LookupValue( - Variable::cast((*value.declarable()))->name() + "." + field.name)); - GenerateAssignToVariable( - field_variable, VisitResult{source_field->type(), source_field}); - } else { - GenerateAssignToVariable( - field_variable, VisitResult{field_variable->type(), - value.RValue() + "." + field.name}); - } +LocationReference ImplementationVisitor::GetLocationReference( + IdentifierExpression* expr) { + Value* value = declarations()->LookupValue(expr->name); + if (auto* constant = ModuleConstant::DynamicCast(value)) { + if (constant->type()->IsConstexpr()) { + return LocationReference::Temporary( + VisitResult(constant->type(), constant->constant_name() + "()"), + "module constant " + expr->name); } - } else { - VisitResult casted_value = GenerateImplicitConvert(var->type(), value); - GenerateIndent(); - VisitResult var_value = {var->type(), var}; - source_out() << var_value.LValue() << " = " - << RValueFlattenStructs(casted_value) << ";\n"; + assembler().Emit(ModuleConstantInstruction{constant}); + StackRange stack_range = + assembler().TopRange(LoweredSlotCount(constant->type())); + return LocationReference::Temporary( + VisitResult(constant->type(), stack_range), + "module constant " + expr->name); } - var->Define(); -} - -void ImplementationVisitor::GenerateAssignToLocation( - LocationExpression* location, const LocationReference& reference, - VisitResult assignment_value) { - if (reference.value != nullptr) { - Value* value = reference.value; - Variable* var = Variable::cast(value); - if (var->IsConst()) { - std::stringstream s; - s << "\"" << var->name() - << "\" is declared const (maybe implicitly) and cannot be assigned to"; - ReportError(s.str()); - } - GenerateAssignToVariable(var, assignment_value); - } else if (auto access = FieldAccessExpression::DynamicCast(location)) { - GenerateCall(std::string(".") + access->field + "=", - {{reference.base, assignment_value}, {}}); - } else { - DCHECK_NOT_NULL(ElementAccessExpression::cast(location)); - GenerateCall("[]=", - {{reference.base, reference.index, assignment_value}, {}}); + if (value->IsConst()) { + return LocationReference::Temporary(value->value(), + "constant value " + expr->name); } + DCHECK(value->IsVariable()); + return LocationReference::VariableAccess(value->value()); } -void ImplementationVisitor::GenerateVariableDeclaration(const Variable* var) { - const Type* var_type = var->type(); - if (var_type->IsStructType()) { - const StructType* struct_type = StructType::cast(var_type); - for (auto& field : struct_type->fields()) { - GenerateVariableDeclaration(Variable::cast( - declarations()->LookupValue(var->name() + "." + field.name))); - } +VisitResult ImplementationVisitor::GenerateFetchFromLocation( + const LocationReference& reference) { + if (reference.IsTemporary()) { + return GenerateCopy(reference.temporary()); + } else if (reference.IsVariableAccess()) { + return GenerateCopy(reference.variable()); } else { - std::string value = var->value(); - GenerateIndent(); - if (var_type->IsConstexpr()) { - source_out() << var_type->GetGeneratedTypeName(); - source_out() << " " << value << "_impl;\n"; - } else if (var->IsConst()) { - source_out() << "TNode<" << var->type()->GetGeneratedTNodeTypeName(); - source_out() << "> " << var->value() << "_impl;\n"; - } else { - source_out() << "TVARIABLE("; - source_out() << var_type->GetGeneratedTNodeTypeName(); - source_out() << ", " << value << "_impl);\n"; - } - GenerateIndent(); - source_out() << "auto " << value << " = &" << value << "_impl;\n"; - GenerateIndent(); - source_out() << "USE(" << value << ");\n"; - } -} - -Variable* ImplementationVisitor::GeneratePredeclaredVariableDeclaration( - const std::string& name, - const base::Optional<VisitResult>& initialization) { - Variable* variable = Variable::cast(declarations()->LookupValue(name)); - GenerateVariableDeclaration(variable); - if (initialization) { - GenerateAssignToVariable(variable, *initialization); + DCHECK(reference.IsCallAccess()); + return GenerateCall(reference.eval_function(), + Arguments{reference.call_arguments(), {}}); } - return variable; } -Variable* ImplementationVisitor::GenerateVariableDeclaration( - AstNode* node, const std::string& name, bool is_const, - const base::Optional<const Type*>& type, - const base::Optional<VisitResult>& initialization) { - Variable* variable = nullptr; - if (declarations()->IsDeclaredInCurrentScope(name)) { - variable = Variable::cast(declarations()->LookupValue(name)); +void ImplementationVisitor::GenerateAssignToLocation( + const LocationReference& reference, const VisitResult& assignment_value) { + if (reference.IsCallAccess()) { + Arguments arguments{reference.call_arguments(), {}}; + arguments.parameters.push_back(assignment_value); + GenerateCall(reference.assign_function(), arguments); + } else if (reference.IsVariableAccess()) { + VisitResult variable = reference.variable(); + VisitResult converted_value = + GenerateImplicitConvert(variable.type(), assignment_value); + assembler().Poke(variable.stack_range(), converted_value.stack_range(), + variable.type()); } else { - variable = declarations()->DeclareVariable( - name, type ? *type : initialization->type(), is_const); - if (!is_const) { - // Because the variable is being defined during code generation, it must - // be assumed that it changes along all control split paths because it's - // no longer possible to run the control-flow anlaysis in the declaration - // pass over the variable. - global_context_.MarkVariableChanged( - node, declarations()->GetCurrentSpecializationTypeNamesVector(), - variable); - } - } - GenerateVariableDeclaration(variable); - if (initialization) { - GenerateAssignToVariable(variable, *initialization); - } - return variable; -} - -void ImplementationVisitor::GenerateParameter( - const std::string& parameter_name) { - const Value* val = declarations()->LookupValue(parameter_name); - std::string var = val->value(); - GenerateIndent(); - source_out() << val->type()->GetGeneratedTypeName() << " " << var << " = "; - - source_out() << "UncheckedCast<" << val->type()->GetGeneratedTNodeTypeName() - << ">(Parameter(Descriptor::k" << CamelifyString(parameter_name) - << "));\n"; - GenerateIndent(); - source_out() << "USE(" << var << ");\n"; -} - -void ImplementationVisitor::GenerateParameterList(const NameVector& list, - size_t first) { - for (auto p : list) { - if (first == 0) { - GenerateParameter(p); - } else { - first--; - } + DCHECK(reference.IsTemporary()); + ReportError("cannot assign to ", reference.temporary_description()); } } VisitResult ImplementationVisitor::GeneratePointerCall( Expression* callee, const Arguments& arguments, bool is_tailcall) { + StackScope scope(this); TypeVector parameter_types(arguments.parameters.GetTypeVector()); VisitResult callee_result = Visit(callee); if (!callee_result.type()->IsFunctionPointerType()) { @@ -1637,28 +1615,13 @@ VisitResult ImplementationVisitor::GeneratePointerCall( ReportError(stream.str()); } - std::vector<std::string> variables; + callee_result = GenerateCopy(callee_result); + StackRange arg_range = assembler().TopRange(0); for (size_t current = 0; current < arguments.parameters.size(); ++current) { const Type* to_type = type->parameter_types()[current]; - VisitResult result = - GenerateImplicitConvert(to_type, arguments.parameters[current]); - variables.push_back(RValueFlattenStructs(result)); - } - - std::string result_variable_name; - bool no_result = type->return_type()->IsVoidOrNever() || is_tailcall; - if (no_result) { - GenerateIndent(); - } else { - const Type* return_type = type->return_type(); - result_variable_name = GenerateNewTempVariable(return_type); - if (return_type->IsStructType()) { - source_out() << "("; - } else { - source_out() << "UncheckedCast<"; - source_out() << type->return_type()->GetGeneratedTNodeTypeName(); - source_out() << ">("; - } + arg_range.Extend( + GenerateImplicitConvert(to_type, arguments.parameters[current]) + .stack_range()); } Builtin* example_builtin = @@ -1669,27 +1632,14 @@ VisitResult ImplementationVisitor::GeneratePointerCall( ReportError(stream.str()); } - if (is_tailcall) { - source_out() << "TailCallStub("; - } else { - source_out() << "CallStub("; - } - source_out() << "Builtins::CallableFor(isolate(), Builtins::k" - << example_builtin->name() << ").descriptor(), " - << RValueFlattenStructs(callee_result) << ", "; + assembler().Emit(CallBuiltinPointerInstruction{is_tailcall, example_builtin, + arg_range.Size()}); - size_t total_parameters = 0; - for (size_t i = 0; i < arguments.parameters.size(); ++i) { - if (total_parameters++ != 0) { - source_out() << ", "; - } - source_out() << variables[i]; - } - if (!no_result) { - source_out() << ")"; + if (is_tailcall) { + return VisitResult::NeverResult(); } - source_out() << ");\n"; - return VisitResult(type->return_type(), result_variable_name); + DCHECK_EQ(1, LoweredSlotCount(type->return_type())); + return scope.Yield(VisitResult(type->return_type(), assembler().TopRange(1))); } VisitResult ImplementationVisitor::GenerateCall( @@ -1708,67 +1658,29 @@ VisitResult ImplementationVisitor::GenerateCall( arguments.labels.push_back(false_label); } - const Type* result_type = callable->signature().return_type; + const Type* return_type = callable->signature().return_type; - std::vector<std::string> variables; + std::vector<VisitResult> converted_arguments; + StackRange argument_range = assembler().TopRange(0); + std::vector<std::string> constexpr_arguments; for (size_t current = 0; current < arguments.parameters.size(); ++current) { const Type* to_type = (current >= callable->signature().types().size()) ? TypeOracle::GetObjectType() : callable->signature().types()[current]; - VisitResult result = + VisitResult converted = GenerateImplicitConvert(to_type, arguments.parameters[current]); - variables.push_back(RValueFlattenStructs(result)); - } - - std::string result_variable_name; - if (result_type->IsVoidOrNever() || is_tailcall) { - GenerateIndent(); - } else { - result_variable_name = GenerateNewTempVariable(result_type); - if (!result_type->IsConstexpr()) { - if (result_type->IsStructType()) { - source_out() << "("; - } else { - source_out() << "UncheckedCast<"; - source_out() << result_type->GetGeneratedTNodeTypeName(); - source_out() << ">("; - } - } - } - if (callable->IsBuiltin()) { - if (is_tailcall) { - source_out() << "TailCallBuiltin(Builtins::k" << callable->name() << ", "; + converted_arguments.push_back(converted); + if (converted.IsOnStack()) { + argument_range.Extend(converted.stack_range()); } else { - source_out() << "CallBuiltin(Builtins::k" << callable->name() << ", "; + constexpr_arguments.push_back(converted.constexpr_value()); } - } else if (callable->IsMacro()) { - if (is_tailcall) { - std::stringstream stream; - stream << "can't tail call a macro"; - ReportError(stream.str()); - } - source_out() << callable->name() << "("; - } else if (callable->IsRuntimeFunction()) { - if (is_tailcall) { - source_out() << "TailCallRuntime(Runtime::k" << callable->name() << ", "; - } else { - source_out() << "CallRuntime(Runtime::k" << callable->name() << ", "; - } - } else { - UNREACHABLE(); } + if (global_context_.verbose()) { std::cout << "generating code for call to " << callable_name << "\n"; } - size_t total_parameters = 0; - for (size_t i = 0; i < arguments.parameters.size(); ++i) { - if (total_parameters++ != 0) { - source_out() << ", "; - } - source_out() << variables[i]; - } - size_t label_count = callable->signature().labels.size(); if (label_count != arguments.labels.size()) { std::stringstream s; @@ -1777,49 +1689,114 @@ VisitResult ImplementationVisitor::GenerateCall( << std::to_string(arguments.labels.size()) << ")"; ReportError(s.str()); } - for (size_t i = 0; i < label_count; ++i) { - if (total_parameters++ != 0) { - source_out() << ", "; + + if (auto* builtin = Builtin::DynamicCast(callable)) { + assembler().Emit( + CallBuiltinInstruction{is_tailcall, builtin, argument_range.Size()}); + if (is_tailcall) { + return VisitResult::NeverResult(); + } else { + size_t slot_count = LoweredSlotCount(return_type); + DCHECK_LE(slot_count, 1); + // TODO(tebbi): Actually, builtins have to return a value, so we should + // assert slot_count == 1 here. + return VisitResult(return_type, assembler().TopRange(slot_count)); } - Label* label = arguments.labels[i]; - size_t callee_label_parameters = - callable->signature().labels[i].types.size(); - if (label->GetParameterCount() != callee_label_parameters) { - std::stringstream s; - s << "label " << label->name() - << " doesn't have the right number of parameters (found " - << std::to_string(label->GetParameterCount()) << " expected " - << std::to_string(callee_label_parameters) << ")"; - ReportError(s.str()); + } else if (auto* macro = Macro::DynamicCast(callable)) { + if (is_tailcall) { + ReportError("can't tail call a macro"); } - source_out() << label->generated(); - size_t j = 0; - for (auto t : callable->signature().labels[i].types) { - source_out() << ", "; - Variable* variable = label->GetParameter(j); - if (!(variable->type() == t)) { - std::stringstream s; - s << "mismatch of label parameters (expected " << *t << " got " - << *label->GetParameter(j)->type() << " for parameter " - << std::to_string(i + 1) << ")"; - ReportError(s.str()); + if (return_type->IsConstexpr()) { + DCHECK_EQ(0, arguments.labels.size()); + std::stringstream result; + result << "(" << macro->name() << "("; + bool first = true; + for (VisitResult arg : arguments.parameters) { + DCHECK(!arg.IsOnStack()); + if (!first) { + result << ", "; + } + first = false; + result << arg.constexpr_value(); + } + result << "))"; + return VisitResult(return_type, result.str()); + } else if (arguments.labels.empty() && + return_type != TypeOracle::GetNeverType()) { + assembler().Emit(CallCsaMacroInstruction{macro, constexpr_arguments}); + size_t return_slot_count = LoweredSlotCount(return_type); + return VisitResult(return_type, assembler().TopRange(return_slot_count)); + } else { + base::Optional<Block*> return_continuation; + if (return_type != TypeOracle::GetNeverType()) { + return_continuation = assembler().NewBlock(); } - j++; - source_out() << variable->value(); - } - label->MarkUsed(); - } - if (global_context_.verbose()) { - std::cout << "finished generating code for call to " << callable_name - << "\n"; - } - if (!result_type->IsVoidOrNever() && !is_tailcall && - !result_type->IsConstexpr()) { - source_out() << ")"; + std::vector<Block*> label_blocks; + + for (size_t i = 0; i < label_count; ++i) { + label_blocks.push_back(assembler().NewBlock()); + } + + assembler().Emit(CallCsaMacroAndBranchInstruction{ + macro, constexpr_arguments, return_continuation, label_blocks}); + + for (size_t i = 0; i < label_count; ++i) { + Label* label = arguments.labels[i]; + size_t callee_label_parameters = + callable->signature().labels[i].types.size(); + if (label->GetParameterCount() != callee_label_parameters) { + std::stringstream s; + s << "label " << label->name() + << " doesn't have the right number of parameters (found " + << std::to_string(label->GetParameterCount()) << " expected " + << std::to_string(callee_label_parameters) << ")"; + ReportError(s.str()); + } + assembler().Bind(label_blocks[i]); + assembler().Goto( + label->block(), + LowerParameterTypes(callable->signature().labels[i].types).size()); + + size_t j = 0; + for (auto t : callable->signature().labels[i].types) { + Variable* variable = label->GetParameter(j); + if (!(variable->type() == t)) { + std::stringstream s; + s << "mismatch of label parameters (expected " << *t << " got " + << *label->GetParameter(j)->type() << " for parameter " + << std::to_string(i + 1) << ")"; + ReportError(s.str()); + } + j++; + } + label->MarkUsed(); + } + + if (return_continuation) { + assembler().Bind(*return_continuation); + size_t return_slot_count = LoweredSlotCount(return_type); + return VisitResult(return_type, + assembler().TopRange(return_slot_count)); + } else { + return VisitResult::NeverResult(); + } + } + } else if (auto* runtime_function = RuntimeFunction::DynamicCast(callable)) { + assembler().Emit(CallRuntimeInstruction{is_tailcall, runtime_function, + argument_range.Size()}); + if (is_tailcall) { + return VisitResult::NeverResult(); + } else { + size_t slot_count = LoweredSlotCount(return_type); + DCHECK_LE(slot_count, 1); + // TODO(tebbi): Actually, runtime functions have to return a value, so + // we should assert slot_count == 1 here. + return VisitResult(return_type, assembler().TopRange(slot_count)); + } + } else { + UNREACHABLE(); } - source_out() << ");\n"; - return VisitResult(result_type, result_variable_name); } void ImplementationVisitor::Visit(StandardDeclaration* decl) { @@ -1856,45 +1833,40 @@ void ImplementationVisitor::Visit(SpecializationDeclaration* decl) { VisitResult ImplementationVisitor::Visit(CallExpression* expr, bool is_tailcall) { + StackScope scope(this); Arguments arguments; std::string name = expr->callee.name; - TypeVector specialization_types = - GetTypeVector(expr->callee.generic_arguments); - bool has_template_arguments = !specialization_types.empty(); - for (Expression* arg : expr->arguments) - arguments.parameters.push_back(Visit(arg)); - arguments.labels = LabelsFromIdentifiers(expr->labels); - VisitResult result; - if (!has_template_arguments && - declarations()->Lookup(expr->callee.name)->IsValue()) { - result = GeneratePointerCall(&expr->callee, arguments, is_tailcall); + TypeVector specialization_types = + GetTypeVector(expr->callee.generic_arguments); + bool has_template_arguments = !specialization_types.empty(); + for (Expression* arg : expr->arguments) + arguments.parameters.push_back(Visit(arg)); + arguments.labels = LabelsFromIdentifiers(expr->labels); + VisitResult result; + if (!has_template_arguments && + declarations()->Lookup(expr->callee.name)->IsValue()) { + return scope.Yield( + GeneratePointerCall(&expr->callee, arguments, is_tailcall)); } else { - result = GenerateCall(name, arguments, specialization_types, is_tailcall); - } - if (!result.type()->IsVoidOrNever()) { - GenerateIndent(); - source_out() << "USE(" << RValueFlattenStructs(result) << ");\n"; - } - if (is_tailcall) { - result = {TypeOracle::GetNeverType(), ""}; + return scope.Yield( + GenerateCall(name, arguments, specialization_types, is_tailcall)); } - return result; } bool ImplementationVisitor::GenerateLabeledStatementBlocks( const std::vector<Statement*>& blocks, - const std::vector<Label*>& statement_labels, Label* merge_label) { + const std::vector<Label*>& statement_labels, Block* merge_block) { bool live = false; auto label_iterator = statement_labels.begin(); for (Statement* block : blocks) { - GenerateIndent(); - source_out() << "if (" << (*label_iterator)->generated() - << "->is_used())\n"; - ScopedIndent indent(this); - GenerateLabelBind(*label_iterator++); - if (!Visit(block)->IsNever()) { - GenerateLabelGoto(merge_label); + const Type* stmt_result; + { + StackScope stack_scope(this); + stmt_result = Visit(block); + } + if (stmt_result != TypeOracle::GetNeverType()) { + assembler().Goto(merge_block); live = true; } } @@ -1904,15 +1876,14 @@ bool ImplementationVisitor::GenerateLabeledStatementBlocks( void ImplementationVisitor::GenerateBranch(const VisitResult& condition, Label* true_label, Label* false_label) { - GenerateIndent(); - source_out() << "Branch(" << RValueFlattenStructs(condition) << ", " - << true_label->generated() << ", " << false_label->generated() - << ");\n"; + DCHECK_EQ(condition, + VisitResult(TypeOracle::GetBoolType(), assembler().TopRange(1))); + assembler().Branch(true_label->block(), false_label->block()); } bool ImplementationVisitor::GenerateExpressionBranch( Expression* expression, const std::vector<Label*>& statement_labels, - const std::vector<Statement*>& statement_blocks, Label* merge_label) { + const std::vector<Statement*>& statement_blocks, Block* merge_block) { // Activate a new scope to define True/False catch labels Declarations::NodeScopeActivator scope(declarations(), expression); @@ -1929,23 +1900,28 @@ bool ImplementationVisitor::GenerateExpressionBranch( } return GenerateLabeledStatementBlocks(statement_blocks, statement_labels, - merge_label); + merge_block); } VisitResult ImplementationVisitor::GenerateImplicitConvert( const Type* destination_type, VisitResult source) { + StackScope scope(this); + if (source.type() == TypeOracle::GetNeverType()) { + ReportError("it is not allowed to use a value of type never"); + } + if (destination_type == source.type()) { - return source; + return scope.Yield(GenerateCopy(source)); } if (TypeOracle::IsImplicitlyConvertableFrom(destination_type, source.type())) { std::string name = GetGeneratedCallableName(kFromConstexprMacroName, {destination_type}); - return GenerateCall(name, {{source}, {}}, {}, false); + return scope.Yield(GenerateCall(name, {{source}, {}}, {}, false)); } else if (IsAssignableFrom(destination_type, source.type())) { source.SetType(destination_type); - return source; + return scope.Yield(GenerateCopy(source)); } else { std::stringstream s; s << "cannot use expression of type " << *source.type() @@ -1954,56 +1930,53 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert( } } -std::string ImplementationVisitor::NewTempVariable() { - std::string name("t"); - name += std::to_string(next_temp_++); - return name; -} - -std::string ImplementationVisitor::GenerateNewTempVariable(const Type* type) { - std::string temp = NewTempVariable(); - GenerateIndent(); - source_out() << type->GetGeneratedTypeName() << " " << temp << " = "; - return temp; -} - -void ImplementationVisitor::GenerateLabelDefinition(Label* label, - AstNode* node) { - std::string label_string = label->generated(); - std::string label_string_impl = label_string + "_impl"; - GenerateIndent(); - source_out() << "Label " + label_string_impl + "(this"; - if (node != nullptr) { - source_out() << ", "; - GenerateChangedVarsFromControlSplit(node); - } - source_out() << ");\n"; - GenerateIndent(); - source_out() << "Label* " + label_string + " = &" << label_string_impl - << ";\n"; - GenerateIndent(); - source_out() << "USE(" << label_string << ");\n"; +void ImplementationVisitor::CreateBlockForLabel(Label* label, + Stack<const Type*> stack) { + label->set_block(assembler().NewBlock(std::move(stack), label->IsDeferred())); } void ImplementationVisitor::GenerateLabelBind(Label* label) { - GenerateIndent(); - source_out() << "BIND(" << label->generated() << ");\n"; + assembler().Bind(label->block()); } -void ImplementationVisitor::GenerateLabelGoto(Label* label) { - GenerateIndent(); - source_out() << "Goto(" << label->generated() << ");\n"; +StackRange ImplementationVisitor::GenerateLabelGoto( + Label* label, base::Optional<StackRange> arguments) { + return assembler().Goto(label->block(), arguments ? arguments->Size() : 0); } std::vector<Label*> ImplementationVisitor::LabelsFromIdentifiers( const std::vector<std::string>& names) { std::vector<Label*> result; - for (auto name : names) { + result.reserve(names.size()); + for (const auto& name : names) { result.push_back(declarations()->LookupLabel(name)); } return result; } +StackRange ImplementationVisitor::LowerParameter( + const Type* type, const std::string& parameter_name, + Stack<std::string>* lowered_parameters) { + if (type->IsStructType()) { + const StructType* struct_type = StructType::cast(type); + StackRange range = lowered_parameters->TopRange(0); + for (auto& field : struct_type->fields()) { + StackRange parameter_range = LowerParameter( + field.type, parameter_name + "." + field.name, lowered_parameters); + range.Extend(parameter_range); + } + return range; + } else { + lowered_parameters->Push(parameter_name); + return lowered_parameters->TopRange(1); + } +} + +std::string ImplementationVisitor::ExternalLabelParameterName(Label* label, + size_t i) { + return label->external_label_name() + "_parameter_" + std::to_string(i); +} + } // namespace torque } // namespace internal } // namespace v8 |