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 
11 namespace v8 {
12 namespace internal {
13 namespace torque {
14 namespace {
15 
16 template <class T>
EnsureNonempty(std::vector<T> list,const std::string & name,const char * kind)17 std::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 
25 template <class T, class Name>
26 T 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 
36 template <class T>
CheckAlreadyDeclared(const std::string & name,const char * new_type)37 void 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 
LookupGlobalScope(const QualifiedName & name)48 std::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 
LookupTypeAlias(const QualifiedName & name)60 const TypeAlias* Declarations::LookupTypeAlias(const QualifiedName& name) {
61   TypeAlias* declaration =
62       EnsureUnique(FilterDeclarables<TypeAlias>(Lookup(name)), name, "type");
63   return declaration;
64 }
65 
LookupType(const QualifiedName & name)66 const Type* Declarations::LookupType(const QualifiedName& name) {
67   return LookupTypeAlias(name)->type();
68 }
69 
LookupType(const Identifier * name)70 const 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 
TryLookupType(const QualifiedName & name)79 base::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 
LookupGlobalType(const QualifiedName & name)86 const Type* Declarations::LookupGlobalType(const QualifiedName& name) {
87   TypeAlias* declaration = EnsureUnique(
88       FilterDeclarables<TypeAlias>(LookupGlobalScope(name)), name, "type");
89   return declaration->type();
90 }
91 
FindSomeInternalBuiltinWithType(const BuiltinPointerType * type)92 Builtin* 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 
LookupValue(const QualifiedName & name)107 Value* Declarations::LookupValue(const QualifiedName& name) {
108   return EnsureUnique(FilterDeclarables<Value>(Lookup(name)), name, "value");
109 }
110 
TryLookupMacro(const std::string & name,const TypeVector & types)111 Macro* 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 
TryLookupBuiltin(const QualifiedName & name)123 base::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 
LookupGeneric(const std::string & name)130 std::vector<GenericCallable*> Declarations::LookupGeneric(
131     const std::string& name) {
132   return EnsureNonempty(
133       FilterDeclarables<GenericCallable>(Lookup(QualifiedName(name))), name,
134       "generic callable");
135 }
136 
LookupUniqueGeneric(const QualifiedName & name)137 GenericCallable* Declarations::LookupUniqueGeneric(const QualifiedName& name) {
138   return EnsureUnique(FilterDeclarables<GenericCallable>(Lookup(name)), name,
139                       "generic callable");
140 }
141 
LookupUniqueGenericType(const QualifiedName & name)142 GenericType* Declarations::LookupUniqueGenericType(const QualifiedName& name) {
143   return EnsureUnique(FilterDeclarables<GenericType>(Lookup(name)), name,
144                       "generic type");
145 }
146 
LookupGlobalUniqueGenericType(const std::string & name)147 GenericType* Declarations::LookupGlobalUniqueGenericType(
148     const std::string& name) {
149   return EnsureUnique(
150       FilterDeclarables<GenericType>(LookupGlobalScope(QualifiedName(name))),
151       name, "generic type");
152 }
153 
TryLookupGenericType(const QualifiedName & name)154 base::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 
DeclareNamespace(const std::string & name)161 Namespace* Declarations::DeclareNamespace(const std::string& name) {
162   return Declare(name, std::make_unique<Namespace>(name));
163 }
164 
DeclareType(const Identifier * name,const Type * type)165 TypeAlias* 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 
PredeclareTypeAlias(const Identifier * name,TypeDeclaration * type,bool redeclaration)171 const TypeAlias* 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 
CreateTorqueMacro(std::string external_name,std::string readable_name,bool exported_to_csa,Signature signature,base::Optional<Statement * > body,bool is_user_defined)180 TorqueMacro* 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 
CreateExternMacro(std::string name,std::string external_assembler_name,Signature signature)192 ExternMacro* 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 
DeclareMacro(const std::string & name,bool accessible_from_csa,base::Optional<std::string> external_assembler_name,const Signature & signature,base::Optional<Statement * > body,base::Optional<std::string> op,bool is_user_defined)200 Macro* 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 (TryLookupMacro(name, signature.GetExplicitTypes())) {
206     ReportError("cannot redeclare macro ", name,
207                 " with identical explicit parameters");
208   }
209   Macro* macro;
210   if (external_assembler_name) {
211     macro =
212         CreateExternMacro(name, std::move(*external_assembler_name), signature);
213   } else {
214     macro = CreateTorqueMacro(name, name, accessible_from_csa, signature, body,
215                               is_user_defined);
216   }
217 
218   Declare(name, macro);
219   if (op) {
220     if (TryLookupMacro(*op, signature.GetExplicitTypes())) {
221       ReportError("cannot redeclare operator ", name,
222                   " with identical explicit parameters");
223     }
224     DeclareOperator(*op, macro);
225   }
226   return macro;
227 }
228 
CreateMethod(AggregateType * container_type,const std::string & name,Signature signature,Statement * body)229 Method* Declarations::CreateMethod(AggregateType* container_type,
230                                    const std::string& name, Signature signature,
231                                    Statement* body) {
232   std::string generated_name = GlobalContext::MakeUniqueName(
233       "Method_" + container_type->SimpleName() + "_" + name);
234   Method* result = RegisterDeclarable(std::unique_ptr<Method>(new Method(
235       container_type, generated_name, name, std::move(signature), body)));
236   container_type->RegisterMethod(result);
237   return result;
238 }
239 
CreateIntrinsic(const std::string & name,const Signature & signature)240 Intrinsic* Declarations::CreateIntrinsic(const std::string& name,
241                                          const Signature& signature) {
242   Intrinsic* result = RegisterDeclarable(std::unique_ptr<Intrinsic>(
243       new Intrinsic(std::move(name), std::move(signature))));
244   return result;
245 }
246 
DeclareIntrinsic(const std::string & name,const Signature & signature)247 Intrinsic* Declarations::DeclareIntrinsic(const std::string& name,
248                                           const Signature& signature) {
249   Intrinsic* result = CreateIntrinsic(std::move(name), std::move(signature));
250   Declare(name, result);
251   return result;
252 }
253 
CreateBuiltin(std::string external_name,std::string readable_name,Builtin::Kind kind,Signature signature,base::Optional<Statement * > body)254 Builtin* Declarations::CreateBuiltin(std::string external_name,
255                                      std::string readable_name,
256                                      Builtin::Kind kind, Signature signature,
257 
258                                      base::Optional<Statement*> body) {
259   return RegisterDeclarable(std::unique_ptr<Builtin>(
260       new Builtin(std::move(external_name), std::move(readable_name), kind,
261                   std::move(signature), body)));
262 }
263 
DeclareBuiltin(const std::string & name,Builtin::Kind kind,const Signature & signature,base::Optional<Statement * > body)264 Builtin* Declarations::DeclareBuiltin(const std::string& name,
265                                       Builtin::Kind kind,
266                                       const Signature& signature,
267 
268                                       base::Optional<Statement*> body) {
269   CheckAlreadyDeclared<Builtin>(name, "builtin");
270   return Declare(name, CreateBuiltin(name, name, kind, signature, body));
271 }
272 
DeclareRuntimeFunction(const std::string & name,const Signature & signature)273 RuntimeFunction* Declarations::DeclareRuntimeFunction(
274     const std::string& name, const Signature& signature) {
275   CheckAlreadyDeclared<RuntimeFunction>(name, "runtime function");
276   return Declare(name, RegisterDeclarable(std::unique_ptr<RuntimeFunction>(
277                            new RuntimeFunction(name, signature))));
278 }
279 
DeclareExternConstant(Identifier * name,const Type * type,std::string value)280 void Declarations::DeclareExternConstant(Identifier* name, const Type* type,
281                                          std::string value) {
282   CheckAlreadyDeclared<Value>(name->value, "constant");
283   Declare(name->value, std::unique_ptr<ExternConstant>(
284                            new ExternConstant(name, type, value)));
285 }
286 
DeclareNamespaceConstant(Identifier * name,const Type * type,Expression * body)287 NamespaceConstant* Declarations::DeclareNamespaceConstant(Identifier* name,
288                                                           const Type* type,
289                                                           Expression* body) {
290   CheckAlreadyDeclared<Value>(name->value, "constant");
291   std::string external_name = GlobalContext::MakeUniqueName(name->value);
292   std::unique_ptr<NamespaceConstant> namespaceConstant(
293       new NamespaceConstant(name, std::move(external_name), type, body));
294   NamespaceConstant* result = namespaceConstant.get();
295   Declare(name->value, std::move(namespaceConstant));
296   return result;
297 }
298 
DeclareGenericCallable(const std::string & name,GenericCallableDeclaration * ast_node)299 GenericCallable* Declarations::DeclareGenericCallable(
300     const std::string& name, GenericCallableDeclaration* ast_node) {
301   return Declare(name, std::unique_ptr<GenericCallable>(
302                            new GenericCallable(name, ast_node)));
303 }
304 
DeclareGenericType(const std::string & name,GenericTypeDeclaration * ast_node)305 GenericType* Declarations::DeclareGenericType(
306     const std::string& name, GenericTypeDeclaration* ast_node) {
307   return Declare(name,
308                  std::unique_ptr<GenericType>(new GenericType(name, ast_node)));
309 }
310 
GetGeneratedCallableName(const std::string & name,const TypeVector & specialized_types)311 std::string Declarations::GetGeneratedCallableName(
312     const std::string& name, const TypeVector& specialized_types) {
313   std::string result = name;
314   for (auto type : specialized_types) {
315     result += "_" + type->SimpleName();
316   }
317   return result;
318 }
319 
DeclareOperator(const std::string & name,Macro * m)320 Macro* Declarations::DeclareOperator(const std::string& name, Macro* m) {
321   GlobalContext::GetDefaultNamespace()->AddDeclarable(name, m);
322   return m;
323 }
324 
325 }  // namespace torque
326 }  // namespace internal
327 }  // namespace v8
328