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