summaryrefslogtreecommitdiff
path: root/deps/v8/src/torque/declaration-visitor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/torque/declaration-visitor.cc')
-rw-r--r--deps/v8/src/torque/declaration-visitor.cc472
1 files changed, 395 insertions, 77 deletions
diff --git a/deps/v8/src/torque/declaration-visitor.cc b/deps/v8/src/torque/declaration-visitor.cc
index a841a9d823..b83dbb3bc3 100644
--- a/deps/v8/src/torque/declaration-visitor.cc
+++ b/deps/v8/src/torque/declaration-visitor.cc
@@ -90,11 +90,20 @@ Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
declarations()->LookupGlobalType(OBJECT_TYPE_STRING))) {
std::stringstream stream;
stream << "second parameter to javascript builtin " << decl->name
- << " is " << signature.types()[1] << " but should be Object";
+ << " is " << *signature.types()[1] << " but should be Object";
ReportError(stream.str());
}
}
+ if (const StructType* struct_type =
+ StructType::DynamicCast(signature.return_type)) {
+ std::stringstream stream;
+ stream << "builtins (in this case" << decl->name
+ << ") cannot return structs (in this case " << struct_type->name()
+ << ")";
+ ReportError(stream.str());
+ }
+
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
return declarations()->DeclareBuiltin(generated_name, kind, external,
@@ -117,6 +126,15 @@ void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
ReportError(stream.str());
}
+ if (signature.return_type->IsStructType()) {
+ std::stringstream stream;
+ stream << "runtime functions (in this case" << decl->name
+ << ") cannot return structs (in this case "
+ << static_cast<const StructType*>(signature.return_type)->name()
+ << ")";
+ ReportError(stream.str());
+ }
+
declarations()->DeclareRuntimeFunction(decl->name, signature);
}
@@ -129,31 +147,7 @@ void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
- declarations()->DeclareMacro(generated_name, signature);
- if (decl->op) {
- OperationHandler handler(
- {decl->name, signature.parameter_types, signature.return_type});
- auto i = global_context_.op_handlers_.find(*decl->op);
- if (i == global_context_.op_handlers_.end()) {
- global_context_.op_handlers_[*decl->op] = std::vector<OperationHandler>();
- i = global_context_.op_handlers_.find(*decl->op);
- }
- i->second.push_back(handler);
- }
-
- if (decl->implicit) {
- if (!decl->op || *decl->op != "convert<>") {
- ReportError("implicit can only be used with cast<> operator");
- }
-
- const TypeVector& parameter_types = signature.parameter_types.types;
- if (parameter_types.size() != 1 || signature.parameter_types.var_args) {
- ReportError(
- "implicit cast operators doesn't only have a single parameter");
- }
- GetTypeOracle().RegisterImplicitConversion(signature.return_type,
- parameter_types[0]);
- }
+ declarations()->DeclareMacro(generated_name, signature, decl->op);
}
void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
@@ -162,9 +156,9 @@ void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
CurrentCallableActivator activator(global_context_, builtin, decl);
DeclareSignature(signature);
if (signature.parameter_types.var_args) {
- declarations()->DeclareConstant(
+ declarations()->DeclareExternConstant(
decl->signature->parameters.arguments_variable,
- GetTypeOracle().GetArgumentsType(), "arguments");
+ TypeOracle::GetArgumentsType(), "arguments");
}
torque_builtins_.push_back(builtin);
Visit(body);
@@ -174,27 +168,38 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
const Signature& signature, Statement* body) {
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
- Macro* macro = declarations()->DeclareMacro(generated_name, signature);
+ Macro* macro =
+ declarations()->DeclareMacro(generated_name, signature, decl->op);
CurrentCallableActivator activator(global_context_, macro, decl);
DeclareSignature(signature);
+ Variable* return_variable = nullptr;
if (!signature.return_type->IsVoidOrNever()) {
- declarations()->DeclareVariable(kReturnValueVariable,
- signature.return_type);
+ return_variable =
+ DeclareVariable(kReturnValueVariable, signature.return_type,
+ signature.return_type->IsConstexpr());
}
PushControlSplit();
- Visit(body);
+ if (body != nullptr) {
+ Visit(body);
+ }
auto changed_vars = PopControlSplit();
+ if (return_variable) changed_vars.insert(return_variable);
global_context_.AddControlSplitChangedVariables(
decl, declarations()->GetCurrentSpecializationTypeNamesVector(),
changed_vars);
}
+void DeclarationVisitor::Visit(ConstDeclaration* decl) {
+ declarations()->DeclareModuleConstant(decl->name,
+ declarations()->GetType(decl->type));
+ Visit(decl->expression);
+}
+
void DeclarationVisitor::Visit(StandardDeclaration* decl) {
- Signature signature =
- MakeSignature(decl->callable, decl->callable->signature.get());
+ Signature signature = MakeSignature(decl->callable->signature.get());
Visit(decl->callable, signature, decl->body);
}
@@ -203,45 +208,213 @@ void DeclarationVisitor::Visit(GenericDeclaration* decl) {
}
void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
- Generic* generic = declarations()->LookupGeneric(decl->name);
- SpecializationKey key = {generic, GetTypeVector(decl->generic_parameters)};
- CallableNode* callable = generic->declaration()->callable;
+ if ((decl->body != nullptr) == decl->external) {
+ std::stringstream stream;
+ stream << "specialization of " << decl->name
+ << " must either be marked 'extern' or have a body";
+ ReportError(stream.str());
+ }
- {
- Signature signature_with_types =
- MakeSignature(callable, decl->signature.get());
+ GenericList* generic_list = declarations()->LookupGeneric(decl->name);
+ // Find the matching generic specialization based on the concrete parameter
+ // list.
+ CallableNode* matching_callable = nullptr;
+ SpecializationKey matching_key;
+ Signature signature_with_types = MakeSignature(decl->signature.get());
+ for (Generic* generic : generic_list->list()) {
+ SpecializationKey key = {generic, GetTypeVector(decl->generic_parameters)};
+ CallableNode* callable_candidate = generic->declaration()->callable;
// Abuse the Specialization nodes' scope to temporarily declare the
// specialization aliases for the generic types to compare signatures. This
// scope is never used for anything else, so it's OK to pollute it.
- Declarations::NodeScopeActivator specialization_activator(declarations(),
- decl);
+ Declarations::CleanNodeScopeActivator specialization_activator(
+ declarations(), decl);
DeclareSpecializedTypes(key);
Signature generic_signature_with_types =
- MakeSignature(generic->declaration()->callable,
- generic->declaration()->callable->signature.get());
- if (!signature_with_types.HasSameTypesAs(generic_signature_with_types)) {
- std::stringstream stream;
- stream << "specialization of " << callable->name
- << " has incompatible parameter list or label list with generic "
- "definition";
- ReportError(stream.str());
+ MakeSignature(generic->declaration()->callable->signature.get());
+ if (signature_with_types.HasSameTypesAs(generic_signature_with_types)) {
+ if (matching_callable != nullptr) {
+ std::stringstream stream;
+ stream << "specialization of " << callable_candidate->name
+ << " is ambigous, it matches more than one generic declaration ("
+ << *matching_key.first << " and " << *key.first << ")";
+ ReportError(stream.str());
+ }
+ matching_callable = callable_candidate;
+ matching_key = key;
}
}
- SpecializeGeneric({key, callable, decl->signature.get(), decl->body});
+ if (matching_callable == nullptr) {
+ std::stringstream stream;
+ stream << "specialization of " << decl->name
+ << " doesn't match any generic declaration";
+ ReportError(stream.str());
+ }
+
+ // Make sure the declarations of the parameter types for the specialization
+ // are the ones from the matching generic.
+ {
+ Declarations::CleanNodeScopeActivator specialization_activator(
+ declarations(), decl);
+ DeclareSpecializedTypes(matching_key);
+ }
+
+ SpecializeGeneric({matching_key, matching_callable, decl->signature.get(),
+ decl->body, decl->pos});
}
void DeclarationVisitor::Visit(ReturnStatement* stmt) {
- const Callable* callable = global_context_.GetCurrentCallable();
- if (callable->IsMacro() && callable->HasReturnValue()) {
- MarkVariableModified(
- Variable::cast(declarations()->LookupValue(kReturnValueVariable)));
- }
if (stmt->value) {
Visit(*stmt->value);
}
}
+Variable* DeclarationVisitor::DeclareVariable(const std::string& name,
+ const Type* type, bool is_const) {
+ Variable* result = declarations()->DeclareVariable(name, type, is_const);
+ if (type->IsStructType()) {
+ const StructType* struct_type = StructType::cast(type);
+ for (auto& field : struct_type->fields()) {
+ std::string field_var_name = name + "." + field.name;
+ DeclareVariable(field_var_name, field.type, is_const);
+ }
+ }
+ return result;
+}
+
+Parameter* DeclarationVisitor::DeclareParameter(const std::string& name,
+ const Type* type) {
+ Parameter* result = declarations()->DeclareParameter(
+ name, GetParameterVariableFromName(name), type);
+ if (type->IsStructType()) {
+ const StructType* struct_type = StructType::cast(type);
+ for (auto& field : struct_type->fields()) {
+ std::string field_var_name = name + "." + field.name;
+ DeclareParameter(field_var_name, field.type);
+ }
+ }
+ return result;
+}
+
+void DeclarationVisitor::Visit(VarDeclarationStatement* stmt) {
+ std::string variable_name = stmt->name;
+ const Type* type = declarations()->GetType(stmt->type);
+ if (type->IsConstexpr() && !stmt->const_qualified) {
+ ReportError(
+ "cannot declare variable with constexpr type. Use 'const' instead.");
+ }
+ DeclareVariable(variable_name, type, stmt->const_qualified);
+ if (global_context_.verbose()) {
+ std::cout << "declared variable " << variable_name << " with type " << *type
+ << "\n";
+ }
+
+ // const qualified variables are required to be initialized properly.
+ if (stmt->const_qualified && !stmt->initializer) {
+ std::stringstream stream;
+ stream << "local constant \"" << variable_name << "\" is not initialized.";
+ ReportError(stream.str());
+ }
+
+ if (stmt->initializer) {
+ Visit(*stmt->initializer);
+ if (global_context_.verbose()) {
+ std::cout << "variable has initialization expression at "
+ << CurrentPositionAsString() << "\n";
+ }
+ }
+}
+
+void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
+ const Type* type = declarations()->GetType(decl->type);
+ if (!type->IsConstexpr()) {
+ std::stringstream stream;
+ stream << "extern constants must have constexpr type, but found: \""
+ << *type << "\"\n";
+ ReportError(stream.str());
+ }
+
+ declarations()->DeclareExternConstant(decl->name, type, decl->literal);
+}
+
+void DeclarationVisitor::Visit(StructDeclaration* decl) {
+ std::vector<NameAndType> fields;
+ for (auto& field : decl->fields) {
+ const Type* field_type = declarations()->GetType(field.type);
+ fields.push_back({field.name, field_type});
+ }
+ declarations()->DeclareStruct(CurrentModule(), decl->name, fields);
+}
+
+void DeclarationVisitor::Visit(LogicalOrExpression* expr) {
+ {
+ Declarations::NodeScopeActivator scope(declarations(), expr->left);
+ declarations()->DeclareLabel(kFalseLabelName);
+ Visit(expr->left);
+ }
+ Visit(expr->right);
+}
+
+void DeclarationVisitor::Visit(LogicalAndExpression* expr) {
+ {
+ Declarations::NodeScopeActivator scope(declarations(), expr->left);
+ declarations()->DeclareLabel(kTrueLabelName);
+ Visit(expr->left);
+ }
+ Visit(expr->right);
+}
+
+void DeclarationVisitor::DeclareExpressionForBranch(Expression* node) {
+ Declarations::NodeScopeActivator scope(declarations(), node);
+ // Conditional expressions can either explicitly return a bit
+ // type, or they can be backed by macros that don't return but
+ // take a true and false label. By declaring the labels before
+ // visiting the conditional expression, those label-based
+ // macro conditionals will be able to find them through normal
+ // label lookups.
+ declarations()->DeclareLabel(kTrueLabelName);
+ declarations()->DeclareLabel(kFalseLabelName);
+ Visit(node);
+}
+
+void DeclarationVisitor::Visit(ConditionalExpression* expr) {
+ DeclareExpressionForBranch(expr->condition);
+ PushControlSplit();
+ Visit(expr->if_true);
+ Visit(expr->if_false);
+ auto changed_vars = PopControlSplit();
+ global_context_.AddControlSplitChangedVariables(
+ expr, declarations()->GetCurrentSpecializationTypeNamesVector(),
+ changed_vars);
+}
+
+void DeclarationVisitor::Visit(IfStatement* stmt) {
+ if (!stmt->is_constexpr) {
+ PushControlSplit();
+ }
+ DeclareExpressionForBranch(stmt->condition);
+ Visit(stmt->if_true);
+ if (stmt->if_false) Visit(*stmt->if_false);
+ if (!stmt->is_constexpr) {
+ auto changed_vars = PopControlSplit();
+ global_context_.AddControlSplitChangedVariables(
+ stmt, declarations()->GetCurrentSpecializationTypeNamesVector(),
+ changed_vars);
+ }
+}
+
+void DeclarationVisitor::Visit(WhileStatement* stmt) {
+ Declarations::NodeScopeActivator scope(declarations(), stmt);
+ DeclareExpressionForBranch(stmt->condition);
+ PushControlSplit();
+ Visit(stmt->body);
+ auto changed_vars = PopControlSplit();
+ global_context_.AddControlSplitChangedVariables(
+ stmt, declarations()->GetCurrentSpecializationTypeNamesVector(),
+ changed_vars);
+}
+
void DeclarationVisitor::Visit(ForOfLoopStatement* stmt) {
// Scope for for iteration variable
Declarations::NodeScopeActivator scope(declarations(), stmt);
@@ -257,13 +430,26 @@ void DeclarationVisitor::Visit(ForOfLoopStatement* stmt) {
changed_vars);
}
-void DeclarationVisitor::Visit(TryCatchStatement* stmt) {
- // Activate a new scope to declare catch handler labels, they should not be
- // visible outside the catch.
+void DeclarationVisitor::Visit(ForLoopStatement* stmt) {
+ Declarations::NodeScopeActivator scope(declarations(), stmt);
+ if (stmt->var_declaration) Visit(*stmt->var_declaration);
+ PushControlSplit();
+ DeclareExpressionForBranch(stmt->test);
+ Visit(stmt->body);
+ Visit(stmt->action);
+ auto changed_vars = PopControlSplit();
+ global_context_.AddControlSplitChangedVariables(
+ stmt, declarations()->GetCurrentSpecializationTypeNamesVector(),
+ changed_vars);
+}
+
+void DeclarationVisitor::Visit(TryLabelStatement* stmt) {
+ // Activate a new scope to declare handler labels, they should not be
+ // visible outside the label block.
{
Declarations::NodeScopeActivator scope(declarations(), stmt);
- // Declare catch labels
+ // Declare labels
for (LabelBlock* block : stmt->label_blocks) {
CurrentSourcePosition::Scope scope(block->pos);
Label* shared_label = declarations()->DeclareLabel(block->label);
@@ -277,42 +463,96 @@ void DeclarationVisitor::Visit(TryCatchStatement* stmt) {
size_t i = 0;
for (auto p : block->parameters.names) {
- shared_label->AddVariable(declarations()->DeclareVariable(
- p, declarations()->GetType(block->parameters.types[i])));
+ const Type* type =
+ declarations()->GetType(block->parameters.types[i]);
+ if (type->IsConstexpr()) {
+ ReportError("no constexpr type allowed for label arguments");
+ }
+
+ shared_label->AddVariable(DeclareVariable(p, type, false));
++i;
}
}
if (global_context_.verbose()) {
- std::cout << " declaring catch for exception " << block->label << "\n";
+ std::cout << " declaring label " << block->label << "\n";
}
}
- // Try catch not supported yet
- DCHECK_EQ(stmt->catch_blocks.size(), 0);
-
Visit(stmt->try_block);
}
- for (CatchBlock* block : stmt->catch_blocks) {
+ for (LabelBlock* block : stmt->label_blocks) {
Visit(block->body);
}
+}
- for (LabelBlock* block : stmt->label_blocks) {
- Visit(block->body);
+void DeclarationVisitor::GenerateHeader(std::string& file_name) {
+ std::stringstream new_contents_stream;
+ new_contents_stream
+ << "#ifndef V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n"
+ "#define V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n"
+ "\n"
+ "#define BUILTIN_LIST_FROM_DSL(CPP, API, TFJ, TFC, TFS, TFH, ASM) "
+ "\\\n";
+ for (auto builtin : torque_builtins_) {
+ int firstParameterIndex = 1;
+ bool declareParameters = true;
+ if (builtin->IsStub()) {
+ new_contents_stream << "TFS(" << builtin->name();
+ } else {
+ new_contents_stream << "TFJ(" << builtin->name();
+ if (builtin->IsVarArgsJavaScript()) {
+ new_contents_stream
+ << ", SharedFunctionInfo::kDontAdaptArgumentsSentinel";
+ declareParameters = false;
+ } else {
+ assert(builtin->IsFixedArgsJavaScript());
+ // FixedArg javascript builtins need to offer the parameter
+ // count.
+ assert(builtin->parameter_names().size() >= 2);
+ new_contents_stream << ", " << (builtin->parameter_names().size() - 2);
+ // And the receiver is explicitly declared.
+ new_contents_stream << ", kReceiver";
+ firstParameterIndex = 2;
+ }
+ }
+ if (declareParameters) {
+ int index = 0;
+ for (auto parameter : builtin->parameter_names()) {
+ if (index >= firstParameterIndex) {
+ new_contents_stream << ", k" << CamelifyString(parameter);
+ }
+ index++;
+ }
+ }
+ new_contents_stream << ") \\\n";
}
+ new_contents_stream
+ << "\n"
+ "#endif // V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n";
+
+ std::string new_contents(new_contents_stream.str());
+ ReplaceFileContentsIfDifferent(file_name, new_contents);
}
void DeclarationVisitor::Visit(IdentifierExpression* expr) {
if (expr->generic_arguments.size() != 0) {
- Generic* generic = declarations()->LookupGeneric(expr->name);
TypeVector specialization_types;
for (auto t : expr->generic_arguments) {
specialization_types.push_back(declarations()->GetType(t));
}
- CallableNode* callable = generic->declaration()->callable;
- QueueGenericSpecialization({generic, specialization_types}, callable,
- callable->signature.get(),
- generic->declaration()->body);
+ // Specialize all versions of the generic, since the exact parameter type
+ // list cannot be resolved until the call's parameter expressions are
+ // evaluated. This is an overly conservative but simple way to make sure
+ // that the correct specialization exists.
+ for (auto generic : declarations()->LookupGeneric(expr->name)->list()) {
+ CallableNode* callable = generic->declaration()->callable;
+ if (generic->declaration()->body) {
+ QueueGenericSpecialization({generic, specialization_types}, callable,
+ callable->signature.get(),
+ generic->declaration()->body);
+ }
+ }
}
}
@@ -321,9 +561,85 @@ void DeclarationVisitor::Visit(CallExpression* expr) {
for (Expression* arg : expr->arguments) Visit(arg);
}
+void DeclarationVisitor::Visit(TypeDeclaration* decl) {
+ std::string generates = decl->generates ? *decl->generates : std::string("");
+ const AbstractType* type = declarations()->DeclareAbstractType(
+ decl->name, generates, {}, decl->extends);
+
+ if (decl->constexpr_generates) {
+ std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
+ base::Optional<std::string> constexpr_extends;
+ if (decl->extends)
+ constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
+ declarations()->DeclareAbstractType(
+ constexpr_name, *decl->constexpr_generates, type, constexpr_extends);
+ }
+}
+
+void DeclarationVisitor::MarkLocationModified(Expression* location) {
+ if (IdentifierExpression* id = IdentifierExpression::cast(location)) {
+ const Value* value = declarations()->LookupValue(id->name);
+ if (value->IsVariable()) {
+ const Variable* variable = Variable::cast(value);
+ bool was_live = MarkVariableModified(variable);
+ if (was_live && global_context_.verbose()) {
+ std::cout << *variable << " was modified in control split at "
+ << PositionAsString(id->pos) << "\n";
+ }
+ }
+ }
+}
+
+bool DeclarationVisitor::MarkVariableModified(const Variable* variable) {
+ auto e = live_and_changed_variables_.rend();
+ auto c = live_and_changed_variables_.rbegin();
+ bool was_live_in_preceeding_split = false;
+ while (c != e) {
+ if (c->live.find(variable) != c->live.end()) {
+ c->changed.insert(variable);
+ was_live_in_preceeding_split = true;
+ }
+ c++;
+ }
+ return was_live_in_preceeding_split;
+}
+
+void DeclarationVisitor::DeclareSignature(const Signature& signature) {
+ auto type_iterator = signature.parameter_types.types.begin();
+ for (auto name : signature.parameter_names) {
+ const Type* t(*type_iterator++);
+ if (name.size() != 0) {
+ DeclareParameter(name, t);
+ }
+ }
+ for (auto& label : signature.labels) {
+ auto label_params = label.types;
+ Label* new_label = declarations()->DeclareLabel(label.name);
+ size_t i = 0;
+ for (auto var_type : label_params) {
+ if (var_type->IsConstexpr()) {
+ ReportError("no constexpr type allowed for label arguments");
+ }
+
+ std::string var_name = label.name + std::to_string(i++);
+ new_label->AddVariable(DeclareVariable(var_name, var_type, false));
+ }
+ }
+}
+
void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
size_t i = 0;
Generic* generic = key.first;
+ const std::size_t generic_parameter_count =
+ generic->declaration()->generic_parameters.size();
+ if (generic_parameter_count != key.second.size()) {
+ std::stringstream stream;
+ stream << "Wrong generic argument count for specialization of \""
+ << generic->name() << "\", expected: " << generic_parameter_count
+ << ", actual: " << key.second.size();
+ ReportError(stream.str());
+ }
+
for (auto type : key.second) {
std::string generic_type_name =
generic->declaration()->generic_parameters[i++];
@@ -339,7 +655,7 @@ void DeclarationVisitor::Specialize(const SpecializationKey& key,
// TODO(tebbi): The error should point to the source position where the
// instantiation was requested.
- CurrentSourcePosition::Scope scope(generic->declaration()->pos);
+ CurrentSourcePosition::Scope pos_scope(generic->declaration()->pos);
size_t generic_parameter_count =
generic->declaration()->generic_parameters.size();
if (generic_parameter_count != key.second.size()) {
@@ -352,14 +668,16 @@ void DeclarationVisitor::Specialize(const SpecializationKey& key,
ReportError(stream.str());
}
+ Signature type_signature;
{
// Manually activate the specialized generic's scope when declaring the
// generic parameter specializations.
- Declarations::GenericScopeActivator scope(declarations(), key);
+ Declarations::GenericScopeActivator namespace_scope(declarations(), key);
DeclareSpecializedTypes(key);
+ type_signature = MakeSignature(signature);
}
- Visit(callable, MakeSignature(callable, signature), body);
+ Visit(callable, type_signature, body);
}
} // namespace torque