V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
implementation-visitor.cc
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 <algorithm>
6 
7 #include "src/torque/csa-generator.h"
8 #include "src/torque/declaration-visitor.h"
9 #include "src/torque/implementation-visitor.h"
10 #include "src/torque/parameter-difference.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace torque {
15 
16 VisitResult ImplementationVisitor::Visit(Expression* expr) {
17  CurrentSourcePosition::Scope scope(expr->pos);
18  switch (expr->kind) {
19 #define ENUM_ITEM(name) \
20  case AstNode::Kind::k##name: \
21  return Visit(name::cast(expr));
22  AST_EXPRESSION_NODE_KIND_LIST(ENUM_ITEM)
23 #undef ENUM_ITEM
24  default:
25  UNREACHABLE();
26  }
27 }
28 
29 const Type* ImplementationVisitor::Visit(Statement* stmt) {
30  CurrentSourcePosition::Scope scope(stmt->pos);
31  StackScope stack_scope(this);
32  const Type* result;
33  switch (stmt->kind) {
34 #define ENUM_ITEM(name) \
35  case AstNode::Kind::k##name: \
36  result = Visit(name::cast(stmt)); \
37  break;
38  AST_STATEMENT_NODE_KIND_LIST(ENUM_ITEM)
39 #undef ENUM_ITEM
40  default:
41  UNREACHABLE();
42  }
43  DCHECK_EQ(result == TypeOracle::GetNeverType(),
44  assembler().CurrentBlockIsComplete());
45  return result;
46 }
47 
48 void ImplementationVisitor::BeginNamespaceFile(Namespace* nspace) {
49  std::ostream& source = nspace->source_stream();
50  std::ostream& header = nspace->header_stream();
51 
52  source << "#include \"src/objects/arguments.h\"\n";
53  source << "#include \"src/builtins/builtins-utils-gen.h\"\n";
54  source << "#include \"src/builtins/builtins.h\"\n";
55  source << "#include \"src/code-factory.h\"\n";
56  source << "#include \"src/elements-kind.h\"\n";
57  source << "#include \"src/heap/factory-inl.h\"\n";
58  source << "#include \"src/objects.h\"\n";
59  source << "#include \"src/objects/bigint.h\"\n";
60 
61  for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
62  source << "#include \"torque-generated/builtins-" +
63  DashifyString(n->name()) + "-from-dsl-gen.h\"\n";
64  if (n != GlobalContext::GetDefaultNamespace()) {
65  source << "#include \"src/builtins/builtins-" + DashifyString(n->name()) +
66  "-gen.h\"\n";
67  }
68  }
69  source << "\n";
70 
71  source << "namespace v8 {\n"
72  << "namespace internal {\n"
73  << "\n";
74 
75  std::string upper_name(nspace->name());
76  transform(upper_name.begin(), upper_name.end(), upper_name.begin(),
77  ::toupper);
78  std::string headerDefine =
79  std::string("V8_TORQUE_") + upper_name + "_FROM_DSL_BASE_H__";
80  header << "#ifndef " << headerDefine << "\n";
81  header << "#define " << headerDefine << "\n\n";
82  header << "#include \"src/compiler/code-assembler.h\"\n";
83  if (nspace != GlobalContext::GetDefaultNamespace()) {
84  header << "#include \"src/code-stub-assembler.h\"\n";
85  }
86  header << "\n";
87 
88  header << "namespace v8 {\n"
89  << "namespace internal {\n"
90  << "\n";
91 
92  header << "class " << nspace->ExternalName() << " {\n";
93  header << " public:\n";
94  header << " explicit " << nspace->ExternalName()
95  << "(compiler::CodeAssemblerState* state) : state_(state), ca_(state) "
96  "{ USE(state_, ca_); }\n";
97 }
98 
99 void ImplementationVisitor::EndNamespaceFile(Namespace* nspace) {
100  std::ostream& source = nspace->source_stream();
101  std::ostream& header = nspace->header_stream();
102 
103  std::string upper_name(nspace->name());
104  transform(upper_name.begin(), upper_name.end(), upper_name.begin(),
105  ::toupper);
106  std::string headerDefine =
107  std::string("V8_TORQUE_") + upper_name + "_FROM_DSL_BASE_H__";
108 
109  source << "} // namespace internal\n"
110  << "} // namespace v8\n"
111  << "\n";
112 
113  header << " private:\n"
114  << " compiler::CodeAssemblerState* const state_;\n"
115  << " compiler::CodeAssembler ca_;"
116  << "}; \n\n";
117  header << "} // namespace internal\n"
118  << "} // namespace v8\n"
119  << "\n";
120  header << "#endif // " << headerDefine << "\n";
121 }
122 
123 void ImplementationVisitor::Visit(NamespaceConstant* decl) {
124  Signature signature{{}, base::nullopt, {{}, false}, 0, decl->type(), {}};
125  const std::string& name = decl->name();
126 
127  BindingsManagersScope bindings_managers_scope;
128 
129  header_out() << " ";
130  GenerateFunctionDeclaration(header_out(), "", name, signature, {});
131  header_out() << ";\n";
132 
133  GenerateFunctionDeclaration(source_out(),
134  CurrentNamespace()->ExternalName() + "::", name,
135  signature, {});
136  source_out() << " {\n";
137 
138  DCHECK(!signature.return_type->IsVoidOrNever());
139 
140  assembler_ = CfgAssembler(Stack<const Type*>{});
141 
142  VisitResult expression_result = Visit(decl->body());
143  VisitResult return_result =
144  GenerateImplicitConvert(signature.return_type, expression_result);
145 
146  CSAGenerator csa_generator{assembler().Result(), source_out()};
147  Stack<std::string> values = *csa_generator.EmitGraph(Stack<std::string>{});
148 
149  assembler_ = base::nullopt;
150 
151  source_out() << "return ";
152  CSAGenerator::EmitCSAValue(return_result, values, source_out());
153  source_out() << ";\n";
154  source_out() << "}\n\n";
155 }
156 
157 void ImplementationVisitor::Visit(TypeAlias* alias) {
158  if (alias->IsRedeclaration()) return;
159  const StructType* struct_type = StructType::DynamicCast(alias->type());
160  if (!struct_type) return;
161  const std::string& name = struct_type->name();
162  header_out() << " struct " << name << " {\n";
163  for (auto& field : struct_type->fields()) {
164  header_out() << " " << field.type->GetGeneratedTypeName();
165  header_out() << " " << field.name << ";\n";
166  }
167  header_out() << "\n std::tuple<";
168  bool first = true;
169  for (const Type* type : LowerType(struct_type)) {
170  if (!first) {
171  header_out() << ", ";
172  }
173  first = false;
174  header_out() << type->GetGeneratedTypeName();
175  }
176  header_out() << "> Flatten() const {\n"
177  << " return std::tuple_cat(";
178  first = true;
179  for (auto& field : struct_type->fields()) {
180  if (!first) {
181  header_out() << ", ";
182  }
183  first = false;
184  if (field.type->IsStructType()) {
185  header_out() << field.name << ".Flatten()";
186  } else {
187  header_out() << "std::make_tuple(" << field.name << ")";
188  }
189  }
190  header_out() << ");\n";
191  header_out() << " }\n";
192  header_out() << " };\n";
193 }
194 
195 void ImplementationVisitor::Visit(Macro* macro) {
196  if (macro->IsExternal()) return;
197  CurrentScope::Scope current_scope(macro);
198  const Signature& signature = macro->signature();
199  const Type* return_type = macro->signature().return_type;
200  bool can_return = return_type != TypeOracle::GetNeverType();
201  bool has_return_value =
202  can_return && return_type != TypeOracle::GetVoidType();
203 
204  CurrentCallable::Scope current_callable(macro);
205 
206  header_out() << " ";
207  GenerateMacroFunctionDeclaration(header_out(), "", macro);
208  header_out() << ";\n";
209 
210  GenerateMacroFunctionDeclaration(
211  source_out(), CurrentNamespace()->ExternalName() + "::", macro);
212  source_out() << " {\n";
213 
214  Stack<std::string> lowered_parameters;
215  Stack<const Type*> lowered_parameter_types;
216 
217  BindingsManagersScope bindings_managers_scope;
218 
219  BlockBindings<LocalValue> parameter_bindings(&ValueBindingsManager::Get());
220  for (size_t i = 0; i < macro->signature().parameter_names.size(); ++i) {
221  const std::string& name = macro->parameter_names()[i];
222  std::string external_name = GetParameterVariableFromName(name);
223  const Type* type = macro->signature().types()[i];
224  if (type->IsConstexpr()) {
225  parameter_bindings.Add(
226  name, LocalValue{true, VisitResult(type, external_name)});
227  } else {
228  LowerParameter(type, external_name, &lowered_parameters);
229  StackRange range = lowered_parameter_types.PushMany(LowerType(type));
230  parameter_bindings.Add(name, LocalValue{true, VisitResult(type, range)});
231  }
232  }
233 
234  DCHECK_EQ(lowered_parameters.Size(), lowered_parameter_types.Size());
235  assembler_ = CfgAssembler(lowered_parameter_types);
236 
237  BlockBindings<LocalLabel> label_bindings(&LabelBindingsManager::Get());
238  for (const LabelDeclaration& label_info : signature.labels) {
239  Stack<const Type*> label_input_stack;
240  for (const Type* type : label_info.types) {
241  label_input_stack.PushMany(LowerType(type));
242  }
243  Block* block = assembler().NewBlock(std::move(label_input_stack));
244  label_bindings.Add(label_info.name, LocalLabel{block, label_info.types});
245  }
246 
247  Block* macro_end;
248  base::Optional<Binding<LocalLabel>> macro_end_binding;
249  if (can_return) {
250  macro_end = assembler().NewBlock(
251  Stack<const Type*>{LowerType(signature.return_type)});
252  macro_end_binding.emplace(&LabelBindingsManager::Get(), "_macro_end",
253  LocalLabel{macro_end, {signature.return_type}});
254  }
255 
256  const Type* result = Visit(*macro->body());
257 
258  if (result->IsNever()) {
259  if (!macro->signature().return_type->IsNever() && !macro->HasReturns()) {
260  std::stringstream s;
261  s << "macro " << macro->ReadableName()
262  << " that never returns must have return type never";
263  ReportError(s.str());
264  }
265  } else {
266  if (macro->signature().return_type->IsNever()) {
267  std::stringstream s;
268  s << "macro " << macro->ReadableName()
269  << " has implicit return at end of its declartion but return type "
270  "never";
271  ReportError(s.str());
272  } else if (!macro->signature().return_type->IsVoid()) {
273  std::stringstream s;
274  s << "macro " << macro->ReadableName()
275  << " expects to return a value but doesn't on all paths";
276  ReportError(s.str());
277  }
278  }
279  if (!result->IsNever()) {
280  assembler().Goto(macro_end);
281  }
282 
283  for (auto* label_binding : label_bindings.bindings()) {
284  assembler().Bind(label_binding->block);
285  std::vector<std::string> label_parameter_variables;
286  for (size_t i = 0; i < label_binding->parameter_types.size(); ++i) {
287  label_parameter_variables.push_back(
288  ExternalLabelParameterName(label_binding->name(), i));
289  }
290  assembler().Emit(GotoExternalInstruction{
291  ExternalLabelName(label_binding->name()), label_parameter_variables});
292  }
293 
294  if (macro->HasReturns() || !result->IsNever()) {
295  assembler().Bind(macro_end);
296  }
297 
298  CSAGenerator csa_generator{assembler().Result(), source_out()};
299  base::Optional<Stack<std::string>> values =
300  csa_generator.EmitGraph(lowered_parameters);
301 
302  assembler_ = base::nullopt;
303 
304  if (has_return_value) {
305  source_out() << " return ";
306  CSAGenerator::EmitCSAValue(GetAndClearReturnValue(), *values, source_out());
307  source_out() << ";\n";
308  }
309  source_out() << "}\n\n";
310 }
311 
312 namespace {
313 
314 std::string AddParameter(size_t i, Builtin* builtin,
315  Stack<std::string>* parameters,
316  Stack<const Type*>* parameter_types,
317  BlockBindings<LocalValue>* parameter_bindings) {
318  const std::string& name = builtin->signature().parameter_names[i];
319  const Type* type = builtin->signature().types()[i];
320  std::string external_name = "parameter" + std::to_string(i);
321  parameters->Push(external_name);
322  StackRange range = parameter_types->PushMany(LowerType(type));
323  parameter_bindings->Add(name, LocalValue{true, VisitResult(type, range)});
324  return external_name;
325 }
326 
327 } // namespace
328 
329 void ImplementationVisitor::Visit(Builtin* builtin) {
330  if (builtin->IsExternal()) return;
331  CurrentScope::Scope current_scope(builtin);
332  const std::string& name = builtin->ExternalName();
333  const Signature& signature = builtin->signature();
334  source_out() << "TF_BUILTIN(" << name << ", CodeStubAssembler) {\n"
335  << " compiler::CodeAssemblerState* state_ = state();"
336  << " compiler::CodeAssembler ca_(state());\n";
337 
338  CurrentCallable::Scope current_callable(builtin);
339 
340  Stack<const Type*> parameter_types;
341  Stack<std::string> parameters;
342 
343  BindingsManagersScope bindings_managers_scope;
344 
345  BlockBindings<LocalValue> parameter_bindings(&ValueBindingsManager::Get());
346 
347  // Context
348  std::string parameter0 = AddParameter(0, builtin, &parameters,
349  &parameter_types, &parameter_bindings);
350  source_out() << " TNode<Context> " << parameter0
351  << " = UncheckedCast<Context>(Parameter("
352  << "Descriptor::kContext));\n";
353  source_out() << " USE(" << parameter0 << ");\n";
354 
355  size_t first = 1;
356  if (builtin->IsVarArgsJavaScript()) {
357  DCHECK(signature.parameter_types.var_args);
358  source_out()
359  << " Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);\n";
360  source_out() << " CodeStubArguments arguments_impl(this, "
361  "ChangeInt32ToIntPtr(argc));\n";
362  std::string parameter1 = AddParameter(
363  1, builtin, &parameters, &parameter_types, &parameter_bindings);
364 
365  source_out() << " TNode<Object> " << parameter1
366  << " = arguments_impl.GetReceiver();\n";
367  source_out() << "auto " << CSAGenerator::ARGUMENTS_VARIABLE_STRING
368  << " = &arguments_impl;\n";
369  source_out() << "USE(arguments);\n";
370  source_out() << "USE(" << parameter1 << ");\n";
371  parameter_bindings.Add(
372  *signature.arguments_variable,
373  LocalValue{true,
374  VisitResult(TypeOracle::GetArgumentsType(), "arguments")});
375  first = 2;
376  }
377 
378  for (size_t i = 0; i < signature.parameter_names.size(); ++i) {
379  if (i < first) continue;
380  const std::string& parameter_name = signature.parameter_names[i];
381  const Type* type = signature.types()[i];
382  std::string var = AddParameter(i, builtin, &parameters, &parameter_types,
383  &parameter_bindings);
384  source_out() << " " << type->GetGeneratedTypeName() << " " << var << " = "
385  << "UncheckedCast<" << type->GetGeneratedTNodeTypeName()
386  << ">(Parameter(Descriptor::k"
387  << CamelifyString(parameter_name) << "));\n";
388  source_out() << " USE(" << var << ");\n";
389  }
390 
391  assembler_ = CfgAssembler(parameter_types);
392  const Type* body_result = Visit(*builtin->body());
393  if (body_result != TypeOracle::GetNeverType()) {
394  ReportError("control reaches end of builtin, expected return of a value");
395  }
396  CSAGenerator csa_generator{assembler().Result(), source_out(),
397  builtin->kind()};
398  csa_generator.EmitGraph(parameters);
399  assembler_ = base::nullopt;
400  source_out() << "}\n\n";
401 }
402 
403 const Type* ImplementationVisitor::Visit(VarDeclarationStatement* stmt) {
404  BlockBindings<LocalValue> block_bindings(&ValueBindingsManager::Get());
405  return Visit(stmt, &block_bindings);
406 }
407 
408 const Type* ImplementationVisitor::Visit(
409  VarDeclarationStatement* stmt, BlockBindings<LocalValue>* block_bindings) {
410  if (!stmt->const_qualified && !stmt->type) {
411  ReportError(
412  "variable declaration is missing type. Only 'const' bindings can "
413  "infer the type.");
414  }
415  // const qualified variables are required to be initialized properly.
416  if (stmt->const_qualified && !stmt->initializer) {
417  ReportError("local constant \"", stmt->name, "\" is not initialized.");
418  }
419 
420  base::Optional<const Type*> type;
421  if (stmt->type) {
422  type = Declarations::GetType(*stmt->type);
423  if ((*type)->IsConstexpr() && !stmt->const_qualified) {
424  ReportError(
425  "cannot declare variable with constexpr type. Use 'const' instead.");
426  }
427  }
428  base::Optional<VisitResult> init_result;
429  if (stmt->initializer) {
430  StackScope scope(this);
431  init_result = Visit(*stmt->initializer);
432  if (type) {
433  init_result = GenerateImplicitConvert(*type, *init_result);
434  }
435  init_result = scope.Yield(*init_result);
436  } else {
437  DCHECK(type.has_value());
438  if ((*type)->IsConstexpr()) {
439  ReportError("constexpr variables need an initializer");
440  }
441  TypeVector lowered_types = LowerType(*type);
442  for (const Type* type : lowered_types) {
443  assembler().Emit(PushUninitializedInstruction{TypeOracle::GetTopType(
444  "unitialized variable '" + stmt->name + "' of type " +
445  type->ToString() + " originally defined at " +
446  PositionAsString(stmt->pos),
447  type)});
448  }
449  init_result =
450  VisitResult(*type, assembler().TopRange(lowered_types.size()));
451  }
452  block_bindings->Add(stmt->name,
453  LocalValue{stmt->const_qualified, *init_result});
454  return TypeOracle::GetVoidType();
455 }
456 
457 const Type* ImplementationVisitor::Visit(TailCallStatement* stmt) {
458  return Visit(stmt->call, true).type();
459 }
460 
461 VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) {
462  Block* true_block = assembler().NewBlock(assembler().CurrentStack());
463  Block* false_block = assembler().NewBlock(assembler().CurrentStack());
464  Block* done_block = assembler().NewBlock();
465  Block* true_conversion_block = assembler().NewBlock();
466  GenerateExpressionBranch(expr->condition, true_block, false_block);
467 
468  VisitResult left;
469  VisitResult right;
470 
471  {
472  // The code for both paths of the conditional need to be generated first
473  // before evaluating the conditional expression because the common type of
474  // the result of both the true and false of the condition needs to be known
475  // to convert both branches to a common type.
476  assembler().Bind(true_block);
477  StackScope left_scope(this);
478  left = Visit(expr->if_true);
479  assembler().Goto(true_conversion_block);
480 
481  const Type* common_type;
482  {
483  assembler().Bind(false_block);
484  StackScope right_scope(this);
485  right = Visit(expr->if_false);
486  common_type = GetCommonType(left.type(), right.type());
487  right = right_scope.Yield(GenerateImplicitConvert(common_type, right));
488  assembler().Goto(done_block);
489  }
490 
491  assembler().Bind(true_conversion_block);
492  left = left_scope.Yield(GenerateImplicitConvert(common_type, left));
493  assembler().Goto(done_block);
494  }
495 
496  assembler().Bind(done_block);
497  CHECK_EQ(left, right);
498  return left;
499 }
500 
501 VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) {
502  VisitResult left_result;
503  {
504  Block* false_block = assembler().NewBlock(assembler().CurrentStack());
505  Binding<LocalLabel> false_binding{&LabelBindingsManager::Get(),
506  kFalseLabelName, LocalLabel{false_block}};
507  left_result = Visit(expr->left);
508  if (left_result.type()->IsBool()) {
509  Block* true_block = LookupSimpleLabel(kTrueLabelName);
510  assembler().Branch(true_block, false_block);
511  assembler().Bind(false_block);
512  } else if (left_result.type()->IsNever()) {
513  assembler().Bind(false_block);
514  } else if (!left_result.type()->IsConstexprBool()) {
515  ReportError(
516  "expected type bool, constexpr bool, or never on left-hand side of "
517  "operator ||");
518  }
519  }
520 
521  if (left_result.type()->IsConstexprBool()) {
522  VisitResult right_result = Visit(expr->right);
523  if (!right_result.type()->IsConstexprBool()) {
524  ReportError(
525  "expected type constexpr bool on right-hand side of operator "
526  "||");
527  }
528  return VisitResult(TypeOracle::GetConstexprBoolType(),
529  std::string("(") + left_result.constexpr_value() +
530  " || " + right_result.constexpr_value() + ")");
531  }
532 
533  VisitResult right_result = Visit(expr->right);
534  if (right_result.type()->IsBool()) {
535  Block* true_block = LookupSimpleLabel(kTrueLabelName);
536  Block* false_block = LookupSimpleLabel(kFalseLabelName);
537  assembler().Branch(true_block, false_block);
538  return VisitResult::NeverResult();
539  } else if (!right_result.type()->IsNever()) {
540  ReportError(
541  "expected type bool or never on right-hand side of operator ||");
542  }
543  return right_result;
544 }
545 
546 VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) {
547  VisitResult left_result;
548  {
549  Block* true_block = assembler().NewBlock(assembler().CurrentStack());
550  Binding<LocalLabel> false_binding{&LabelBindingsManager::Get(),
551  kTrueLabelName, LocalLabel{true_block}};
552  left_result = Visit(expr->left);
553  if (left_result.type()->IsBool()) {
554  Block* false_block = LookupSimpleLabel(kFalseLabelName);
555  assembler().Branch(true_block, false_block);
556  assembler().Bind(true_block);
557  } else if (left_result.type()->IsNever()) {
558  assembler().Bind(true_block);
559  } else if (!left_result.type()->IsConstexprBool()) {
560  ReportError(
561  "expected type bool, constexpr bool, or never on left-hand side of "
562  "operator &&");
563  }
564  }
565 
566  if (left_result.type()->IsConstexprBool()) {
567  VisitResult right_result = Visit(expr->right);
568  if (!right_result.type()->IsConstexprBool()) {
569  ReportError(
570  "expected type constexpr bool on right-hand side of operator "
571  "&&");
572  }
573  return VisitResult(TypeOracle::GetConstexprBoolType(),
574  std::string("(") + left_result.constexpr_value() +
575  " && " + right_result.constexpr_value() + ")");
576  }
577 
578  VisitResult right_result = Visit(expr->right);
579  if (right_result.type()->IsBool()) {
580  Block* true_block = LookupSimpleLabel(kTrueLabelName);
581  Block* false_block = LookupSimpleLabel(kFalseLabelName);
582  assembler().Branch(true_block, false_block);
583  return VisitResult::NeverResult();
584  } else if (!right_result.type()->IsNever()) {
585  ReportError(
586  "expected type bool or never on right-hand side of operator &&");
587  }
588  return right_result;
589 }
590 
591 VisitResult ImplementationVisitor::Visit(IncrementDecrementExpression* expr) {
592  StackScope scope(this);
593  LocationReference location_ref = GetLocationReference(expr->location);
594  VisitResult current_value = GenerateFetchFromLocation(location_ref);
595  VisitResult one = {TypeOracle::GetConstInt31Type(), "1"};
596  Arguments args;
597  args.parameters = {current_value, one};
598  VisitResult assignment_value = GenerateCall(
599  expr->op == IncrementDecrementOperator::kIncrement ? "+" : "-", args);
600  GenerateAssignToLocation(location_ref, assignment_value);
601  return scope.Yield(expr->postfix ? current_value : assignment_value);
602 }
603 
604 VisitResult ImplementationVisitor::Visit(AssignmentExpression* expr) {
605  StackScope scope(this);
606  LocationReference location_ref = GetLocationReference(expr->location);
607  VisitResult assignment_value;
608  if (expr->op) {
609  VisitResult location_value = GenerateFetchFromLocation(location_ref);
610  assignment_value = Visit(expr->value);
611  Arguments args;
612  args.parameters = {location_value, assignment_value};
613  assignment_value = GenerateCall(*expr->op, args);
614  GenerateAssignToLocation(location_ref, assignment_value);
615  } else {
616  assignment_value = Visit(expr->value);
617  GenerateAssignToLocation(location_ref, assignment_value);
618  }
619  return scope.Yield(assignment_value);
620 }
621 
622 VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) {
623  // TODO(tebbi): Do not silently loose precision; support 64bit literals.
624  double d = std::stod(expr->number.c_str());
625  int32_t i = static_cast<int32_t>(d);
626  const Type* result_type = Declarations::LookupType(CONST_FLOAT64_TYPE_STRING);
627  if (i == d) {
628  if ((i >> 30) == (i >> 31)) {
629  result_type = Declarations::LookupType(CONST_INT31_TYPE_STRING);
630  } else {
631  result_type = Declarations::LookupType(CONST_INT32_TYPE_STRING);
632  }
633  }
634  return VisitResult{result_type, expr->number};
635 }
636 
637 VisitResult ImplementationVisitor::Visit(AssumeTypeImpossibleExpression* expr) {
638  VisitResult result = Visit(expr->expression);
639  const Type* result_type =
640  SubtractType(result.type(), Declarations::GetType(expr->excluded_type));
641  if (result_type->IsNever()) {
642  ReportError("unreachable code");
643  }
644  CHECK_EQ(LowerType(result_type), TypeVector{result_type});
645  assembler().Emit(UnsafeCastInstruction{result_type});
646  result.SetType(result_type);
647  return result;
648 }
649 
650 VisitResult ImplementationVisitor::Visit(StringLiteralExpression* expr) {
651  return VisitResult{
652  TypeOracle::GetConstStringType(),
653  "\"" + expr->literal.substr(1, expr->literal.size() - 2) + "\""};
654 }
655 
656 VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) {
657  if (builtin->IsExternal() || builtin->kind() != Builtin::kStub) {
658  ReportError(
659  "creating function pointers is only allowed for internal builtins with "
660  "stub linkage");
661  }
662  const Type* type = TypeOracle::GetFunctionPointerType(
663  builtin->signature().parameter_types.types,
664  builtin->signature().return_type);
665  assembler().Emit(PushCodePointerInstruction{builtin->ExternalName(), type});
666  return VisitResult(type, assembler().TopRange(1));
667 }
668 
669 VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) {
670  StackScope scope(this);
671  return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
672 }
673 
674 const Type* ImplementationVisitor::Visit(GotoStatement* stmt) {
675  LocalLabel* label = LookupLabel(stmt->label);
676  size_t parameter_count = label->parameter_types.size();
677  if (stmt->arguments.size() != parameter_count) {
678  ReportError("goto to label has incorrect number of parameters (expected ",
679  parameter_count, " found ", stmt->arguments.size(), ")");
680  }
681 
682  size_t i = 0;
683  StackRange arguments = assembler().TopRange(0);
684  for (Expression* e : stmt->arguments) {
685  StackScope scope(this);
686  VisitResult result = Visit(e);
687  const Type* parameter_type = label->parameter_types[i++];
688  result = GenerateImplicitConvert(parameter_type, result);
689  arguments.Extend(scope.Yield(result).stack_range());
690  }
691 
692  assembler().Goto(label->block, arguments.Size());
693  return TypeOracle::GetNeverType();
694 }
695 
696 const Type* ImplementationVisitor::Visit(IfStatement* stmt) {
697  bool has_else = stmt->if_false.has_value();
698 
699  if (stmt->is_constexpr) {
700  VisitResult expression_result = Visit(stmt->condition);
701 
702  if (!(expression_result.type() == TypeOracle::GetConstexprBoolType())) {
703  std::stringstream stream;
704  stream << "expression should return type constexpr bool "
705  << "but returns type " << *expression_result.type();
706  ReportError(stream.str());
707  }
708 
709  Block* true_block = assembler().NewBlock();
710  Block* false_block = assembler().NewBlock();
711  Block* done_block = assembler().NewBlock();
712 
713  assembler().Emit(ConstexprBranchInstruction{
714  expression_result.constexpr_value(), true_block, false_block});
715 
716  assembler().Bind(true_block);
717  const Type* left_result = Visit(stmt->if_true);
718  if (left_result == TypeOracle::GetVoidType()) {
719  assembler().Goto(done_block);
720  }
721 
722  assembler().Bind(false_block);
723  const Type* right_result = TypeOracle::GetVoidType();
724  if (has_else) {
725  right_result = Visit(*stmt->if_false);
726  }
727  if (right_result == TypeOracle::GetVoidType()) {
728  assembler().Goto(done_block);
729  }
730 
731  if (left_result->IsNever() != right_result->IsNever()) {
732  std::stringstream stream;
733  stream << "either both or neither branches in a constexpr if statement "
734  "must reach their end at"
735  << PositionAsString(stmt->pos);
736  ReportError(stream.str());
737  }
738 
739  if (left_result != TypeOracle::GetNeverType()) {
740  assembler().Bind(done_block);
741  }
742  return left_result;
743  } else {
744  Block* true_block = assembler().NewBlock(assembler().CurrentStack(),
745  IsDeferred(stmt->if_true));
746  Block* false_block =
747  assembler().NewBlock(assembler().CurrentStack(),
748  stmt->if_false && IsDeferred(*stmt->if_false));
749  GenerateExpressionBranch(stmt->condition, true_block, false_block);
750 
751  Block* done_block;
752  bool live = false;
753  if (has_else) {
754  done_block = assembler().NewBlock();
755  } else {
756  done_block = false_block;
757  live = true;
758  }
759 
760  assembler().Bind(true_block);
761  {
762  const Type* result = Visit(stmt->if_true);
763  if (result == TypeOracle::GetVoidType()) {
764  live = true;
765  assembler().Goto(done_block);
766  }
767  }
768 
769  if (has_else) {
770  assembler().Bind(false_block);
771  const Type* result = Visit(*stmt->if_false);
772  if (result == TypeOracle::GetVoidType()) {
773  live = true;
774  assembler().Goto(done_block);
775  }
776  }
777 
778  if (live) {
779  assembler().Bind(done_block);
780  }
781  return live ? TypeOracle::GetVoidType() : TypeOracle::GetNeverType();
782  }
783 }
784 
785 const Type* ImplementationVisitor::Visit(WhileStatement* stmt) {
786  Block* body_block = assembler().NewBlock(assembler().CurrentStack());
787  Block* exit_block = assembler().NewBlock(assembler().CurrentStack());
788 
789  Block* header_block = assembler().NewBlock();
790  assembler().Goto(header_block);
791 
792  assembler().Bind(header_block);
793  GenerateExpressionBranch(stmt->condition, body_block, exit_block);
794 
795  assembler().Bind(body_block);
796  {
797  BreakContinueActivator activator{exit_block, header_block};
798  const Type* body_result = Visit(stmt->body);
799  if (body_result != TypeOracle::GetNeverType()) {
800  assembler().Goto(header_block);
801  }
802  }
803 
804  assembler().Bind(exit_block);
805  return TypeOracle::GetVoidType();
806 }
807 
808 const Type* ImplementationVisitor::Visit(BlockStatement* block) {
809  BlockBindings<LocalValue> block_bindings(&ValueBindingsManager::Get());
810  const Type* type = TypeOracle::GetVoidType();
811  for (Statement* s : block->statements) {
812  CurrentSourcePosition::Scope source_position(s->pos);
813  if (type->IsNever()) {
814  ReportError("statement after non-returning statement");
815  }
816  if (auto* var_declaration = VarDeclarationStatement::DynamicCast(s)) {
817  type = Visit(var_declaration, &block_bindings);
818  } else {
819  type = Visit(s);
820  }
821  }
822  return type;
823 }
824 
825 const Type* ImplementationVisitor::Visit(DebugStatement* stmt) {
826 #if defined(DEBUG)
827  assembler().Emit(PrintConstantStringInstruction{"halting because of '" +
828  stmt->reason + "' at " +
829  PositionAsString(stmt->pos)});
830 #endif
831  assembler().Emit(AbortInstruction{stmt->never_continues
832  ? AbortInstruction::Kind::kUnreachable
833  : AbortInstruction::Kind::kDebugBreak});
834  if (stmt->never_continues) {
835  return TypeOracle::GetNeverType();
836  } else {
837  return TypeOracle::GetVoidType();
838  }
839 }
840 
841 namespace {
842 
843 std::string FormatAssertSource(const std::string& str) {
844  // Replace all whitespace characters with a space character.
845  std::string str_no_newlines = str;
846  std::replace_if(str_no_newlines.begin(), str_no_newlines.end(),
847  [](unsigned char c) { return isspace(c); }, ' ');
848 
849  // str might include indentation, squash multiple space characters into one.
850  std::string result;
851  std::unique_copy(str_no_newlines.begin(), str_no_newlines.end(),
852  std::back_inserter(result),
853  [](char a, char b) { return a == ' ' && b == ' '; });
854  return result;
855 }
856 
857 } // namespace
858 
859 const Type* ImplementationVisitor::Visit(AssertStatement* stmt) {
860  bool do_check = !stmt->debug_only;
861 #if defined(DEBUG)
862  do_check = true;
863 #endif
864  if (do_check) {
865  // CSA_ASSERT & co. are not used here on purpose for two reasons. First,
866  // Torque allows and handles two types of expressions in the if protocol
867  // automagically, ones that return TNode<BoolT> and those that use the
868  // BranchIf(..., Label* true, Label* false) idiom. Because the machinery to
869  // handle this is embedded in the expression handling and to it's not
870  // possible to make the decision to use CSA_ASSERT or CSA_ASSERT_BRANCH
871  // isn't trivial up-front. Secondly, on failure, the assert text should be
872  // the corresponding Torque code, not the -gen.cc code, which would be the
873  // case when using CSA_ASSERT_XXX.
874  Block* true_block = assembler().NewBlock(assembler().CurrentStack());
875  Block* false_block = assembler().NewBlock(assembler().CurrentStack(), true);
876  GenerateExpressionBranch(stmt->expression, true_block, false_block);
877 
878  assembler().Bind(false_block);
879 
880  assembler().Emit(AbortInstruction{
881  AbortInstruction::Kind::kAssertionFailure,
882  "Torque assert '" + FormatAssertSource(stmt->source) + "' failed"});
883 
884  assembler().Bind(true_block);
885  }
886  return TypeOracle::GetVoidType();
887 }
888 
889 const Type* ImplementationVisitor::Visit(ExpressionStatement* stmt) {
890  const Type* type = Visit(stmt->expression).type();
891  return type->IsNever() ? type : TypeOracle::GetVoidType();
892 }
893 
894 const Type* ImplementationVisitor::Visit(ReturnStatement* stmt) {
895  Callable* current_callable = CurrentCallable::Get();
896  if (current_callable->signature().return_type->IsNever()) {
897  std::stringstream s;
898  s << "cannot return from a function with return type never";
899  ReportError(s.str());
900  }
901  LocalLabel* end =
902  current_callable->IsMacro() ? LookupLabel("_macro_end") : nullptr;
903  if (current_callable->HasReturnValue()) {
904  if (!stmt->value) {
905  std::stringstream s;
906  s << "return expression needs to be specified for a return type of "
907  << *current_callable->signature().return_type;
908  ReportError(s.str());
909  }
910  VisitResult expression_result = Visit(*stmt->value);
911  VisitResult return_result = GenerateImplicitConvert(
912  current_callable->signature().return_type, expression_result);
913  if (current_callable->IsMacro()) {
914  if (return_result.IsOnStack()) {
915  StackRange return_value_range =
916  GenerateLabelGoto(end, return_result.stack_range());
917  SetReturnValue(VisitResult(return_result.type(), return_value_range));
918  } else {
919  GenerateLabelGoto(end);
920  SetReturnValue(return_result);
921  }
922  } else if (current_callable->IsBuiltin()) {
923  assembler().Emit(ReturnInstruction{});
924  } else {
925  UNREACHABLE();
926  }
927  } else {
928  if (stmt->value) {
929  std::stringstream s;
930  s << "return expression can't be specified for a void or never return "
931  "type";
932  ReportError(s.str());
933  }
934  GenerateLabelGoto(end);
935  }
936  current_callable->IncrementReturns();
937  return TypeOracle::GetNeverType();
938 }
939 
940 const Type* ImplementationVisitor::Visit(ForOfLoopStatement* stmt) {
941  VisitResult expression_result = Visit(stmt->iterable);
942  VisitResult begin = stmt->begin
943  ? Visit(*stmt->begin)
944  : VisitResult(TypeOracle::GetConstInt31Type(), "0");
945 
946  VisitResult end = stmt->end
947  ? Visit(*stmt->end)
948  : GenerateCall(".length", {{expression_result}, {}});
949 
950  const Type* common_type = GetCommonType(begin.type(), end.type());
951  VisitResult index = GenerateImplicitConvert(common_type, begin);
952 
953  Block* body_block = assembler().NewBlock();
954  Block* increment_block = assembler().NewBlock(assembler().CurrentStack());
955  Block* exit_block = assembler().NewBlock(assembler().CurrentStack());
956 
957  Block* header_block = assembler().NewBlock();
958 
959  assembler().Goto(header_block);
960 
961  assembler().Bind(header_block);
962 
963  BreakContinueActivator activator(exit_block, increment_block);
964 
965  {
966  StackScope comparison_scope(this);
967  VisitResult result = GenerateCall("<", {{index, end}, {}});
968  if (result.type() != TypeOracle::GetBoolType()) {
969  ReportError("operator < with arguments(", *index.type(), ", ",
970  *end.type(),
971  ") used in for-of loop has to return type bool, but "
972  "returned type ",
973  *result.type());
974  }
975  comparison_scope.Yield(result);
976  }
977  assembler().Branch(body_block, exit_block);
978 
979  assembler().Bind(body_block);
980  {
981  VisitResult element_result;
982  {
983  StackScope element_scope(this);
984  VisitResult result = GenerateCall("[]", {{expression_result, index}, {}});
985  if (stmt->var_declaration->type) {
986  const Type* declared_type =
987  Declarations::GetType(*stmt->var_declaration->type);
988  result = GenerateImplicitConvert(declared_type, result);
989  }
990  element_result = element_scope.Yield(result);
991  }
992  Binding<LocalValue> element_var_binding{&ValueBindingsManager::Get(),
993  stmt->var_declaration->name,
994  LocalValue{true, element_result}};
995  Visit(stmt->body);
996  }
997  assembler().Goto(increment_block);
998 
999  assembler().Bind(increment_block);
1000  {
1001  Arguments increment_args;
1002  increment_args.parameters = {index, {TypeOracle::GetConstInt31Type(), "1"}};
1003  VisitResult increment_result = GenerateCall("+", increment_args);
1004 
1005  GenerateAssignToLocation(LocationReference::VariableAccess(index),
1006  increment_result);
1007  }
1008 
1009  assembler().Goto(header_block);
1010 
1011  assembler().Bind(exit_block);
1012  return TypeOracle::GetVoidType();
1013 }
1014 
1015 VisitResult ImplementationVisitor::Visit(TryLabelExpression* expr) {
1016  size_t parameter_count = expr->label_block->parameters.names.size();
1017  std::vector<VisitResult> parameters;
1018 
1019  Block* label_block = nullptr;
1020  Block* done_block = assembler().NewBlock();
1021  VisitResult try_result;
1022 
1023  {
1024  CurrentSourcePosition::Scope source_position(expr->label_block->pos);
1025  if (expr->label_block->parameters.has_varargs) {
1026  ReportError("cannot use ... for label parameters");
1027  }
1028  Stack<const Type*> label_input_stack = assembler().CurrentStack();
1029  TypeVector parameter_types;
1030  for (size_t i = 0; i < parameter_count; ++i) {
1031  const Type* type =
1032  Declarations::GetType(expr->label_block->parameters.types[i]);
1033  parameter_types.push_back(type);
1034  if (type->IsConstexpr()) {
1035  ReportError("no constexpr type allowed for label arguments");
1036  }
1037  StackRange range = label_input_stack.PushMany(LowerType(type));
1038  parameters.push_back(VisitResult(type, range));
1039  }
1040  label_block = assembler().NewBlock(label_input_stack,
1041  IsDeferred(expr->label_block->body));
1042 
1043  Binding<LocalLabel> label_binding{&LabelBindingsManager::Get(),
1044  expr->label_block->label,
1045  LocalLabel{label_block, parameter_types}};
1046 
1047  // Visit try
1048  StackScope stack_scope(this);
1049  try_result = Visit(expr->try_expression);
1050  if (try_result.type() != TypeOracle::GetNeverType()) {
1051  try_result = stack_scope.Yield(try_result);
1052  assembler().Goto(done_block);
1053  }
1054  }
1055 
1056  // Visit and output the code for the label block. If the label block falls
1057  // through, then the try must not return a value. Also, if the try doesn't
1058  // fall through, but the label does, then overall the try-label block
1059  // returns type void.
1060  assembler().Bind(label_block);
1061  const Type* label_result;
1062  {
1063  BlockBindings<LocalValue> parameter_bindings(&ValueBindingsManager::Get());
1064  for (size_t i = 0; i < parameter_count; ++i) {
1065  parameter_bindings.Add(expr->label_block->parameters.names[i],
1066  LocalValue{true, parameters[i]});
1067  }
1068 
1069  label_result = Visit(expr->label_block->body);
1070  }
1071  if (!try_result.type()->IsVoidOrNever() && label_result->IsVoid()) {
1072  ReportError(
1073  "otherwise clauses cannot fall through in a non-void expression");
1074  }
1075  if (label_result != TypeOracle::GetNeverType()) {
1076  assembler().Goto(done_block);
1077  }
1078  if (label_result->IsVoid() && try_result.type()->IsNever()) {
1079  try_result =
1080  VisitResult(TypeOracle::GetVoidType(), try_result.stack_range());
1081  }
1082 
1083  if (!try_result.type()->IsNever()) {
1084  assembler().Bind(done_block);
1085  }
1086  return try_result;
1087 }
1088 
1089 VisitResult ImplementationVisitor::Visit(StatementExpression* expr) {
1090  return VisitResult{Visit(expr->statement), assembler().TopRange(0)};
1091 }
1092 
1093 const Type* ImplementationVisitor::Visit(BreakStatement* stmt) {
1094  base::Optional<Binding<LocalLabel>*> break_label = TryLookupLabel("_break");
1095  if (!break_label) {
1096  ReportError("break used outside of loop");
1097  }
1098  assembler().Goto((*break_label)->block);
1099  return TypeOracle::GetNeverType();
1100 }
1101 
1102 const Type* ImplementationVisitor::Visit(ContinueStatement* stmt) {
1103  base::Optional<Binding<LocalLabel>*> continue_label =
1104  TryLookupLabel("_continue");
1105  if (!continue_label) {
1106  ReportError("continue used outside of loop");
1107  }
1108  assembler().Goto((*continue_label)->block);
1109  return TypeOracle::GetNeverType();
1110 }
1111 
1112 const Type* ImplementationVisitor::Visit(ForLoopStatement* stmt) {
1113  BlockBindings<LocalValue> loop_bindings(&ValueBindingsManager::Get());
1114 
1115  if (stmt->var_declaration) Visit(*stmt->var_declaration, &loop_bindings);
1116 
1117  Block* body_block = assembler().NewBlock(assembler().CurrentStack());
1118  Block* exit_block = assembler().NewBlock(assembler().CurrentStack());
1119 
1120  Block* header_block = assembler().NewBlock();
1121  assembler().Goto(header_block);
1122  assembler().Bind(header_block);
1123 
1124  // The continue label is where "continue" statements jump to. If no action
1125  // expression is provided, we jump directly to the header.
1126  Block* continue_block = header_block;
1127 
1128  // The action label is only needed when an action expression was provided.
1129  Block* action_block = nullptr;
1130  if (stmt->action) {
1131  action_block = assembler().NewBlock();
1132 
1133  // The action expression needs to be executed on a continue.
1134  continue_block = action_block;
1135  }
1136 
1137  if (stmt->test) {
1138  GenerateExpressionBranch(*stmt->test, body_block, exit_block);
1139  } else {
1140  assembler().Goto(body_block);
1141  }
1142 
1143  assembler().Bind(body_block);
1144  {
1145  BreakContinueActivator activator(exit_block, continue_block);
1146  const Type* body_result = Visit(stmt->body);
1147  if (body_result != TypeOracle::GetNeverType()) {
1148  assembler().Goto(continue_block);
1149  }
1150  }
1151 
1152  if (stmt->action) {
1153  assembler().Bind(action_block);
1154  const Type* action_result = Visit(*stmt->action);
1155  if (action_result != TypeOracle::GetNeverType()) {
1156  assembler().Goto(header_block);
1157  }
1158  }
1159 
1160  assembler().Bind(exit_block);
1161  return TypeOracle::GetVoidType();
1162 }
1163 
1164 void ImplementationVisitor::GenerateImplementation(const std::string& dir,
1165  Namespace* nspace) {
1166  std::string new_source(nspace->source());
1167  std::string base_file_name =
1168  "builtins-" + DashifyString(nspace->name()) + "-from-dsl-gen";
1169 
1170  std::string source_file_name = dir + "/" + base_file_name + ".cc";
1171  ReplaceFileContentsIfDifferent(source_file_name, new_source);
1172  std::string new_header(nspace->header());
1173  std::string header_file_name = dir + "/" + base_file_name + ".h";
1174  ReplaceFileContentsIfDifferent(header_file_name, new_header);
1175 }
1176 
1177 void ImplementationVisitor::GenerateMacroFunctionDeclaration(
1178  std::ostream& o, const std::string& macro_prefix, Macro* macro) {
1179  GenerateFunctionDeclaration(o, macro_prefix, macro->ExternalName(),
1180  macro->signature(), macro->parameter_names());
1181 }
1182 
1183 void ImplementationVisitor::GenerateFunctionDeclaration(
1184  std::ostream& o, const std::string& macro_prefix, const std::string& name,
1185  const Signature& signature, const NameVector& parameter_names) {
1186  if (GlobalContext::verbose()) {
1187  std::cout << "generating source for declaration " << name << "\n";
1188  }
1189 
1190  if (signature.return_type->IsVoidOrNever()) {
1191  o << "void";
1192  } else {
1193  o << signature.return_type->GetGeneratedTypeName();
1194  }
1195  o << " " << macro_prefix << name << "(";
1196 
1197  DCHECK_EQ(signature.types().size(), parameter_names.size());
1198  auto type_iterator = signature.types().begin();
1199  bool first = true;
1200  for (const std::string& name : parameter_names) {
1201  if (!first) {
1202  o << ", ";
1203  }
1204  const Type* parameter_type = *type_iterator;
1205  const std::string& generated_type_name =
1206  parameter_type->GetGeneratedTypeName();
1207  o << generated_type_name << " " << ExternalParameterName(name);
1208  type_iterator++;
1209  first = false;
1210  }
1211 
1212  for (const LabelDeclaration& label_info : signature.labels) {
1213  if (!first) {
1214  o << ", ";
1215  }
1216  o << "compiler::CodeAssemblerLabel* " << ExternalLabelName(label_info.name);
1217  size_t i = 0;
1218  for (const Type* type : label_info.types) {
1219  std::string generated_type_name("compiler::TypedCodeAssemblerVariable<");
1220  generated_type_name += type->GetGeneratedTNodeTypeName();
1221  generated_type_name += ">*";
1222  o << ", ";
1223  o << generated_type_name << " "
1224  << ExternalLabelParameterName(label_info.name, i);
1225  ++i;
1226  }
1227  }
1228 
1229  o << ")";
1230 }
1231 
1232 namespace {
1233 
1234 void FailCallableLookup(const std::string& reason, const QualifiedName& name,
1235  const Arguments& arguments,
1236  const std::vector<Signature>& candidates) {
1237  std::stringstream stream;
1238  stream << "\n"
1239  << reason << ": \n " << name << "("
1240  << arguments.parameters.GetTypeVector() << ")";
1241  if (arguments.labels.size() != 0) {
1242  stream << " labels ";
1243  for (size_t i = 0; i < arguments.labels.size(); ++i) {
1244  stream << arguments.labels[i]->name() << "("
1245  << arguments.labels[i]->parameter_types << ")";
1246  }
1247  }
1248  stream << "\ncandidates are:";
1249  for (const Signature& signature : candidates) {
1250  stream << "\n " << name;
1251  PrintSignature(stream, signature, false);
1252  }
1253  ReportError(stream.str());
1254 }
1255 
1256 Callable* GetOrCreateSpecialization(const SpecializationKey& key) {
1257  if (base::Optional<Callable*> specialization =
1258  key.generic->GetSpecialization(key.specialized_types)) {
1259  return *specialization;
1260  }
1261  return DeclarationVisitor().SpecializeImplicit(key);
1262 }
1263 
1264 } // namespace
1265 
1266 base::Optional<Binding<LocalValue>*> ImplementationVisitor::TryLookupLocalValue(
1267  const std::string& name) {
1268  return ValueBindingsManager::Get().TryLookup(name);
1269 }
1270 
1271 base::Optional<Binding<LocalLabel>*> ImplementationVisitor::TryLookupLabel(
1272  const std::string& name) {
1273  return LabelBindingsManager::Get().TryLookup(name);
1274 }
1275 
1276 Binding<LocalLabel>* ImplementationVisitor::LookupLabel(
1277  const std::string& name) {
1278  base::Optional<Binding<LocalLabel>*> label = TryLookupLabel(name);
1279  if (!label) ReportError("cannot find label ", name);
1280  return *label;
1281 }
1282 
1283 Block* ImplementationVisitor::LookupSimpleLabel(const std::string& name) {
1284  LocalLabel* label = LookupLabel(name);
1285  if (!label->parameter_types.empty()) {
1286  ReportError("label ", name,
1287  "was expected to have no parameters, but has parameters (",
1288  label->parameter_types, ")");
1289  }
1290  return label->block;
1291 }
1292 
1293 Callable* ImplementationVisitor::LookupCall(
1294  const QualifiedName& name, const Arguments& arguments,
1295  const TypeVector& specialization_types) {
1296  Callable* result = nullptr;
1297  TypeVector parameter_types(arguments.parameters.GetTypeVector());
1298 
1299  std::vector<Declarable*> overloads;
1300  std::vector<Signature> overload_signatures;
1301  for (Declarable* declarable : Declarations::Lookup(name)) {
1302  if (Generic* generic = Generic::DynamicCast(declarable)) {
1303  base::Optional<TypeVector> inferred_specialization_types =
1304  generic->InferSpecializationTypes(specialization_types,
1305  parameter_types);
1306  if (!inferred_specialization_types) continue;
1307  overloads.push_back(generic);
1308  overload_signatures.push_back(
1309  DeclarationVisitor().MakeSpecializedSignature(
1310  SpecializationKey{generic, *inferred_specialization_types}));
1311  } else if (Callable* callable = Callable::DynamicCast(declarable)) {
1312  overloads.push_back(callable);
1313  overload_signatures.push_back(callable->signature());
1314  }
1315  }
1316  // Indices of candidates in overloads/overload_signatures.
1317  std::vector<size_t> candidates;
1318  for (size_t i = 0; i < overloads.size(); ++i) {
1319  const Signature& signature = overload_signatures[i];
1320  bool try_bool_context = arguments.labels.size() == 0 &&
1321  signature.return_type == TypeOracle::GetNeverType();
1322  base::Optional<Binding<LocalLabel>*> true_label;
1323  base::Optional<Binding<LocalLabel>*> false_label;
1324  if (try_bool_context) {
1325  true_label = TryLookupLabel(kTrueLabelName);
1326  false_label = TryLookupLabel(kFalseLabelName);
1327  }
1328  if (IsCompatibleSignature(signature, parameter_types, arguments.labels) ||
1329  (true_label && false_label &&
1330  IsCompatibleSignature(signature, parameter_types,
1331  {*true_label, *false_label}))) {
1332  candidates.push_back(i);
1333  }
1334  }
1335 
1336  if (overloads.empty()) {
1337  std::stringstream stream;
1338  stream << "no matching declaration found for " << name;
1339  ReportError(stream.str());
1340  } else if (candidates.empty()) {
1341  FailCallableLookup("cannot find suitable callable with name", name,
1342  arguments, overload_signatures);
1343  }
1344 
1345  auto is_better_candidate = [&](size_t a, size_t b) {
1346  return ParameterDifference(overload_signatures[a].GetExplicitTypes(),
1347  parameter_types)
1348  .StrictlyBetterThan(ParameterDifference(
1349  overload_signatures[b].GetExplicitTypes(), parameter_types));
1350  };
1351 
1352  size_t best = *std::min_element(candidates.begin(), candidates.end(),
1353  is_better_candidate);
1354  // This check is contained in libstdc++'s std::min_element.
1355  DCHECK(!is_better_candidate(best, best));
1356  for (size_t candidate : candidates) {
1357  if (candidate != best && !is_better_candidate(best, candidate)) {
1358  std::vector<Signature> candidate_signatures;
1359  for (size_t i : candidates) {
1360  candidate_signatures.push_back(overload_signatures[i]);
1361  }
1362  FailCallableLookup("ambiguous callable", name, arguments,
1363  candidate_signatures);
1364  }
1365  }
1366 
1367  if (Generic* generic = Generic::DynamicCast(overloads[best])) {
1368  result = GetOrCreateSpecialization(
1369  SpecializationKey{generic, *generic->InferSpecializationTypes(
1370  specialization_types, parameter_types)});
1371  } else {
1372  result = Callable::cast(overloads[best]);
1373  }
1374 
1375  size_t caller_size = parameter_types.size();
1376  size_t callee_size =
1377  result->signature().types().size() - result->signature().implicit_count;
1378  if (caller_size != callee_size &&
1379  !result->signature().parameter_types.var_args) {
1380  std::stringstream stream;
1381  stream << "parameter count mismatch calling " << *result << " - expected "
1382  << std::to_string(callee_size) << ", found "
1383  << std::to_string(caller_size);
1384  ReportError(stream.str());
1385  }
1386 
1387  return result;
1388 }
1389 
1390 const Type* ImplementationVisitor::GetCommonType(const Type* left,
1391  const Type* right) {
1392  const Type* common_type;
1393  if (IsAssignableFrom(left, right)) {
1394  common_type = left;
1395  } else if (IsAssignableFrom(right, left)) {
1396  common_type = right;
1397  } else {
1398  common_type = TypeOracle::GetUnionType(left, right);
1399  }
1400  common_type = common_type->NonConstexprVersion();
1401  return common_type;
1402 }
1403 
1404 VisitResult ImplementationVisitor::GenerateCopy(const VisitResult& to_copy) {
1405  if (to_copy.IsOnStack()) {
1406  return VisitResult(to_copy.type(),
1407  assembler().Peek(to_copy.stack_range(), to_copy.type()));
1408  }
1409  return to_copy;
1410 }
1411 
1412 VisitResult ImplementationVisitor::Visit(StructExpression* decl) {
1413  const Type* raw_type = Declarations::LookupType(
1414  QualifiedName(decl->namespace_qualification, decl->name));
1415  if (!raw_type->IsStructType()) {
1416  std::stringstream s;
1417  s << decl->name << " is not a struct but used like one ";
1418  ReportError(s.str());
1419  }
1420  const StructType* struct_type = StructType::cast(raw_type);
1421  if (struct_type->fields().size() != decl->expressions.size()) {
1422  std::stringstream s;
1423  s << "initializer count mismatch for struct " << decl->name << " (expected "
1424  << struct_type->fields().size() << ", found " << decl->expressions.size()
1425  << ")";
1426  ReportError(s.str());
1427  }
1428  StackRange stack_range = assembler().TopRange(0);
1429  for (size_t i = 0; i < struct_type->fields().size(); ++i) {
1430  const NameAndType& field = struct_type->fields()[i];
1431  StackScope scope(this);
1432  VisitResult value = Visit(decl->expressions[i]);
1433  value = GenerateImplicitConvert(field.type, value);
1434  stack_range.Extend(scope.Yield(value).stack_range());
1435  }
1436  return VisitResult(struct_type, stack_range);
1437 }
1438 
1439 LocationReference ImplementationVisitor::GetLocationReference(
1440  Expression* location) {
1441  switch (location->kind) {
1442  case AstNode::Kind::kIdentifierExpression:
1443  return GetLocationReference(static_cast<IdentifierExpression*>(location));
1444  case AstNode::Kind::kFieldAccessExpression:
1445  return GetLocationReference(
1446  static_cast<FieldAccessExpression*>(location));
1447  case AstNode::Kind::kElementAccessExpression:
1448  return GetLocationReference(
1449  static_cast<ElementAccessExpression*>(location));
1450  default:
1451  return LocationReference::Temporary(Visit(location), "expression");
1452  }
1453 }
1454 
1455 LocationReference ImplementationVisitor::GetLocationReference(
1456  FieldAccessExpression* expr) {
1457  LocationReference reference = GetLocationReference(expr->object);
1458  if (reference.IsVariableAccess() &&
1459  reference.variable().type()->IsStructType()) {
1460  return LocationReference::VariableAccess(
1461  ProjectStructField(reference.variable(), expr->field));
1462  }
1463  if (reference.IsTemporary() && reference.temporary().type()->IsStructType()) {
1464  return LocationReference::Temporary(
1465  ProjectStructField(reference.temporary(), expr->field),
1466  reference.temporary_description());
1467  }
1468  return LocationReference::FieldAccess(GenerateFetchFromLocation(reference),
1469  expr->field);
1470 }
1471 
1472 LocationReference ImplementationVisitor::GetLocationReference(
1473  ElementAccessExpression* expr) {
1474  VisitResult array = Visit(expr->array);
1475  VisitResult index = Visit(expr->index);
1476  return LocationReference::ArrayAccess(array, index);
1477 }
1478 
1479 LocationReference ImplementationVisitor::GetLocationReference(
1480  IdentifierExpression* expr) {
1481  if (expr->namespace_qualification.empty()) {
1482  if (base::Optional<Binding<LocalValue>*> value =
1483  TryLookupLocalValue(expr->name)) {
1484  if (expr->generic_arguments.size() != 0) {
1485  ReportError("cannot have generic parameters on local name ",
1486  expr->name);
1487  }
1488  if ((*value)->is_const) {
1489  return LocationReference::Temporary((*value)->value,
1490  "constant value " + expr->name);
1491  }
1492  return LocationReference::VariableAccess((*value)->value);
1493  }
1494  }
1495 
1496  QualifiedName name = QualifiedName(expr->namespace_qualification, expr->name);
1497  if (base::Optional<Builtin*> builtin = Declarations::TryLookupBuiltin(name)) {
1498  return LocationReference::Temporary(GetBuiltinCode(*builtin),
1499  "builtin " + expr->name);
1500  }
1501  if (expr->generic_arguments.size() != 0) {
1502  Generic* generic = Declarations::LookupUniqueGeneric(name);
1503  Callable* specialization = GetOrCreateSpecialization(
1504  SpecializationKey{generic, GetTypeVector(expr->generic_arguments)});
1505  if (Builtin* builtin = Builtin::DynamicCast(specialization)) {
1506  DCHECK(!builtin->IsExternal());
1507  return LocationReference::Temporary(GetBuiltinCode(builtin),
1508  "builtin " + expr->name);
1509  } else {
1510  ReportError("cannot create function pointer for non-builtin ",
1511  generic->name());
1512  }
1513  }
1514  Value* value = Declarations::LookupValue(name);
1515  if (auto* constant = NamespaceConstant::DynamicCast(value)) {
1516  if (constant->type()->IsConstexpr()) {
1517  return LocationReference::Temporary(
1518  VisitResult(constant->type(), constant->ExternalAssemblerName() +
1519  "(state_)." +
1520  constant->constant_name() + "()"),
1521  "namespace constant " + expr->name);
1522  }
1523  assembler().Emit(NamespaceConstantInstruction{constant});
1524  StackRange stack_range =
1525  assembler().TopRange(LoweredSlotCount(constant->type()));
1526  return LocationReference::Temporary(
1527  VisitResult(constant->type(), stack_range),
1528  "namespace constant " + expr->name);
1529  }
1530  ExternConstant* constant = ExternConstant::cast(value);
1531  return LocationReference::Temporary(constant->value(),
1532  "extern value " + expr->name);
1533 }
1534 
1535 VisitResult ImplementationVisitor::GenerateFetchFromLocation(
1536  const LocationReference& reference) {
1537  if (reference.IsTemporary()) {
1538  return GenerateCopy(reference.temporary());
1539  } else if (reference.IsVariableAccess()) {
1540  return GenerateCopy(reference.variable());
1541  } else {
1542  DCHECK(reference.IsCallAccess());
1543  return GenerateCall(reference.eval_function(),
1544  Arguments{reference.call_arguments(), {}});
1545  }
1546 }
1547 
1548 void ImplementationVisitor::GenerateAssignToLocation(
1549  const LocationReference& reference, const VisitResult& assignment_value) {
1550  if (reference.IsCallAccess()) {
1551  Arguments arguments{reference.call_arguments(), {}};
1552  arguments.parameters.push_back(assignment_value);
1553  GenerateCall(reference.assign_function(), arguments);
1554  } else if (reference.IsVariableAccess()) {
1555  VisitResult variable = reference.variable();
1556  VisitResult converted_value =
1557  GenerateImplicitConvert(variable.type(), assignment_value);
1558  assembler().Poke(variable.stack_range(), converted_value.stack_range(),
1559  variable.type());
1560  } else {
1561  DCHECK(reference.IsTemporary());
1562  ReportError("cannot assign to ", reference.temporary_description());
1563  }
1564 }
1565 
1566 VisitResult ImplementationVisitor::GeneratePointerCall(
1567  Expression* callee, const Arguments& arguments, bool is_tailcall) {
1568  StackScope scope(this);
1569  TypeVector parameter_types(arguments.parameters.GetTypeVector());
1570  VisitResult callee_result = Visit(callee);
1571  if (!callee_result.type()->IsFunctionPointerType()) {
1572  std::stringstream stream;
1573  stream << "Expected a function pointer type but found "
1574  << *callee_result.type();
1575  ReportError(stream.str());
1576  }
1577  const FunctionPointerType* type =
1578  FunctionPointerType::cast(callee_result.type());
1579 
1580  if (type->parameter_types().size() != parameter_types.size()) {
1581  std::stringstream stream;
1582  stream << "parameter count mismatch calling function pointer with Type: "
1583  << *type << " - expected "
1584  << std::to_string(type->parameter_types().size()) << ", found "
1585  << std::to_string(parameter_types.size());
1586  ReportError(stream.str());
1587  }
1588 
1589  ParameterTypes types{type->parameter_types(), false};
1590  Signature sig;
1591  sig.parameter_types = types;
1592  if (!IsCompatibleSignature(sig, parameter_types, {})) {
1593  std::stringstream stream;
1594  stream << "parameters do not match function pointer signature. Expected: ("
1595  << type->parameter_types() << ") but got: (" << parameter_types
1596  << ")";
1597  ReportError(stream.str());
1598  }
1599 
1600  callee_result = GenerateCopy(callee_result);
1601  StackRange arg_range = assembler().TopRange(0);
1602  for (size_t current = 0; current < arguments.parameters.size(); ++current) {
1603  const Type* to_type = type->parameter_types()[current];
1604  arg_range.Extend(
1605  GenerateImplicitConvert(to_type, arguments.parameters[current])
1606  .stack_range());
1607  }
1608 
1609  assembler().Emit(
1610  CallBuiltinPointerInstruction{is_tailcall, type, arg_range.Size()});
1611 
1612  if (is_tailcall) {
1613  return VisitResult::NeverResult();
1614  }
1615  DCHECK_EQ(1, LoweredSlotCount(type->return_type()));
1616  return scope.Yield(VisitResult(type->return_type(), assembler().TopRange(1)));
1617 }
1618 
1619 VisitResult ImplementationVisitor::GenerateCall(
1620  const QualifiedName& callable_name, Arguments arguments,
1621  const TypeVector& specialization_types, bool is_tailcall) {
1622  Callable* callable =
1623  LookupCall(callable_name, arguments, specialization_types);
1624 
1625  // Operators used in a branching context can also be function calls that never
1626  // return but have a True and False label
1627  if (arguments.labels.size() == 0 &&
1628  callable->signature().labels.size() == 2) {
1629  Binding<LocalLabel>* true_label = LookupLabel(kTrueLabelName);
1630  arguments.labels.push_back(true_label);
1631  Binding<LocalLabel>* false_label = LookupLabel(kFalseLabelName);
1632  arguments.labels.push_back(false_label);
1633  }
1634 
1635  const Type* return_type = callable->signature().return_type;
1636 
1637  std::vector<VisitResult> converted_arguments;
1638  StackRange argument_range = assembler().TopRange(0);
1639  std::vector<std::string> constexpr_arguments;
1640 
1641  for (size_t current = 0; current < callable->signature().implicit_count;
1642  ++current) {
1643  std::string implicit_name = callable->signature().parameter_names[current];
1644  base::Optional<Binding<LocalValue>*> val =
1645  TryLookupLocalValue(implicit_name);
1646  if (!val) {
1647  ReportError("implicit parameter '", implicit_name,
1648  "' required for call to '", callable_name,
1649  "' is not defined");
1650  }
1651  VisitResult converted = GenerateImplicitConvert(
1652  callable->signature().parameter_types.types[current], (*val)->value);
1653  converted_arguments.push_back(converted);
1654  if (converted.IsOnStack()) {
1655  argument_range.Extend(converted.stack_range());
1656  } else {
1657  constexpr_arguments.push_back(converted.constexpr_value());
1658  }
1659  }
1660 
1661  for (size_t current = 0; current < arguments.parameters.size(); ++current) {
1662  size_t current_after_implicit =
1663  current + callable->signature().implicit_count;
1664  const Type* to_type =
1665  (current_after_implicit >= callable->signature().types().size())
1666  ? TypeOracle::GetObjectType()
1667  : callable->signature().types()[current_after_implicit];
1668  VisitResult converted =
1669  GenerateImplicitConvert(to_type, arguments.parameters[current]);
1670  converted_arguments.push_back(converted);
1671  if (converted.IsOnStack()) {
1672  argument_range.Extend(converted.stack_range());
1673  } else {
1674  constexpr_arguments.push_back(converted.constexpr_value());
1675  }
1676  }
1677 
1678  if (GlobalContext::verbose()) {
1679  std::cout << "generating code for call to " << callable_name << "\n";
1680  }
1681 
1682  size_t label_count = callable->signature().labels.size();
1683  if (label_count != arguments.labels.size()) {
1684  std::stringstream s;
1685  s << "unexpected number of otherwise labels for "
1686  << callable->ReadableName() << " (expected "
1687  << std::to_string(label_count) << " found "
1688  << std::to_string(arguments.labels.size()) << ")";
1689  ReportError(s.str());
1690  }
1691 
1692  if (callable->IsTransitioning()) {
1693  if (!CurrentCallable::Get()->IsTransitioning()) {
1694  std::stringstream s;
1695  s << *CurrentCallable::Get()
1696  << " isn't marked transitioning but calls the transitioning "
1697  << *callable;
1698  ReportError(s.str());
1699  }
1700  }
1701 
1702  if (auto* builtin = Builtin::DynamicCast(callable)) {
1703  base::Optional<Block*> catch_block = GetCatchBlock();
1704  assembler().Emit(CallBuiltinInstruction{
1705  is_tailcall, builtin, argument_range.Size(), catch_block});
1706  GenerateCatchBlock(catch_block);
1707  if (is_tailcall) {
1708  return VisitResult::NeverResult();
1709  } else {
1710  size_t slot_count = LoweredSlotCount(return_type);
1711  DCHECK_LE(slot_count, 1);
1712  // TODO(tebbi): Actually, builtins have to return a value, so we should
1713  // assert slot_count == 1 here.
1714  return VisitResult(return_type, assembler().TopRange(slot_count));
1715  }
1716  } else if (auto* macro = Macro::DynamicCast(callable)) {
1717  if (is_tailcall) {
1718  ReportError("can't tail call a macro");
1719  }
1720  if (return_type->IsConstexpr()) {
1721  DCHECK_EQ(0, arguments.labels.size());
1722  std::stringstream result;
1723  result << "(" << macro->external_assembler_name() << "(state_)."
1724  << macro->ExternalName() << "(";
1725  bool first = true;
1726  for (VisitResult arg : arguments.parameters) {
1727  DCHECK(!arg.IsOnStack());
1728  if (!first) {
1729  result << ", ";
1730  }
1731  first = false;
1732  result << arg.constexpr_value();
1733  }
1734  result << "))";
1735  return VisitResult(return_type, result.str());
1736  } else if (arguments.labels.empty() &&
1737  return_type != TypeOracle::GetNeverType()) {
1738  base::Optional<Block*> catch_block = GetCatchBlock();
1739  assembler().Emit(
1740  CallCsaMacroInstruction{macro, constexpr_arguments, catch_block});
1741  GenerateCatchBlock(catch_block);
1742  size_t return_slot_count = LoweredSlotCount(return_type);
1743  return VisitResult(return_type, assembler().TopRange(return_slot_count));
1744  } else {
1745  base::Optional<Block*> return_continuation;
1746  if (return_type != TypeOracle::GetNeverType()) {
1747  return_continuation = assembler().NewBlock();
1748  }
1749 
1750  std::vector<Block*> label_blocks;
1751 
1752  for (size_t i = 0; i < label_count; ++i) {
1753  label_blocks.push_back(assembler().NewBlock());
1754  }
1755  base::Optional<Block*> catch_block = GetCatchBlock();
1756  assembler().Emit(CallCsaMacroAndBranchInstruction{
1757  macro, constexpr_arguments, return_continuation, label_blocks,
1758  catch_block});
1759  GenerateCatchBlock(catch_block);
1760 
1761  for (size_t i = 0; i < label_count; ++i) {
1762  Binding<LocalLabel>* label = arguments.labels[i];
1763  size_t callee_label_parameters =
1764  callable->signature().labels[i].types.size();
1765  if (label->parameter_types.size() != callee_label_parameters) {
1766  std::stringstream s;
1767  s << "label " << label->name()
1768  << " doesn't have the right number of parameters (found "
1769  << std::to_string(label->parameter_types.size()) << " expected "
1770  << std::to_string(callee_label_parameters) << ")";
1771  ReportError(s.str());
1772  }
1773  assembler().Bind(label_blocks[i]);
1774  assembler().Goto(
1775  label->block,
1776  LowerParameterTypes(callable->signature().labels[i].types).size());
1777 
1778  size_t j = 0;
1779  for (auto t : callable->signature().labels[i].types) {
1780  const Type* parameter_type = label->parameter_types[j];
1781  if (parameter_type != t) {
1782  ReportError("mismatch of label parameters (expected ", *t, " got ",
1783  parameter_type, " for parameter ", i + 1, ")");
1784  }
1785  j++;
1786  }
1787  }
1788 
1789  if (return_continuation) {
1790  assembler().Bind(*return_continuation);
1791  size_t return_slot_count = LoweredSlotCount(return_type);
1792  return VisitResult(return_type,
1793  assembler().TopRange(return_slot_count));
1794  } else {
1795  return VisitResult::NeverResult();
1796  }
1797  }
1798  } else if (auto* runtime_function = RuntimeFunction::DynamicCast(callable)) {
1799  base::Optional<Block*> catch_block = GetCatchBlock();
1800  assembler().Emit(CallRuntimeInstruction{
1801  is_tailcall, runtime_function, argument_range.Size(), catch_block});
1802  GenerateCatchBlock(catch_block);
1803  if (is_tailcall || return_type == TypeOracle::GetNeverType()) {
1804  return VisitResult::NeverResult();
1805  } else {
1806  size_t slot_count = LoweredSlotCount(return_type);
1807  DCHECK_LE(slot_count, 1);
1808  // TODO(tebbi): Actually, runtime functions have to return a value, so
1809  // we should assert slot_count == 1 here.
1810  return VisitResult(return_type, assembler().TopRange(slot_count));
1811  }
1812  } else if (auto* intrinsic = Intrinsic::DynamicCast(callable)) {
1813  assembler().Emit(CallIntrinsicInstruction{intrinsic, constexpr_arguments});
1814  size_t return_slot_count =
1815  LoweredSlotCount(intrinsic->signature().return_type);
1816  return VisitResult(return_type, assembler().TopRange(return_slot_count));
1817  } else {
1818  UNREACHABLE();
1819  }
1820 }
1821 
1822 VisitResult ImplementationVisitor::Visit(CallExpression* expr,
1823  bool is_tailcall) {
1824  StackScope scope(this);
1825  Arguments arguments;
1826  QualifiedName name =
1827  QualifiedName(expr->callee->namespace_qualification, expr->callee->name);
1828  TypeVector specialization_types =
1829  GetTypeVector(expr->callee->generic_arguments);
1830  bool has_template_arguments = !specialization_types.empty();
1831  for (Expression* arg : expr->arguments)
1832  arguments.parameters.push_back(Visit(arg));
1833  arguments.labels = LabelsFromIdentifiers(expr->labels);
1834  VisitResult result;
1835  if (!has_template_arguments && name.namespace_qualification.empty() &&
1836  TryLookupLocalValue(name.name)) {
1837  return scope.Yield(
1838  GeneratePointerCall(expr->callee, arguments, is_tailcall));
1839  } else {
1840  return scope.Yield(
1841  GenerateCall(name, arguments, specialization_types, is_tailcall));
1842  }
1843 }
1844 
1845 VisitResult ImplementationVisitor::Visit(IntrinsicCallExpression* expr) {
1846  StackScope scope(this);
1847  Arguments arguments;
1848  TypeVector specialization_types = GetTypeVector(expr->generic_arguments);
1849  for (Expression* arg : expr->arguments)
1850  arguments.parameters.push_back(Visit(arg));
1851  return scope.Yield(
1852  GenerateCall(expr->name, arguments, specialization_types, false));
1853 }
1854 
1855 void ImplementationVisitor::GenerateBranch(const VisitResult& condition,
1856  Block* true_block,
1857  Block* false_block) {
1858  DCHECK_EQ(condition,
1859  VisitResult(TypeOracle::GetBoolType(), assembler().TopRange(1)));
1860  assembler().Branch(true_block, false_block);
1861 }
1862 
1863 void ImplementationVisitor::GenerateExpressionBranch(Expression* expression,
1864  Block* true_block,
1865  Block* false_block) {
1866  // Conditional expressions can either explicitly return a bit
1867  // type, or they can be backed by macros that don't return but
1868  // take a true and false label. By declaring the labels before
1869  // visiting the conditional expression, those label-based
1870  // macro conditionals will be able to find them through normal
1871  // label lookups.
1872  Binding<LocalLabel> true_binding{&LabelBindingsManager::Get(), kTrueLabelName,
1873  LocalLabel{true_block}};
1874  Binding<LocalLabel> false_binding{&LabelBindingsManager::Get(),
1875  kFalseLabelName, LocalLabel{false_block}};
1876  StackScope stack_scope(this);
1877  VisitResult expression_result = Visit(expression);
1878  if (!expression_result.type()->IsNever()) {
1879  expression_result = stack_scope.Yield(
1880  GenerateImplicitConvert(TypeOracle::GetBoolType(), expression_result));
1881  GenerateBranch(expression_result, true_block, false_block);
1882  }
1883 }
1884 
1885 VisitResult ImplementationVisitor::GenerateImplicitConvert(
1886  const Type* destination_type, VisitResult source) {
1887  StackScope scope(this);
1888  if (source.type() == TypeOracle::GetNeverType()) {
1889  ReportError("it is not allowed to use a value of type never");
1890  }
1891 
1892  if (destination_type == source.type()) {
1893  return scope.Yield(GenerateCopy(source));
1894  }
1895 
1896  if (TypeOracle::IsImplicitlyConvertableFrom(destination_type,
1897  source.type())) {
1898  return scope.Yield(GenerateCall(kFromConstexprMacroName, {{source}, {}},
1899  {destination_type}, false));
1900  } else if (IsAssignableFrom(destination_type, source.type())) {
1901  source.SetType(destination_type);
1902  return scope.Yield(GenerateCopy(source));
1903  } else {
1904  std::stringstream s;
1905  s << "cannot use expression of type " << *source.type()
1906  << " as a value of type " << *destination_type;
1907  ReportError(s.str());
1908  }
1909 }
1910 
1911 StackRange ImplementationVisitor::GenerateLabelGoto(
1912  LocalLabel* label, base::Optional<StackRange> arguments) {
1913  return assembler().Goto(label->block, arguments ? arguments->Size() : 0);
1914 }
1915 
1916 std::vector<Binding<LocalLabel>*> ImplementationVisitor::LabelsFromIdentifiers(
1917  const std::vector<std::string>& names) {
1918  std::vector<Binding<LocalLabel>*> result;
1919  result.reserve(names.size());
1920  for (const auto& name : names) {
1921  result.push_back(LookupLabel(name));
1922  }
1923  return result;
1924 }
1925 
1926 StackRange ImplementationVisitor::LowerParameter(
1927  const Type* type, const std::string& parameter_name,
1928  Stack<std::string>* lowered_parameters) {
1929  if (type->IsStructType()) {
1930  const StructType* struct_type = StructType::cast(type);
1931  StackRange range = lowered_parameters->TopRange(0);
1932  for (auto& field : struct_type->fields()) {
1933  StackRange parameter_range = LowerParameter(
1934  field.type, parameter_name + "." + field.name, lowered_parameters);
1935  range.Extend(parameter_range);
1936  }
1937  return range;
1938  } else {
1939  lowered_parameters->Push(parameter_name);
1940  return lowered_parameters->TopRange(1);
1941  }
1942 }
1943 
1944 std::string ImplementationVisitor::ExternalLabelName(
1945  const std::string& label_name) {
1946  return "label_" + label_name;
1947 }
1948 
1949 std::string ImplementationVisitor::ExternalLabelParameterName(
1950  const std::string& label_name, size_t i) {
1951  return "label_" + label_name + "_parameter_" + std::to_string(i);
1952 }
1953 
1954 std::string ImplementationVisitor::ExternalParameterName(
1955  const std::string& name) {
1956  return std::string("p_") + name;
1957 }
1958 
1959 DEFINE_CONTEXTUAL_VARIABLE(ImplementationVisitor::ValueBindingsManager);
1960 DEFINE_CONTEXTUAL_VARIABLE(ImplementationVisitor::LabelBindingsManager);
1961 DEFINE_CONTEXTUAL_VARIABLE(ImplementationVisitor::CurrentCallable);
1962 
1963 bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
1964  const std::vector<Binding<LocalLabel>*>& labels) {
1965  auto i = sig.parameter_types.types.begin() + sig.implicit_count;
1966  if ((sig.parameter_types.types.size() - sig.implicit_count) > types.size())
1967  return false;
1968  // TODO(danno): The test below is actually insufficient. The labels'
1969  // parameters must be checked too. ideally, the named part of
1970  // LabelDeclarationVector would be factored out so that the label count and
1971  // parameter types could be passed separately.
1972  if (sig.labels.size() != labels.size()) return false;
1973  for (auto current : types) {
1974  if (i == sig.parameter_types.types.end()) {
1975  if (!sig.parameter_types.var_args) return false;
1976  if (!IsAssignableFrom(TypeOracle::GetObjectType(), current)) return false;
1977  } else {
1978  if (!IsAssignableFrom(*i++, current)) return false;
1979  }
1980  }
1981  return true;
1982 }
1983 
1984 base::Optional<Block*> ImplementationVisitor::GetCatchBlock() {
1985  base::Optional<Block*> catch_block;
1986  if (base::Optional<Binding<LocalLabel>*> catch_handler =
1987  TryLookupLabel("_catch")) {
1988  catch_block = assembler().NewBlock(base::nullopt, true);
1989  }
1990  return catch_block;
1991 }
1992 
1993 void ImplementationVisitor::GenerateCatchBlock(
1994  base::Optional<Block*> catch_block) {
1995  if (catch_block) {
1996  base::Optional<Binding<LocalLabel>*> catch_handler =
1997  TryLookupLabel("_catch");
1998  if (assembler().CurrentBlockIsComplete()) {
1999  assembler().Bind(*catch_block);
2000  assembler().Goto((*catch_handler)->block, 1);
2001  } else {
2002  CfgAssemblerScopedTemporaryBlock temp(&assembler(), *catch_block);
2003  assembler().Goto((*catch_handler)->block, 1);
2004  }
2005  }
2006 }
2007 
2008 void ImplementationVisitor::VisitAllDeclarables() {
2009  const std::vector<std::unique_ptr<Declarable>>& all_declarables =
2010  GlobalContext::AllDeclarables();
2011  // This has to be an index-based loop because all_declarables can be extended
2012  // during the loop.
2013  for (size_t i = 0; i < all_declarables.size(); ++i) {
2014  Visit(all_declarables[i].get());
2015  }
2016 }
2017 
2018 void ImplementationVisitor::Visit(Declarable* declarable) {
2019  CurrentScope::Scope current_scope(declarable->ParentScope());
2020  CurrentSourcePosition::Scope current_source_position(declarable->pos());
2021  switch (declarable->kind()) {
2022  case Declarable::kMacro:
2023  return Visit(Macro::cast(declarable));
2024  case Declarable::kBuiltin:
2025  return Visit(Builtin::cast(declarable));
2026  case Declarable::kTypeAlias:
2027  return Visit(TypeAlias::cast(declarable));
2028  case Declarable::kNamespaceConstant:
2029  return Visit(NamespaceConstant::cast(declarable));
2030  case Declarable::kRuntimeFunction:
2031  case Declarable::kIntrinsic:
2032  case Declarable::kExternConstant:
2033  case Declarable::kNamespace:
2034  case Declarable::kGeneric:
2035  return;
2036  }
2037 }
2038 
2039 void ImplementationVisitor::GenerateBuiltinDefinitions(std::string& file_name) {
2040  std::stringstream new_contents_stream;
2041  new_contents_stream
2042  << "#ifndef V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n"
2043  "#define V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n"
2044  "\n"
2045  "#define BUILTIN_LIST_FROM_DSL(CPP, API, TFJ, TFC, TFS, TFH, ASM) "
2046  "\\\n";
2047  for (auto& declarable : GlobalContext::AllDeclarables()) {
2048  Builtin* builtin = Builtin::DynamicCast(declarable.get());
2049  if (!builtin || builtin->IsExternal()) continue;
2050  int firstParameterIndex = 1;
2051  bool declareParameters = true;
2052  if (builtin->IsStub()) {
2053  new_contents_stream << "TFS(" << builtin->ExternalName();
2054  } else {
2055  new_contents_stream << "TFJ(" << builtin->ExternalName();
2056  if (builtin->IsVarArgsJavaScript()) {
2057  new_contents_stream
2058  << ", SharedFunctionInfo::kDontAdaptArgumentsSentinel";
2059  declareParameters = false;
2060  } else {
2061  assert(builtin->IsFixedArgsJavaScript());
2062  // FixedArg javascript builtins need to offer the parameter
2063  // count.
2064  assert(builtin->parameter_names().size() >= 2);
2065  new_contents_stream << ", " << (builtin->parameter_names().size() - 2);
2066  // And the receiver is explicitly declared.
2067  new_contents_stream << ", kReceiver";
2068  firstParameterIndex = 2;
2069  }
2070  }
2071  if (declareParameters) {
2072  int index = 0;
2073  for (const auto& parameter : builtin->parameter_names()) {
2074  if (index >= firstParameterIndex) {
2075  new_contents_stream << ", k" << CamelifyString(parameter);
2076  }
2077  index++;
2078  }
2079  }
2080  new_contents_stream << ") \\\n";
2081  }
2082  new_contents_stream << "\n";
2083 
2084  new_contents_stream
2085  << "#define TORQUE_FUNCTION_POINTER_TYPE_TO_BUILTIN_MAP(V) \\\n";
2086  for (const FunctionPointerType* type :
2087  TypeOracle::AllFunctionPointerTypes()) {
2088  Builtin* example_builtin =
2089  Declarations::FindSomeInternalBuiltinWithType(type);
2090  if (!example_builtin) {
2091  CurrentSourcePosition::Scope current_source_position(
2092  SourcePosition{CurrentSourceFile::Get(), -1, -1});
2093  ReportError("unable to find any builtin with type \"", *type, "\"");
2094  }
2095  new_contents_stream << " V(" << type->function_pointer_type_id() << ","
2096  << example_builtin->ExternalName() << ")\\\n";
2097  }
2098  new_contents_stream << "\n";
2099 
2100  new_contents_stream
2101  << "#endif // V8_BUILTINS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n";
2102 
2103  std::string new_contents(new_contents_stream.str());
2104  ReplaceFileContentsIfDifferent(file_name, new_contents);
2105 }
2106 
2107 } // namespace torque
2108 } // namespace internal
2109 } // namespace v8
Definition: libplatform.h:13