summaryrefslogtreecommitdiff
path: root/deps/v8/src/torque/implementation-visitor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/torque/implementation-visitor.cc')
-rw-r--r--deps/v8/src/torque/implementation-visitor.cc1589
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, &parameters, &parameter_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, &parameters, &parameter_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, &parameters, &parameter_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