V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
csa-generator.cc
1 // Copyright 2018 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/csa-generator.h"
6 
7 #include "src/torque/type-oracle.h"
8 #include "src/torque/utils.h"
9 
10 namespace v8 {
11 namespace internal {
12 namespace torque {
13 
14 base::Optional<Stack<std::string>> CSAGenerator::EmitGraph(
15  Stack<std::string> parameters) {
16  for (Block* block : cfg_.blocks()) {
17  out_ << " compiler::CodeAssemblerParameterizedLabel<";
18  PrintCommaSeparatedList(out_, block->InputTypes(), [](const Type* t) {
19  return t->GetGeneratedTNodeTypeName();
20  });
21  out_ << "> " << BlockName(block) << "(&ca_, compiler::CodeAssemblerLabel::"
22  << (block->IsDeferred() ? "kDeferred" : "kNonDeferred") << ");\n";
23  }
24 
25  EmitInstruction(GotoInstruction{cfg_.start()}, &parameters);
26  for (Block* block : cfg_.blocks()) {
27  if (cfg_.end() && *cfg_.end() == block) continue;
28  out_ << "\n if (" << BlockName(block) << ".is_used()) {\n";
29  EmitBlock(block);
30  out_ << " }\n";
31  }
32  if (cfg_.end()) {
33  out_ << "\n";
34  return EmitBlock(*cfg_.end());
35  }
36  return base::nullopt;
37 }
38 
39 Stack<std::string> CSAGenerator::EmitBlock(const Block* block) {
40  Stack<std::string> stack;
41  for (const Type* t : block->InputTypes()) {
42  stack.Push(FreshNodeName());
43  out_ << " compiler::TNode<" << t->GetGeneratedTNodeTypeName() << "> "
44  << stack.Top() << ";\n";
45  }
46  out_ << " ca_.Bind(&" << BlockName(block);
47  for (const std::string& name : stack) {
48  out_ << ", &" << name;
49  }
50  out_ << ");\n";
51  for (const Instruction& instruction : block->instructions()) {
52  EmitInstruction(instruction, &stack);
53  }
54  return stack;
55 }
56 
57 void CSAGenerator::EmitInstruction(const Instruction& instruction,
58  Stack<std::string>* stack) {
59  switch (instruction.kind()) {
60 #define ENUM_ITEM(T) \
61  case InstructionKind::k##T: \
62  return EmitInstruction(instruction.Cast<T>(), stack);
63  TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
64 #undef ENUM_ITEM
65  }
66 }
67 
68 void CSAGenerator::EmitInstruction(const PeekInstruction& instruction,
69  Stack<std::string>* stack) {
70  stack->Push(stack->Peek(instruction.slot));
71 }
72 
73 void CSAGenerator::EmitInstruction(const PokeInstruction& instruction,
74  Stack<std::string>* stack) {
75  stack->Poke(instruction.slot, stack->Top());
76  stack->Pop();
77 }
78 
79 void CSAGenerator::EmitInstruction(const DeleteRangeInstruction& instruction,
80  Stack<std::string>* stack) {
81  stack->DeleteRange(instruction.range);
82 }
83 
84 void CSAGenerator::EmitInstruction(
85  const PushUninitializedInstruction& instruction,
86  Stack<std::string>* stack) {
87  // TODO(tebbi): This can trigger an error in CSA if it is used. Instead, we
88  // should prevent usage of uninitialized in the type system. This
89  // requires "if constexpr" being evaluated at Torque time.
90  stack->Push("ca_.Uninitialized<" +
91  instruction.type->GetGeneratedTNodeTypeName() + ">()");
92 }
93 
94 void CSAGenerator::EmitInstruction(
95  const PushCodePointerInstruction& instruction, Stack<std::string>* stack) {
96  stack->Push(
97  "ca_.UncheckedCast<Code>(ca_.HeapConstant(Builtins::CallableFor(ca_."
98  "isolate(), Builtins::k" +
99  instruction.external_name + ").code()))");
100 }
101 
102 void CSAGenerator::EmitInstruction(
103  const NamespaceConstantInstruction& instruction,
104  Stack<std::string>* stack) {
105  const Type* type = instruction.constant->type();
106  std::vector<std::string> results;
107  for (const Type* lowered : LowerType(type)) {
108  results.push_back(FreshNodeName());
109  stack->Push(results.back());
110  out_ << " compiler::TNode<" << lowered->GetGeneratedTNodeTypeName()
111  << "> " << stack->Top() << ";\n";
112  out_ << " USE(" << stack->Top() << ");\n";
113  }
114  out_ << " ";
115  if (type->IsStructType()) {
116  out_ << "std::tie(";
117  PrintCommaSeparatedList(out_, results);
118  out_ << ") = ";
119  } else if (results.size() == 1) {
120  out_ << results[0] << " = ";
121  }
122  out_ << instruction.constant->ExternalAssemblerName() << "(state_)."
123  << instruction.constant->constant_name() << "()";
124  if (type->IsStructType()) {
125  out_ << ".Flatten();\n";
126  } else {
127  out_ << ";\n";
128  }
129 }
130 
131 void CSAGenerator::ProcessArgumentsCommon(
132  const TypeVector& parameter_types, std::vector<std::string>* args,
133  std::vector<std::string>* constexpr_arguments, Stack<std::string>* stack) {
134  for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) {
135  const Type* type = *it;
136  VisitResult arg;
137  if (type->IsConstexpr()) {
138  args->push_back(std::move(constexpr_arguments->back()));
139  constexpr_arguments->pop_back();
140  } else {
141  std::stringstream s;
142  size_t slot_count = LoweredSlotCount(type);
143  VisitResult arg = VisitResult(type, stack->TopRange(slot_count));
144  EmitCSAValue(arg, *stack, s);
145  args->push_back(s.str());
146  stack->PopMany(slot_count);
147  }
148  }
149  std::reverse(args->begin(), args->end());
150 }
151 
152 void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
153  Stack<std::string>* stack) {
154  std::vector<std::string> constexpr_arguments =
155  instruction.constexpr_arguments;
156  std::vector<std::string> args;
157  TypeVector parameter_types =
158  instruction.intrinsic->signature().parameter_types.types;
159  ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
160 
161  Stack<std::string> pre_call_stack = *stack;
162  const Type* return_type = instruction.intrinsic->signature().return_type;
163  std::vector<std::string> results;
164  for (const Type* type : LowerType(return_type)) {
165  results.push_back(FreshNodeName());
166  stack->Push(results.back());
167  out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
168  << stack->Top() << ";\n";
169  out_ << " USE(" << stack->Top() << ");\n";
170  }
171  out_ << " ";
172 
173  if (return_type->IsStructType()) {
174  out_ << "std::tie(";
175  PrintCommaSeparatedList(out_, results);
176  out_ << ") = ";
177  } else {
178  if (results.size() == 1) {
179  out_ << results[0] << " = ";
180  }
181  }
182 
183  if (instruction.intrinsic->ExternalName() == "%RawCast") {
184  if (!return_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
185  ReportError("%RawCast must cast to subtype of Object");
186  }
187  out_ << "TORQUE_CAST";
188  } else {
189  ReportError("no built in intrinsic with name " +
190  instruction.intrinsic->ExternalName());
191  }
192 
193  out_ << "(";
194  PrintCommaSeparatedList(out_, args);
195  if (return_type->IsStructType()) {
196  out_ << ").Flatten();\n";
197  } else {
198  out_ << ");\n";
199  }
200 }
201 
202 void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
203  Stack<std::string>* stack) {
204  std::vector<std::string> constexpr_arguments =
205  instruction.constexpr_arguments;
206  std::vector<std::string> args;
207  TypeVector parameter_types =
208  instruction.macro->signature().parameter_types.types;
209  ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
210 
211  Stack<std::string> pre_call_stack = *stack;
212  const Type* return_type = instruction.macro->signature().return_type;
213  std::vector<std::string> results;
214  for (const Type* type : LowerType(return_type)) {
215  results.push_back(FreshNodeName());
216  stack->Push(results.back());
217  out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
218  << stack->Top() << ";\n";
219  out_ << " USE(" << stack->Top() << ");\n";
220  }
221  std::string catch_name =
222  PreCallableExceptionPreparation(instruction.catch_block);
223  out_ << " ";
224  if (return_type->IsStructType()) {
225  out_ << "std::tie(";
226  PrintCommaSeparatedList(out_, results);
227  out_ << ") = ";
228  } else {
229  if (results.size() == 1) {
230  out_ << results[0] << " = ca_.UncheckedCast<"
231  << return_type->GetGeneratedTNodeTypeName() << ">(";
232  }
233  }
234  out_ << instruction.macro->external_assembler_name() << "(state_)."
235  << instruction.macro->ExternalName() << "(";
236  PrintCommaSeparatedList(out_, args);
237  if (return_type->IsStructType()) {
238  out_ << ").Flatten();\n";
239  } else {
240  if (results.size() == 1) out_ << ")";
241  out_ << ");\n";
242  }
243  PostCallableExceptionPreparation(catch_name, return_type,
244  instruction.catch_block, &pre_call_stack);
245 }
246 
247 void CSAGenerator::EmitInstruction(
248  const CallCsaMacroAndBranchInstruction& instruction,
249  Stack<std::string>* stack) {
250  std::vector<std::string> constexpr_arguments =
251  instruction.constexpr_arguments;
252  std::vector<std::string> args;
253  TypeVector parameter_types =
254  instruction.macro->signature().parameter_types.types;
255  ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
256 
257  Stack<std::string> pre_call_stack = *stack;
258  std::vector<std::string> results;
259  const Type* return_type = instruction.macro->signature().return_type;
260  if (return_type != TypeOracle::GetNeverType()) {
261  for (const Type* type :
262  LowerType(instruction.macro->signature().return_type)) {
263  results.push_back(FreshNodeName());
264  out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName()
265  << "> " << results.back() << ";\n";
266  out_ << " USE(" << results.back() << ");\n";
267  }
268  }
269 
270  std::vector<std::string> label_names;
271  std::vector<std::vector<std::string>> var_names;
272  const LabelDeclarationVector& labels = instruction.macro->signature().labels;
273  DCHECK_EQ(labels.size(), instruction.label_blocks.size());
274  for (size_t i = 0; i < labels.size(); ++i) {
275  TypeVector label_parameters = labels[i].types;
276  label_names.push_back("label" + std::to_string(i));
277  var_names.push_back({});
278  for (size_t j = 0; j < label_parameters.size(); ++j) {
279  var_names[i].push_back("result_" + std::to_string(i) + "_" +
280  std::to_string(j));
281  out_ << " compiler::TypedCodeAssemblerVariable<"
282  << label_parameters[j]->GetGeneratedTNodeTypeName() << "> "
283  << var_names[i][j] << "(&ca_);\n";
284  }
285  out_ << " compiler::CodeAssemblerLabel " << label_names[i]
286  << "(&ca_);\n";
287  }
288 
289  std::string catch_name =
290  PreCallableExceptionPreparation(instruction.catch_block);
291  out_ << " ";
292  if (results.size() == 1) {
293  out_ << results[0] << " = ";
294  } else if (results.size() > 1) {
295  out_ << "std::tie(";
296  PrintCommaSeparatedList(out_, results);
297  out_ << ") = ";
298  }
299  out_ << instruction.macro->external_assembler_name() << "(state_)."
300  << instruction.macro->ExternalName() << "(";
301  PrintCommaSeparatedList(out_, args);
302  bool first = args.empty();
303  for (size_t i = 0; i < label_names.size(); ++i) {
304  if (!first) out_ << ", ";
305  out_ << "&" << label_names[i];
306  first = false;
307  for (size_t j = 0; j < var_names[i].size(); ++j) {
308  out_ << ", &" << var_names[i][j];
309  }
310  }
311  if (return_type->IsStructType()) {
312  out_ << ").Flatten();\n";
313  } else {
314  out_ << ");\n";
315  }
316 
317  PostCallableExceptionPreparation(catch_name, return_type,
318  instruction.catch_block, &pre_call_stack);
319 
320  if (instruction.return_continuation) {
321  out_ << " ca_.Goto(&" << BlockName(*instruction.return_continuation);
322  for (const std::string& value : *stack) {
323  out_ << ", " << value;
324  }
325  for (const std::string& result : results) {
326  out_ << ", " << result;
327  }
328  out_ << ");\n";
329  }
330  for (size_t i = 0; i < label_names.size(); ++i) {
331  out_ << " if (" << label_names[i] << ".is_used()) {\n";
332  out_ << " ca_.Bind(&" << label_names[i] << ");\n";
333  out_ << " ca_.Goto(&" << BlockName(instruction.label_blocks[i]);
334  for (const std::string& value : *stack) {
335  out_ << ", " << value;
336  }
337  for (const std::string& var : var_names[i]) {
338  out_ << ", " << var << ".value()";
339  }
340  out_ << ");\n";
341 
342  out_ << " }\n";
343  }
344 }
345 
346 void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction,
347  Stack<std::string>* stack) {
348  std::vector<std::string> arguments = stack->PopMany(instruction.argc);
349  std::vector<const Type*> result_types =
350  LowerType(instruction.builtin->signature().return_type);
351  if (instruction.is_tailcall) {
352  out_ << " CodeStubAssembler(state_).TailCallBuiltin(Builtins::k"
353  << instruction.builtin->ExternalName() << ", ";
354  PrintCommaSeparatedList(out_, arguments);
355  out_ << ");\n";
356  } else {
357  std::string result_name = FreshNodeName();
358  if (result_types.size() == 1) {
359  out_ << " compiler::TNode<"
360  << result_types[0]->GetGeneratedTNodeTypeName() << "> "
361  << result_name << ";\n";
362  }
363  std::string catch_name =
364  PreCallableExceptionPreparation(instruction.catch_block);
365  Stack<std::string> pre_call_stack = *stack;
366  if (result_types.size() == 1) {
367  std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
368  stack->Push(result_name);
369  out_ << " " << result_name << " = ";
370  if (generated_type != "Object") out_ << "TORQUE_CAST(";
371  out_ << "CodeStubAssembler(state_).CallBuiltin(Builtins::k"
372  << instruction.builtin->ExternalName() << ", ";
373  PrintCommaSeparatedList(out_, arguments);
374  if (generated_type != "Object") out_ << ")";
375  out_ << ");\n";
376  out_ << " USE(" << result_name << ");\n";
377  } else {
378  DCHECK_EQ(0, result_types.size());
379  // TODO(tebbi): Actually, builtins have to return a value, so we should
380  // not have to handle this case.
381  out_ << " CodeStubAssembler(state_).CallBuiltin(Builtins::k"
382  << instruction.builtin->ExternalName() << ", ";
383  PrintCommaSeparatedList(out_, arguments);
384  out_ << ");\n";
385  }
386  PostCallableExceptionPreparation(
387  catch_name,
388  result_types.size() == 0 ? TypeOracle::GetVoidType() : result_types[0],
389  instruction.catch_block, &pre_call_stack);
390  }
391 }
392 
393 void CSAGenerator::EmitInstruction(
394  const CallBuiltinPointerInstruction& instruction,
395  Stack<std::string>* stack) {
396  std::vector<std::string> function_and_arguments =
397  stack->PopMany(1 + instruction.argc);
398  std::vector<const Type*> result_types =
399  LowerType(instruction.type->return_type());
400  if (result_types.size() != 1) {
401  ReportError("builtins must have exactly one result");
402  }
403  if (instruction.is_tailcall) {
404  out_ << " "
405  "CodeStubAssembler(state_).TailCallBuiltin(Builtins::CallableFor("
406  "ca_.isolate(), "
407  "ExampleBuiltinForTorqueFunctionPointerType("
408  << instruction.type->function_pointer_type_id() << ")).descriptor(), ";
409  PrintCommaSeparatedList(out_, function_and_arguments);
410  out_ << ");\n";
411  } else {
412  stack->Push(FreshNodeName());
413  std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
414  out_ << " compiler::TNode<" << generated_type << "> " << stack->Top()
415  << " = ";
416  if (generated_type != "Object") out_ << "TORQUE_CAST(";
417  out_ << "CodeStubAssembler(state_).CallStub(Builtins::CallableFor(ca_."
418  "isolate(),"
419  "ExampleBuiltinForTorqueFunctionPointerType("
420  << instruction.type->function_pointer_type_id() << ")).descriptor(), ";
421  PrintCommaSeparatedList(out_, function_and_arguments);
422  out_ << ")";
423  if (generated_type != "Object") out_ << ")";
424  out_ << "; \n";
425  out_ << " USE(" << stack->Top() << ");\n";
426  }
427 }
428 
429 std::string CSAGenerator::PreCallableExceptionPreparation(
430  base::Optional<Block*> catch_block) {
431  std::string catch_name;
432  if (catch_block) {
433  catch_name = FreshCatchName();
434  out_ << " compiler::CodeAssemblerExceptionHandlerLabel " << catch_name
435  << "_label(&ca_, compiler::CodeAssemblerLabel::kDeferred);\n";
436  out_ << " { compiler::CodeAssemblerScopedExceptionHandler s(&ca_, &"
437  << catch_name << "_label);\n";
438  }
439  return catch_name;
440 }
441 
442 void CSAGenerator::PostCallableExceptionPreparation(
443  const std::string& catch_name, const Type* return_type,
444  base::Optional<Block*> catch_block, Stack<std::string>* stack) {
445  if (catch_block) {
446  std::string block_name = BlockName(*catch_block);
447  out_ << " }\n";
448  out_ << " if (" << catch_name << "_label.is_used()) {\n";
449  out_ << " compiler::CodeAssemblerLabel " << catch_name
450  << "_skip(&ca_);\n";
451  if (!return_type->IsNever()) {
452  out_ << " ca_.Goto(&" << catch_name << "_skip);\n";
453  }
454  out_ << " compiler::TNode<Object> " << catch_name
455  << "_exception_object;\n";
456  out_ << " ca_.Bind(&" << catch_name << "_label, &" << catch_name
457  << "_exception_object);\n";
458  out_ << " ca_.Goto(&" << block_name;
459  for (size_t i = 0; i < stack->Size(); ++i) {
460  out_ << ", " << stack->begin()[i];
461  }
462  out_ << ", " << catch_name << "_exception_object);\n";
463  if (!return_type->IsNever()) {
464  out_ << " ca_.Bind(&" << catch_name << "_skip);\n";
465  }
466  out_ << " }\n";
467  }
468 }
469 
470 void CSAGenerator::EmitInstruction(const CallRuntimeInstruction& instruction,
471  Stack<std::string>* stack) {
472  std::vector<std::string> arguments = stack->PopMany(instruction.argc);
473  const Type* return_type =
474  instruction.runtime_function->signature().return_type;
475  std::vector<const Type*> result_types;
476  if (return_type != TypeOracle::GetNeverType()) {
477  result_types = LowerType(return_type);
478  }
479  if (result_types.size() > 1) {
480  ReportError("runtime function must have at most one result");
481  }
482  if (instruction.is_tailcall) {
483  out_ << " CodeStubAssembler(state_).TailCallRuntime(Runtime::k"
484  << instruction.runtime_function->ExternalName() << ", ";
485  PrintCommaSeparatedList(out_, arguments);
486  out_ << ");\n";
487  } else {
488  std::string result_name = FreshNodeName();
489  if (result_types.size() == 1) {
490  out_ << " compiler::TNode<"
491  << result_types[0]->GetGeneratedTNodeTypeName() << "> "
492  << result_name << ";\n";
493  }
494  std::string catch_name =
495  PreCallableExceptionPreparation(instruction.catch_block);
496  Stack<std::string> pre_call_stack = *stack;
497  if (result_types.size() == 1) {
498  stack->Push(result_name);
499  out_ << " " << result_name
500  << " = TORQUE_CAST(CodeStubAssembler(state_).CallRuntime(Runtime::k"
501  << instruction.runtime_function->ExternalName() << ", ";
502  PrintCommaSeparatedList(out_, arguments);
503  out_ << "));\n";
504  out_ << " USE(" << result_name << ");\n";
505  } else {
506  DCHECK_EQ(0, result_types.size());
507  out_ << " CodeStubAssembler(state_).CallRuntime(Runtime::k"
508  << instruction.runtime_function->ExternalName() << ", ";
509  PrintCommaSeparatedList(out_, arguments);
510  out_ << ");\n";
511  if (return_type == TypeOracle::GetNeverType()) {
512  out_ << " CodeStubAssembler(state_).Unreachable();\n";
513  } else {
514  DCHECK(return_type == TypeOracle::GetVoidType());
515  }
516  }
517  PostCallableExceptionPreparation(catch_name, return_type,
518  instruction.catch_block, &pre_call_stack);
519  }
520 }
521 
522 void CSAGenerator::EmitInstruction(const BranchInstruction& instruction,
523  Stack<std::string>* stack) {
524  out_ << " ca_.Branch(" << stack->Pop() << ", &"
525  << BlockName(instruction.if_true) << ", &"
526  << BlockName(instruction.if_false);
527  for (const std::string& value : *stack) {
528  out_ << ", " << value;
529  }
530  out_ << ");\n";
531 }
532 
533 void CSAGenerator::EmitInstruction(
534  const ConstexprBranchInstruction& instruction, Stack<std::string>* stack) {
535  out_ << " if (" << instruction.condition << ") {\n";
536  out_ << " ca_.Goto(&" << BlockName(instruction.if_true);
537  for (const std::string& value : *stack) {
538  out_ << ", " << value;
539  }
540  out_ << ");\n";
541  out_ << " } else {\n";
542  out_ << " ca_.Goto(&" << BlockName(instruction.if_false);
543  for (const std::string& value : *stack) {
544  out_ << ", " << value;
545  }
546  out_ << ");\n";
547 
548  out_ << " }\n";
549 }
550 
551 void CSAGenerator::EmitInstruction(const GotoInstruction& instruction,
552  Stack<std::string>* stack) {
553  out_ << " ca_.Goto(&" << BlockName(instruction.destination);
554  for (const std::string& value : *stack) {
555  out_ << ", " << value;
556  }
557  out_ << ");\n";
558 }
559 
560 void CSAGenerator::EmitInstruction(const GotoExternalInstruction& instruction,
561  Stack<std::string>* stack) {
562  for (auto it = instruction.variable_names.rbegin();
563  it != instruction.variable_names.rend(); ++it) {
564  out_ << " *" << *it << " = " << stack->Pop() << ";\n";
565  }
566  out_ << " ca_.Goto(" << instruction.destination << ");\n";
567 }
568 
569 void CSAGenerator::EmitInstruction(const ReturnInstruction& instruction,
570  Stack<std::string>* stack) {
571  if (*linkage_ == Builtin::kVarArgsJavaScript) {
572  out_ << " " << ARGUMENTS_VARIABLE_STRING << "->PopAndReturn(";
573  } else {
574  out_ << " CodeStubAssembler(state_).Return(";
575  }
576  out_ << stack->Pop() << ");\n";
577 }
578 
579 void CSAGenerator::EmitInstruction(
580  const PrintConstantStringInstruction& instruction,
581  Stack<std::string>* stack) {
582  out_ << " CodeStubAssembler(state_).Print("
583  << StringLiteralQuote(instruction.message) << ");\n";
584 }
585 
586 void CSAGenerator::EmitInstruction(const AbortInstruction& instruction,
587  Stack<std::string>* stack) {
588  switch (instruction.kind) {
589  case AbortInstruction::Kind::kUnreachable:
590  DCHECK(instruction.message.empty());
591  out_ << " CodeStubAssembler(state_).Unreachable();\n";
592  break;
593  case AbortInstruction::Kind::kDebugBreak:
594  DCHECK(instruction.message.empty());
595  out_ << " CodeStubAssembler(state_).DebugBreak();\n";
596  break;
597  case AbortInstruction::Kind::kAssertionFailure: {
598  std::string file =
599  StringLiteralQuote(SourceFileMap::GetSource(instruction.pos.source));
600  out_ << " CodeStubAssembler(state_).FailAssert("
601  << StringLiteralQuote(instruction.message) << ", " << file << ", "
602  << instruction.pos.line + 1 << ");\n";
603  break;
604  }
605  }
606 }
607 
608 void CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction,
609  Stack<std::string>* stack) {
610  stack->Poke(stack->AboveTop() - 1,
611  "ca_.UncheckedCast<" +
612  instruction.destination_type->GetGeneratedTNodeTypeName() +
613  ">(" + stack->Top() + ")");
614 }
615 
616 // static
617 void CSAGenerator::EmitCSAValue(VisitResult result,
618  const Stack<std::string>& values,
619  std::ostream& out) {
620  if (!result.IsOnStack()) {
621  out << result.constexpr_value();
622  } else if (auto* struct_type = StructType::DynamicCast(result.type())) {
623  out << struct_type->GetGeneratedTypeName() << "{";
624  bool first = true;
625  for (auto& field : struct_type->fields()) {
626  if (!first) {
627  out << ", ";
628  }
629  first = false;
630  EmitCSAValue(ProjectStructField(result, field.name), values, out);
631  }
632  out << "}";
633  } else {
634  DCHECK_EQ(1, result.stack_range().Size());
635  out << "TNode<" << result.type()->GetGeneratedTNodeTypeName() << ">{"
636  << values.Peek(result.stack_range().begin()) << "}";
637  }
638 }
639 
640 } // namespace torque
641 } // namespace internal
642 } // namespace v8
Definition: libplatform.h:13