5 #include "src/torque/instructions.h" 6 #include "src/torque/cfg.h" 7 #include "src/torque/type-oracle.h" 13 #define TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS(Name) \ 14 const InstructionKind Name::kKind = InstructionKind::k##Name; \ 15 std::unique_ptr<InstructionBase> Name::Clone() const { \ 16 return std::unique_ptr<InstructionBase>(new Name(*this)); \ 18 void Name::Assign(const InstructionBase& other) { \ 19 *this = static_cast<const Name&>(other); \ 21 TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS)
22 #undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS 24 void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
25 ControlFlowGraph* cfg)
const {
26 const Type* type = stack->Peek(slot);
28 if (type->IsTopType()) {
29 const TopType* top_type = TopType::cast(type);
30 ReportError(
"use of " + top_type->reason());
32 if (!type->IsSubtypeOf(*widened_type)) {
33 ReportError(
"type ", *type,
" is not a subtype of ", **widened_type);
40 void PokeInstruction::TypeInstruction(Stack<const Type*>* stack,
41 ControlFlowGraph* cfg)
const {
42 const Type* type = stack->Top();
44 if (!type->IsSubtypeOf(*widened_type)) {
45 ReportError(
"type ", type,
" is not a subtype of ", *widened_type);
49 stack->Poke(slot, type);
53 void DeleteRangeInstruction::TypeInstruction(Stack<const Type*>* stack,
54 ControlFlowGraph* cfg)
const {
55 stack->DeleteRange(range);
58 void PushUninitializedInstruction::TypeInstruction(
59 Stack<const Type*>* stack, ControlFlowGraph* cfg)
const {
63 void PushCodePointerInstruction::TypeInstruction(Stack<const Type*>* stack,
64 ControlFlowGraph* cfg)
const {
68 void NamespaceConstantInstruction::TypeInstruction(
69 Stack<const Type*>* stack, ControlFlowGraph* cfg)
const {
70 stack->PushMany(LowerType(constant->type()));
73 void InstructionBase::InvalidateTransientTypes(
74 Stack<const Type*>* stack)
const {
75 auto current = stack->begin();
76 while (current != stack->end()) {
77 if ((*current)->IsTransient()) {
78 std::stringstream stream;
79 stream <<
"type " << **current
80 <<
" is made invalid by transitioning callable invocation at " 81 << PositionAsString(pos);
82 *current = TypeOracle::GetTopType(stream.str(), *current);
88 void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack,
89 ControlFlowGraph* cfg)
const {
90 std::vector<const Type*> parameter_types =
91 LowerParameterTypes(intrinsic->signature().parameter_types);
92 for (intptr_t
i = parameter_types.size() - 1;
i >= 0; --
i) {
93 const Type* arg_type = stack->Pop();
94 const Type* parameter_type = parameter_types.back();
95 parameter_types.pop_back();
96 if (arg_type != parameter_type) {
97 ReportError(
"parameter ",
i,
": expected type ", *parameter_type,
98 " but found type ", *arg_type);
101 if (intrinsic->IsTransitioning()) {
102 InvalidateTransientTypes(stack);
104 stack->PushMany(LowerType(intrinsic->signature().return_type));
107 void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
108 ControlFlowGraph* cfg)
const {
109 std::vector<const Type*> parameter_types =
110 LowerParameterTypes(macro->signature().parameter_types);
111 for (intptr_t
i = parameter_types.size() - 1;
i >= 0; --
i) {
112 const Type* arg_type = stack->Pop();
113 const Type* parameter_type = parameter_types.back();
114 parameter_types.pop_back();
115 if (arg_type != parameter_type) {
116 ReportError(
"parameter ",
i,
": expected type ", *parameter_type,
117 " but found type ", *arg_type);
121 if (macro->IsTransitioning()) {
122 InvalidateTransientTypes(stack);
126 Stack<const Type*> catch_stack = *stack;
127 catch_stack.Push(TypeOracle::GetObjectType());
128 (*catch_block)->SetInputTypes(catch_stack);
131 stack->PushMany(LowerType(macro->signature().return_type));
134 void CallCsaMacroAndBranchInstruction::TypeInstruction(
135 Stack<const Type*>* stack, ControlFlowGraph* cfg)
const {
136 std::vector<const Type*> parameter_types =
137 LowerParameterTypes(macro->signature().parameter_types);
138 for (intptr_t
i = parameter_types.size() - 1;
i >= 0; --
i) {
139 const Type* arg_type = stack->Pop();
140 const Type* parameter_type = parameter_types.back();
141 parameter_types.pop_back();
142 if (arg_type != parameter_type) {
143 ReportError(
"parameter ",
i,
": expected type ", *parameter_type,
144 " but found type ", *arg_type);
148 if (label_blocks.size() != macro->signature().labels.size()) {
149 ReportError(
"wrong number of labels");
151 for (
size_t i = 0;
i < label_blocks.size(); ++
i) {
152 Stack<const Type*> continuation_stack = *stack;
153 continuation_stack.PushMany(
154 LowerParameterTypes(macro->signature().labels[
i].types));
155 label_blocks[
i]->SetInputTypes(std::move(continuation_stack));
158 if (macro->IsTransitioning()) {
159 InvalidateTransientTypes(stack);
163 Stack<const Type*> catch_stack = *stack;
164 catch_stack.Push(TypeOracle::GetObjectType());
165 (*catch_block)->SetInputTypes(catch_stack);
168 if (macro->signature().return_type != TypeOracle::GetNeverType()) {
169 Stack<const Type*> return_stack = *stack;
170 return_stack.PushMany(LowerType(macro->signature().return_type));
171 if (return_continuation == base::nullopt) {
172 ReportError(
"missing return continuation.");
174 (*return_continuation)->SetInputTypes(return_stack);
176 if (return_continuation != base::nullopt) {
177 ReportError(
"unreachable return continuation.");
182 void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack,
183 ControlFlowGraph* cfg)
const {
184 std::vector<const Type*> argument_types = stack->PopMany(argc);
185 if (argument_types !=
186 LowerParameterTypes(builtin->signature().parameter_types)) {
187 ReportError(
"wrong argument types");
189 if (builtin->IsTransitioning()) {
190 InvalidateTransientTypes(stack);
194 Stack<const Type*> catch_stack = *stack;
195 catch_stack.Push(TypeOracle::GetObjectType());
196 (*catch_block)->SetInputTypes(catch_stack);
199 stack->PushMany(LowerType(builtin->signature().return_type));
202 void CallBuiltinPointerInstruction::TypeInstruction(
203 Stack<const Type*>* stack, ControlFlowGraph* cfg)
const {
204 std::vector<const Type*> argument_types = stack->PopMany(argc);
205 const FunctionPointerType* f = FunctionPointerType::DynamicCast(stack->Pop());
206 if (!f) ReportError(
"expected function pointer type");
207 if (argument_types != LowerParameterTypes(f->parameter_types())) {
208 ReportError(
"wrong argument types");
212 InvalidateTransientTypes(stack);
213 stack->PushMany(LowerType(f->return_type()));
216 void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack,
217 ControlFlowGraph* cfg)
const {
218 std::vector<const Type*> argument_types = stack->PopMany(argc);
219 if (argument_types !=
220 LowerParameterTypes(runtime_function->signature().parameter_types,
222 ReportError(
"wrong argument types");
224 if (runtime_function->IsTransitioning()) {
225 InvalidateTransientTypes(stack);
229 Stack<const Type*> catch_stack = *stack;
230 catch_stack.Push(TypeOracle::GetObjectType());
231 (*catch_block)->SetInputTypes(catch_stack);
234 const Type* return_type = runtime_function->signature().return_type;
235 if (return_type != TypeOracle::GetNeverType()) {
236 stack->PushMany(LowerType(return_type));
240 void BranchInstruction::TypeInstruction(Stack<const Type*>* stack,
241 ControlFlowGraph* cfg)
const {
242 const Type* condition_type = stack->Pop();
243 if (condition_type != TypeOracle::GetBoolType()) {
244 ReportError(
"condition has to have type bool");
246 if_true->SetInputTypes(*stack);
247 if_false->SetInputTypes(*stack);
250 void ConstexprBranchInstruction::TypeInstruction(Stack<const Type*>* stack,
251 ControlFlowGraph* cfg)
const {
252 if_true->SetInputTypes(*stack);
253 if_false->SetInputTypes(*stack);
256 void GotoInstruction::TypeInstruction(Stack<const Type*>* stack,
257 ControlFlowGraph* cfg)
const {
258 destination->SetInputTypes(*stack);
261 void GotoExternalInstruction::TypeInstruction(Stack<const Type*>* stack,
262 ControlFlowGraph* cfg)
const {
263 if (variable_names.size() != stack->Size()) {
264 ReportError(
"goto external label with wrong parameter count.");
268 void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack,
269 ControlFlowGraph* cfg)
const {
270 cfg->SetReturnType(stack->Pop());
273 void PrintConstantStringInstruction::TypeInstruction(
274 Stack<const Type*>* stack, ControlFlowGraph* cfg)
const {}
276 void AbortInstruction::TypeInstruction(Stack<const Type*>* stack,
277 ControlFlowGraph* cfg)
const {}
279 void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack,
280 ControlFlowGraph* cfg)
const {
281 stack->Poke(stack->AboveTop() - 1, destination_type);
284 bool CallRuntimeInstruction::IsBlockTerminator()
const {
285 return is_tailcall || runtime_function->signature().return_type ==
286 TypeOracle::GetNeverType();