26 std::stringstream out_buffer;
27 std::ostream* old_out =
out_;
33 if (
cfg_.end() && *
cfg_.end() == block)
continue;
34 if (block->IsDead())
continue;
38 std::optional<Stack<std::string>>
result;
46 out() << out_buffer.str();
58 const auto& def = block->InputDefinitions().Peek(
i);
60 if (def.IsPhiFromBlock(block)) {
62 << (
is_cc_debug_ ? block->InputTypes().Peek(
i)->GetDebugType()
63 : block->InputTypes().Peek(
i)->GetRuntimeType())
64 <<
" " << stack.Top() <<
"{}; USE(" << stack.Top() <<
");\n";
68 for (
const Instruction& instruction : block->instructions()) {
79 out() <<
" // " << file <<
":" << (
pos.start.line + 1) <<
"\n";
87 ReportError(
"Not supported in C++ output: PushUninitialized");
91 const PushBuiltinPointerInstruction& instruction,
92 Stack<std::string>* stack) {
93 ReportError(
"Not supported in C++ output: PushBuiltinPointer");
97 const NamespaceConstantInstruction& instruction,
98 Stack<std::string>* stack) {
99 ReportError(
"Not supported in C++ output: NamespaceConstantInstruction");
105 std::vector<std::string>
args;
106 for (
auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) {
107 const Type* type = *it;
108 if (type->IsConstexpr()) {
109 args.push_back(std::move(constexpr_arguments.back()));
110 constexpr_arguments.pop_back();
116 args.push_back(s.str());
117 stack->PopMany(slot_count);
120 std::reverse(
args.begin(),
args.end());
127 instruction.intrinsic->signature().parameter_types.types;
129 parameter_types, instruction.constexpr_arguments, stack);
132 const Type* return_type = instruction.intrinsic->signature().return_type;
133 std::vector<std::string> results;
135 const auto lowered =
LowerType(return_type);
136 for (std::size_t
i = 0;
i < lowered.
size(); ++
i) {
138 stack->Push(results.back());
141 : lowered[
i]->GetRuntimeType())
142 <<
" " << stack->Top() <<
"{}; USE(" << stack->Top() <<
");\n";
147 out() <<
"std::tie(";
151 if (results.size() == 1) {
152 out() << results[0] <<
" = ";
156 if (instruction.intrinsic->ExternalName() ==
"%RawDownCast") {
157 if (parameter_types.size() != 1) {
158 ReportError(
"%RawDownCast must take a single parameter");
160 const Type* original_type = parameter_types[0];
166 ReportError(
"%RawDownCast error: ", *return_type,
" is not a subtype of ",
169 if (!original_type->StructSupertype() &&
170 return_type->
GetRuntimeType() != original_type->GetRuntimeType()) {
173 }
else if (instruction.intrinsic->ExternalName() ==
"%GetClassMapConstant") {
174 ReportError(
"C++ generator doesn't yet support %GetClassMapConstant");
175 }
else if (instruction.intrinsic->ExternalName() ==
"%FromConstexpr") {
176 if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) {
178 "%FromConstexpr must take a single parameter with constexpr "
182 ReportError(
"%FromConstexpr must return a non-constexpr type");
186 out() <<
"Internals::IntToSmi";
188 out() <<
"Smi::FromInt";
193 out() <<
"(CastToUnderlyingTypeIfEnum";
196 instruction.intrinsic->ExternalName());
201 if (instruction.intrinsic->ExternalName() ==
"%FromConstexpr") {
208 Stack<std::string>* stack) {
210 instruction.macro->signature().parameter_types.types;
212 parameter_types, instruction.constexpr_arguments, stack);
214 Stack<std::string> pre_call_stack = *
stack;
215 const Type* return_type = instruction.macro->signature().return_type;
216 std::vector<std::string> results;
218 const auto lowered =
LowerType(return_type);
219 for (std::size_t
i = 0;
i < lowered.
size(); ++
i) {
221 stack->Push(results.back());
224 : lowered[
i]->GetRuntimeType())
225 <<
" " << stack->Top() <<
"{}; USE(" << stack->Top() <<
");\n";
229 CHECK(!instruction.catch_block);
231 if (return_type->StructSupertype().has_value()) {
232 out() <<
"std::tie(";
236 if (results.size() == 1) {
244 out() << instruction.macro->CCDebugName() <<
"(accessor";
245 if (!
args.empty())
out() <<
", ";
247 out() << instruction.macro->CCName() <<
"(";
258 const CallCsaMacroAndBranchInstruction& instruction,
259 Stack<std::string>* stack) {
260 ReportError(
"Not supported in C++ output: CallCsaMacroAndBranch");
264 Stack<std::string>* stack) {
265 ReportError(
"Not supported in C++ output: MakeLazyNode");
269 Stack<std::string>* stack) {
270 ReportError(
"Not supported in C++ output: CallBuiltin");
274 const CallBuiltinPointerInstruction& instruction,
275 Stack<std::string>* stack) {
276 ReportError(
"Not supported in C++ output: CallBuiltinPointer");
280 Stack<std::string>* stack) {
281 ReportError(
"Not supported in C++ output: CallRuntime");
285 Stack<std::string>* stack) {
286 out() <<
" if (" << stack->Pop() <<
") {\n";
287 EmitGoto(instruction.if_true, stack,
" ");
288 out() <<
" } else {\n";
289 EmitGoto(instruction.if_false, stack,
" ");
294 Stack<std::string>* stack) {
295 out() <<
" if ((" << instruction.condition <<
")) {\n";
296 EmitGoto(instruction.if_true, stack,
" ");
297 out() <<
" } else {\n";
298 EmitGoto(instruction.if_false, stack,
" ");
303 std::string indentation) {
304 const auto& destination_definitions =
destination->InputDefinitions();
305 DCHECK_EQ(stack->Size(), destination_definitions.Size());
310 << stack->Peek(
i) <<
";\n";
318 EmitGoto(instruction.destination, stack,
" ");
322 Stack<std::string>* stack) {
323 ReportError(
"Not supported in C++ output: GotoExternal");
327 Stack<std::string>* stack) {
328 ReportError(
"Not supported in C++ output: Return");
332 Stack<std::string>* stack) {
338 Stack<std::string>* stack) {
339 switch (instruction.kind) {
341 DCHECK(instruction.message.empty());
342 out() <<
" UNREACHABLE();\n";
345 DCHECK(instruction.message.empty());
346 out() <<
" base::OS::DebugBreak();\n";
351 out() <<
" CHECK(false, \"Failed Torque assertion: '\""
355 std::to_string(instruction.pos.start.line + 1))
363 Stack<std::string>* stack) {
364 const std::string str =
"static_cast<" +
365 instruction.destination_type->GetRuntimeType() +
366 ">(" + stack->Top() +
")";
367 stack->Poke(stack->AboveTop() - 1, str);
372 Stack<std::string>* stack) {
373 std::string result_name =
376 std::string
offset = stack->Pop();
377 std::string
object = stack->Pop();
378 stack->Push(result_name);
381 std::string result_type = instruction.type->GetRuntimeType();
382 decls() <<
" " << result_type <<
" " << result_name <<
"{}; USE("
383 << result_name <<
");\n";
384 out() <<
" " << result_name <<
" = ";
393 "Not supported in C++ output: LoadReference on non-smi tagged "
400 "Torque doesn't support @cppRelaxedLoad/@cppAcquireLoad on tagged "
406 out() <<
"TaggedField<" << result_type
407 <<
">::load(UncheckedCast<HeapObject>(" <<
object
408 <<
"), static_cast<int>(" <<
offset <<
"));\n";
413 switch (instruction.synchronization) {
418 load =
"Relaxed_ReadField";
422 "Torque doesn't support @cppAcquireLoad on untagged data");
424 out() <<
"(" <<
object <<
")->" << load <<
"<" << result_type <<
">("
428 std::string result_type = instruction.type->GetDebugType();
429 decls() <<
" " << result_type <<
" " << result_name <<
"{}; USE("
430 << result_name <<
");\n";
432 out() <<
" READ_TAGGED_FIELD_OR_FAIL(" << result_name <<
", accessor, "
433 <<
object <<
", static_cast<int>(" <<
offset <<
"));\n";
435 out() <<
" READ_FIELD_OR_FAIL(" << result_type <<
", " << result_name
436 <<
", accessor, " <<
object <<
", " <<
offset <<
");\n";
442 Stack<std::string>* stack) {
443 ReportError(
"Not supported in C++ output: StoreReference");
447std::string GetBitFieldSpecialization(
const Type* container,
448 const BitField& field) {
449 std::stringstream stream;
450 stream <<
"base::BitField<"
451 << field.name_and_type.type->GetConstexprGeneratedTypeName() <<
", "
452 << field.offset <<
", " << field.num_bits <<
", "
453 << container->GetConstexprGeneratedTypeName() <<
">";
459 Stack<std::string>* stack) {
460 std::string result_name =
463 std::string bit_field_struct = stack->Pop();
464 stack->Push(result_name);
466 const Type* struct_type = instruction.bit_field_struct_type;
468 decls() <<
" " << instruction.bit_field.name_and_type.type->GetRuntimeType()
469 <<
" " << result_name <<
"{}; USE(" << result_name <<
");\n";
471 std::optional<const Type*> smi_tagged_type =
473 if (smi_tagged_type) {
476 bit_field_struct =
"Internals::SmiValue(" + bit_field_struct +
")";
478 bit_field_struct = bit_field_struct +
".value()";
480 struct_type = *smi_tagged_type;
483 out() <<
" " << result_name <<
" = CastToUnderlyingTypeIfEnum("
484 << GetBitFieldSpecialization(struct_type, instruction.bit_field)
485 <<
"::decode(" << bit_field_struct <<
"));\n";
489 Stack<std::string>* stack) {
490 ReportError(
"Not supported in C++ output: StoreBitField");
495void CollectAllFields(
const VisitResult&
result,
496 const Stack<std::string>& values,
497 std::vector<std::string>& all_fields) {
498 if (!
result.IsOnStack()) {
499 all_fields.push_back(
result.constexpr_value());
500 }
else if (
auto struct_type =
result.type()->StructSupertype()) {
501 for (
const Field& field : (*struct_type)->fields()) {
507 all_fields.push_back(values.Peek(
result.stack_range().begin()));
517 std::vector<std::string> all_fields;
518 CollectAllFields(
result, values, all_fields);
519 if (all_fields.size() == 1) {
520 out << all_fields[0];
522 out <<
"std::make_tuple(";
std::optional< Stack< std::string > > EmitGraph(Stack< std::string > parameters)
void EmitGoto(const Block *destination, Stack< std::string > *stack, std::string indentation)
Stack< std::string > EmitBlock(const Block *block)
void EmitSourcePosition(SourcePosition pos, bool always_emit=false) override
std::vector< std::string > ProcessArgumentsCommon(const TypeVector ¶meter_types, std::vector< std::string > constexpr_arguments, Stack< std::string > *stack)
static void EmitCCValue(VisitResult result, const Stack< std::string > &values, std::ostream &out)
bool IsPhiFromBlock(const Block *block) const
static DefinitionLocation Parameter(std::size_t index)
static const std::string & PathFromV8Root(SourceId file)
static std::string AbsolutePath(SourceId file)
BottomOffset AboveTop() const
const T & Peek(BottomOffset from_bottom) const
SourcePosition previous_position_
void SetDefinitionVariable(const DefinitionLocation &definition, const std::string &str)
const ControlFlowGraph & cfg_
std::string DefinitionToVariable(const DefinitionLocation &location)
std::string BlockName(const Block *block)
void EmitInstruction(const Instruction &instruction, Stack< std::string > *stack)
static GenericType * GetSmiTaggedGeneric()
static const Type * GetUninitializedHeapObjectType()
static const Type * GetTaggedType()
static const Type * GetHeapObjectType()
static const Type * GetSmiType()
static std::optional< const Type * > MatchUnaryGeneric(const Type *type, GenericType *generic)
virtual bool IsSubtypeOf(const Type *supertype) const
virtual std::string GetRuntimeType() const
std::optional< const StructType * > StructSupertype() const
virtual bool IsConstexpr() const
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
ZoneStack< RpoNumber > & stack
InstructionOperand destination
size_t LoweredSlotCount(const Type *type)
std::string StringLiteralQuote(const std::string &s)
void ReportError(Args &&... args)
VisitResult ProjectStructField(VisitResult structure, const std::string &fieldname)
std::vector< const Type * > TypeVector
TypeVector LowerType(const Type *type)
void PrintCommaSeparatedList(std::ostream &os, const T &list, C &&transform)
MessageBuilder Error(Args &&... args)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
bool CompareStartIgnoreColumn(const SourcePosition &pos) const