// 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/global-context.h" #include "src/torque/type-oracle.h" namespace v8 { namespace internal { namespace torque { DEFINE_CONTEXTUAL_VARIABLE(GlobalContext) namespace { template <class T> std::vector<T> EnsureNonempty(std::vector<T> list, const std::string& name, const char* kind) { if (list.empty()) { ReportError("there is no ", kind, " named ", name); } return std::move(list); } template <class T, class Name> T EnsureUnique(const std::vector<T>& list, const Name& name, const char* kind) { if (list.empty()) { ReportError("there is no ", kind, " named ", name); } if (list.size() >= 2) { ReportError("ambiguous reference to ", kind, " ", name); } return list.front(); } template <class T> void CheckAlreadyDeclared(const std::string& name, const char* new_type) { std::vector<T*> declarations = FilterDeclarables<T>(Declarations::TryLookupShallow(QualifiedName(name))); if (!declarations.empty()) { Scope* scope = CurrentScope::Get(); ReportError("cannot redeclare ", name, " (type ", new_type, scope, ")"); } } } // namespace std::vector<Declarable*> Declarations::LookupGlobalScope( const std::string& name) { std::vector<Declarable*> d = GlobalContext::GetDefaultNamespace()->Lookup(QualifiedName(name)); if (d.empty()) { std::stringstream s; s << "cannot find \"" << name << "\" in global scope"; ReportError(s.str()); } return d; } const Type* Declarations::LookupType(const QualifiedName& name) { TypeAlias* declaration = EnsureUnique(FilterDeclarables<TypeAlias>(Lookup(name)), name, "type"); return declaration->type(); } const Type* Declarations::LookupType(std::string name) { return LookupType(QualifiedName(std::move(name))); } const Type* Declarations::LookupGlobalType(const std::string& name) { TypeAlias* declaration = EnsureUnique( FilterDeclarables<TypeAlias>(LookupGlobalScope(name)), name, "type"); return declaration->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(QualifiedName{basic->namespace_qualification, 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::GetBuiltinPointerType( argument_types, GetType(function_type_exp->return_type)); } } Builtin* Declarations::FindSomeInternalBuiltinWithType( const BuiltinPointerType* type) { for (auto& declarable : GlobalContext::AllDeclarables()) { 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 QualifiedName& name) { return EnsureUnique(FilterDeclarables<Value>(Lookup(name)), name, "value"); } Macro* Declarations::TryLookupMacro(const std::string& name, const TypeVector& types) { std::vector<Macro*> macros = TryLookup<Macro>(QualifiedName(name)); for (auto& m : macros) { auto signature_types = m->signature().GetExplicitTypes(); if (signature_types == types && !m->signature().parameter_types.var_args) { return m; } } return nullptr; } base::Optional<Builtin*> Declarations::TryLookupBuiltin( const QualifiedName& name) { std::vector<Builtin*> builtins = TryLookup<Builtin>(name); if (builtins.empty()) return base::nullopt; return EnsureUnique(builtins, name.name, "builtin"); } std::vector<Generic*> Declarations::LookupGeneric(const std::string& name) { return EnsureNonempty(FilterDeclarables<Generic>(Lookup(QualifiedName(name))), name, "generic"); } Generic* Declarations::LookupUniqueGeneric(const QualifiedName& name) { return EnsureUnique(FilterDeclarables<Generic>(Lookup(name)), name, "generic"); } Namespace* Declarations::DeclareNamespace(const std::string& name) { return Declare(name, std::unique_ptr<Namespace>(new Namespace(name))); } const AbstractType* Declarations::DeclareAbstractType( const std::string& name, bool transient, std::string generated, base::Optional<const AbstractType*> non_constexpr_version, const base::Optional<std::string>& parent) { CheckAlreadyDeclared<TypeAlias>(name, "type"); const Type* parent_type = nullptr; if (parent) { parent_type = LookupType(QualifiedName{*parent}); } if (generated == "" && parent) { generated = parent_type->GetGeneratedTNodeTypeName(); } const AbstractType* type = TypeOracle::GetAbstractType( parent_type, name, transient, generated, non_constexpr_version); DeclareType(name, type, false); return type; } void Declarations::DeclareType(const std::string& name, const Type* type, bool redeclaration) { CheckAlreadyDeclared<TypeAlias>(name, "type"); Declare(name, std::unique_ptr<TypeAlias>(new TypeAlias(type, redeclaration))); } StructType* Declarations::DeclareStruct(const std::string& name) { StructType* new_type = TypeOracle::GetStructType(name); DeclareType(name, new_type, false); return new_type; } ClassType* Declarations::DeclareClass(const Type* super_type, const std::string& name, bool is_extern, bool transient, const std::string& generates) { ClassType* new_type = TypeOracle::GetClassType(super_type, name, is_extern, transient, generates); DeclareType(name, new_type, false); return new_type; } Macro* Declarations::CreateMacro( std::string external_name, std::string readable_name, base::Optional<std::string> external_assembler_name, Signature signature, bool transitioning, base::Optional<Statement*> body) { if (!external_assembler_name) { external_assembler_name = CurrentNamespace()->ExternalName(); } return RegisterDeclarable(std::unique_ptr<Macro>( new Macro(std::move(external_name), std::move(readable_name), std::move(*external_assembler_name), std::move(signature), transitioning, body))); } Macro* Declarations::DeclareMacro( const std::string& name, base::Optional<std::string> external_assembler_name, const Signature& signature, bool transitioning, base::Optional<Statement*> body, base::Optional<std::string> op) { if (TryLookupMacro(name, signature.GetExplicitTypes())) { ReportError("cannot redeclare macro ", name, " with identical explicit parameters"); } Macro* macro = CreateMacro(name, name, std::move(external_assembler_name), signature, transitioning, body); Declare(name, macro); if (op) { if (TryLookupMacro(*op, signature.GetExplicitTypes())) { ReportError("cannot redeclare operator ", name, " with identical explicit parameters"); } DeclareOperator(*op, macro); } return macro; } Method* Declarations::CreateMethod(AggregateType* container_type, const std::string& name, Signature signature, bool transitioning, Statement* body) { std::string generated_name{container_type->GetGeneratedMethodName(name)}; Method* result = RegisterDeclarable(std::unique_ptr<Method>( new Method(container_type, container_type->GetGeneratedMethodName(name), name, CurrentNamespace()->ExternalName(), std::move(signature), transitioning, body))); container_type->RegisterMethod(result); return result; } Intrinsic* Declarations::CreateIntrinsic(const std::string& name, const Signature& signature) { Intrinsic* result = RegisterDeclarable(std::unique_ptr<Intrinsic>( new Intrinsic(std::move(name), std::move(signature)))); return result; } Intrinsic* Declarations::DeclareIntrinsic(const std::string& name, const Signature& signature) { Intrinsic* result = CreateIntrinsic(std::move(name), std::move(signature)); Declare(name, result); return result; } Builtin* Declarations::CreateBuiltin(std::string external_name, std::string readable_name, Builtin::Kind kind, Signature signature, bool transitioning, base::Optional<Statement*> body) { return RegisterDeclarable(std::unique_ptr<Builtin>( new Builtin(std::move(external_name), std::move(readable_name), kind, std::move(signature), transitioning, body))); } Builtin* Declarations::DeclareBuiltin(const std::string& name, Builtin::Kind kind, const Signature& signature, bool transitioning, base::Optional<Statement*> body) { CheckAlreadyDeclared<Builtin>(name, "builtin"); return Declare( name, CreateBuiltin(name, name, kind, signature, transitioning, body)); } RuntimeFunction* Declarations::DeclareRuntimeFunction( const std::string& name, const Signature& signature, bool transitioning) { CheckAlreadyDeclared<RuntimeFunction>(name, "runtime function"); return Declare(name, RegisterDeclarable(std::unique_ptr<RuntimeFunction>( new RuntimeFunction(name, signature, transitioning)))); } void Declarations::DeclareExternConstant(const std::string& name, const Type* type, std::string value) { CheckAlreadyDeclared<Value>(name, "constant"); ExternConstant* result = new ExternConstant(name, type, value); Declare(name, std::unique_ptr<Declarable>(result)); } NamespaceConstant* Declarations::DeclareNamespaceConstant( const std::string& name, const Type* type, Expression* body) { CheckAlreadyDeclared<Value>(name, "constant"); NamespaceConstant* result = new NamespaceConstant(name, type, body); Declare(name, std::unique_ptr<Declarable>(result)); return result; } Generic* Declarations::DeclareGeneric(const std::string& name, GenericDeclaration* generic) { return Declare(name, std::unique_ptr<Generic>(new Generic(name, generic))); } std::string Declarations::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; } Macro* Declarations::DeclareOperator(const std::string& name, Macro* m) { GlobalContext::GetDefaultNamespace()->AddDeclarable(name, m); return m; } } // namespace torque } // namespace internal } // namespace v8