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