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>
EnsureUnique(const std::vector<T> & list,const Name & name,const char * kind)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 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 (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
CreateMethod(AggregateType * container_type,const std::string & name,Signature signature,Statement * body)232 Method* 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
CreateIntrinsic(const std::string & name,const Signature & signature)243 Intrinsic* 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
DeclareIntrinsic(const std::string & name,const Signature & signature)250 Intrinsic* 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
CreateBuiltin(std::string external_name,std::string readable_name,Builtin::Kind kind,Signature signature,base::Optional<Statement * > body)257 Builtin* 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
DeclareBuiltin(const std::string & name,Builtin::Kind kind,const Signature & signature,base::Optional<Statement * > body)267 Builtin* 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
DeclareRuntimeFunction(const std::string & name,const Signature & signature)276 RuntimeFunction* 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
DeclareExternConstant(Identifier * name,const Type * type,std::string value)283 ExternConstant* 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
DeclareNamespaceConstant(Identifier * name,const Type * type,Expression * body)291 NamespaceConstant* 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
DeclareGenericCallable(const std::string & name,GenericCallableDeclaration * ast_node)303 GenericCallable* 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
DeclareGenericType(const std::string & name,GenericTypeDeclaration * ast_node)309 GenericType* 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
GetGeneratedCallableName(const std::string & name,const TypeVector & specialized_types)315 std::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
DeclareOperator(const std::string & name,Macro * m)324 Macro* 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