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 namespace v8 {
8 namespace internal {
9 namespace torque {
10
Visit(Expression * expr)11 void DeclarationVisitor::Visit(Expression* expr) {
12 CurrentSourcePosition::Scope scope(expr->pos);
13 switch (expr->kind) {
14 #define ENUM_ITEM(name) \
15 case AstNode::Kind::k##name: \
16 return Visit(name::cast(expr));
17 AST_EXPRESSION_NODE_KIND_LIST(ENUM_ITEM)
18 #undef ENUM_ITEM
19 default:
20 UNIMPLEMENTED();
21 }
22 }
23
Visit(Statement * stmt)24 void DeclarationVisitor::Visit(Statement* stmt) {
25 CurrentSourcePosition::Scope scope(stmt->pos);
26 switch (stmt->kind) {
27 #define ENUM_ITEM(name) \
28 case AstNode::Kind::k##name: \
29 return Visit(name::cast(stmt));
30 AST_STATEMENT_NODE_KIND_LIST(ENUM_ITEM)
31 #undef ENUM_ITEM
32 default:
33 UNIMPLEMENTED();
34 }
35 }
36
Visit(Declaration * decl)37 void DeclarationVisitor::Visit(Declaration* decl) {
38 CurrentSourcePosition::Scope scope(decl->pos);
39 switch (decl->kind) {
40 #define ENUM_ITEM(name) \
41 case AstNode::Kind::k##name: \
42 return Visit(name::cast(decl));
43 AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
44 #undef ENUM_ITEM
45 default:
46 UNIMPLEMENTED();
47 }
48 }
49
Visit(CallableNode * decl,const Signature & signature,Statement * body)50 void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
51 Statement* body) {
52 switch (decl->kind) {
53 #define ENUM_ITEM(name) \
54 case AstNode::Kind::k##name: \
55 return Visit(name::cast(decl), signature, body);
56 AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
57 #undef ENUM_ITEM
58 default:
59 UNIMPLEMENTED();
60 }
61 }
62
BuiltinDeclarationCommon(BuiltinDeclaration * decl,bool external,const Signature & signature)63 Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
64 BuiltinDeclaration* decl, bool external, const Signature& signature) {
65 const bool javascript = decl->javascript_linkage;
66 const bool varargs = decl->signature->parameters.has_varargs;
67 Builtin::Kind kind = !javascript ? Builtin::kStub
68 : varargs ? Builtin::kVarArgsJavaScript
69 : Builtin::kFixedArgsJavaScript;
70
71 if (signature.types().size() == 0 ||
72 !(signature.types()[0] ==
73 declarations()->LookupGlobalType(CONTEXT_TYPE_STRING))) {
74 std::stringstream stream;
75 stream << "first parameter to builtin " << decl->name
76 << " is not a context but should be";
77 ReportError(stream.str());
78 }
79
80 if (varargs && !javascript) {
81 std::stringstream stream;
82 stream << "builtin " << decl->name
83 << " with rest parameters must be a JavaScript builtin";
84 ReportError(stream.str());
85 }
86
87 if (javascript) {
88 if (signature.types().size() < 2 ||
89 !(signature.types()[1] ==
90 declarations()->LookupGlobalType(OBJECT_TYPE_STRING))) {
91 std::stringstream stream;
92 stream << "second parameter to javascript builtin " << decl->name
93 << " is " << *signature.types()[1] << " but should be Object";
94 ReportError(stream.str());
95 }
96 }
97
98 if (const StructType* struct_type =
99 StructType::DynamicCast(signature.return_type)) {
100 std::stringstream stream;
101 stream << "builtins (in this case" << decl->name
102 << ") cannot return structs (in this case " << struct_type->name()
103 << ")";
104 ReportError(stream.str());
105 }
106
107 std::string generated_name = GetGeneratedCallableName(
108 decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
109 return declarations()->DeclareBuiltin(generated_name, kind, external,
110 signature);
111 }
112
Visit(ExternalRuntimeDeclaration * decl,const Signature & signature,Statement * body)113 void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
114 const Signature& signature, Statement* body) {
115 if (global_context_.verbose()) {
116 std::cout << "found declaration of external runtime " << decl->name
117 << " with signature ";
118 }
119
120 if (signature.parameter_types.types.size() == 0 ||
121 !(signature.parameter_types.types[0] ==
122 declarations()->LookupGlobalType(CONTEXT_TYPE_STRING))) {
123 std::stringstream stream;
124 stream << "first parameter to runtime " << decl->name
125 << " is not a context but should be";
126 ReportError(stream.str());
127 }
128
129 if (signature.return_type->IsStructType()) {
130 std::stringstream stream;
131 stream << "runtime functions (in this case" << decl->name
132 << ") cannot return structs (in this case "
133 << static_cast<const StructType*>(signature.return_type)->name()
134 << ")";
135 ReportError(stream.str());
136 }
137
138 declarations()->DeclareRuntimeFunction(decl->name, signature);
139 }
140
Visit(ExternalMacroDeclaration * decl,const Signature & signature,Statement * body)141 void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
142 const Signature& signature, Statement* body) {
143 if (global_context_.verbose()) {
144 std::cout << "found declaration of external macro " << decl->name
145 << " with signature ";
146 }
147
148 std::string generated_name = GetGeneratedCallableName(
149 decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
150 declarations()->DeclareMacro(generated_name, signature, decl->op);
151 }
152
Visit(TorqueBuiltinDeclaration * decl,const Signature & signature,Statement * body)153 void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
154 const Signature& signature, Statement* body) {
155 Builtin* builtin = BuiltinDeclarationCommon(decl, false, signature);
156 CurrentCallableActivator activator(global_context_, builtin, decl);
157 DeclareSignature(signature);
158 if (signature.parameter_types.var_args) {
159 declarations()->DeclareExternConstant(
160 decl->signature->parameters.arguments_variable,
161 TypeOracle::GetArgumentsType(), "arguments");
162 }
163 torque_builtins_.push_back(builtin);
164 Visit(body);
165 }
166
Visit(TorqueMacroDeclaration * decl,const Signature & signature,Statement * body)167 void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
168 const Signature& signature, Statement* body) {
169 std::string generated_name = GetGeneratedCallableName(
170 decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
171 Macro* macro =
172 declarations()->DeclareMacro(generated_name, signature, decl->op);
173
174 CurrentCallableActivator activator(global_context_, macro, decl);
175
176 DeclareSignature(signature);
177 Variable* return_variable = nullptr;
178 if (!signature.return_type->IsVoidOrNever()) {
179 return_variable =
180 DeclareVariable(kReturnValueVariable, signature.return_type,
181 signature.return_type->IsConstexpr());
182 }
183
184 PushControlSplit();
185 if (body != nullptr) {
186 Visit(body);
187 }
188 auto changed_vars = PopControlSplit();
189 if (return_variable) changed_vars.insert(return_variable);
190 global_context_.AddControlSplitChangedVariables(
191 decl, declarations()->GetCurrentSpecializationTypeNamesVector(),
192 changed_vars);
193 }
194
Visit(ConstDeclaration * decl)195 void DeclarationVisitor::Visit(ConstDeclaration* decl) {
196 declarations()->DeclareModuleConstant(decl->name,
197 declarations()->GetType(decl->type));
198 Visit(decl->expression);
199 }
200
Visit(StandardDeclaration * decl)201 void DeclarationVisitor::Visit(StandardDeclaration* decl) {
202 Signature signature = MakeSignature(decl->callable->signature.get());
203 Visit(decl->callable, signature, decl->body);
204 }
205
Visit(GenericDeclaration * decl)206 void DeclarationVisitor::Visit(GenericDeclaration* decl) {
207 declarations()->DeclareGeneric(decl->callable->name, CurrentModule(), decl);
208 }
209
Visit(SpecializationDeclaration * decl)210 void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
211 if ((decl->body != nullptr) == decl->external) {
212 std::stringstream stream;
213 stream << "specialization of " << decl->name
214 << " must either be marked 'extern' or have a body";
215 ReportError(stream.str());
216 }
217
218 GenericList* generic_list = declarations()->LookupGeneric(decl->name);
219 // Find the matching generic specialization based on the concrete parameter
220 // list.
221 CallableNode* matching_callable = nullptr;
222 SpecializationKey matching_key;
223 Signature signature_with_types = MakeSignature(decl->signature.get());
224 for (Generic* generic : generic_list->list()) {
225 SpecializationKey key = {generic, GetTypeVector(decl->generic_parameters)};
226 CallableNode* callable_candidate = generic->declaration()->callable;
227 // Abuse the Specialization nodes' scope to temporarily declare the
228 // specialization aliases for the generic types to compare signatures. This
229 // scope is never used for anything else, so it's OK to pollute it.
230 Declarations::CleanNodeScopeActivator specialization_activator(
231 declarations(), decl);
232 DeclareSpecializedTypes(key);
233 Signature generic_signature_with_types =
234 MakeSignature(generic->declaration()->callable->signature.get());
235 if (signature_with_types.HasSameTypesAs(generic_signature_with_types)) {
236 if (matching_callable != nullptr) {
237 std::stringstream stream;
238 stream << "specialization of " << callable_candidate->name
239 << " is ambigous, it matches more than one generic declaration ("
240 << *matching_key.first << " and " << *key.first << ")";
241 ReportError(stream.str());
242 }
243 matching_callable = callable_candidate;
244 matching_key = key;
245 }
246 }
247
248 if (matching_callable == nullptr) {
249 std::stringstream stream;
250 stream << "specialization of " << decl->name
251 << " doesn't match any generic declaration";
252 ReportError(stream.str());
253 }
254
255 // Make sure the declarations of the parameter types for the specialization
256 // are the ones from the matching generic.
257 {
258 Declarations::CleanNodeScopeActivator specialization_activator(
259 declarations(), decl);
260 DeclareSpecializedTypes(matching_key);
261 }
262
263 SpecializeGeneric({matching_key, matching_callable, decl->signature.get(),
264 decl->body, decl->pos});
265 }
266
Visit(ReturnStatement * stmt)267 void DeclarationVisitor::Visit(ReturnStatement* stmt) {
268 if (stmt->value) {
269 Visit(*stmt->value);
270 }
271 }
272
DeclareVariable(const std::string & name,const Type * type,bool is_const)273 Variable* DeclarationVisitor::DeclareVariable(const std::string& name,
274 const Type* type, bool is_const) {
275 Variable* result = declarations()->DeclareVariable(name, type, is_const);
276 if (type->IsStructType()) {
277 const StructType* struct_type = StructType::cast(type);
278 for (auto& field : struct_type->fields()) {
279 std::string field_var_name = name + "." + field.name;
280 DeclareVariable(field_var_name, field.type, is_const);
281 }
282 }
283 return result;
284 }
285
DeclareParameter(const std::string & name,const Type * type)286 Parameter* DeclarationVisitor::DeclareParameter(const std::string& name,
287 const Type* type) {
288 Parameter* result = declarations()->DeclareParameter(
289 name, GetParameterVariableFromName(name), type);
290 if (type->IsStructType()) {
291 const StructType* struct_type = StructType::cast(type);
292 for (auto& field : struct_type->fields()) {
293 std::string field_var_name = name + "." + field.name;
294 DeclareParameter(field_var_name, field.type);
295 }
296 }
297 return result;
298 }
299
Visit(VarDeclarationStatement * stmt)300 void DeclarationVisitor::Visit(VarDeclarationStatement* stmt) {
301 std::string variable_name = stmt->name;
302 if (!stmt->const_qualified) {
303 if (!stmt->type) {
304 ReportError(
305 "variable declaration is missing type. Only 'const' bindings can "
306 "infer the type.");
307 }
308 const Type* type = declarations()->GetType(*stmt->type);
309 if (type->IsConstexpr()) {
310 ReportError(
311 "cannot declare variable with constexpr type. Use 'const' instead.");
312 }
313 DeclareVariable(variable_name, type, stmt->const_qualified);
314 if (global_context_.verbose()) {
315 std::cout << "declared variable " << variable_name << " with type "
316 << *type << "\n";
317 }
318 }
319
320 // const qualified variables are required to be initialized properly.
321 if (stmt->const_qualified && !stmt->initializer) {
322 std::stringstream stream;
323 stream << "local constant \"" << variable_name << "\" is not initialized.";
324 ReportError(stream.str());
325 }
326
327 if (stmt->initializer) {
328 Visit(*stmt->initializer);
329 if (global_context_.verbose()) {
330 std::cout << "variable has initialization expression at "
331 << CurrentPositionAsString() << "\n";
332 }
333 }
334 }
335
Visit(ExternConstDeclaration * decl)336 void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
337 const Type* type = declarations()->GetType(decl->type);
338 if (!type->IsConstexpr()) {
339 std::stringstream stream;
340 stream << "extern constants must have constexpr type, but found: \""
341 << *type << "\"\n";
342 ReportError(stream.str());
343 }
344
345 declarations()->DeclareExternConstant(decl->name, type, decl->literal);
346 }
347
Visit(StructDeclaration * decl)348 void DeclarationVisitor::Visit(StructDeclaration* decl) {
349 std::vector<NameAndType> fields;
350 for (auto& field : decl->fields) {
351 const Type* field_type = declarations()->GetType(field.type);
352 fields.push_back({field.name, field_type});
353 }
354 declarations()->DeclareStruct(CurrentModule(), decl->name, fields);
355 }
356
Visit(LogicalOrExpression * expr)357 void DeclarationVisitor::Visit(LogicalOrExpression* expr) {
358 {
359 Declarations::NodeScopeActivator scope(declarations(), expr->left);
360 declarations()->DeclareLabel(kFalseLabelName);
361 Visit(expr->left);
362 }
363 Visit(expr->right);
364 }
365
Visit(LogicalAndExpression * expr)366 void DeclarationVisitor::Visit(LogicalAndExpression* expr) {
367 {
368 Declarations::NodeScopeActivator scope(declarations(), expr->left);
369 declarations()->DeclareLabel(kTrueLabelName);
370 Visit(expr->left);
371 }
372 Visit(expr->right);
373 }
374
DeclareExpressionForBranch(Expression * node)375 void DeclarationVisitor::DeclareExpressionForBranch(Expression* node) {
376 Declarations::NodeScopeActivator scope(declarations(), node);
377 // Conditional expressions can either explicitly return a bit
378 // type, or they can be backed by macros that don't return but
379 // take a true and false label. By declaring the labels before
380 // visiting the conditional expression, those label-based
381 // macro conditionals will be able to find them through normal
382 // label lookups.
383 declarations()->DeclareLabel(kTrueLabelName);
384 declarations()->DeclareLabel(kFalseLabelName);
385 Visit(node);
386 }
387
Visit(ConditionalExpression * expr)388 void DeclarationVisitor::Visit(ConditionalExpression* expr) {
389 DeclareExpressionForBranch(expr->condition);
390 PushControlSplit();
391 Visit(expr->if_true);
392 Visit(expr->if_false);
393 auto changed_vars = PopControlSplit();
394 global_context_.AddControlSplitChangedVariables(
395 expr, declarations()->GetCurrentSpecializationTypeNamesVector(),
396 changed_vars);
397 }
398
Visit(IfStatement * stmt)399 void DeclarationVisitor::Visit(IfStatement* stmt) {
400 if (!stmt->is_constexpr) {
401 PushControlSplit();
402 }
403 DeclareExpressionForBranch(stmt->condition);
404 Visit(stmt->if_true);
405 if (stmt->if_false) Visit(*stmt->if_false);
406 if (!stmt->is_constexpr) {
407 auto changed_vars = PopControlSplit();
408 global_context_.AddControlSplitChangedVariables(
409 stmt, declarations()->GetCurrentSpecializationTypeNamesVector(),
410 changed_vars);
411 }
412 }
413
Visit(WhileStatement * stmt)414 void DeclarationVisitor::Visit(WhileStatement* stmt) {
415 Declarations::NodeScopeActivator scope(declarations(), stmt);
416 DeclareExpressionForBranch(stmt->condition);
417 PushControlSplit();
418 Visit(stmt->body);
419 auto changed_vars = PopControlSplit();
420 global_context_.AddControlSplitChangedVariables(
421 stmt, declarations()->GetCurrentSpecializationTypeNamesVector(),
422 changed_vars);
423 }
424
Visit(ForOfLoopStatement * stmt)425 void DeclarationVisitor::Visit(ForOfLoopStatement* stmt) {
426 // Scope for for iteration variable
427 Declarations::NodeScopeActivator scope(declarations(), stmt);
428 Visit(stmt->var_declaration);
429 Visit(stmt->iterable);
430 if (stmt->begin) Visit(*stmt->begin);
431 if (stmt->end) Visit(*stmt->end);
432 PushControlSplit();
433 Visit(stmt->body);
434 auto changed_vars = PopControlSplit();
435 global_context_.AddControlSplitChangedVariables(
436 stmt, declarations()->GetCurrentSpecializationTypeNamesVector(),
437 changed_vars);
438 }
439
Visit(ForLoopStatement * stmt)440 void DeclarationVisitor::Visit(ForLoopStatement* stmt) {
441 Declarations::NodeScopeActivator scope(declarations(), stmt);
442 if (stmt->var_declaration) Visit(*stmt->var_declaration);
443 PushControlSplit();
444
445 // Same as DeclareExpressionForBranch, but without the extra scope.
446 // If no test expression is present we can not use it for the scope.
447 declarations()->DeclareLabel(kTrueLabelName);
448 declarations()->DeclareLabel(kFalseLabelName);
449 if (stmt->test) Visit(*stmt->test);
450
451 Visit(stmt->body);
452 if (stmt->action) Visit(*stmt->action);
453 auto changed_vars = PopControlSplit();
454 global_context_.AddControlSplitChangedVariables(
455 stmt, declarations()->GetCurrentSpecializationTypeNamesVector(),
456 changed_vars);
457 }
458
Visit(TryLabelStatement * stmt)459 void DeclarationVisitor::Visit(TryLabelStatement* stmt) {
460 // Activate a new scope to declare handler labels, they should not be
461 // visible outside the label block.
462 {
463 Declarations::NodeScopeActivator scope(declarations(), stmt);
464
465 // Declare labels
466 for (LabelBlock* block : stmt->label_blocks) {
467 CurrentSourcePosition::Scope scope(block->pos);
468 Label* shared_label = declarations()->DeclareLabel(block->label);
469 {
470 Declarations::NodeScopeActivator scope(declarations(), block->body);
471 if (block->parameters.has_varargs) {
472 std::stringstream stream;
473 stream << "cannot use ... for label parameters";
474 ReportError(stream.str());
475 }
476
477 size_t i = 0;
478 for (auto p : block->parameters.names) {
479 const Type* type =
480 declarations()->GetType(block->parameters.types[i]);
481 if (type->IsConstexpr()) {
482 ReportError("no constexpr type allowed for label arguments");
483 }
484
485 shared_label->AddVariable(DeclareVariable(p, type, false));
486 ++i;
487 }
488 }
489 if (global_context_.verbose()) {
490 std::cout << " declaring label " << block->label << "\n";
491 }
492 }
493
494 Visit(stmt->try_block);
495 }
496
497 for (LabelBlock* block : stmt->label_blocks) {
498 Visit(block->body);
499 }
500 }
501
GenerateHeader(std::string & file_name)502 void DeclarationVisitor::GenerateHeader(std::string& file_name) {
503 std::stringstream new_contents_stream;
504 new_contents_stream
505 << "#ifndef V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n"
506 "#define V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n"
507 "\n"
508 "#define BUILTIN_LIST_FROM_DSL(CPP, API, TFJ, TFC, TFS, TFH, ASM) "
509 "\\\n";
510 for (auto builtin : torque_builtins_) {
511 int firstParameterIndex = 1;
512 bool declareParameters = true;
513 if (builtin->IsStub()) {
514 new_contents_stream << "TFS(" << builtin->name();
515 } else {
516 new_contents_stream << "TFJ(" << builtin->name();
517 if (builtin->IsVarArgsJavaScript()) {
518 new_contents_stream
519 << ", SharedFunctionInfo::kDontAdaptArgumentsSentinel";
520 declareParameters = false;
521 } else {
522 assert(builtin->IsFixedArgsJavaScript());
523 // FixedArg javascript builtins need to offer the parameter
524 // count.
525 assert(builtin->parameter_names().size() >= 2);
526 new_contents_stream << ", " << (builtin->parameter_names().size() - 2);
527 // And the receiver is explicitly declared.
528 new_contents_stream << ", kReceiver";
529 firstParameterIndex = 2;
530 }
531 }
532 if (declareParameters) {
533 int index = 0;
534 for (auto parameter : builtin->parameter_names()) {
535 if (index >= firstParameterIndex) {
536 new_contents_stream << ", k" << CamelifyString(parameter);
537 }
538 index++;
539 }
540 }
541 new_contents_stream << ") \\\n";
542 }
543 new_contents_stream
544 << "\n"
545 "#endif // V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n";
546
547 std::string new_contents(new_contents_stream.str());
548 ReplaceFileContentsIfDifferent(file_name, new_contents);
549 }
550
Visit(IdentifierExpression * expr)551 void DeclarationVisitor::Visit(IdentifierExpression* expr) {
552 if (expr->generic_arguments.size() != 0) {
553 TypeVector specialization_types;
554 for (auto t : expr->generic_arguments) {
555 specialization_types.push_back(declarations()->GetType(t));
556 }
557 // Specialize all versions of the generic, since the exact parameter type
558 // list cannot be resolved until the call's parameter expressions are
559 // evaluated. This is an overly conservative but simple way to make sure
560 // that the correct specialization exists.
561 for (auto generic : declarations()->LookupGeneric(expr->name)->list()) {
562 CallableNode* callable = generic->declaration()->callable;
563 if (generic->declaration()->body) {
564 QueueGenericSpecialization({generic, specialization_types}, callable,
565 callable->signature.get(),
566 generic->declaration()->body);
567 }
568 }
569 }
570 }
571
Visit(CallExpression * expr)572 void DeclarationVisitor::Visit(CallExpression* expr) {
573 Visit(&expr->callee);
574 for (Expression* arg : expr->arguments) Visit(arg);
575 }
576
Visit(TypeDeclaration * decl)577 void DeclarationVisitor::Visit(TypeDeclaration* decl) {
578 std::string generates = decl->generates ? *decl->generates : std::string("");
579 const AbstractType* type = declarations()->DeclareAbstractType(
580 decl->name, generates, {}, decl->extends);
581
582 if (decl->constexpr_generates) {
583 std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
584 base::Optional<std::string> constexpr_extends;
585 if (decl->extends)
586 constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
587 declarations()->DeclareAbstractType(
588 constexpr_name, *decl->constexpr_generates, type, constexpr_extends);
589 }
590 }
591
MarkLocationModified(Expression * location)592 void DeclarationVisitor::MarkLocationModified(Expression* location) {
593 if (IdentifierExpression* id = IdentifierExpression::cast(location)) {
594 const Value* value = declarations()->LookupValue(id->name);
595 if (value->IsVariable()) {
596 const Variable* variable = Variable::cast(value);
597 bool was_live = MarkVariableModified(variable);
598 if (was_live && global_context_.verbose()) {
599 std::cout << *variable << " was modified in control split at "
600 << PositionAsString(id->pos) << "\n";
601 }
602 }
603 }
604 }
605
MarkVariableModified(const Variable * variable)606 bool DeclarationVisitor::MarkVariableModified(const Variable* variable) {
607 auto e = live_and_changed_variables_.rend();
608 auto c = live_and_changed_variables_.rbegin();
609 bool was_live_in_preceeding_split = false;
610 while (c != e) {
611 if (c->live.find(variable) != c->live.end()) {
612 c->changed.insert(variable);
613 was_live_in_preceeding_split = true;
614 }
615 c++;
616 }
617 return was_live_in_preceeding_split;
618 }
619
DeclareSignature(const Signature & signature)620 void DeclarationVisitor::DeclareSignature(const Signature& signature) {
621 auto type_iterator = signature.parameter_types.types.begin();
622 for (auto name : signature.parameter_names) {
623 const Type* t(*type_iterator++);
624 if (name.size() != 0) {
625 DeclareParameter(name, t);
626 }
627 }
628 for (auto& label : signature.labels) {
629 auto label_params = label.types;
630 Label* new_label = declarations()->DeclareLabel(label.name);
631 size_t i = 0;
632 for (auto var_type : label_params) {
633 if (var_type->IsConstexpr()) {
634 ReportError("no constexpr type allowed for label arguments");
635 }
636
637 std::string var_name = label.name + std::to_string(i++);
638 new_label->AddVariable(DeclareVariable(var_name, var_type, false));
639 }
640 }
641 }
642
DeclareSpecializedTypes(const SpecializationKey & key)643 void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
644 size_t i = 0;
645 Generic* generic = key.first;
646 const std::size_t generic_parameter_count =
647 generic->declaration()->generic_parameters.size();
648 if (generic_parameter_count != key.second.size()) {
649 std::stringstream stream;
650 stream << "Wrong generic argument count for specialization of \""
651 << generic->name() << "\", expected: " << generic_parameter_count
652 << ", actual: " << key.second.size();
653 ReportError(stream.str());
654 }
655
656 for (auto type : key.second) {
657 std::string generic_type_name =
658 generic->declaration()->generic_parameters[i++];
659 declarations()->DeclareType(generic_type_name, type);
660 }
661 }
662
Specialize(const SpecializationKey & key,CallableNode * callable,const CallableNodeSignature * signature,Statement * body)663 void DeclarationVisitor::Specialize(const SpecializationKey& key,
664 CallableNode* callable,
665 const CallableNodeSignature* signature,
666 Statement* body) {
667 Generic* generic = key.first;
668
669 // TODO(tebbi): The error should point to the source position where the
670 // instantiation was requested.
671 CurrentSourcePosition::Scope pos_scope(generic->declaration()->pos);
672 size_t generic_parameter_count =
673 generic->declaration()->generic_parameters.size();
674 if (generic_parameter_count != key.second.size()) {
675 std::stringstream stream;
676 stream << "number of template parameters ("
677 << std::to_string(key.second.size())
678 << ") to intantiation of generic " << callable->name
679 << " doesnt match the generic's declaration ("
680 << std::to_string(generic_parameter_count) << ")";
681 ReportError(stream.str());
682 }
683
684 Signature type_signature;
685 {
686 // Manually activate the specialized generic's scope when declaring the
687 // generic parameter specializations.
688 Declarations::GenericScopeActivator namespace_scope(declarations(), key);
689 DeclareSpecializedTypes(key);
690 type_signature = MakeSignature(signature);
691 }
692
693 Visit(callable, type_signature, body);
694 }
695
696 } // namespace torque
697 } // namespace internal
698 } // namespace v8
699