Line data Source code
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 : #include "src/torque/ast.h"
7 :
8 : namespace v8 {
9 : namespace internal {
10 : namespace torque {
11 :
12 1090 : void DeclarationVisitor::Visit(Declaration* decl) {
13 1090 : CurrentSourcePosition::Scope scope(decl->pos);
14 1090 : switch (decl->kind) {
15 : #define ENUM_ITEM(name) \
16 : case AstNode::Kind::k##name: \
17 : return Visit(name::cast(decl));
18 1042 : AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
19 : #undef ENUM_ITEM
20 : default:
21 0 : UNIMPLEMENTED();
22 : }
23 : }
24 :
25 649 : void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
26 : base::Optional<Statement*> body) {
27 649 : switch (decl->kind) {
28 : #define ENUM_ITEM(name) \
29 : case AstNode::Kind::k##name: \
30 : return Visit(name::cast(decl), signature, body);
31 649 : AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
32 : #undef ENUM_ITEM
33 : default:
34 0 : UNIMPLEMENTED();
35 : }
36 : }
37 :
38 134 : Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
39 : std::string external_name,
40 : std::string readable_name,
41 : Signature signature,
42 : base::Optional<Statement*> body) {
43 134 : const bool javascript = decl->javascript_linkage;
44 134 : const bool varargs = decl->signature->parameters.has_varargs;
45 : Builtin::Kind kind = !javascript ? Builtin::kStub
46 : : varargs ? Builtin::kVarArgsJavaScript
47 134 : : Builtin::kFixedArgsJavaScript;
48 :
49 536 : if (signature.types().size() == 0 ||
50 : !(signature.types()[0] ==
51 536 : Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
52 0 : std::stringstream stream;
53 0 : stream << "first parameter to builtin " << decl->name
54 0 : << " is not a context but should be";
55 0 : ReportError(stream.str());
56 : }
57 :
58 134 : if (varargs && !javascript) {
59 0 : std::stringstream stream;
60 0 : stream << "builtin " << decl->name
61 0 : << " with rest parameters must be a JavaScript builtin";
62 0 : ReportError(stream.str());
63 : }
64 :
65 134 : if (javascript) {
66 188 : if (signature.types().size() < 2 ||
67 : !(signature.types()[1] ==
68 188 : Declarations::LookupGlobalType(OBJECT_TYPE_STRING))) {
69 0 : std::stringstream stream;
70 0 : stream << "second parameter to javascript builtin " << decl->name
71 0 : << " is " << *signature.types()[1] << " but should be Object";
72 0 : ReportError(stream.str());
73 : }
74 : }
75 :
76 134 : if (const StructType* struct_type =
77 134 : StructType::DynamicCast(signature.return_type)) {
78 0 : std::stringstream stream;
79 0 : stream << "builtins (in this case" << decl->name
80 0 : << ") cannot return structs (in this case " << struct_type->name()
81 0 : << ")";
82 0 : ReportError(stream.str());
83 : }
84 :
85 : return Declarations::CreateBuiltin(
86 : std::move(external_name), std::move(readable_name), kind,
87 536 : std::move(signature), decl->transitioning, body);
88 : }
89 :
90 11 : void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
91 : const Signature& signature,
92 : base::Optional<Statement*> body) {
93 11 : if (GlobalContext::verbose()) {
94 0 : std::cout << "found declaration of external runtime " << decl->name
95 0 : << " with signature ";
96 : }
97 :
98 44 : if (signature.parameter_types.types.size() == 0 ||
99 : !(signature.parameter_types.types[0] ==
100 44 : Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
101 0 : std::stringstream stream;
102 0 : stream << "first parameter to runtime " << decl->name
103 0 : << " is not a context but should be";
104 0 : ReportError(stream.str());
105 : }
106 :
107 22 : if (signature.return_type->IsStructType()) {
108 0 : std::stringstream stream;
109 0 : stream << "runtime functions (in this case" << decl->name
110 0 : << ") cannot return structs (in this case "
111 0 : << static_cast<const StructType*>(signature.return_type)->name()
112 0 : << ")";
113 0 : ReportError(stream.str());
114 : }
115 :
116 : Declarations::DeclareRuntimeFunction(decl->name, signature,
117 11 : decl->transitioning);
118 11 : }
119 :
120 356 : void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
121 : const Signature& signature,
122 : base::Optional<Statement*> body) {
123 356 : if (GlobalContext::verbose()) {
124 0 : std::cout << "found declaration of external macro " << decl->name
125 0 : << " with signature ";
126 : }
127 :
128 : Declarations::DeclareMacro(decl->name, decl->external_assembler_name,
129 1424 : signature, decl->transitioning, body, decl->op);
130 356 : }
131 :
132 64 : void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
133 : const Signature& signature,
134 : base::Optional<Statement*> body) {
135 : Declarations::Declare(
136 192 : decl->name, CreateBuiltin(decl, decl->name, decl->name, signature, body));
137 64 : }
138 :
139 204 : void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
140 : const Signature& signature,
141 : base::Optional<Statement*> body) {
142 : Declarations::DeclareMacro(decl->name, base::nullopt, signature,
143 816 : decl->transitioning, body, decl->op);
144 204 : }
145 :
146 0 : void DeclarationVisitor::Visit(IntrinsicDeclaration* decl,
147 : const Signature& signature,
148 : base::Optional<Statement*> body) {
149 0 : Declarations::DeclareIntrinsic(decl->name, signature);
150 0 : }
151 :
152 40 : void DeclarationVisitor::Visit(ConstDeclaration* decl) {
153 : Declarations::DeclareNamespaceConstant(
154 40 : decl->name, Declarations::GetType(decl->type), decl->expression);
155 40 : }
156 :
157 649 : void DeclarationVisitor::Visit(StandardDeclaration* decl) {
158 1298 : Signature signature = MakeSignature(decl->callable->signature.get());
159 649 : Visit(decl->callable, signature, decl->body);
160 649 : }
161 :
162 0 : void DeclarationVisitor::Visit(GenericDeclaration* decl) {
163 48 : Declarations::DeclareGeneric(decl->callable->name, decl);
164 0 : }
165 :
166 17 : static Statement* WrapBodyWithNoThrow(Statement* body, std::string reason) {
167 : return MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>(
168 : true, MakeNode<StatementExpression>(body),
169 : MakeNode<LabelBlock>("_catch", ParameterList{},
170 51 : MakeNode<DebugStatement>(reason, true))));
171 : }
172 :
173 131 : void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
174 131 : if ((decl->body != nullptr) == decl->external) {
175 0 : std::stringstream stream;
176 0 : stream << "specialization of " << decl->name
177 0 : << " must either be marked 'extern' or have a body";
178 0 : ReportError(stream.str());
179 : }
180 :
181 131 : std::vector<Generic*> generic_list = Declarations::LookupGeneric(decl->name);
182 : // Find the matching generic specialization based on the concrete parameter
183 : // list.
184 131 : Generic* matching_generic = nullptr;
185 262 : Signature signature_with_types = MakeSignature(decl->signature.get());
186 401 : for (Generic* generic : generic_list) {
187 : Signature generic_signature_with_types = MakeSpecializedSignature(
188 278 : SpecializationKey{generic, GetTypeVector(decl->generic_parameters)});
189 139 : if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
190 : ParameterMode::kIgnoreImplicit)) {
191 131 : if (matching_generic != nullptr) {
192 0 : std::stringstream stream;
193 0 : stream << "specialization of " << decl->name
194 0 : << " is ambigous, it matches more than one generic declaration ("
195 0 : << *matching_generic << " and " << *generic << ")";
196 0 : ReportError(stream.str());
197 : }
198 : matching_generic = generic;
199 : }
200 139 : }
201 :
202 131 : if (matching_generic == nullptr) {
203 0 : std::stringstream stream;
204 0 : if (generic_list.size() == 0) {
205 0 : stream << "no generic defined with the name " << decl->name;
206 0 : ReportError(stream.str());
207 : }
208 0 : stream << "specialization of " << decl->name
209 0 : << " doesn't match any generic declaration\n";
210 0 : stream << "specialization signature:";
211 0 : stream << "\n " << signature_with_types;
212 0 : stream << "\ncandidates are:";
213 0 : for (Generic* generic : generic_list) {
214 0 : stream << "\n "
215 : << MakeSpecializedSignature(SpecializationKey{
216 0 : generic, GetTypeVector(decl->generic_parameters)});
217 : }
218 0 : ReportError(stream.str());
219 : }
220 :
221 : Specialize(SpecializationKey{matching_generic,
222 : GetTypeVector(decl->generic_parameters)},
223 : matching_generic->declaration()->callable, decl->signature.get(),
224 262 : decl->body);
225 131 : }
226 :
227 70 : void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
228 70 : const Type* type = Declarations::GetType(decl->type);
229 70 : if (!type->IsConstexpr()) {
230 0 : std::stringstream stream;
231 0 : stream << "extern constants must have constexpr type, but found: \""
232 0 : << *type << "\"\n";
233 0 : ReportError(stream.str());
234 : }
235 :
236 140 : Declarations::DeclareExternConstant(decl->name, type, decl->literal);
237 70 : }
238 :
239 17 : void DeclarationVisitor::DeclareMethods(
240 : AggregateType* container_type, const std::vector<Declaration*>& methods) {
241 : // Declare the class' methods
242 : IdentifierExpression* constructor_this = MakeNode<IdentifierExpression>(
243 17 : std::vector<std::string>{}, kThisParameterName);
244 38 : for (auto declaration : methods) {
245 : StandardDeclaration* standard_declaration =
246 : StandardDeclaration::DynamicCast(declaration);
247 : DCHECK(standard_declaration);
248 : TorqueMacroDeclaration* method =
249 4 : TorqueMacroDeclaration::DynamicCast(standard_declaration->callable);
250 4 : Signature signature = MakeSignature(method->signature.get());
251 : signature.parameter_names.insert(signature.parameter_names.begin(),
252 8 : kThisParameterName);
253 : signature.parameter_types.types.insert(
254 8 : signature.parameter_types.types.begin(), container_type);
255 4 : signature.implicit_count++;
256 4 : Statement* body = *(standard_declaration->body);
257 4 : std::string method_name(method->name);
258 4 : if (method->name == kConstructMethodName) {
259 : // Constructor
260 1 : if (!signature.return_type->IsVoid()) {
261 0 : ReportError("constructors musn't have a return type");
262 : }
263 2 : if (signature.labels.size() != 0) {
264 0 : ReportError("constructors musn't have labels");
265 : }
266 : method_name = kConstructMethodName;
267 1 : signature.return_type = container_type;
268 : ReturnStatement* return_statement = MakeNode<ReturnStatement>(
269 1 : MakeNode<IdentifierExpression>(kThisParameterName));
270 : body = MakeNode<BlockStatement>(
271 3 : false, std::vector<Statement*>{body, return_statement});
272 2 : body = WrapBodyWithNoThrow(body, "exception thrown from constructor");
273 : }
274 : Declarations::CreateMethod(container_type, method_name, signature, false,
275 4 : body);
276 4 : }
277 :
278 35 : if (container_type->Constructors().size() != 0) return;
279 :
280 : // Generate default constructor.
281 : Signature constructor_signature;
282 16 : constructor_signature.parameter_types.var_args = false;
283 16 : constructor_signature.return_type = container_type;
284 16 : std::vector<const AggregateType*> hierarchy = container_type->GetHierarchy();
285 :
286 : std::vector<Statement*> statements;
287 : std::vector<Statement*> initializer_statements;
288 :
289 : size_t parameter_number = 0;
290 32 : constructor_signature.parameter_names.push_back(kThisParameterName);
291 32 : constructor_signature.parameter_types.types.push_back(container_type);
292 16 : constructor_signature.implicit_count = 1;
293 : std::vector<Expression*> super_arguments;
294 60 : for (auto current_type : hierarchy) {
295 105 : for (auto& f : current_type->fields()) {
296 98 : std::string parameter_name("p" + std::to_string(parameter_number++));
297 49 : constructor_signature.parameter_names.push_back(parameter_name);
298 : constructor_signature.parameter_types.types.push_back(
299 49 : f.name_and_type.type);
300 : IdentifierExpression* value = MakeNode<IdentifierExpression>(
301 147 : std::vector<std::string>{}, parameter_name);
302 49 : if (container_type != current_type) {
303 : super_arguments.push_back(MakeNode<IdentifierExpression>(
304 48 : std::vector<std::string>{}, parameter_name));
305 37 : } else if (container_type->IsClassType()) {
306 : Statement* statement =
307 : MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>(
308 24 : constructor_this, f.name_and_type.name, value));
309 12 : initializer_statements.push_back(statement);
310 : } else {
311 : DCHECK(container_type->IsStructType());
312 : LocationExpression* location = MakeNode<FieldAccessExpression>(
313 50 : constructor_this, f.name_and_type.name);
314 : Statement* statement = MakeNode<ExpressionStatement>(
315 25 : MakeNode<AssignmentExpression>(location, base::nullopt, value));
316 25 : initializer_statements.push_back(statement);
317 : }
318 : }
319 : }
320 :
321 32 : if (hierarchy.size() > 1) {
322 : IdentifierExpression* super_identifier = MakeNode<IdentifierExpression>(
323 5 : std::vector<std::string>{}, kSuperMethodName);
324 : Statement* super_call_statement =
325 : MakeNode<ExpressionStatement>(MakeNode<CallMethodExpression>(
326 : constructor_this, super_identifier, super_arguments,
327 10 : std::vector<std::string>{}));
328 5 : statements.push_back(super_call_statement);
329 : }
330 :
331 69 : for (auto s : initializer_statements) {
332 37 : statements.push_back(s);
333 : }
334 :
335 : statements.push_back(MakeNode<ReturnStatement>(MakeNode<IdentifierExpression>(
336 32 : std::vector<std::string>{}, kThisParameterName)));
337 :
338 32 : Statement* constructor_body = MakeNode<BlockStatement>(false, statements);
339 :
340 : constructor_body = WrapBodyWithNoThrow(constructor_body,
341 32 : "exception thrown from constructor");
342 :
343 : Declarations::CreateMethod(container_type, kConstructMethodName,
344 48 : constructor_signature, false, constructor_body);
345 : }
346 :
347 10 : void DeclarationVisitor::Visit(StructDeclaration* decl) {
348 : std::vector<Field> fields;
349 : size_t offset = 0;
350 45 : for (auto& field : decl->fields) {
351 25 : const Type* field_type = Declarations::GetType(field.type);
352 50 : fields.push_back({{field.name, field_type}, offset, false});
353 25 : offset += LoweredSlotCount(field_type);
354 : }
355 10 : StructType* struct_type = Declarations::DeclareStruct(decl->name, fields);
356 10 : DeclareMethods(struct_type, decl->methods);
357 10 : }
358 :
359 7 : void DeclarationVisitor::Visit(ClassDeclaration* decl) {
360 : // Compute the offset of the class' first member. If the class extends
361 : // another class, it's the size of the extended class, otherwise zero.
362 : size_t first_field_offset = 0;
363 7 : if (decl->extends) {
364 14 : const Type* super_type = Declarations::LookupType(*decl->extends);
365 7 : if (super_type != TypeOracle::GetTaggedType()) {
366 6 : const ClassType* super_class = ClassType::DynamicCast(super_type);
367 6 : if (!super_class) {
368 : ReportError(
369 : "class \"", decl->name,
370 0 : "\" must extend either Tagged or an already declared class");
371 : }
372 : first_field_offset = super_class->size();
373 : }
374 : }
375 :
376 : // The generates clause must create a TNode<>
377 7 : std::string generates = decl->name;
378 7 : if (decl->generates) {
379 0 : if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
380 0 : generates.substr(generates.length() - 1, 1) != ">") {
381 : ReportError("generated type \"", generates,
382 0 : "\" should be of the form \"TNode<...>\"");
383 : }
384 0 : generates = generates.substr(6, generates.length() - 7);
385 : }
386 :
387 7 : std::vector<Field> fields;
388 : size_t offset = first_field_offset;
389 : bool seen_strong = false;
390 : bool seen_weak = false;
391 27 : for (ClassFieldExpression& field : decl->fields) {
392 13 : const Type* field_type = Declarations::GetType(field.name_and_type.type);
393 13 : if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
394 13 : if (field.weak) {
395 : seen_weak = true;
396 : } else {
397 11 : if (seen_weak) {
398 : ReportError("cannot declare strong field \"",
399 : field.name_and_type.name,
400 0 : "\" after weak Tagged references");
401 : }
402 : seen_strong = true;
403 : }
404 : } else {
405 0 : if (seen_strong || seen_weak) {
406 : ReportError("cannot declare scalar field \"", field.name_and_type.name,
407 0 : "\" after strong or weak Tagged references");
408 : }
409 : }
410 13 : if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
411 : ReportError(
412 : "field \"", field.name_and_type.name, "\" of class \"", decl->name,
413 0 : "\" must be a subtype of Tagged (other types not yet supported)");
414 : }
415 : fields.push_back(
416 26 : {{field.name_and_type.name, field_type}, offset, field.weak});
417 13 : offset += kTaggedSize;
418 : }
419 :
420 : auto new_class = Declarations::DeclareClass(
421 21 : decl->extends, decl->name, decl->transient, generates, fields, offset);
422 7 : DeclareMethods(new_class, decl->methods);
423 :
424 : // For each field, construct AST snippits that implement a CSA accessor
425 : // function and define a corresponding '.field' operator. The
426 : // implementation iterator will turn the snippits into code.
427 27 : for (auto& field : new_class->fields()) {
428 : IdentifierExpression* parameter =
429 26 : MakeNode<IdentifierExpression>(std::string{"o"});
430 :
431 : // Load accessor
432 13 : std::string camel_field_name = CamelifyString(field.name_and_type.name);
433 26 : std::string load_macro_name = "Load" + new_class->name() + camel_field_name;
434 13 : std::string load_operator_name = "." + field.name_and_type.name;
435 13 : Signature load_signature;
436 26 : load_signature.parameter_names.push_back("o");
437 26 : load_signature.parameter_types.types.push_back(new_class);
438 13 : load_signature.parameter_types.var_args = false;
439 13 : load_signature.return_type = field.name_and_type.type;
440 : Statement* load_body =
441 : MakeNode<ReturnStatement>(MakeNode<LoadObjectFieldExpression>(
442 26 : parameter, field.name_and_type.name));
443 : Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
444 39 : false, load_body, load_operator_name);
445 :
446 : // Store accessor
447 : IdentifierExpression* value = MakeNode<IdentifierExpression>(
448 39 : std::vector<std::string>{}, std::string{"v"});
449 : std::string store_macro_name =
450 26 : "Store" + new_class->name() + camel_field_name;
451 26 : std::string store_operator_name = "." + field.name_and_type.name + "=";
452 13 : Signature store_signature;
453 26 : store_signature.parameter_names.push_back("o");
454 26 : store_signature.parameter_names.push_back("v");
455 26 : store_signature.parameter_types.types.push_back(new_class);
456 13 : store_signature.parameter_types.types.push_back(field.name_and_type.type);
457 13 : store_signature.parameter_types.var_args = false;
458 : // TODO(danno): Store macros probably should return their value argument
459 13 : store_signature.return_type = TypeOracle::GetVoidType();
460 : Statement* store_body =
461 : MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>(
462 26 : parameter, field.name_and_type.name, value));
463 : Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
464 39 : false, store_body, store_operator_name);
465 : }
466 :
467 7 : GlobalContext::RegisterClass(decl->name, new_class);
468 7 : }
469 :
470 13 : void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
471 26 : GlobalContext::AddCppInclude(decl->include_path);
472 13 : }
473 :
474 84 : void DeclarationVisitor::Visit(TypeDeclaration* decl) {
475 84 : std::string generates = decl->generates ? *decl->generates : std::string("");
476 84 : if (decl->generates) {
477 290 : if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
478 174 : generates.substr(generates.length() - 1, 1) != ">") {
479 : ReportError("generated type \"", generates,
480 0 : "\" should be of the form \"TNode<...>\"");
481 : }
482 116 : generates = generates.substr(6, generates.length() - 7);
483 : }
484 :
485 : const AbstractType* type = Declarations::DeclareAbstractType(
486 199 : decl->name, decl->transient, generates, {}, decl->extends);
487 :
488 84 : if (decl->constexpr_generates) {
489 31 : if (decl->transient) {
490 0 : ReportError("cannot declare a transient type that is also constexpr");
491 : }
492 31 : std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
493 31 : base::Optional<std::string> constexpr_extends;
494 31 : if (decl->extends)
495 16 : constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
496 : Declarations::DeclareAbstractType(constexpr_name, false,
497 31 : *decl->constexpr_generates, type,
498 31 : constexpr_extends);
499 : }
500 84 : }
501 :
502 2330 : void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
503 : size_t i = 0;
504 : const std::size_t generic_parameter_count =
505 6026 : key.generic->declaration()->generic_parameters.size();
506 4660 : if (generic_parameter_count != key.specialized_types.size()) {
507 0 : std::stringstream stream;
508 0 : stream << "Wrong generic argument count for specialization of \""
509 0 : << key.generic->name() << "\", expected: " << generic_parameter_count
510 0 : << ", actual: " << key.specialized_types.size();
511 0 : ReportError(stream.str());
512 : }
513 :
514 9722 : for (auto type : key.specialized_types) {
515 : std::string generic_type_name =
516 11088 : key.generic->declaration()->generic_parameters[i++];
517 3696 : Declarations::DeclareType(generic_type_name, type, true);
518 : }
519 2330 : }
520 :
521 2159 : Signature DeclarationVisitor::MakeSpecializedSignature(
522 : const SpecializationKey& key) {
523 4318 : CurrentScope::Scope generic_scope(key.generic->ParentScope());
524 : // Create a temporary fake-namespace just to temporarily declare the
525 : // specialization aliases for the generic types to create a signature.
526 6477 : Namespace tmp_namespace("_tmp");
527 2159 : CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
528 2159 : DeclareSpecializedTypes(key);
529 8636 : return MakeSignature(key.generic->declaration()->callable->signature.get());
530 : }
531 :
532 171 : Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
533 391 : if (!key.generic->declaration()->body &&
534 49 : IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
535 : nullptr) {
536 0 : ReportError("missing specialization of ", key.generic->name(),
537 : " with types <", key.specialized_types, "> declared at ",
538 0 : key.generic->pos());
539 : }
540 171 : CurrentScope::Scope generic_scope(key.generic->ParentScope());
541 : Callable* result =
542 : Specialize(key, key.generic->declaration()->callable, base::nullopt,
543 342 : key.generic->declaration()->body);
544 171 : CurrentScope::Scope callable_scope(result);
545 171 : DeclareSpecializedTypes(key);
546 342 : return result;
547 : }
548 :
549 302 : Callable* DeclarationVisitor::Specialize(
550 : const SpecializationKey& key, CallableNode* declaration,
551 302 : base::Optional<const CallableNodeSignature*> signature,
552 : base::Optional<Statement*> body) {
553 : // TODO(tebbi): The error should point to the source position where the
554 : // instantiation was requested.
555 604 : CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
556 : size_t generic_parameter_count =
557 604 : key.generic->declaration()->generic_parameters.size();
558 604 : if (generic_parameter_count != key.specialized_types.size()) {
559 0 : std::stringstream stream;
560 0 : stream << "number of template parameters ("
561 0 : << std::to_string(key.specialized_types.size())
562 0 : << ") to intantiation of generic " << declaration->name
563 0 : << " doesnt match the generic's declaration ("
564 0 : << std::to_string(generic_parameter_count) << ")";
565 0 : ReportError(stream.str());
566 : }
567 302 : if (key.generic->GetSpecialization(key.specialized_types)) {
568 0 : ReportError("cannot redeclare specialization of ", key.generic->name(),
569 0 : " with types <", key.specialized_types, ">");
570 : }
571 :
572 : Signature type_signature =
573 604 : signature ? MakeSignature(*signature) : MakeSpecializedSignature(key);
574 :
575 : std::string generated_name = Declarations::GetGeneratedCallableName(
576 302 : declaration->name, key.specialized_types);
577 604 : std::stringstream readable_name;
578 302 : readable_name << declaration->name << "<";
579 : bool first = true;
580 992 : for (const Type* t : key.specialized_types) {
581 388 : if (!first) readable_name << ", ";
582 388 : readable_name << *t;
583 : first = false;
584 : }
585 302 : readable_name << ">";
586 : Callable* callable;
587 302 : if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
588 : callable = Declarations::CreateMacro(generated_name, readable_name.str(),
589 : base::nullopt, type_signature,
590 985 : declaration->transitioning, *body);
591 105 : } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
592 49 : callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
593 : } else {
594 : BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
595 : callable = CreateBuiltin(builtin, generated_name, readable_name.str(),
596 224 : type_signature, *body);
597 : }
598 302 : key.generic->AddSpecialization(key.specialized_types, callable);
599 302 : return callable;
600 : }
601 :
602 : } // namespace torque
603 : } // namespace internal
604 9078 : } // namespace v8
|