Line data Source code
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/instructions.h"
6 : #include "src/torque/cfg.h"
7 : #include "src/torque/type-oracle.h"
8 :
9 : namespace v8 {
10 : namespace internal {
11 : namespace torque {
12 :
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)); \
17 : } \
18 : void Name::Assign(const InstructionBase& other) { \
19 : *this = static_cast<const Name&>(other); \
20 : }
21 218066 : TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS)
22 : #undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS
23 :
24 15680 : void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
25 : ControlFlowGraph* cfg) const {
26 15680 : const Type* type = stack->Peek(slot);
27 15680 : if (widened_type) {
28 15680 : if (type->IsTopType()) {
29 : const TopType* top_type = TopType::cast(type);
30 0 : ReportError("use of " + top_type->reason());
31 : }
32 15680 : if (!type->IsSubtypeOf(*widened_type)) {
33 0 : ReportError("type ", *type, " is not a subtype of ", **widened_type);
34 : }
35 15680 : type = *widened_type;
36 : }
37 : stack->Push(type);
38 15680 : }
39 :
40 859 : void PokeInstruction::TypeInstruction(Stack<const Type*>* stack,
41 : ControlFlowGraph* cfg) const {
42 859 : const Type* type = stack->Top();
43 859 : if (widened_type) {
44 859 : if (!type->IsSubtypeOf(*widened_type)) {
45 0 : ReportError("type ", type, " is not a subtype of ", *widened_type);
46 : }
47 859 : type = *widened_type;
48 : }
49 859 : stack->Poke(slot, type);
50 : stack->Pop();
51 859 : }
52 :
53 7936 : void DeleteRangeInstruction::TypeInstruction(Stack<const Type*>* stack,
54 : ControlFlowGraph* cfg) const {
55 7936 : stack->DeleteRange(range);
56 7936 : }
57 :
58 195 : void PushUninitializedInstruction::TypeInstruction(
59 : Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
60 195 : stack->Push(type);
61 195 : }
62 :
63 95 : void PushBuiltinPointerInstruction::TypeInstruction(
64 : Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
65 95 : stack->Push(type);
66 95 : }
67 :
68 311 : void NamespaceConstantInstruction::TypeInstruction(
69 : Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
70 622 : stack->PushMany(LowerType(constant->type()));
71 311 : }
72 :
73 217 : void InstructionBase::InvalidateTransientTypes(
74 : Stack<const Type*>* stack) const {
75 : auto current = stack->begin();
76 3410 : while (current != stack->end()) {
77 2976 : if ((*current)->IsTransient()) {
78 83 : std::stringstream stream;
79 83 : stream << "type " << **current
80 83 : << " is made invalid by transitioning callable invocation at "
81 166 : << PositionAsString(pos);
82 249 : *current = TypeOracle::GetTopType(stream.str(), *current);
83 : }
84 2976 : ++current;
85 : }
86 217 : }
87 :
88 98 : void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack,
89 : ControlFlowGraph* cfg) const {
90 : std::vector<const Type*> parameter_types =
91 196 : LowerParameterTypes(intrinsic->signature().parameter_types);
92 276 : for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
93 : const Type* arg_type = stack->Pop();
94 80 : const Type* parameter_type = parameter_types.back();
95 : parameter_types.pop_back();
96 80 : if (arg_type != parameter_type) {
97 : ReportError("parameter ", i, ": expected type ", *parameter_type,
98 0 : " but found type ", *arg_type);
99 : }
100 : }
101 196 : if (intrinsic->IsTransitioning()) {
102 0 : InvalidateTransientTypes(stack);
103 : }
104 196 : stack->PushMany(LowerType(intrinsic->signature().return_type));
105 98 : }
106 :
107 4287 : void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
108 : ControlFlowGraph* cfg) const {
109 : std::vector<const Type*> parameter_types =
110 8574 : LowerParameterTypes(macro->signature().parameter_types);
111 14042 : for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
112 : const Type* arg_type = stack->Pop();
113 5468 : const Type* parameter_type = parameter_types.back();
114 : parameter_types.pop_back();
115 5468 : if (arg_type != parameter_type) {
116 : ReportError("parameter ", i, ": expected type ", *parameter_type,
117 0 : " but found type ", *arg_type);
118 : }
119 : }
120 :
121 8574 : if (macro->IsTransitioning()) {
122 98 : InvalidateTransientTypes(stack);
123 : }
124 :
125 4287 : if (catch_block) {
126 : Stack<const Type*> catch_stack = *stack;
127 8 : catch_stack.Push(TypeOracle::GetObjectType());
128 8 : (*catch_block)->SetInputTypes(catch_stack);
129 : }
130 :
131 8574 : stack->PushMany(LowerType(macro->signature().return_type));
132 4287 : }
133 :
134 466 : void CallCsaMacroAndBranchInstruction::TypeInstruction(
135 : Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
136 : std::vector<const Type*> parameter_types =
137 932 : LowerParameterTypes(macro->signature().parameter_types);
138 1820 : for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
139 : const Type* arg_type = stack->Pop();
140 888 : const Type* parameter_type = parameter_types.back();
141 : parameter_types.pop_back();
142 888 : if (arg_type != parameter_type) {
143 : ReportError("parameter ", i, ": expected type ", *parameter_type,
144 0 : " but found type ", *arg_type);
145 : }
146 : }
147 :
148 2854 : if (label_blocks.size() != macro->signature().labels.size()) {
149 0 : ReportError("wrong number of labels");
150 : }
151 1456 : for (size_t i = 0; i < label_blocks.size(); ++i) {
152 : Stack<const Type*> continuation_stack = *stack;
153 : continuation_stack.PushMany(
154 1485 : LowerParameterTypes(macro->signature().labels[i].types));
155 495 : label_blocks[i]->SetInputTypes(std::move(continuation_stack));
156 : }
157 :
158 932 : if (macro->IsTransitioning()) {
159 26 : InvalidateTransientTypes(stack);
160 : }
161 :
162 466 : if (catch_block) {
163 : Stack<const Type*> catch_stack = *stack;
164 4 : catch_stack.Push(TypeOracle::GetObjectType());
165 4 : (*catch_block)->SetInputTypes(catch_stack);
166 : }
167 :
168 466 : if (macro->signature().return_type != TypeOracle::GetNeverType()) {
169 : Stack<const Type*> return_stack = *stack;
170 678 : return_stack.PushMany(LowerType(macro->signature().return_type));
171 339 : if (return_continuation == base::nullopt) {
172 0 : ReportError("missing return continuation.");
173 : }
174 339 : (*return_continuation)->SetInputTypes(return_stack);
175 : } else {
176 127 : if (return_continuation != base::nullopt) {
177 0 : ReportError("unreachable return continuation.");
178 : }
179 : }
180 466 : }
181 :
182 98 : void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack,
183 : ControlFlowGraph* cfg) const {
184 98 : std::vector<const Type*> argument_types = stack->PopMany(argc);
185 196 : if (argument_types !=
186 196 : LowerParameterTypes(builtin->signature().parameter_types)) {
187 0 : ReportError("wrong argument types");
188 : }
189 196 : if (builtin->IsTransitioning()) {
190 66 : InvalidateTransientTypes(stack);
191 : }
192 :
193 98 : if (catch_block) {
194 : Stack<const Type*> catch_stack = *stack;
195 0 : catch_stack.Push(TypeOracle::GetObjectType());
196 0 : (*catch_block)->SetInputTypes(catch_stack);
197 : }
198 :
199 196 : stack->PushMany(LowerType(builtin->signature().return_type));
200 98 : }
201 :
202 14 : void CallBuiltinPointerInstruction::TypeInstruction(
203 : Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
204 14 : std::vector<const Type*> argument_types = stack->PopMany(argc);
205 14 : const BuiltinPointerType* f = BuiltinPointerType::DynamicCast(stack->Pop());
206 14 : if (!f) ReportError("expected function pointer type");
207 28 : if (argument_types != LowerParameterTypes(f->parameter_types())) {
208 0 : ReportError("wrong argument types");
209 : }
210 : // TODO(tebbi): Only invalidate transient types if the function pointer type
211 : // is transitioning.
212 14 : InvalidateTransientTypes(stack);
213 28 : stack->PushMany(LowerType(f->return_type()));
214 14 : }
215 :
216 32 : void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack,
217 : ControlFlowGraph* cfg) const {
218 32 : std::vector<const Type*> argument_types = stack->PopMany(argc);
219 96 : if (argument_types !=
220 64 : LowerParameterTypes(runtime_function->signature().parameter_types,
221 : argc)) {
222 0 : ReportError("wrong argument types");
223 : }
224 64 : if (runtime_function->IsTransitioning()) {
225 13 : InvalidateTransientTypes(stack);
226 : }
227 :
228 32 : if (catch_block) {
229 : Stack<const Type*> catch_stack = *stack;
230 1 : catch_stack.Push(TypeOracle::GetObjectType());
231 1 : (*catch_block)->SetInputTypes(catch_stack);
232 : }
233 :
234 32 : const Type* return_type = runtime_function->signature().return_type;
235 32 : if (return_type != TypeOracle::GetNeverType()) {
236 42 : stack->PushMany(LowerType(return_type));
237 : }
238 32 : }
239 :
240 757 : void BranchInstruction::TypeInstruction(Stack<const Type*>* stack,
241 : ControlFlowGraph* cfg) const {
242 : const Type* condition_type = stack->Pop();
243 757 : if (condition_type != TypeOracle::GetBoolType()) {
244 0 : ReportError("condition has to have type bool");
245 : }
246 757 : if_true->SetInputTypes(*stack);
247 757 : if_false->SetInputTypes(*stack);
248 757 : }
249 :
250 54 : void ConstexprBranchInstruction::TypeInstruction(Stack<const Type*>* stack,
251 : ControlFlowGraph* cfg) const {
252 54 : if_true->SetInputTypes(*stack);
253 54 : if_false->SetInputTypes(*stack);
254 54 : }
255 :
256 3270 : void GotoInstruction::TypeInstruction(Stack<const Type*>* stack,
257 : ControlFlowGraph* cfg) const {
258 3270 : destination->SetInputTypes(*stack);
259 3270 : }
260 :
261 134 : void GotoExternalInstruction::TypeInstruction(Stack<const Type*>* stack,
262 : ControlFlowGraph* cfg) const {
263 268 : if (variable_names.size() != stack->Size()) {
264 0 : ReportError("goto external label with wrong parameter count.");
265 : }
266 134 : }
267 :
268 183 : void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack,
269 : ControlFlowGraph* cfg) const {
270 183 : cfg->SetReturnType(stack->Pop());
271 183 : }
272 :
273 0 : void PrintConstantStringInstruction::TypeInstruction(
274 0 : Stack<const Type*>* stack, ControlFlowGraph* cfg) const {}
275 :
276 186 : void AbortInstruction::TypeInstruction(Stack<const Type*>* stack,
277 186 : ControlFlowGraph* cfg) const {}
278 :
279 48 : void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack,
280 : ControlFlowGraph* cfg) const {
281 96 : stack->Poke(stack->AboveTop() - 1, destination_type);
282 48 : }
283 :
284 58 : void LoadObjectFieldInstruction::TypeInstruction(Stack<const Type*>* stack,
285 : ControlFlowGraph* cfg) const {
286 58 : const ClassType* stack_class_type = ClassType::DynamicCast(stack->Top());
287 58 : if (!stack_class_type) {
288 : ReportError(
289 : "first argument to a LoadObjectFieldInstruction instruction isn't a "
290 0 : "class");
291 : }
292 58 : if (stack_class_type != class_type) {
293 : ReportError(
294 : "first argument to a LoadObjectFieldInstruction doesn't match "
295 0 : "instruction's type");
296 : }
297 58 : const Field& field = class_type->LookupField(field_name);
298 116 : stack->Poke(stack->AboveTop() - 1, field.name_and_type.type);
299 58 : }
300 :
301 124 : void StoreObjectFieldInstruction::TypeInstruction(Stack<const Type*>* stack,
302 : ControlFlowGraph* cfg) const {
303 : auto value = stack->Pop();
304 124 : const ClassType* stack_class_type = ClassType::DynamicCast(stack->Top());
305 124 : if (!stack_class_type) {
306 : ReportError(
307 : "first argument to a StoreObjectFieldInstruction instruction isn't a "
308 0 : "class");
309 : }
310 124 : if (stack_class_type != class_type) {
311 : ReportError(
312 : "first argument to a StoreObjectFieldInstruction doesn't match "
313 0 : "instruction's type");
314 : }
315 : stack->Pop();
316 : stack->Push(value);
317 124 : }
318 :
319 42 : bool CallRuntimeInstruction::IsBlockTerminator() const {
320 84 : return is_tailcall || runtime_function->signature().return_type ==
321 84 : TypeOracle::GetNeverType();
322 : }
323 :
324 : } // namespace torque
325 : } // namespace internal
326 9114 : } // namespace v8
|