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/declaration-visitor.h"
6
7 #include "src/torque/ast.h"
8 #include "src/torque/kythe-data.h"
9 #include "src/torque/server-data.h"
10 #include "src/torque/type-inference.h"
11 #include "src/torque/type-visitor.h"
12
13 namespace v8 {
14 namespace internal {
15 namespace torque {
16
GetOrCreateNamespace(const std::string & name)17 Namespace* GetOrCreateNamespace(const std::string& name) {
18 std::vector<Namespace*> existing_namespaces = FilterDeclarables<Namespace>(
19 Declarations::TryLookupShallow(QualifiedName(name)));
20 if (existing_namespaces.empty()) {
21 return Declarations::DeclareNamespace(name);
22 }
23 DCHECK_EQ(1, existing_namespaces.size());
24 return existing_namespaces.front();
25 }
26
Predeclare(Declaration * decl)27 void PredeclarationVisitor::Predeclare(Declaration* decl) {
28 CurrentSourcePosition::Scope scope(decl->pos);
29 switch (decl->kind) {
30 #define ENUM_ITEM(name) \
31 case AstNode::Kind::k##name: \
32 return Predeclare(name::cast(decl));
33 AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
34 #undef ENUM_ITEM
35 case AstNode::Kind::kNamespaceDeclaration:
36 return Predeclare(NamespaceDeclaration::cast(decl));
37 case AstNode::Kind::kGenericCallableDeclaration:
38 return Predeclare(GenericCallableDeclaration::cast(decl));
39 case AstNode::Kind::kGenericTypeDeclaration:
40 return Predeclare(GenericTypeDeclaration::cast(decl));
41
42 default:
43 // Only processes type declaration nodes, namespaces and generics.
44 break;
45 }
46 }
47
Visit(Declaration * decl)48 void DeclarationVisitor::Visit(Declaration* decl) {
49 CurrentSourcePosition::Scope scope(decl->pos);
50 switch (decl->kind) {
51 #define ENUM_ITEM(name) \
52 case AstNode::Kind::k##name: \
53 return Visit(name::cast(decl));
54 AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
55 #undef ENUM_ITEM
56 default:
57 UNIMPLEMENTED();
58 }
59 }
60
CreateBuiltin(BuiltinDeclaration * decl,std::string external_name,std::string readable_name,Signature signature,base::Optional<Statement * > body)61 Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
62 std::string external_name,
63 std::string readable_name,
64 Signature signature,
65 base::Optional<Statement*> body) {
66 const bool javascript = decl->javascript_linkage;
67 const bool varargs = decl->parameters.has_varargs;
68 Builtin::Kind kind = !javascript ? Builtin::kStub
69 : varargs ? Builtin::kVarArgsJavaScript
70 : Builtin::kFixedArgsJavaScript;
71
72 if (varargs && !javascript) {
73 Error("Rest parameters require ", decl->name,
74 " to be a JavaScript builtin");
75 }
76
77 if (javascript) {
78 if (!signature.return_type->IsSubtypeOf(TypeOracle::GetJSAnyType())) {
79 Error("Return type of JavaScript-linkage builtins has to be JSAny.")
80 .Position(decl->return_type->pos);
81 }
82 for (size_t i = signature.implicit_count;
83 i < signature.parameter_types.types.size(); ++i) {
84 const Type* parameter_type = signature.parameter_types.types[i];
85 if (!TypeOracle::GetJSAnyType()->IsSubtypeOf(parameter_type)) {
86 Error(
87 "Parameters of JavaScript-linkage builtins have to be a supertype "
88 "of JSAny.")
89 .Position(decl->parameters.types[i]->pos);
90 }
91 }
92 }
93
94 for (size_t i = 0; i < signature.types().size(); ++i) {
95 if (signature.types()[i]->StructSupertype()) {
96 Error("Builtin do not support structs as arguments, but argument ",
97 signature.parameter_names[i], " has type ", *signature.types()[i],
98 ".");
99 }
100 }
101
102 if (signature.return_type->StructSupertype() && javascript) {
103 Error(
104 "Builtins with JS linkage cannot return structs, but the return type "
105 "is ",
106 *signature.return_type, ".");
107 }
108
109 if (signature.return_type == TypeOracle::GetVoidType()) {
110 Error("Builtins cannot have return type void.");
111 }
112
113 Builtin* builtin = Declarations::CreateBuiltin(std::move(external_name),
114 std::move(readable_name), kind,
115 std::move(signature), body);
116 // TODO(v8:12261): Recheck this.
117 // builtin->SetIdentifierPosition(decl->name->pos);
118 return builtin;
119 }
120
Visit(ExternalBuiltinDeclaration * decl)121 void DeclarationVisitor::Visit(ExternalBuiltinDeclaration* decl) {
122 Builtin* builtin =
123 CreateBuiltin(decl, decl->name->value, decl->name->value,
124 TypeVisitor::MakeSignature(decl), base::nullopt);
125 builtin->SetIdentifierPosition(decl->name->pos);
126 Declarations::Declare(decl->name->value, builtin);
127 }
128
Visit(ExternalRuntimeDeclaration * decl)129 void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl) {
130 Signature signature = TypeVisitor::MakeSignature(decl);
131 if (signature.parameter_types.types.size() == 0) {
132 ReportError(
133 "Missing parameters for runtime function, at least the context "
134 "parameter is required.");
135 }
136 if (!(signature.parameter_types.types[0] == TypeOracle::GetContextType() ||
137 signature.parameter_types.types[0] == TypeOracle::GetNoContextType())) {
138 ReportError(
139 "first parameter to runtime functions has to be the context and have "
140 "type Context or NoContext, but found type ",
141 *signature.parameter_types.types[0]);
142 }
143 if (!(signature.return_type->IsSubtypeOf(TypeOracle::GetStrongTaggedType()) ||
144 signature.return_type == TypeOracle::GetVoidType() ||
145 signature.return_type == TypeOracle::GetNeverType())) {
146 ReportError(
147 "runtime functions can only return strong tagged values, but "
148 "found type ",
149 *signature.return_type);
150 }
151 for (const Type* parameter_type : signature.parameter_types.types) {
152 if (!parameter_type->IsSubtypeOf(TypeOracle::GetStrongTaggedType())) {
153 ReportError(
154 "runtime functions can only take strong tagged parameters, but "
155 "found type ",
156 *parameter_type);
157 }
158 }
159
160 RuntimeFunction* function =
161 Declarations::DeclareRuntimeFunction(decl->name->value, signature);
162 function->SetIdentifierPosition(decl->name->pos);
163 function->SetPosition(decl->pos);
164 if (GlobalContext::collect_kythe_data()) {
165 KytheData::AddFunctionDefinition(function);
166 }
167 }
168
Visit(ExternalMacroDeclaration * decl)169 void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl) {
170 Macro* macro = Declarations::DeclareMacro(
171 decl->name->value, true, decl->external_assembler_name,
172 TypeVisitor::MakeSignature(decl), base::nullopt, decl->op);
173 macro->SetIdentifierPosition(decl->name->pos);
174 macro->SetPosition(decl->pos);
175 if (GlobalContext::collect_kythe_data()) {
176 KytheData::AddFunctionDefinition(macro);
177 }
178 }
179
Visit(TorqueBuiltinDeclaration * decl)180 void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl) {
181 auto builtin = CreateBuiltin(decl, decl->name->value, decl->name->value,
182 TypeVisitor::MakeSignature(decl), decl->body);
183 builtin->SetIdentifierPosition(decl->name->pos);
184 builtin->SetPosition(decl->pos);
185 Declarations::Declare(decl->name->value, builtin);
186 }
187
Visit(TorqueMacroDeclaration * decl)188 void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl) {
189 Macro* macro = Declarations::DeclareMacro(
190 decl->name->value, decl->export_to_csa, base::nullopt,
191 TypeVisitor::MakeSignature(decl), decl->body, decl->op);
192 macro->SetIdentifierPosition(decl->name->pos);
193 macro->SetPosition(decl->pos);
194 if (GlobalContext::collect_kythe_data()) {
195 KytheData::AddFunctionDefinition(macro);
196 }
197 }
198
Visit(IntrinsicDeclaration * decl)199 void DeclarationVisitor::Visit(IntrinsicDeclaration* decl) {
200 Declarations::DeclareIntrinsic(decl->name->value,
201 TypeVisitor::MakeSignature(decl));
202 }
203
Visit(ConstDeclaration * decl)204 void DeclarationVisitor::Visit(ConstDeclaration* decl) {
205 auto constant = Declarations::DeclareNamespaceConstant(
206 decl->name, TypeVisitor::ComputeType(decl->type), decl->expression);
207 if (GlobalContext::collect_kythe_data()) {
208 KytheData::AddConstantDefinition(constant);
209 }
210 }
211
Visit(SpecializationDeclaration * decl)212 void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
213 std::vector<GenericCallable*> generic_list =
214 Declarations::LookupGeneric(decl->name->value);
215 // Find the matching generic specialization based on the concrete parameter
216 // list.
217 GenericCallable* matching_generic = nullptr;
218 Signature signature_with_types = TypeVisitor::MakeSignature(decl);
219 for (GenericCallable* generic : generic_list) {
220 // This argument inference is just to trigger constraint checking on the
221 // generic arguments.
222 TypeArgumentInference inference = generic->InferSpecializationTypes(
223 TypeVisitor::ComputeTypeVector(decl->generic_parameters), {});
224 if (inference.HasFailed()) {
225 continue;
226 }
227 Signature generic_signature_with_types =
228 MakeSpecializedSignature(SpecializationKey<GenericCallable>{
229 generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
230 if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
231 ParameterMode::kIgnoreImplicit)) {
232 if (matching_generic != nullptr) {
233 std::stringstream stream;
234 stream << "specialization of " << decl->name
235 << " is ambigous, it matches more than one generic declaration ("
236 << *matching_generic << " and " << *generic << ")";
237 ReportError(stream.str());
238 }
239 matching_generic = generic;
240 }
241 }
242
243 if (matching_generic == nullptr) {
244 std::stringstream stream;
245 if (generic_list.size() == 0) {
246 stream << "no generic defined with the name " << decl->name;
247 ReportError(stream.str());
248 }
249 stream << "specialization of " << decl->name
250 << " doesn't match any generic declaration\n";
251 stream << "specialization signature:";
252 stream << "\n " << signature_with_types;
253 stream << "\ncandidates are:";
254 for (GenericCallable* generic : generic_list) {
255 stream << "\n "
256 << MakeSpecializedSignature(SpecializationKey<GenericCallable>{
257 generic,
258 TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
259 }
260 ReportError(stream.str());
261 }
262
263 if (GlobalContext::collect_language_server_data()) {
264 LanguageServerData::AddDefinition(decl->name->pos,
265 matching_generic->IdentifierPosition());
266 }
267
268 CallableDeclaration* generic_declaration = matching_generic->declaration();
269
270 Specialize(SpecializationKey<GenericCallable>{matching_generic,
271 TypeVisitor::ComputeTypeVector(
272 decl->generic_parameters)},
273 generic_declaration, decl, decl->body, decl->pos);
274 }
275
Visit(ExternConstDeclaration * decl)276 void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
277 const Type* type = TypeVisitor::ComputeType(decl->type);
278 if (!type->IsConstexpr()) {
279 std::stringstream stream;
280 stream << "extern constants must have constexpr type, but found: \""
281 << *type << "\"\n";
282 ReportError(stream.str());
283 }
284
285 ExternConstant* constant =
286 Declarations::DeclareExternConstant(decl->name, type, decl->literal);
287 if (GlobalContext::collect_kythe_data()) {
288 KytheData::AddConstantDefinition(constant);
289 }
290 }
291
Visit(CppIncludeDeclaration * decl)292 void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
293 GlobalContext::AddCppInclude(decl->include_path);
294 }
295
DeclareSpecializedTypes(const SpecializationKey<GenericCallable> & key)296 void DeclarationVisitor::DeclareSpecializedTypes(
297 const SpecializationKey<GenericCallable>& key) {
298 size_t i = 0;
299 const std::size_t generic_parameter_count =
300 key.generic->generic_parameters().size();
301 if (generic_parameter_count != key.specialized_types.size()) {
302 std::stringstream stream;
303 stream << "Wrong generic argument count for specialization of \""
304 << key.generic->name() << "\", expected: " << generic_parameter_count
305 << ", actual: " << key.specialized_types.size();
306 ReportError(stream.str());
307 }
308
309 for (auto type : key.specialized_types) {
310 Identifier* generic_type_name = key.generic->generic_parameters()[i++].name;
311 TypeAlias* alias = Declarations::DeclareType(generic_type_name, type);
312 alias->SetIsUserDefined(false);
313 }
314 }
315
MakeSpecializedSignature(const SpecializationKey<GenericCallable> & key)316 Signature DeclarationVisitor::MakeSpecializedSignature(
317 const SpecializationKey<GenericCallable>& key) {
318 CurrentScope::Scope generic_scope(key.generic->ParentScope());
319 // Create a temporary fake-namespace just to temporarily declare the
320 // specialization aliases for the generic types to create a signature.
321 Namespace tmp_namespace("_tmp");
322 CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
323 DeclareSpecializedTypes(key);
324 return TypeVisitor::MakeSignature(key.generic->declaration());
325 }
326
SpecializeImplicit(const SpecializationKey<GenericCallable> & key)327 Callable* DeclarationVisitor::SpecializeImplicit(
328 const SpecializationKey<GenericCallable>& key) {
329 base::Optional<Statement*> body = key.generic->CallableBody();
330 if (!body && IntrinsicDeclaration::DynamicCast(key.generic->declaration()) ==
331 nullptr) {
332 ReportError("missing specialization of ", key.generic->name(),
333 " with types <", key.specialized_types, "> declared at ",
334 key.generic->Position());
335 }
336 SpecializationRequester requester{CurrentSourcePosition::Get(),
337 CurrentScope::Get(), ""};
338 CurrentScope::Scope generic_scope(key.generic->ParentScope());
339 Callable* result = Specialize(key, key.generic->declaration(), base::nullopt,
340 body, CurrentSourcePosition::Get());
341 result->SetIsUserDefined(false);
342 requester.name = result->ReadableName();
343 result->SetSpecializationRequester(requester);
344 CurrentScope::Scope callable_scope(result);
345 DeclareSpecializedTypes(key);
346 return result;
347 }
348
Specialize(const SpecializationKey<GenericCallable> & key,CallableDeclaration * declaration,base::Optional<const SpecializationDeclaration * > explicit_specialization,base::Optional<Statement * > body,SourcePosition position)349 Callable* DeclarationVisitor::Specialize(
350 const SpecializationKey<GenericCallable>& key,
351 CallableDeclaration* declaration,
352 base::Optional<const SpecializationDeclaration*> explicit_specialization,
353 base::Optional<Statement*> body, SourcePosition position) {
354 CurrentSourcePosition::Scope pos_scope(position);
355 size_t generic_parameter_count = key.generic->generic_parameters().size();
356 if (generic_parameter_count != key.specialized_types.size()) {
357 std::stringstream stream;
358 stream << "number of template parameters ("
359 << std::to_string(key.specialized_types.size())
360 << ") to intantiation of generic " << declaration->name
361 << " doesnt match the generic's declaration ("
362 << std::to_string(generic_parameter_count) << ")";
363 ReportError(stream.str());
364 }
365 if (key.generic->GetSpecialization(key.specialized_types)) {
366 ReportError("cannot redeclare specialization of ", key.generic->name(),
367 " with types <", key.specialized_types, ">");
368 }
369
370 Signature type_signature =
371 explicit_specialization
372 ? TypeVisitor::MakeSignature(*explicit_specialization)
373 : MakeSpecializedSignature(key);
374
375 std::string generated_name = Declarations::GetGeneratedCallableName(
376 declaration->name->value, key.specialized_types);
377 std::stringstream readable_name;
378 readable_name << declaration->name->value << "<";
379 bool first = true;
380 for (const Type* t : key.specialized_types) {
381 if (!first) readable_name << ", ";
382 readable_name << *t;
383 first = false;
384 }
385 readable_name << ">";
386 Callable* callable;
387 if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
388 callable =
389 Declarations::CreateTorqueMacro(generated_name, readable_name.str(),
390 false, type_signature, *body, true);
391 } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
392 callable =
393 Declarations::CreateIntrinsic(declaration->name->value, type_signature);
394 } else {
395 BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
396 callable =
397 CreateBuiltin(builtin, GlobalContext::MakeUniqueName(generated_name),
398 readable_name.str(), type_signature, *body);
399 }
400 key.generic->AddSpecialization(key.specialized_types, callable);
401 return callable;
402 }
403
ResolvePredeclarations()404 void PredeclarationVisitor::ResolvePredeclarations() {
405 const auto& all_declarables = GlobalContext::AllDeclarables();
406 for (size_t i = 0; i < all_declarables.size(); ++i) {
407 Declarable* declarable = all_declarables[i].get();
408 if (const TypeAlias* alias = TypeAlias::DynamicCast(declarable)) {
409 CurrentScope::Scope scope_activator(alias->ParentScope());
410 CurrentSourcePosition::Scope position_activator(alias->Position());
411 alias->Resolve();
412 }
413 }
414 }
415
416 } // namespace torque
417 } // namespace internal
418 } // namespace v8
419