• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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