// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/torque/declarations.h" #include "src/torque/declarable.h" #include "src/torque/type-oracle.h" namespace v8 { namespace internal { namespace torque { Scope* Declarations::GetModuleScope(const Module* module) { auto i = module_scopes_.find(module); if (i != module_scopes_.end()) return i->second; Scope* result = chain_.NewScope(); module_scopes_[module] = result; return result; } Scope* Declarations::GetNodeScope(const AstNode* node, bool reset_scope) { std::pair key( node, current_generic_specialization_ == nullptr ? TypeVector() : current_generic_specialization_->second); if (!reset_scope) { auto i = scopes_.find(key); if (i != scopes_.end()) return i->second; } Scope* result = chain_.NewScope(); scopes_[key] = result; return result; } Scope* Declarations::GetGenericScope(Generic* generic, const TypeVector& types) { std::pair key(generic->declaration()->callable, types); auto i = scopes_.find(key); if (i != scopes_.end()) return i->second; Scope* result = chain_.NewScope(); scopes_[key] = result; return result; } bool Declarations::IsDeclaredInCurrentScope(const std::string& name) { return chain_.ShallowLookup(name) != nullptr; } void Declarations::CheckAlreadyDeclared(const std::string& name, const char* new_type) { if (IsDeclaredInCurrentScope(name)) { std::stringstream s; s << "cannot redeclare " << name << " (type " << new_type << ")"; ReportError(s.str()); } } const Type* Declarations::LookupType(const std::string& name) { Declarable* raw = Lookup(name); if (raw->IsTypeAlias()) { return TypeAlias::cast(raw)->type(); } std::stringstream s; s << "declaration \"" << name << "\" is not a Type"; ReportError(s.str()); return nullptr; } const Type* Declarations::LookupGlobalType(const std::string& name) { Declarable* raw = LookupGlobalScope(name); if (!raw->IsTypeAlias()) { std::stringstream s; s << "declaration \"" << name << "\" is not a Type"; ReportError(s.str()); } return TypeAlias::cast(raw)->type(); } const Type* Declarations::GetType(TypeExpression* type_expression) { if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) { std::string name = (basic->is_constexpr ? CONSTEXPR_TYPE_PREFIX : "") + basic->name; return LookupType(name); } else if (auto* union_type = UnionTypeExpression::cast(type_expression)) { return TypeOracle::GetUnionType(GetType(union_type->a), GetType(union_type->b)); } else { auto* function_type_exp = FunctionTypeExpression::cast(type_expression); TypeVector argument_types; for (TypeExpression* type_exp : function_type_exp->parameters) { argument_types.push_back(GetType(type_exp)); } return TypeOracle::GetFunctionPointerType( argument_types, GetType(function_type_exp->return_type)); } } Builtin* Declarations::FindSomeInternalBuiltinWithType( const FunctionPointerType* type) { for (auto& declarable : declarables_) { if (Builtin* builtin = Builtin::DynamicCast(declarable.get())) { if (!builtin->IsExternal() && builtin->kind() == Builtin::kStub && builtin->signature().return_type == type->return_type() && builtin->signature().parameter_types.types == type->parameter_types()) { return builtin; } } } return nullptr; } Value* Declarations::LookupValue(const std::string& name) { Declarable* d = Lookup(name); if (!d->IsValue()) { std::stringstream s; s << "declaration \"" << name << "\" is not a Value"; ReportError(s.str()); } return Value::cast(d); } Label* Declarations::LookupLabel(const std::string& name) { Declarable* d = Lookup(name); if (!d->IsLabel()) { std::stringstream s; s << "declaration \"" << name << "\" is not a Label"; ReportError(s.str()); } return Label::cast(d); } Macro* Declarations::TryLookupMacro(const std::string& name, const TypeVector& types) { Declarable* declarable = TryLookup(name); if (declarable != nullptr) { if (declarable->IsMacroList()) { for (auto& m : MacroList::cast(declarable)->list()) { if (m->signature().parameter_types.types == types && !m->signature().parameter_types.var_args) { return m; } } } } return nullptr; } Macro* Declarations::LookupMacro(const std::string& name, const TypeVector& types) { Macro* result = TryLookupMacro(name, types); if (result != nullptr) return result; std::stringstream stream; stream << "macro " << name << " with parameter types " << types << " is not defined"; ReportError(stream.str()); return nullptr; } Builtin* Declarations::LookupBuiltin(const std::string& name) { Declarable* declarable = Lookup(name); if (declarable != nullptr) { if (declarable->IsBuiltin()) { return Builtin::cast(declarable); } ReportError(name + " is not a builtin"); } ReportError(std::string("builtin ") + name + " is not defined"); return nullptr; } GenericList* Declarations::LookupGeneric(const std::string& name) { Declarable* declarable_list = Lookup(name); if (declarable_list != nullptr) { if (declarable_list->IsGenericList()) { return GenericList::cast(declarable_list); } ReportError(name + " is not a generic"); } ReportError(std::string("generic ") + name + " is not defined"); return nullptr; } ModuleConstant* Declarations::LookupModuleConstant(const std::string& name) { Declarable* declarable = Lookup(name); if (declarable != nullptr) { if (declarable->IsModuleConstant()) { return ModuleConstant::cast(declarable); } ReportError(name + " is not a constant"); } ReportError(std::string("constant \"") + name + "\" is not defined"); return nullptr; } const AbstractType* Declarations::DeclareAbstractType( const std::string& name, const std::string& generated, base::Optional non_constexpr_version, const base::Optional& parent) { CheckAlreadyDeclared(name, "type"); const Type* parent_type = nullptr; if (parent) { Declarable* maybe_parent_type = Lookup(*parent); if (maybe_parent_type == nullptr) { std::stringstream s; s << "cannot find parent type \"" << *parent << "\""; ReportError(s.str()); } if (!maybe_parent_type->IsTypeAlias()) { std::stringstream s; s << "parent \"" << *parent << "\" of type \"" << name << "\"" << " is not a type"; ReportError(s.str()); } parent_type = TypeAlias::cast(maybe_parent_type)->type(); } const AbstractType* type = TypeOracle::GetAbstractType( parent_type, name, generated, non_constexpr_version); DeclareType(name, type); return type; } void Declarations::DeclareType(const std::string& name, const Type* type) { CheckAlreadyDeclared(name, "type"); TypeAlias* result = new TypeAlias(type); Declare(name, std::unique_ptr(result)); } void Declarations::DeclareStruct(Module* module, const std::string& name, const std::vector& fields) { const StructType* new_type = TypeOracle::GetStructType(module, name, fields); DeclareType(name, new_type); } Label* Declarations::DeclareLabel(const std::string& name) { CheckAlreadyDeclared(name, "label"); Label* result = new Label(name); Declare(name, std::unique_ptr(result)); return result; } MacroList* Declarations::GetMacroListForName(const std::string& name, const Signature& signature) { auto previous = chain_.Lookup(name); MacroList* macro_list = nullptr; if (previous == nullptr) { macro_list = new MacroList(); Declare(name, std::unique_ptr(macro_list)); } else if (!previous->IsMacroList()) { std::stringstream s; s << "cannot redeclare non-macro " << name << " as a macro"; ReportError(s.str()); } else { macro_list = MacroList::cast(previous); } for (auto& macro : macro_list->list()) { if (signature.parameter_types.types == macro->signature().parameter_types.types && signature.parameter_types.var_args == macro->signature().parameter_types.var_args) { std::stringstream s; s << "cannot redeclare " << name << " as a macro with identical parameter list " << signature.parameter_types; ReportError(s.str()); } } return macro_list; } Macro* Declarations::DeclareMacro(const std::string& name, const Signature& signature, base::Optional op) { Macro* macro = RegisterDeclarable( std::unique_ptr(new Macro(name, signature, GetCurrentGeneric()))); GetMacroListForName(name, signature)->AddMacro(macro); if (op) GetMacroListForName(*op, signature)->AddMacro(macro); return macro; } Builtin* Declarations::DeclareBuiltin(const std::string& name, Builtin::Kind kind, bool external, const Signature& signature) { CheckAlreadyDeclared(name, "builtin"); Builtin* result = new Builtin(name, kind, external, signature, GetCurrentGeneric()); Declare(name, std::unique_ptr(result)); return result; } RuntimeFunction* Declarations::DeclareRuntimeFunction( const std::string& name, const Signature& signature) { CheckAlreadyDeclared(name, "runtime function"); RuntimeFunction* result = new RuntimeFunction(name, signature, GetCurrentGeneric()); Declare(name, std::unique_ptr(result)); return result; } Variable* Declarations::DeclareVariable(const std::string& var, const Type* type, bool is_const) { std::string name(var + "_" + std::to_string(GetNextUniqueDeclarationNumber())); std::replace(name.begin(), name.end(), '.', '_'); CheckAlreadyDeclared(var, "variable"); Variable* result = new Variable(var, name, type, is_const); Declare(var, std::unique_ptr(result)); return result; } Parameter* Declarations::DeclareParameter(const std::string& name, const std::string& var_name, const Type* type) { CheckAlreadyDeclared(name, "parameter"); Parameter* result = new Parameter(name, type, var_name); Declare(name, std::unique_ptr(result)); return result; } Label* Declarations::DeclarePrivateLabel(const std::string& raw_name) { std::string name = raw_name + "_" + std::to_string(GetNextUniqueDeclarationNumber()); CheckAlreadyDeclared(name, "label"); Label* result = new Label(name); Declare(name, std::unique_ptr(result)); return result; } void Declarations::DeclareExternConstant(const std::string& name, const Type* type, const std::string& value) { CheckAlreadyDeclared(name, "constant, parameter or arguments"); ExternConstant* result = new ExternConstant(name, type, value); Declare(name, std::unique_ptr(result)); } ModuleConstant* Declarations::DeclareModuleConstant(const std::string& name, const Type* type) { CheckAlreadyDeclared(name, "module constant"); ModuleConstant* result = new ModuleConstant(name, type); Declare(name, std::unique_ptr(result)); return result; } Generic* Declarations::DeclareGeneric(const std::string& name, Module* module, GenericDeclaration* generic) { auto previous = chain_.Lookup(name); GenericList* generic_list = nullptr; if (previous == nullptr) { generic_list = new GenericList(); Declare(name, std::unique_ptr(generic_list)); } else if (!previous->IsGenericList()) { std::stringstream s; s << "cannot redeclare non-generic " << name << " as a generic"; ReportError(s.str()); } else { generic_list = GenericList::cast(previous); } Generic* result = RegisterDeclarable( std::unique_ptr(new Generic(name, module, generic))); generic_list->AddGeneric(result); generic_declaration_scopes_[result] = GetScopeChainSnapshot(); return result; } TypeVector Declarations::GetCurrentSpecializationTypeNamesVector() { TypeVector result; if (current_generic_specialization_ != nullptr) { result = current_generic_specialization_->second; } return result; } base::Optional Declarations::GetCurrentGeneric() { if (current_generic_specialization_ != nullptr) { return current_generic_specialization_->first; } return base::nullopt; } std::string GetGeneratedCallableName(const std::string& name, const TypeVector& specialized_types) { std::string result = name; for (auto type : specialized_types) { std::string type_string = type->MangledName(); result += std::to_string(type_string.size()) + type_string; } return result; } } // namespace torque } // namespace internal } // namespace v8