diff options
Diffstat (limited to 'deps/v8/src/torque/declaration-visitor.cc')
-rw-r--r-- | deps/v8/src/torque/declaration-visitor.cc | 472 |
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 |