1// Copyright 2017 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/torque/declarations.h" 6#include "src/torque/declarable.h" 7#include "src/torque/global-context.h" 8#include "src/torque/server-data.h" 9#include "src/torque/type-oracle.h" 10 11namespace v8 { 12namespace internal { 13namespace torque { 14namespace { 15 16template <class T> 17std::vector<T> EnsureNonempty(std::vector<T> list, const std::string& name, 18 const char* kind) { 19 if (list.empty()) { 20 ReportError("there is no ", kind, " named ", name); 21 } 22 return std::move(list); 23} 24 25template <class T, class Name> 26T EnsureUnique(const std::vector<T>& list, const Name& name, const char* kind) { 27 if (list.empty()) { 28 ReportError("there is no ", kind, " named ", name); 29 } 30 if (list.size() >= 2) { 31 ReportError("ambiguous reference to ", kind, " ", name); 32 } 33 return list.front(); 34} 35 36template <class T> 37void CheckAlreadyDeclared(const std::string& name, const char* new_type) { 38 std::vector<T*> declarations = 39 FilterDeclarables<T>(Declarations::TryLookupShallow(QualifiedName(name))); 40 if (!declarations.empty()) { 41 Scope* scope = CurrentScope::Get(); 42 ReportError("cannot redeclare ", name, " (type ", *new_type, scope, ")"); 43 } 44} 45 46} // namespace 47 48std::vector<Declarable*> Declarations::LookupGlobalScope( 49 const QualifiedName& name) { 50 std::vector<Declarable*> d = 51 GlobalContext::GetDefaultNamespace()->Lookup(name); 52 if (d.empty()) { 53 std::stringstream s; 54 s << "cannot find \"" << name << "\" in global scope"; 55 ReportError(s.str()); 56 } 57 return d; 58} 59 60const TypeAlias* Declarations::LookupTypeAlias(const QualifiedName& name) { 61 TypeAlias* declaration = 62 EnsureUnique(FilterDeclarables<TypeAlias>(Lookup(name)), name, "type"); 63 return declaration; 64} 65 66const Type* Declarations::LookupType(const QualifiedName& name) { 67 return LookupTypeAlias(name)->type(); 68} 69 70const Type* Declarations::LookupType(const Identifier* name) { 71 const TypeAlias* alias = LookupTypeAlias(QualifiedName(name->value)); 72 if (GlobalContext::collect_language_server_data()) { 73 LanguageServerData::AddDefinition(name->pos, 74 alias->GetDeclarationPosition()); 75 } 76 return alias->type(); 77} 78 79base::Optional<const Type*> Declarations::TryLookupType( 80 const QualifiedName& name) { 81 auto decls = FilterDeclarables<TypeAlias>(TryLookup(name)); 82 if (decls.empty()) return base::nullopt; 83 return EnsureUnique(std::move(decls), name, "type")->type(); 84} 85 86const Type* Declarations::LookupGlobalType(const QualifiedName& name) { 87 TypeAlias* declaration = EnsureUnique( 88 FilterDeclarables<TypeAlias>(LookupGlobalScope(name)), name, "type"); 89 return declaration->type(); 90} 91 92Builtin* Declarations::FindSomeInternalBuiltinWithType( 93 const BuiltinPointerType* type) { 94 for (auto& declarable : GlobalContext::AllDeclarables()) { 95 if (Builtin* builtin = Builtin::DynamicCast(declarable.get())) { 96 if (!builtin->IsExternal() && builtin->kind() == Builtin::kStub && 97 builtin->signature().return_type == type->return_type() && 98 builtin->signature().parameter_types.types == 99 type->parameter_types()) { 100 return builtin; 101 } 102 } 103 } 104 return nullptr; 105} 106 107Value* Declarations::LookupValue(const QualifiedName& name) { 108 return EnsureUnique(FilterDeclarables<Value>(Lookup(name)), name, "value"); 109} 110 111Macro* Declarations::TryLookupMacro(const std::string& name, 112 const TypeVector& types) { 113 std::vector<Macro*> macros = TryLookup<Macro>(QualifiedName(name)); 114 for (auto& m : macros) { 115 auto signature_types = m->signature().GetExplicitTypes(); 116 if (signature_types == types && !m->signature().parameter_types.var_args) { 117 return m; 118 } 119 } 120 return nullptr; 121} 122 123base::Optional<Builtin*> Declarations::TryLookupBuiltin( 124 const QualifiedName& name) { 125 std::vector<Builtin*> builtins = TryLookup<Builtin>(name); 126 if (builtins.empty()) return base::nullopt; 127 return EnsureUnique(builtins, name.name, "builtin"); 128} 129 130std::vector<GenericCallable*> Declarations::LookupGeneric( 131 const std::string& name) { 132 return EnsureNonempty( 133 FilterDeclarables<GenericCallable>(Lookup(QualifiedName(name))), name, 134 "generic callable"); 135} 136 137GenericCallable* Declarations::LookupUniqueGeneric(const QualifiedName& name) { 138 return EnsureUnique(FilterDeclarables<GenericCallable>(Lookup(name)), name, 139 "generic callable"); 140} 141 142GenericType* Declarations::LookupUniqueGenericType(const QualifiedName& name) { 143 return EnsureUnique(FilterDeclarables<GenericType>(Lookup(name)), name, 144 "generic type"); 145} 146 147GenericType* Declarations::LookupGlobalUniqueGenericType( 148 const std::string& name) { 149 return EnsureUnique( 150 FilterDeclarables<GenericType>(LookupGlobalScope(QualifiedName(name))), 151 name, "generic type"); 152} 153 154base::Optional<GenericType*> Declarations::TryLookupGenericType( 155 const QualifiedName& name) { 156 std::vector<GenericType*> results = TryLookup<GenericType>(name); 157 if (results.empty()) return base::nullopt; 158 return EnsureUnique(results, name.name, "generic type"); 159} 160 161Namespace* Declarations::DeclareNamespace(const std::string& name) { 162 return Declare(name, std::make_unique<Namespace>(name)); 163} 164 165TypeAlias* Declarations::DeclareType(const Identifier* name, const Type* type) { 166 CheckAlreadyDeclared<TypeAlias>(name->value, "type"); 167 return Declare(name->value, std::unique_ptr<TypeAlias>( 168 new TypeAlias(type, true, name->pos))); 169} 170 171TypeAlias* Declarations::PredeclareTypeAlias(const Identifier* name, 172 TypeDeclaration* type, 173 bool redeclaration) { 174 CheckAlreadyDeclared<TypeAlias>(name->value, "type"); 175 std::unique_ptr<TypeAlias> alias_ptr( 176 new TypeAlias(type, redeclaration, name->pos)); 177 return Declare(name->value, std::move(alias_ptr)); 178} 179 180TorqueMacro* Declarations::CreateTorqueMacro(std::string external_name, 181 std::string readable_name, 182 bool exported_to_csa, 183 Signature signature, 184 base::Optional<Statement*> body, 185 bool is_user_defined) { 186 external_name = GlobalContext::MakeUniqueName(external_name); 187 return RegisterDeclarable(std::unique_ptr<TorqueMacro>(new TorqueMacro( 188 std::move(external_name), std::move(readable_name), std::move(signature), 189 body, is_user_defined, exported_to_csa))); 190} 191 192ExternMacro* Declarations::CreateExternMacro( 193 std::string name, std::string external_assembler_name, 194 Signature signature) { 195 return RegisterDeclarable(std::unique_ptr<ExternMacro>( 196 new ExternMacro(std::move(name), std::move(external_assembler_name), 197 std::move(signature)))); 198} 199 200Macro* Declarations::DeclareMacro( 201 const std::string& name, bool accessible_from_csa, 202 base::Optional<std::string> external_assembler_name, 203 const Signature& signature, base::Optional<Statement*> body, 204 base::Optional<std::string> op, bool is_user_defined) { 205 if (Macro* existing_macro = 206 TryLookupMacro(name, signature.GetExplicitTypes())) { 207 if (existing_macro->ParentScope() == CurrentScope::Get()) { 208 ReportError("cannot redeclare macro ", name, 209 " with identical explicit parameters"); 210 } 211 } 212 Macro* macro; 213 if (external_assembler_name) { 214 macro = 215 CreateExternMacro(name, std::move(*external_assembler_name), signature); 216 } else { 217 macro = CreateTorqueMacro(name, name, accessible_from_csa, signature, body, 218 is_user_defined); 219 } 220 221 Declare(name, macro); 222 if (op) { 223 if (TryLookupMacro(*op, signature.GetExplicitTypes())) { 224 ReportError("cannot redeclare operator ", name, 225 " with identical explicit parameters"); 226 } 227 DeclareOperator(*op, macro); 228 } 229 return macro; 230} 231 232Method* Declarations::CreateMethod(AggregateType* container_type, 233 const std::string& name, Signature signature, 234 Statement* body) { 235 std::string generated_name = GlobalContext::MakeUniqueName( 236 "Method_" + container_type->SimpleName() + "_" + name); 237 Method* result = RegisterDeclarable(std::unique_ptr<Method>(new Method( 238 container_type, generated_name, name, std::move(signature), body))); 239 container_type->RegisterMethod(result); 240 return result; 241} 242 243Intrinsic* Declarations::CreateIntrinsic(const std::string& name, 244 const Signature& signature) { 245 Intrinsic* result = RegisterDeclarable(std::unique_ptr<Intrinsic>( 246 new Intrinsic(std::move(name), std::move(signature)))); 247 return result; 248} 249 250Intrinsic* Declarations::DeclareIntrinsic(const std::string& name, 251 const Signature& signature) { 252 Intrinsic* result = CreateIntrinsic(std::move(name), std::move(signature)); 253 Declare(name, result); 254 return result; 255} 256 257Builtin* Declarations::CreateBuiltin(std::string external_name, 258 std::string readable_name, 259 Builtin::Kind kind, Signature signature, 260 261 base::Optional<Statement*> body) { 262 return RegisterDeclarable(std::unique_ptr<Builtin>( 263 new Builtin(std::move(external_name), std::move(readable_name), kind, 264 std::move(signature), body))); 265} 266 267Builtin* Declarations::DeclareBuiltin(const std::string& name, 268 Builtin::Kind kind, 269 const Signature& signature, 270 271 base::Optional<Statement*> body) { 272 CheckAlreadyDeclared<Builtin>(name, "builtin"); 273 return Declare(name, CreateBuiltin(name, name, kind, signature, body)); 274} 275 276RuntimeFunction* Declarations::DeclareRuntimeFunction( 277 const std::string& name, const Signature& signature) { 278 CheckAlreadyDeclared<RuntimeFunction>(name, "runtime function"); 279 return Declare(name, RegisterDeclarable(std::unique_ptr<RuntimeFunction>( 280 new RuntimeFunction(name, signature)))); 281} 282 283ExternConstant* Declarations::DeclareExternConstant(Identifier* name, 284 const Type* type, 285 std::string value) { 286 CheckAlreadyDeclared<Value>(name->value, "constant"); 287 return Declare(name->value, std::unique_ptr<ExternConstant>( 288 new ExternConstant(name, type, value))); 289} 290 291NamespaceConstant* Declarations::DeclareNamespaceConstant(Identifier* name, 292 const Type* type, 293 Expression* body) { 294 CheckAlreadyDeclared<Value>(name->value, "constant"); 295 std::string external_name = GlobalContext::MakeUniqueName(name->value); 296 std::unique_ptr<NamespaceConstant> namespaceConstant( 297 new NamespaceConstant(name, std::move(external_name), type, body)); 298 NamespaceConstant* result = namespaceConstant.get(); 299 Declare(name->value, std::move(namespaceConstant)); 300 return result; 301} 302 303GenericCallable* Declarations::DeclareGenericCallable( 304 const std::string& name, GenericCallableDeclaration* ast_node) { 305 return Declare(name, std::unique_ptr<GenericCallable>( 306 new GenericCallable(name, ast_node))); 307} 308 309GenericType* Declarations::DeclareGenericType( 310 const std::string& name, GenericTypeDeclaration* ast_node) { 311 return Declare(name, 312 std::unique_ptr<GenericType>(new GenericType(name, ast_node))); 313} 314 315std::string Declarations::GetGeneratedCallableName( 316 const std::string& name, const TypeVector& specialized_types) { 317 std::string result = name; 318 for (auto type : specialized_types) { 319 result += "_" + type->SimpleName(); 320 } 321 return result; 322} 323 324Macro* Declarations::DeclareOperator(const std::string& name, Macro* m) { 325 GlobalContext::GetDefaultNamespace()->AddDeclarable(name, m); 326 return m; 327} 328 329} // namespace torque 330} // namespace internal 331} // namespace v8 332