OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/verifier.h" | 5 #include "src/compiler/verifier.h" |
6 | 6 |
7 #include <deque> | 7 #include <deque> |
8 #include <queue> | 8 #include <queue> |
9 | 9 |
10 #include "src/compiler/generic-algorithm.h" | 10 #include "src/compiler/generic-algorithm.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {} | 49 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {} |
50 | 50 |
51 // Fulfills the PreNodeCallback interface. | 51 // Fulfills the PreNodeCallback interface. |
52 GenericGraphVisit::Control Pre(Node* node); | 52 GenericGraphVisit::Control Pre(Node* node); |
53 | 53 |
54 Zone* zone; | 54 Zone* zone; |
55 Typing typing; | 55 Typing typing; |
56 | 56 |
57 private: | 57 private: |
58 // TODO(rossberg): Get rid of these once we got rid of NodeProperties. | 58 // TODO(rossberg): Get rid of these once we got rid of NodeProperties. |
59 Bounds bounds(Node* node) { | 59 Bounds bounds(Node* node) { return NodeProperties::GetBounds(node); } |
60 return NodeProperties::GetBounds(node); | 60 Node* ValueInput(Node* node, int i = 0) { |
61 } | |
62 Node* Operand(Node* node, int i = 0) { | |
63 return NodeProperties::GetValueInput(node, i); | 61 return NodeProperties::GetValueInput(node, i); |
64 } | 62 } |
65 FieldAccess Field(Node* node) { | 63 FieldAccess Field(Node* node) { |
66 DCHECK(node->opcode() == IrOpcode::kLoadField || | 64 DCHECK(node->opcode() == IrOpcode::kLoadField || |
67 node->opcode() == IrOpcode::kStoreField); | 65 node->opcode() == IrOpcode::kStoreField); |
68 return OpParameter<FieldAccess>(node); | 66 return OpParameter<FieldAccess>(node); |
69 } | 67 } |
70 ElementAccess Element(Node* node) { | 68 ElementAccess Element(Node* node) { |
71 DCHECK(node->opcode() == IrOpcode::kLoadElement || | 69 DCHECK(node->opcode() == IrOpcode::kLoadElement || |
72 node->opcode() == IrOpcode::kStoreElement); | 70 node->opcode() == IrOpcode::kStoreElement); |
73 return OpParameter<ElementAccess>(node); | 71 return OpParameter<ElementAccess>(node); |
74 } | 72 } |
| 73 void CheckNotTyped(Node* node) { CHECK(!NodeProperties::IsTyped(node)); } |
| 74 void CheckUpperIs(Node* node, Type* type) { |
| 75 if (typing == TYPED) CHECK(bounds(node).upper->Is(type)); |
| 76 } |
| 77 void CheckUpperMaybe(Node* node, Type* type) { |
| 78 if (typing == TYPED) CHECK(bounds(node).upper->Maybe(type)); |
| 79 } |
| 80 void CheckValueInputIs(Node* node, int i, Type* type) { |
| 81 if (typing == TYPED) CHECK(bounds(ValueInput(node, i)).upper->Is(type)); |
| 82 } |
75 }; | 83 }; |
76 | 84 |
77 | 85 |
78 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { | 86 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { |
79 int value_count = OperatorProperties::GetValueInputCount(node->op()); | 87 int value_count = OperatorProperties::GetValueInputCount(node->op()); |
80 int context_count = OperatorProperties::GetContextInputCount(node->op()); | 88 int context_count = OperatorProperties::GetContextInputCount(node->op()); |
81 int frame_state_count = | 89 int frame_state_count = |
82 OperatorProperties::GetFrameStateInputCount(node->op()); | 90 OperatorProperties::GetFrameStateInputCount(node->op()); |
83 int effect_count = OperatorProperties::GetEffectInputCount(node->op()); | 91 int effect_count = OperatorProperties::GetEffectInputCount(node->op()); |
84 int control_count = OperatorProperties::GetControlInputCount(node->op()); | 92 int control_count = OperatorProperties::GetControlInputCount(node->op()); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 // Verify all successors are projections if multiple value outputs exist. | 142 // Verify all successors are projections if multiple value outputs exist. |
135 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) { | 143 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) { |
136 Node::Uses uses = node->uses(); | 144 Node::Uses uses = node->uses(); |
137 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { | 145 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { |
138 CHECK(!NodeProperties::IsValueEdge(it.edge()) || | 146 CHECK(!NodeProperties::IsValueEdge(it.edge()) || |
139 (*it)->opcode() == IrOpcode::kProjection || | 147 (*it)->opcode() == IrOpcode::kProjection || |
140 (*it)->opcode() == IrOpcode::kParameter); | 148 (*it)->opcode() == IrOpcode::kParameter); |
141 } | 149 } |
142 } | 150 } |
143 | 151 |
144 if (typing == TYPED) { | 152 switch (node->opcode()) { |
145 switch (node->opcode()) { | 153 case IrOpcode::kStart: |
146 // Control operators | 154 // Start has no inputs. |
147 // ----------------- | 155 CHECK_EQ(0, input_count); |
148 case IrOpcode::kStart: | 156 // Type is a tuple. |
149 // Start has no inputs. | 157 // TODO(rossberg): Multiple outputs are currently typed as Internal. |
150 CHECK_EQ(0, input_count); | 158 CheckUpperIs(node, Type::Internal()); |
151 // Type is a tuple. | 159 break; |
152 // TODO(rossberg): Multiple outputs are currently typed as Internal. | 160 case IrOpcode::kEnd: |
153 CHECK(bounds(node).upper->Is(Type::Internal())); | 161 // End has no outputs. |
154 break; | 162 CHECK(!OperatorProperties::HasValueOutput(node->op())); |
155 case IrOpcode::kEnd: | 163 CHECK(!OperatorProperties::HasEffectOutput(node->op())); |
156 // End has no outputs. | 164 CHECK(!OperatorProperties::HasControlOutput(node->op())); |
157 CHECK(!OperatorProperties::HasValueOutput(node->op())); | 165 // Type is empty. |
158 CHECK(!OperatorProperties::HasEffectOutput(node->op())); | 166 CheckNotTyped(node); |
159 CHECK(!OperatorProperties::HasControlOutput(node->op())); | 167 break; |
160 // Type is empty. | 168 case IrOpcode::kDead: |
161 CHECK(!NodeProperties::IsTyped(node)); | 169 // Dead is never connected to the graph. |
162 break; | 170 UNREACHABLE(); |
163 case IrOpcode::kDead: | 171 case IrOpcode::kBranch: { |
164 // Dead is never connected to the graph. | 172 // Branch uses are IfTrue and IfFalse. |
165 UNREACHABLE(); | 173 Node::Uses uses = node->uses(); |
166 case IrOpcode::kBranch: { | 174 int count_true = 0, count_false = 0; |
167 // Branch uses are IfTrue and IfFalse. | 175 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { |
168 Node::Uses uses = node->uses(); | 176 CHECK((*it)->opcode() == IrOpcode::kIfTrue || |
169 int count_true = 0, count_false = 0; | 177 (*it)->opcode() == IrOpcode::kIfFalse); |
170 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { | 178 if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true; |
171 CHECK((*it)->opcode() == IrOpcode::kIfTrue || | 179 if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false; |
172 (*it)->opcode() == IrOpcode::kIfFalse); | |
173 if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true; | |
174 if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false; | |
175 } | |
176 CHECK(count_true == 1 && count_false == 1); | |
177 // Type is empty. | |
178 CHECK(!NodeProperties::IsTyped(node)); | |
179 break; | |
180 } | 180 } |
181 case IrOpcode::kIfTrue: | 181 CHECK(count_true == 1 && count_false == 1); |
182 case IrOpcode::kIfFalse: | 182 // Type is empty. |
183 CHECK_EQ(IrOpcode::kBranch, | 183 CheckNotTyped(node); |
184 NodeProperties::GetControlInput(node, 0)->opcode()); | 184 break; |
185 // Type is empty. | 185 } |
186 CHECK(!NodeProperties::IsTyped(node)); | 186 case IrOpcode::kIfTrue: |
187 break; | 187 case IrOpcode::kIfFalse: |
188 case IrOpcode::kLoop: | 188 CHECK_EQ(IrOpcode::kBranch, |
189 case IrOpcode::kMerge: | 189 NodeProperties::GetControlInput(node, 0)->opcode()); |
190 // Type is empty. | 190 // Type is empty. |
191 CHECK(!NodeProperties::IsTyped(node)); | 191 CheckNotTyped(node); |
192 break; | 192 break; |
193 case IrOpcode::kReturn: | 193 case IrOpcode::kLoop: |
194 // TODO(rossberg): check successor is End | 194 case IrOpcode::kMerge: |
195 // Type is empty. | 195 CHECK_EQ(control_count, input_count); |
196 CHECK(!NodeProperties::IsTyped(node)); | 196 // Type is empty. |
197 break; | 197 CheckNotTyped(node); |
198 case IrOpcode::kThrow: | 198 break; |
199 // TODO(rossberg): what are the constraints on these? | 199 case IrOpcode::kReturn: |
200 // Type is empty. | 200 // TODO(rossberg): check successor is End |
201 CHECK(!NodeProperties::IsTyped(node)); | 201 // Type is empty. |
202 break; | 202 CheckNotTyped(node); |
203 | 203 break; |
204 // Common operators | 204 case IrOpcode::kThrow: |
205 // ---------------- | 205 // TODO(rossberg): what are the constraints on these? |
206 case IrOpcode::kParameter: { | 206 // Type is empty. |
207 // Parameters have the start node as inputs. | 207 CheckNotTyped(node); |
208 CHECK_EQ(1, input_count); | 208 break; |
209 CHECK_EQ(IrOpcode::kStart, | 209 |
210 NodeProperties::GetValueInput(node, 0)->opcode()); | 210 // Common operators |
211 // Parameter has an input that produces enough values. | 211 // ---------------- |
212 int index = OpParameter<int>(node); | 212 case IrOpcode::kParameter: { |
213 Node* input = NodeProperties::GetValueInput(node, 0); | 213 // Parameters have the start node as inputs. |
214 // Currently, parameter indices start at -1 instead of 0. | 214 CHECK_EQ(1, input_count); |
215 CHECK_GT( | 215 CHECK_EQ(IrOpcode::kStart, |
216 OperatorProperties::GetValueOutputCount(input->op()), index + 1); | 216 NodeProperties::GetValueInput(node, 0)->opcode()); |
217 // Type can be anything. | 217 // Parameter has an input that produces enough values. |
218 CHECK(bounds(node).upper->Is(Type::Any())); | 218 int index = OpParameter<int>(node); |
219 break; | 219 Node* input = NodeProperties::GetValueInput(node, 0); |
| 220 // Currently, parameter indices start at -1 instead of 0. |
| 221 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index + 1); |
| 222 // Type can be anything. |
| 223 CheckUpperIs(node, Type::Any()); |
| 224 break; |
| 225 } |
| 226 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? |
| 227 // Constants have no inputs. |
| 228 CHECK_EQ(0, input_count); |
| 229 // Type is a 32 bit integer, signed or unsigned. |
| 230 CheckUpperIs(node, Type::Integral32()); |
| 231 break; |
| 232 case IrOpcode::kInt64Constant: |
| 233 // Constants have no inputs. |
| 234 CHECK_EQ(0, input_count); |
| 235 // Type is internal. |
| 236 // TODO(rossberg): Introduce proper Int64 type. |
| 237 CheckUpperIs(node, Type::Internal()); |
| 238 break; |
| 239 case IrOpcode::kFloat32Constant: |
| 240 case IrOpcode::kFloat64Constant: |
| 241 case IrOpcode::kNumberConstant: |
| 242 // Constants have no inputs. |
| 243 CHECK_EQ(0, input_count); |
| 244 // Type is a number. |
| 245 CheckUpperIs(node, Type::Number()); |
| 246 break; |
| 247 case IrOpcode::kHeapConstant: |
| 248 // Constants have no inputs. |
| 249 CHECK_EQ(0, input_count); |
| 250 // Type can be anything represented as a heap pointer. |
| 251 CheckUpperIs(node, Type::TaggedPtr()); |
| 252 break; |
| 253 case IrOpcode::kExternalConstant: |
| 254 // Constants have no inputs. |
| 255 CHECK_EQ(0, input_count); |
| 256 // Type is considered internal. |
| 257 CheckUpperIs(node, Type::Internal()); |
| 258 break; |
| 259 case IrOpcode::kProjection: { |
| 260 // Projection has an input that produces enough values. |
| 261 int index = OpParameter<int>(node->op()); |
| 262 Node* input = NodeProperties::GetValueInput(node, 0); |
| 263 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index); |
| 264 // Type can be anything. |
| 265 // TODO(rossberg): Introduce tuple types for this. |
| 266 // TODO(titzer): Convince rossberg not to. |
| 267 CheckUpperIs(node, Type::Any()); |
| 268 break; |
| 269 } |
| 270 case IrOpcode::kPhi: { |
| 271 // Phi input count matches parent control node. |
| 272 CHECK_EQ(0, effect_count); |
| 273 CHECK_EQ(1, control_count); |
| 274 Node* control = NodeProperties::GetControlInput(node, 0); |
| 275 CHECK_EQ(value_count, |
| 276 OperatorProperties::GetControlInputCount(control->op())); |
| 277 CHECK_EQ(input_count, 1 + value_count); |
| 278 // Type must be subsumed by all input types. |
| 279 // TODO(rossberg): for now at least, narrowing does not really hold. |
| 280 /* |
| 281 for (int i = 0; i < value_count; ++i) { |
| 282 // TODO(rossberg, jarin): Figure out what to do about lower bounds. |
| 283 // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower)); |
| 284 CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper)); |
220 } | 285 } |
221 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? | 286 */ |
222 // Constants have no inputs. | 287 break; |
223 CHECK_EQ(0, input_count); | 288 } |
224 // Type is a 32 bit integer, signed or unsigned. | 289 case IrOpcode::kEffectPhi: { |
225 CHECK(bounds(node).upper->Is(Type::Integral32())); | 290 // EffectPhi input count matches parent control node. |
226 break; | 291 CHECK_EQ(0, value_count); |
227 case IrOpcode::kInt64Constant: | 292 CHECK_EQ(1, control_count); |
228 // Constants have no inputs. | 293 Node* control = NodeProperties::GetControlInput(node, 0); |
229 CHECK_EQ(0, input_count); | 294 CHECK_EQ(effect_count, |
230 // Type is internal. | 295 OperatorProperties::GetControlInputCount(control->op())); |
231 // TODO(rossberg): Introduce proper Int64 type. | 296 CHECK_EQ(input_count, 1 + effect_count); |
232 CHECK(bounds(node).upper->Is(Type::Internal())); | 297 break; |
233 break; | 298 } |
234 case IrOpcode::kFloat32Constant: | 299 case IrOpcode::kValueEffect: |
235 case IrOpcode::kFloat64Constant: | 300 // TODO(rossberg): what are the constraints on these? |
236 case IrOpcode::kNumberConstant: | 301 break; |
237 // Constants have no inputs. | 302 case IrOpcode::kFinish: { |
238 CHECK_EQ(0, input_count); | 303 // TODO(rossberg): what are the constraints on these? |
239 // Type is a number. | 304 // Type must be subsumed by input type. |
240 CHECK(bounds(node).upper->Is(Type::Number())); | 305 if (typing == TYPED) { |
241 break; | 306 CHECK(bounds(ValueInput(node)).lower->Is(bounds(node).lower)); |
242 case IrOpcode::kHeapConstant: | 307 CHECK(bounds(ValueInput(node)).upper->Is(bounds(node).upper)); |
243 // Constants have no inputs. | |
244 CHECK_EQ(0, input_count); | |
245 // Type can be anything represented as a heap pointer. | |
246 CHECK(bounds(node).upper->Is(Type::TaggedPtr())); | |
247 break; | |
248 case IrOpcode::kExternalConstant: | |
249 // Constants have no inputs. | |
250 CHECK_EQ(0, input_count); | |
251 // Type is considered internal. | |
252 CHECK(bounds(node).upper->Is(Type::Internal())); | |
253 break; | |
254 case IrOpcode::kProjection: { | |
255 // Projection has an input that produces enough values. | |
256 int index = OpParameter<int>(node->op()); | |
257 Node* input = NodeProperties::GetValueInput(node, 0); | |
258 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index); | |
259 // Type can be anything. | |
260 // TODO(rossberg): Introduce tuple types for this. | |
261 CHECK(bounds(node).upper->Is(Type::Any())); | |
262 break; | |
263 } | 308 } |
264 case IrOpcode::kPhi: { | 309 break; |
265 // Phi input count matches parent control node. | 310 } |
266 CHECK_EQ(1, control_count); | 311 case IrOpcode::kFrameState: |
267 Node* control = NodeProperties::GetControlInput(node, 0); | 312 // TODO(jarin): what are the constraints on these? |
268 CHECK_EQ(value_count, | 313 break; |
269 OperatorProperties::GetControlInputCount(control->op())); | 314 case IrOpcode::kStateValues: |
270 // Type must be subsumed by all input types. | 315 // TODO(jarin): what are the constraints on these? |
271 // TODO(rossberg): for now at least, narrowing does not really hold. | 316 break; |
272 /* | 317 case IrOpcode::kCall: |
273 for (int i = 0; i < value_count; ++i) { | 318 // TODO(rossberg): what are the constraints on these? |
274 // TODO(rossberg, jarin): Figure out what to do about lower bounds. | 319 break; |
275 // CHECK(bounds(node).lower->Is(bounds(Operand(node, i)).lower)); | 320 |
276 CHECK(bounds(Operand(node, i)).upper->Is(bounds(node).upper)); | 321 // JavaScript operators |
277 } | 322 // -------------------- |
278 */ | 323 case IrOpcode::kJSEqual: |
279 break; | 324 case IrOpcode::kJSNotEqual: |
| 325 case IrOpcode::kJSStrictEqual: |
| 326 case IrOpcode::kJSStrictNotEqual: |
| 327 case IrOpcode::kJSLessThan: |
| 328 case IrOpcode::kJSGreaterThan: |
| 329 case IrOpcode::kJSLessThanOrEqual: |
| 330 case IrOpcode::kJSGreaterThanOrEqual: |
| 331 case IrOpcode::kJSUnaryNot: |
| 332 // Type is Boolean. |
| 333 CheckUpperIs(node, Type::Boolean()); |
| 334 break; |
| 335 |
| 336 case IrOpcode::kJSBitwiseOr: |
| 337 case IrOpcode::kJSBitwiseXor: |
| 338 case IrOpcode::kJSBitwiseAnd: |
| 339 case IrOpcode::kJSShiftLeft: |
| 340 case IrOpcode::kJSShiftRight: |
| 341 case IrOpcode::kJSShiftRightLogical: |
| 342 // Type is 32 bit integral. |
| 343 CheckUpperIs(node, Type::Integral32()); |
| 344 break; |
| 345 case IrOpcode::kJSAdd: |
| 346 // Type is Number or String. |
| 347 CheckUpperIs(node, Type::NumberOrString()); |
| 348 break; |
| 349 case IrOpcode::kJSSubtract: |
| 350 case IrOpcode::kJSMultiply: |
| 351 case IrOpcode::kJSDivide: |
| 352 case IrOpcode::kJSModulus: |
| 353 // Type is Number. |
| 354 CheckUpperIs(node, Type::Number()); |
| 355 break; |
| 356 |
| 357 case IrOpcode::kJSToBoolean: |
| 358 // Type is Boolean. |
| 359 CheckUpperIs(node, Type::Boolean()); |
| 360 break; |
| 361 case IrOpcode::kJSToNumber: |
| 362 // Type is Number. |
| 363 CheckUpperIs(node, Type::Number()); |
| 364 break; |
| 365 case IrOpcode::kJSToString: |
| 366 // Type is String. |
| 367 CheckUpperIs(node, Type::String()); |
| 368 break; |
| 369 case IrOpcode::kJSToName: |
| 370 // Type is Name. |
| 371 CheckUpperIs(node, Type::Name()); |
| 372 break; |
| 373 case IrOpcode::kJSToObject: |
| 374 // Type is Receiver. |
| 375 CheckUpperIs(node, Type::Receiver()); |
| 376 break; |
| 377 |
| 378 case IrOpcode::kJSCreate: |
| 379 // Type is Object. |
| 380 CheckUpperIs(node, Type::Object()); |
| 381 break; |
| 382 case IrOpcode::kJSLoadProperty: |
| 383 case IrOpcode::kJSLoadNamed: |
| 384 // Type can be anything. |
| 385 CheckUpperIs(node, Type::Any()); |
| 386 break; |
| 387 case IrOpcode::kJSStoreProperty: |
| 388 case IrOpcode::kJSStoreNamed: |
| 389 // Type is empty. |
| 390 CheckNotTyped(node); |
| 391 break; |
| 392 case IrOpcode::kJSDeleteProperty: |
| 393 case IrOpcode::kJSHasProperty: |
| 394 case IrOpcode::kJSInstanceOf: |
| 395 // Type is Boolean. |
| 396 CheckUpperIs(node, Type::Boolean()); |
| 397 break; |
| 398 case IrOpcode::kJSTypeOf: |
| 399 // Type is String. |
| 400 CheckUpperIs(node, Type::String()); |
| 401 break; |
| 402 |
| 403 case IrOpcode::kJSLoadContext: |
| 404 // Type can be anything. |
| 405 CheckUpperIs(node, Type::Any()); |
| 406 break; |
| 407 case IrOpcode::kJSStoreContext: |
| 408 // Type is empty. |
| 409 CheckNotTyped(node); |
| 410 break; |
| 411 case IrOpcode::kJSCreateFunctionContext: |
| 412 case IrOpcode::kJSCreateCatchContext: |
| 413 case IrOpcode::kJSCreateWithContext: |
| 414 case IrOpcode::kJSCreateBlockContext: |
| 415 case IrOpcode::kJSCreateModuleContext: |
| 416 case IrOpcode::kJSCreateGlobalContext: { |
| 417 // Type is Context, and operand is Internal. |
| 418 Node* context = NodeProperties::GetContextInput(node); |
| 419 // TODO(rossberg): This should really be Is(Internal), but the typer |
| 420 // currently can't do backwards propagation. |
| 421 CheckUpperMaybe(context, Type::Internal()); |
| 422 if (typing == TYPED) CHECK(bounds(node).upper->IsContext()); |
| 423 break; |
| 424 } |
| 425 |
| 426 case IrOpcode::kJSCallConstruct: |
| 427 // Type is Receiver. |
| 428 CheckUpperIs(node, Type::Receiver()); |
| 429 break; |
| 430 case IrOpcode::kJSCallFunction: |
| 431 case IrOpcode::kJSCallRuntime: |
| 432 case IrOpcode::kJSYield: |
| 433 case IrOpcode::kJSDebugger: |
| 434 // Type can be anything. |
| 435 CheckUpperIs(node, Type::Any()); |
| 436 break; |
| 437 |
| 438 // Simplified operators |
| 439 // ------------------------------- |
| 440 case IrOpcode::kBooleanNot: |
| 441 // Boolean -> Boolean |
| 442 CheckValueInputIs(node, 0, Type::Boolean()); |
| 443 CheckUpperIs(node, Type::Boolean()); |
| 444 break; |
| 445 case IrOpcode::kBooleanToNumber: |
| 446 // Boolean -> Number |
| 447 CheckValueInputIs(node, 0, Type::Boolean()); |
| 448 CheckUpperIs(node, Type::Number()); |
| 449 break; |
| 450 case IrOpcode::kNumberEqual: |
| 451 case IrOpcode::kNumberLessThan: |
| 452 case IrOpcode::kNumberLessThanOrEqual: |
| 453 // (Number, Number) -> Boolean |
| 454 CheckValueInputIs(node, 0, Type::Number()); |
| 455 CheckValueInputIs(node, 1, Type::Number()); |
| 456 CheckUpperIs(node, Type::Boolean()); |
| 457 break; |
| 458 case IrOpcode::kNumberAdd: |
| 459 case IrOpcode::kNumberSubtract: |
| 460 case IrOpcode::kNumberMultiply: |
| 461 case IrOpcode::kNumberDivide: |
| 462 case IrOpcode::kNumberModulus: |
| 463 // (Number, Number) -> Number |
| 464 CheckValueInputIs(node, 0, Type::Number()); |
| 465 CheckValueInputIs(node, 1, Type::Number()); |
| 466 // TODO(rossberg): activate once we retype after opcode changes. |
| 467 // CheckUpperIs(node, Type::Number()); |
| 468 break; |
| 469 case IrOpcode::kNumberToInt32: |
| 470 // Number -> Signed32 |
| 471 CheckValueInputIs(node, 0, Type::Number()); |
| 472 CheckUpperIs(node, Type::Signed32()); |
| 473 break; |
| 474 case IrOpcode::kNumberToUint32: |
| 475 // Number -> Unsigned32 |
| 476 CheckValueInputIs(node, 0, Type::Number()); |
| 477 CheckUpperIs(node, Type::Unsigned32()); |
| 478 break; |
| 479 case IrOpcode::kStringEqual: |
| 480 case IrOpcode::kStringLessThan: |
| 481 case IrOpcode::kStringLessThanOrEqual: |
| 482 // (String, String) -> Boolean |
| 483 CheckValueInputIs(node, 0, Type::String()); |
| 484 CheckValueInputIs(node, 1, Type::String()); |
| 485 CheckUpperIs(node, Type::Boolean()); |
| 486 break; |
| 487 case IrOpcode::kStringAdd: |
| 488 // (String, String) -> String |
| 489 CheckValueInputIs(node, 0, Type::String()); |
| 490 CheckValueInputIs(node, 1, Type::String()); |
| 491 CheckUpperIs(node, Type::String()); |
| 492 break; |
| 493 case IrOpcode::kReferenceEqual: { |
| 494 // (Unique, Any) -> Boolean and |
| 495 // (Any, Unique) -> Boolean |
| 496 if (typing == TYPED) { |
| 497 CHECK(bounds(ValueInput(node, 0)).upper->Is(Type::Unique()) || |
| 498 bounds(ValueInput(node, 1)).upper->Is(Type::Unique())); |
280 } | 499 } |
281 case IrOpcode::kEffectPhi: { | 500 CheckUpperIs(node, Type::Boolean()); |
282 // EffectPhi input count matches parent control node. | 501 break; |
283 CHECK_EQ(1, control_count); | 502 } |
284 Node* control = NodeProperties::GetControlInput(node, 0); | 503 case IrOpcode::kObjectIsSmi: |
285 CHECK_EQ(effect_count, | 504 CheckValueInputIs(node, 0, Type::Any()); |
286 OperatorProperties::GetControlInputCount(control->op())); | 505 CheckUpperIs(node, Type::Boolean()); |
287 break; | 506 break; |
288 } | 507 case IrOpcode::kObjectIsNonNegativeSmi: |
289 case IrOpcode::kValueEffect: | 508 CheckValueInputIs(node, 0, Type::Any()); |
290 // TODO(rossberg): what are the constraints on these? | 509 CheckUpperIs(node, Type::Boolean()); |
291 break; | 510 break; |
292 case IrOpcode::kFinish: { | 511 |
293 // TODO(rossberg): what are the constraints on these? | 512 case IrOpcode::kChangeTaggedToInt32: { |
294 // Type must be subsumed by input type. | 513 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32 |
295 CHECK(bounds(Operand(node)).lower->Is(bounds(node).lower)); | 514 // TODO(neis): Activate once ChangeRepresentation works in typer. |
296 CHECK(bounds(Operand(node)).upper->Is(bounds(node).upper)); | 515 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged()); |
297 break; | 516 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); |
298 } | 517 // CheckValueInputIs(node, 0, from)); |
299 case IrOpcode::kFrameState: | 518 // CheckUpperIs(node, to)); |
300 // TODO(jarin): what are the constraints on these? | 519 break; |
301 break; | 520 } |
302 case IrOpcode::kStateValues: | 521 case IrOpcode::kChangeTaggedToUint32: { |
303 // TODO(jarin): what are the constraints on these? | 522 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32 |
304 break; | 523 // TODO(neis): Activate once ChangeRepresentation works in typer. |
305 case IrOpcode::kCall: | 524 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged()); |
306 // TODO(rossberg): what are the constraints on these? | 525 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32()); |
307 break; | 526 // CheckValueInputIs(node, 0, from)); |
308 | 527 // CheckUpperIs(node, to)); |
309 // JavaScript operators | 528 break; |
310 // -------------------- | 529 } |
311 case IrOpcode::kJSEqual: | 530 case IrOpcode::kChangeTaggedToFloat64: { |
312 case IrOpcode::kJSNotEqual: | 531 // Number /\ Tagged -> Number /\ UntaggedFloat64 |
313 case IrOpcode::kJSStrictEqual: | 532 // TODO(neis): Activate once ChangeRepresentation works in typer. |
314 case IrOpcode::kJSStrictNotEqual: | 533 // Type* from = Type::Intersect(Type::Number(), Type::Tagged()); |
315 case IrOpcode::kJSLessThan: | 534 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64()); |
316 case IrOpcode::kJSGreaterThan: | 535 // CheckValueInputIs(node, 0, from)); |
317 case IrOpcode::kJSLessThanOrEqual: | 536 // CheckUpperIs(node, to)); |
318 case IrOpcode::kJSGreaterThanOrEqual: | 537 break; |
319 case IrOpcode::kJSUnaryNot: | 538 } |
320 // Type is Boolean. | 539 case IrOpcode::kChangeInt32ToTagged: { |
321 CHECK(bounds(node).upper->Is(Type::Boolean())); | 540 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged |
322 break; | 541 // TODO(neis): Activate once ChangeRepresentation works in typer. |
323 | 542 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); |
324 case IrOpcode::kJSBitwiseOr: | 543 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged()); |
325 case IrOpcode::kJSBitwiseXor: | 544 // CheckValueInputIs(node, 0, from)); |
326 case IrOpcode::kJSBitwiseAnd: | 545 // CheckUpperIs(node, to)); |
327 case IrOpcode::kJSShiftLeft: | 546 break; |
328 case IrOpcode::kJSShiftRight: | 547 } |
329 case IrOpcode::kJSShiftRightLogical: | 548 case IrOpcode::kChangeUint32ToTagged: { |
330 // Type is 32 bit integral. | 549 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged |
331 CHECK(bounds(node).upper->Is(Type::Integral32())); | 550 // TODO(neis): Activate once ChangeRepresentation works in typer. |
332 break; | 551 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32()); |
333 case IrOpcode::kJSAdd: | 552 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged()); |
334 // Type is Number or String. | 553 // CheckValueInputIs(node, 0, from)); |
335 CHECK(bounds(node).upper->Is(Type::NumberOrString())); | 554 // CheckUpperIs(node, to)); |
336 break; | 555 break; |
337 case IrOpcode::kJSSubtract: | 556 } |
338 case IrOpcode::kJSMultiply: | 557 case IrOpcode::kChangeFloat64ToTagged: { |
339 case IrOpcode::kJSDivide: | 558 // Number /\ UntaggedFloat64 -> Number /\ Tagged |
340 case IrOpcode::kJSModulus: | 559 // TODO(neis): Activate once ChangeRepresentation works in typer. |
341 // Type is Number. | 560 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64()); |
342 CHECK(bounds(node).upper->Is(Type::Number())); | 561 // Type* to = Type::Intersect(Type::Number(), Type::Tagged()); |
343 break; | 562 // CheckValueInputIs(node, 0, from)); |
344 | 563 // CheckUpperIs(node, to)); |
345 case IrOpcode::kJSToBoolean: | 564 break; |
346 // Type is Boolean. | 565 } |
347 CHECK(bounds(node).upper->Is(Type::Boolean())); | 566 case IrOpcode::kChangeBoolToBit: { |
348 break; | 567 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1 |
349 case IrOpcode::kJSToNumber: | 568 // TODO(neis): Activate once ChangeRepresentation works in typer. |
350 // Type is Number. | 569 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); |
351 CHECK(bounds(node).upper->Is(Type::Number())); | 570 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); |
352 break; | 571 // CheckValueInputIs(node, 0, from)); |
353 case IrOpcode::kJSToString: | 572 // CheckUpperIs(node, to)); |
354 // Type is String. | 573 break; |
355 CHECK(bounds(node).upper->Is(Type::String())); | 574 } |
356 break; | 575 case IrOpcode::kChangeBitToBool: { |
357 case IrOpcode::kJSToName: | 576 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr |
358 // Type is Name. | 577 // TODO(neis): Activate once ChangeRepresentation works in typer. |
359 CHECK(bounds(node).upper->Is(Type::Name())); | 578 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); |
360 break; | 579 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); |
361 case IrOpcode::kJSToObject: | 580 // CheckValueInputIs(node, 0, from)); |
362 // Type is Receiver. | 581 // CheckUpperIs(node, to)); |
363 CHECK(bounds(node).upper->Is(Type::Receiver())); | 582 break; |
364 break; | 583 } |
365 | 584 |
366 case IrOpcode::kJSCreate: | 585 case IrOpcode::kLoadField: |
367 // Type is Object. | 586 // Object -> fieldtype |
368 CHECK(bounds(node).upper->Is(Type::Object())); | 587 // TODO(rossberg): activate once machine ops are typed. |
369 break; | 588 // CheckValueInputIs(node, 0, Type::Object()); |
370 case IrOpcode::kJSLoadProperty: | 589 // CheckUpperIs(node, Field(node).type)); |
371 case IrOpcode::kJSLoadNamed: | 590 break; |
372 // Type can be anything. | 591 case IrOpcode::kLoadElement: |
373 CHECK(bounds(node).upper->Is(Type::Any())); | 592 // Object -> elementtype |
374 break; | 593 // TODO(rossberg): activate once machine ops are typed. |
375 case IrOpcode::kJSStoreProperty: | 594 // CheckValueInputIs(node, 0, Type::Object()); |
376 case IrOpcode::kJSStoreNamed: | 595 // CheckUpperIs(node, Element(node).type)); |
377 // Type is empty. | 596 break; |
378 CHECK(!NodeProperties::IsTyped(node)); | 597 case IrOpcode::kStoreField: |
379 break; | 598 // (Object, fieldtype) -> _|_ |
380 case IrOpcode::kJSDeleteProperty: | 599 // TODO(rossberg): activate once machine ops are typed. |
381 case IrOpcode::kJSHasProperty: | 600 // CheckValueInputIs(node, 0, Type::Object()); |
382 case IrOpcode::kJSInstanceOf: | 601 // CheckValueInputIs(node, 1, Field(node).type)); |
383 // Type is Boolean. | 602 CheckNotTyped(node); |
384 CHECK(bounds(node).upper->Is(Type::Boolean())); | 603 break; |
385 break; | 604 case IrOpcode::kStoreElement: |
386 case IrOpcode::kJSTypeOf: | 605 // (Object, elementtype) -> _|_ |
387 // Type is String. | 606 // TODO(rossberg): activate once machine ops are typed. |
388 CHECK(bounds(node).upper->Is(Type::String())); | 607 // CheckValueInputIs(node, 0, Type::Object()); |
389 break; | 608 // CheckValueInputIs(node, 1, Element(node).type)); |
390 | 609 CheckNotTyped(node); |
391 case IrOpcode::kJSLoadContext: | 610 break; |
392 // Type can be anything. | 611 |
393 CHECK(bounds(node).upper->Is(Type::Any())); | 612 // Machine operators |
394 break; | 613 // ----------------------- |
395 case IrOpcode::kJSStoreContext: | 614 case IrOpcode::kLoad: |
396 // Type is empty. | 615 case IrOpcode::kStore: |
397 CHECK(!NodeProperties::IsTyped(node)); | 616 case IrOpcode::kWord32And: |
398 break; | 617 case IrOpcode::kWord32Or: |
399 case IrOpcode::kJSCreateFunctionContext: | 618 case IrOpcode::kWord32Xor: |
400 case IrOpcode::kJSCreateCatchContext: | 619 case IrOpcode::kWord32Shl: |
401 case IrOpcode::kJSCreateWithContext: | 620 case IrOpcode::kWord32Shr: |
402 case IrOpcode::kJSCreateBlockContext: | 621 case IrOpcode::kWord32Sar: |
403 case IrOpcode::kJSCreateModuleContext: | 622 case IrOpcode::kWord32Ror: |
404 case IrOpcode::kJSCreateGlobalContext: { | 623 case IrOpcode::kWord32Equal: |
405 // Type is Context, and operand is Internal. | 624 case IrOpcode::kWord64And: |
406 Bounds outer = bounds(NodeProperties::GetContextInput(node)); | 625 case IrOpcode::kWord64Or: |
407 // TODO(rossberg): This should really be Is(Internal), but the typer | 626 case IrOpcode::kWord64Xor: |
408 // currently can't do backwards propagation. | 627 case IrOpcode::kWord64Shl: |
409 CHECK(outer.upper->Maybe(Type::Internal())); | 628 case IrOpcode::kWord64Shr: |
410 CHECK(bounds(node).upper->IsContext()); | 629 case IrOpcode::kWord64Sar: |
411 break; | 630 case IrOpcode::kWord64Ror: |
412 } | 631 case IrOpcode::kWord64Equal: |
413 | 632 case IrOpcode::kInt32Add: |
414 case IrOpcode::kJSCallConstruct: | 633 case IrOpcode::kInt32AddWithOverflow: |
415 // Type is Receiver. | 634 case IrOpcode::kInt32Sub: |
416 CHECK(bounds(node).upper->Is(Type::Receiver())); | 635 case IrOpcode::kInt32SubWithOverflow: |
417 break; | 636 case IrOpcode::kInt32Mul: |
418 case IrOpcode::kJSCallFunction: | 637 case IrOpcode::kInt32MulHigh: |
419 case IrOpcode::kJSCallRuntime: | 638 case IrOpcode::kInt32Div: |
420 case IrOpcode::kJSYield: | 639 case IrOpcode::kInt32Mod: |
421 case IrOpcode::kJSDebugger: | 640 case IrOpcode::kInt32LessThan: |
422 // Type can be anything. | 641 case IrOpcode::kInt32LessThanOrEqual: |
423 CHECK(bounds(node).upper->Is(Type::Any())); | 642 case IrOpcode::kUint32Div: |
424 break; | 643 case IrOpcode::kUint32Mod: |
425 | 644 case IrOpcode::kUint32LessThan: |
426 // Simplified operators | 645 case IrOpcode::kUint32LessThanOrEqual: |
427 // ------------------------------- | 646 case IrOpcode::kInt64Add: |
428 case IrOpcode::kBooleanNot: | 647 case IrOpcode::kInt64Sub: |
429 // Boolean -> Boolean | 648 case IrOpcode::kInt64Mul: |
430 CHECK(bounds(Operand(node)).upper->Is(Type::Boolean())); | 649 case IrOpcode::kInt64Div: |
431 CHECK(bounds(node).upper->Is(Type::Boolean())); | 650 case IrOpcode::kInt64Mod: |
432 break; | 651 case IrOpcode::kInt64LessThan: |
433 case IrOpcode::kBooleanToNumber: | 652 case IrOpcode::kInt64LessThanOrEqual: |
434 // Boolean -> Number | 653 case IrOpcode::kUint64Div: |
435 CHECK(bounds(Operand(node)).upper->Is(Type::Boolean())); | 654 case IrOpcode::kUint64Mod: |
436 CHECK(bounds(node).upper->Is(Type::Number())); | 655 case IrOpcode::kUint64LessThan: |
437 break; | 656 case IrOpcode::kFloat64Add: |
438 case IrOpcode::kNumberEqual: | 657 case IrOpcode::kFloat64Sub: |
439 case IrOpcode::kNumberLessThan: | 658 case IrOpcode::kFloat64Mul: |
440 case IrOpcode::kNumberLessThanOrEqual: | 659 case IrOpcode::kFloat64Div: |
441 // (Number, Number) -> Boolean | 660 case IrOpcode::kFloat64Mod: |
442 CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number())); | 661 case IrOpcode::kFloat64Sqrt: |
443 CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number())); | 662 case IrOpcode::kFloat64Equal: |
444 CHECK(bounds(node).upper->Is(Type::Boolean())); | 663 case IrOpcode::kFloat64LessThan: |
445 break; | 664 case IrOpcode::kFloat64LessThanOrEqual: |
446 case IrOpcode::kNumberAdd: | 665 case IrOpcode::kTruncateInt64ToInt32: |
447 case IrOpcode::kNumberSubtract: | 666 case IrOpcode::kTruncateFloat64ToFloat32: |
448 case IrOpcode::kNumberMultiply: | 667 case IrOpcode::kTruncateFloat64ToInt32: |
449 case IrOpcode::kNumberDivide: | 668 case IrOpcode::kChangeInt32ToInt64: |
450 case IrOpcode::kNumberModulus: | 669 case IrOpcode::kChangeUint32ToUint64: |
451 // (Number, Number) -> Number | 670 case IrOpcode::kChangeInt32ToFloat64: |
452 CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number())); | 671 case IrOpcode::kChangeUint32ToFloat64: |
453 CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number())); | 672 case IrOpcode::kChangeFloat32ToFloat64: |
454 // TODO(rossberg): activate once we retype after opcode changes. | 673 case IrOpcode::kChangeFloat64ToInt32: |
455 // CHECK(bounds(node).upper->Is(Type::Number())); | 674 case IrOpcode::kChangeFloat64ToUint32: |
456 break; | 675 case IrOpcode::kLoadStackPointer: |
457 case IrOpcode::kNumberToInt32: | 676 // TODO(rossberg): Check. |
458 // Number -> Signed32 | 677 break; |
459 CHECK(bounds(Operand(node)).upper->Is(Type::Number())); | |
460 CHECK(bounds(node).upper->Is(Type::Signed32())); | |
461 break; | |
462 case IrOpcode::kNumberToUint32: | |
463 // Number -> Unsigned32 | |
464 CHECK(bounds(Operand(node)).upper->Is(Type::Number())); | |
465 CHECK(bounds(node).upper->Is(Type::Unsigned32())); | |
466 break; | |
467 case IrOpcode::kStringEqual: | |
468 case IrOpcode::kStringLessThan: | |
469 case IrOpcode::kStringLessThanOrEqual: | |
470 // (String, String) -> Boolean | |
471 CHECK(bounds(Operand(node, 0)).upper->Is(Type::String())); | |
472 CHECK(bounds(Operand(node, 1)).upper->Is(Type::String())); | |
473 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
474 break; | |
475 case IrOpcode::kStringAdd: | |
476 // (String, String) -> String | |
477 CHECK(bounds(Operand(node, 0)).upper->Is(Type::String())); | |
478 CHECK(bounds(Operand(node, 1)).upper->Is(Type::String())); | |
479 CHECK(bounds(node).upper->Is(Type::String())); | |
480 break; | |
481 case IrOpcode::kReferenceEqual: { | |
482 // (Unique, Any) -> Boolean and | |
483 // (Any, Unique) -> Boolean | |
484 CHECK(bounds(Operand(node, 0)).upper->Is(Type::Unique()) || | |
485 bounds(Operand(node, 1)).upper->Is(Type::Unique())); | |
486 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
487 break; | |
488 } | |
489 case IrOpcode::kObjectIsSmi: | |
490 CHECK(bounds(Operand(node)).upper->Is(Type::Any())); | |
491 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
492 break; | |
493 case IrOpcode::kObjectIsNonNegativeSmi: | |
494 CHECK(bounds(Operand(node)).upper->Is(Type::Any())); | |
495 CHECK(bounds(node).upper->Is(Type::Boolean())); | |
496 break; | |
497 | |
498 case IrOpcode::kChangeTaggedToInt32: { | |
499 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32 | |
500 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
501 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged()); | |
502 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); | |
503 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
504 // CHECK(bounds(node).upper->Is(to)); | |
505 break; | |
506 } | |
507 case IrOpcode::kChangeTaggedToUint32: { | |
508 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32 | |
509 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
510 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged()); | |
511 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32()); | |
512 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
513 // CHECK(bounds(node).upper->Is(to)); | |
514 break; | |
515 } | |
516 case IrOpcode::kChangeTaggedToFloat64: { | |
517 // Number /\ Tagged -> Number /\ UntaggedFloat64 | |
518 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
519 // Type* from = Type::Intersect(Type::Number(), Type::Tagged()); | |
520 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64()); | |
521 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
522 // CHECK(bounds(node).upper->Is(to)); | |
523 break; | |
524 } | |
525 case IrOpcode::kChangeInt32ToTagged: { | |
526 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged | |
527 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
528 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32()); | |
529 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged()); | |
530 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
531 // CHECK(bounds(node).upper->Is(to)); | |
532 break; | |
533 } | |
534 case IrOpcode::kChangeUint32ToTagged: { | |
535 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged | |
536 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
537 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32()); | |
538 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged()); | |
539 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
540 // CHECK(bounds(node).upper->Is(to)); | |
541 break; | |
542 } | |
543 case IrOpcode::kChangeFloat64ToTagged: { | |
544 // Number /\ UntaggedFloat64 -> Number /\ Tagged | |
545 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
546 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64()); | |
547 // Type* to = Type::Intersect(Type::Number(), Type::Tagged()); | |
548 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
549 // CHECK(bounds(node).upper->Is(to)); | |
550 break; | |
551 } | |
552 case IrOpcode::kChangeBoolToBit: { | |
553 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1 | |
554 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
555 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); | |
556 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); | |
557 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
558 // CHECK(bounds(node).upper->Is(to)); | |
559 break; | |
560 } | |
561 case IrOpcode::kChangeBitToBool: { | |
562 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr | |
563 // TODO(neis): Activate once ChangeRepresentation works in typer. | |
564 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1()); | |
565 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr()); | |
566 // CHECK(bounds(Operand(node)).upper->Is(from)); | |
567 // CHECK(bounds(node).upper->Is(to)); | |
568 break; | |
569 } | |
570 | |
571 case IrOpcode::kLoadField: | |
572 // Object -> fieldtype | |
573 // TODO(rossberg): activate once machine ops are typed. | |
574 // CHECK(bounds(Operand(node)).upper->Is(Type::Object())); | |
575 // CHECK(bounds(node).upper->Is(Field(node).type)); | |
576 break; | |
577 case IrOpcode::kLoadElement: | |
578 // Object -> elementtype | |
579 // TODO(rossberg): activate once machine ops are typed. | |
580 // CHECK(bounds(Operand(node)).upper->Is(Type::Object())); | |
581 // CHECK(bounds(node).upper->Is(Element(node).type)); | |
582 break; | |
583 case IrOpcode::kStoreField: | |
584 // (Object, fieldtype) -> _|_ | |
585 // TODO(rossberg): activate once machine ops are typed. | |
586 // CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object())); | |
587 // CHECK(bounds(Operand(node, 1)).upper->Is(Field(node).type)); | |
588 CHECK(!NodeProperties::IsTyped(node)); | |
589 break; | |
590 case IrOpcode::kStoreElement: | |
591 // (Object, elementtype) -> _|_ | |
592 // TODO(rossberg): activate once machine ops are typed. | |
593 // CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object())); | |
594 // CHECK(bounds(Operand(node, 1)).upper->Is(Element(node).type)); | |
595 CHECK(!NodeProperties::IsTyped(node)); | |
596 break; | |
597 | |
598 // Machine operators | |
599 // ----------------------- | |
600 case IrOpcode::kLoad: | |
601 case IrOpcode::kStore: | |
602 case IrOpcode::kWord32And: | |
603 case IrOpcode::kWord32Or: | |
604 case IrOpcode::kWord32Xor: | |
605 case IrOpcode::kWord32Shl: | |
606 case IrOpcode::kWord32Shr: | |
607 case IrOpcode::kWord32Sar: | |
608 case IrOpcode::kWord32Ror: | |
609 case IrOpcode::kWord32Equal: | |
610 case IrOpcode::kWord64And: | |
611 case IrOpcode::kWord64Or: | |
612 case IrOpcode::kWord64Xor: | |
613 case IrOpcode::kWord64Shl: | |
614 case IrOpcode::kWord64Shr: | |
615 case IrOpcode::kWord64Sar: | |
616 case IrOpcode::kWord64Ror: | |
617 case IrOpcode::kWord64Equal: | |
618 case IrOpcode::kInt32Add: | |
619 case IrOpcode::kInt32AddWithOverflow: | |
620 case IrOpcode::kInt32Sub: | |
621 case IrOpcode::kInt32SubWithOverflow: | |
622 case IrOpcode::kInt32Mul: | |
623 case IrOpcode::kInt32MulHigh: | |
624 case IrOpcode::kInt32Div: | |
625 case IrOpcode::kInt32Mod: | |
626 case IrOpcode::kInt32LessThan: | |
627 case IrOpcode::kInt32LessThanOrEqual: | |
628 case IrOpcode::kUint32Div: | |
629 case IrOpcode::kUint32Mod: | |
630 case IrOpcode::kUint32LessThan: | |
631 case IrOpcode::kUint32LessThanOrEqual: | |
632 case IrOpcode::kInt64Add: | |
633 case IrOpcode::kInt64Sub: | |
634 case IrOpcode::kInt64Mul: | |
635 case IrOpcode::kInt64Div: | |
636 case IrOpcode::kInt64Mod: | |
637 case IrOpcode::kInt64LessThan: | |
638 case IrOpcode::kInt64LessThanOrEqual: | |
639 case IrOpcode::kUint64Div: | |
640 case IrOpcode::kUint64Mod: | |
641 case IrOpcode::kUint64LessThan: | |
642 case IrOpcode::kFloat64Add: | |
643 case IrOpcode::kFloat64Sub: | |
644 case IrOpcode::kFloat64Mul: | |
645 case IrOpcode::kFloat64Div: | |
646 case IrOpcode::kFloat64Mod: | |
647 case IrOpcode::kFloat64Sqrt: | |
648 case IrOpcode::kFloat64Equal: | |
649 case IrOpcode::kFloat64LessThan: | |
650 case IrOpcode::kFloat64LessThanOrEqual: | |
651 case IrOpcode::kTruncateInt64ToInt32: | |
652 case IrOpcode::kTruncateFloat64ToFloat32: | |
653 case IrOpcode::kTruncateFloat64ToInt32: | |
654 case IrOpcode::kChangeInt32ToInt64: | |
655 case IrOpcode::kChangeUint32ToUint64: | |
656 case IrOpcode::kChangeInt32ToFloat64: | |
657 case IrOpcode::kChangeUint32ToFloat64: | |
658 case IrOpcode::kChangeFloat32ToFloat64: | |
659 case IrOpcode::kChangeFloat64ToInt32: | |
660 case IrOpcode::kChangeFloat64ToUint32: | |
661 case IrOpcode::kLoadStackPointer: | |
662 // TODO(rossberg): Check. | |
663 break; | |
664 } | |
665 } | 678 } |
666 | 679 |
667 return GenericGraphVisit::CONTINUE; | 680 return GenericGraphVisit::CONTINUE; |
668 } | 681 } |
669 | 682 |
670 | 683 |
671 void Verifier::Run(Graph* graph, Typing typing) { | 684 void Verifier::Run(Graph* graph, Typing typing) { |
672 Visitor visitor(graph->zone(), typing); | 685 Visitor visitor(graph->zone(), typing); |
673 CHECK_NE(NULL, graph->start()); | 686 CHECK_NE(NULL, graph->start()); |
674 CHECK_NE(NULL, graph->end()); | 687 CHECK_NE(NULL, graph->end()); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 // Check inputs for all nodes in the block. | 923 // Check inputs for all nodes in the block. |
911 for (size_t i = 0; i < block->NodeCount(); i++) { | 924 for (size_t i = 0; i < block->NodeCount(); i++) { |
912 Node* node = block->NodeAt(i); | 925 Node* node = block->NodeAt(i); |
913 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); | 926 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); |
914 } | 927 } |
915 } | 928 } |
916 } | 929 } |
917 } | 930 } |
918 } | 931 } |
919 } // namespace v8::internal::compiler | 932 } // namespace v8::internal::compiler |
OLD | NEW |