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