14#define TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS(Name) \
15 const InstructionKind Name::kKind = InstructionKind::k##Name; \
16 std::unique_ptr<InstructionBase> Name::Clone() const { \
17 return std::unique_ptr<InstructionBase>(new Name(*this)); \
19 void Name::Assign(const InstructionBase& other) { \
20 *this = static_cast<const Name&>(other); \
23#undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS
26void ExpectType(
const Type* expected,
const Type* actual) {
27 if (expected != actual) {
28 ReportError(
"expected type ", *expected,
" but found ", *actual);
31void ExpectSubtype(
const Type* subtype,
const Type* supertype) {
32 if (!subtype->IsSubtypeOf(supertype)) {
33 ReportError(
"type ", *subtype,
" is not a subtype of ", *supertype);
39 ControlFlowGraph* cfg)
const {
40 const Type* type = stack->Peek(
slot);
42 if (type->IsTopType()) {
43 const TopType* top_type = TopType::cast(type);
53 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
54 locations->Push(locations->Peek(
slot));
58 ControlFlowGraph* cfg)
const {
59 const Type* type = stack->Top();
64 stack->Poke(
slot, type);
69 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
70 locations->Poke(
slot, locations->Pop());
74 ControlFlowGraph* cfg)
const {
75 stack->DeleteRange(range);
79 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
80 locations->DeleteRange(range);
84 Stack<const Type*>* stack, ControlFlowGraph* cfg)
const {
89 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
103 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
113 stack->PushMany(
LowerType(constant->type()));
117 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
124 return LowerType(constant->type()).size();
128 std::size_t index)
const {
135 return os <<
"NamespaceConstant " << instruction.constant->external_name();
140 auto current = stack->begin();
141 while (current != stack->end()) {
142 if ((*current)->IsTransient()) {
143 std::stringstream stream;
144 stream <<
"type " << **current
145 <<
" is made invalid by transitioning callable invocation at "
155 std::vector<const Type*> parameter_types =
157 for (intptr_t
i = parameter_types.size() - 1;
i >= 0; --
i) {
158 const Type* arg_type = stack->Pop();
159 const Type* parameter_type = parameter_types.back();
160 parameter_types.pop_back();
161 if (arg_type != parameter_type) {
162 ReportError(
"parameter ",
i,
": expected type ", *parameter_type,
163 " but found type ", *arg_type);
173 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
174 auto parameter_types =
176 locations->PopMany(parameter_types.size());
187 std::size_t index)
const {
194 os <<
"CallIntrinsic " << instruction.intrinsic->ReadableName();
195 if (!instruction.specialization_types.empty()) {
198 os, instruction.specialization_types,
199 [](
const Type* type) ->
const Type& { return *type; });
209 ControlFlowGraph* cfg)
const {
210 std::vector<const Type*> parameter_types =
212 for (intptr_t
i = parameter_types.size() - 1;
i >= 0; --
i) {
213 const Type* arg_type = stack->Pop();
214 const Type* parameter_type = parameter_types.back();
215 parameter_types.pop_back();
216 if (arg_type != parameter_type) {
217 ReportError(
"parameter ",
i,
": expected type ", *parameter_type,
218 " but found type ", *arg_type);
222 if (macro->IsTransitioning()) {
227 Stack<const Type*> catch_stack = *
stack;
229 (*catch_block)->SetInputTypes(catch_stack);
232 stack->PushMany(
LowerType(macro->signature().return_type));
236 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
237 auto parameter_types =
239 locations->PopMany(parameter_types.size());
243 (*catch_block)->MergeInputDefinitions(*locations, worklist);
252std::optional<DefinitionLocation>
259 return LowerType(macro->signature().return_type).size();
263 std::size_t index)
const {
270 os <<
"CallCsaMacro " << instruction.macro->ReadableName();
274 if (instruction.catch_block) {
275 os <<
", catch block " << (*instruction.catch_block)->
id();
281 Stack<const Type*>* stack, ControlFlowGraph* cfg)
const {
282 std::vector<const Type*> parameter_types =
284 for (intptr_t
i = parameter_types.size() - 1;
i >= 0; --
i) {
285 const Type* arg_type = stack->Pop();
286 const Type* parameter_type = parameter_types.back();
287 parameter_types.pop_back();
288 if (arg_type != parameter_type) {
289 ReportError(
"parameter ",
i,
": expected type ", *parameter_type,
290 " but found type ", *arg_type);
294 if (
label_blocks.size() != macro->signature().labels.size()) {
298 Stack<const Type*> continuation_stack = *
stack;
299 continuation_stack.PushMany(
301 label_blocks[
i]->SetInputTypes(std::move(continuation_stack));
304 if (macro->IsTransitioning()) {
309 Stack<const Type*> catch_stack = *
stack;
311 (*catch_block)->SetInputTypes(catch_stack);
315 Stack<const Type*> return_stack = *
stack;
316 return_stack.PushMany(
LowerType(macro->signature().return_type));
320 (*return_continuation)->SetInputTypes(return_stack);
329 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
330 auto parameter_types =
332 locations->PopMany(parameter_types.size());
334 for (std::size_t label_index = 0; label_index <
label_blocks.size();
337 for (std::size_t
i = 0;
i <
count; ++
i) {
340 label_blocks[label_index]->MergeInputDefinitions(*locations, worklist);
341 locations->PopMany(count);
346 (*catch_block)->MergeInputDefinitions(*locations, worklist);
353 for (std::size_t
i = 0;
i <
count; ++
i) {
356 (*return_continuation)->MergeInputDefinitions(*locations, worklist);
357 locations->PopMany(count);
367 std::size_t
label)
const {
373 std::size_t
label, std::size_t index)
const {
376 for (std::size_t label_index = 0; label_index <
label; ++label_index) {
385 return LowerType(macro->signature().return_type).size();
389 std::size_t index)
const {
394std::optional<DefinitionLocation>
402 os <<
"CallCsaMacroAndBranch " << instruction.macro->ReadableName();
406 if (instruction.return_continuation) {
407 os <<
", return continuation " << (*instruction.return_continuation)->
id();
409 if (!instruction.label_blocks.empty()) {
410 os <<
", label blocks ";
412 [](
Block* block) { return block->id(); });
414 if (instruction.catch_block) {
415 os <<
", catch block " << (*instruction.catch_block)->
id();
421 ControlFlowGraph* cfg)
const {
422 std::vector<const Type*> argument_types = stack->PopMany(
argc);
423 if (argument_types !=
427 if (builtin->IsTransitioning()) {
432 Stack<const Type*> catch_stack = *
stack;
434 (*catch_block)->SetInputTypes(catch_stack);
437 stack->PushMany(
LowerType(builtin->signature().return_type));
441 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
442 locations->PopMany(
argc);
446 (*catch_block)->MergeInputDefinitions(*locations, worklist);
456 return LowerType(builtin->signature().return_type).size();
460 std::size_t index)
const {
465std::optional<DefinitionLocation>
473 std::vector<const Type*> argument_types = stack->PopMany(
argc);
475 if (!f)
ReportError(
"expected function pointer type");
487 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
488 locations->PopMany(
argc + 1);
495 return LowerType(type->return_type()).size();
499 std::size_t index)
const {
506 os <<
"CallBuiltin " << instruction.builtin->ReadableName()
507 <<
", argc: " << instruction.argc;
508 if (instruction.is_tailcall) {
509 os <<
", is_tailcall";
511 if (instruction.catch_block) {
512 os <<
", catch block " << (*instruction.catch_block)->
id();
518 ControlFlowGraph* cfg)
const {
519 std::vector<const Type*> argument_types = stack->PopMany(
argc);
520 if (argument_types !=
530 Stack<const Type*> catch_stack = *
stack;
532 (*catch_block)->SetInputTypes(catch_stack);
542 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
543 locations->PopMany(
argc);
547 (*catch_block)->MergeInputDefinitions(*locations, worklist);
566 std::size_t index)
const {
571std::optional<DefinitionLocation>
579 os <<
"CallRuntime " << instruction.runtime_function->ReadableName()
580 <<
", argc: " << instruction.argc;
581 if (instruction.is_tailcall) {
582 os <<
", is_tailcall";
584 if (instruction.catch_block) {
585 os <<
", catch block " << (*instruction.catch_block)->
id();
591 ControlFlowGraph* cfg)
const {
592 const Type* condition_type = stack->Pop();
601 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
609 return os <<
"Branch true: " << instruction.if_true->id()
610 <<
", false: " << instruction.if_false->id();
614 ControlFlowGraph* cfg)
const {
620 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
627 return os <<
"ConstexprBranch " << instruction.condition
628 <<
", true: " << instruction.if_true->id()
629 <<
", false: " << instruction.if_false->id();
633 ControlFlowGraph* cfg)
const {
638 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
643 return os <<
"Goto " << instruction.destination->id();
647 ControlFlowGraph* cfg)
const {
649 ReportError(
"goto external label with wrong parameter count.");
654 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {}
657 ControlFlowGraph* cfg)
const {
658 cfg->SetReturnType(stack->PopMany(count));
662 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
663 locations->PopMany(count);
667 ControlFlowGraph* cfg)
const {}
670 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {}
673 ControlFlowGraph* cfg)
const {}
676 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {}
679 ControlFlowGraph* cfg)
const {
684 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
703 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
715 ExpectSubtype(stack->Pop(), type);
723 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
730 ControlFlowGraph* cfg)
const {
736 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
753 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
765 std::vector<const Type*> parameter_types =
767 for (intptr_t
i = parameter_types.size() - 1;
i >= 0; --
i) {
768 const Type* arg_type = stack->Pop();
769 const Type* parameter_type = parameter_types.back();
770 parameter_types.pop_back();
771 if (arg_type != parameter_type) {
772 ReportError(
"parameter ",
i,
": expected type ", *parameter_type,
773 " but found type ", *arg_type);
781 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist)
const {
782 auto parameter_types =
784 locations->PopMany(parameter_types.size());
795 os <<
"MakeLazyNode " << instruction.macro->ReadableName() <<
", "
796 << *instruction.result_type;
797 for (
const std::string& arg : instruction.constexpr_arguments) {
void MergeInputDefinitions(const Stack< DefinitionLocation > &input_definitions, Worklist< Block * > *worklist)
void SetInputTypes(const Stack< const Type * > &input_types)
const TypeVector & parameter_types() const
const Type * return_type() const
const Signature & signature() const
bool IsTransitioning() const
static DefinitionLocation Instruction(const InstructionBase *instruction, std::size_t index=0)
static const Type * GetUnionType(UnionType type)
static const Type * GetHeapObjectType()
static const Type * GetTaggedZeroPatternType()
static const TopType * GetTopType(std::string reason, const Type *source_type)
static const Type * GetIntPtrType()
static const Type * GetBoolType()
static const Type * GetJSAnyType()
static const Type * GetNeverType()
#define TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS(Name)
#define TORQUE_INSTRUCTION_LIST(V)
ZoneStack< RpoNumber > & stack
std::ostream & operator<<(std::ostream &os, Identifier *id)
void ReportError(Args &&... args)
std::string PositionAsString(SourcePosition pos)
TypeVector LowerType(const Type *type)
void PrintCommaSeparatedList(std::ostream &os, const T &list, C &&transform)
TypeVector LowerParameterTypes(const TypeVector ¶meters)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
NameAndType name_and_type
std::optional< DefinitionLocation > GetExceptionObjectDefinition() const
std::size_t GetValueDefinitionCount() const
DefinitionLocation GetValueDefinition(std::size_t index) const
std::optional< Block * > catch_block
DefinitionLocation GetValueDefinition(std::size_t index) const
std::size_t GetValueDefinitionCount() const
std::size_t GetLabelCount() const
std::vector< Block * > label_blocks
DefinitionLocation GetValueDefinition(std::size_t index) const
std::optional< DefinitionLocation > GetExceptionObjectDefinition() const
std::optional< Block * > return_continuation
DefinitionLocation GetLabelValueDefinition(std::size_t label, std::size_t index) const
std::optional< Block * > catch_block
std::size_t GetValueDefinitionCount() const
std::size_t GetLabelValueDefinitionCount(std::size_t label) const
std::optional< DefinitionLocation > GetExceptionObjectDefinition() const
DefinitionLocation GetValueDefinition(std::size_t index) const
std::optional< Block * > catch_block
std::size_t GetValueDefinitionCount() const
std::size_t GetValueDefinitionCount() const
DefinitionLocation GetValueDefinition(std::size_t index) const
DefinitionLocation GetValueDefinition(std::size_t index) const
std::optional< DefinitionLocation > GetExceptionObjectDefinition() const
bool IsBlockTerminator() const override
std::optional< Block * > catch_block
std::size_t GetValueDefinitionCount() const
RuntimeFunction * runtime_function
std::vector< std::string > variable_names
virtual void RecomputeDefinitionLocations(Stack< DefinitionLocation > *locations, Worklist< Block * > *worklist) const =0
void InvalidateTransientTypes(Stack< const Type * > *stack) const
virtual void TypeInstruction(Stack< const Type * > *stack, ControlFlowGraph *cfg) const =0
DefinitionLocation GetValueDefinition() const
const Type * bit_field_struct_type
DefinitionLocation GetValueDefinition() const
DefinitionLocation GetValueDefinition() const
std::size_t GetValueDefinitionCount() const
DefinitionLocation GetValueDefinition(std::size_t index) const
std::optional< const Type * > widened_type
std::optional< const Type * > widened_type
DefinitionLocation GetValueDefinition() const
DefinitionLocation GetValueDefinition() const
DefinitionLocation GetValueDefinition() const
const Type * bit_field_struct_type
const Type * destination_type
DefinitionLocation GetValueDefinition() const