blob: 99480ca2ede64fca7f7b4ba853d69c498d7df879 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#include "src/compiler/verifier.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include <algorithm>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include <deque>
9#include <queue>
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010#include <sstream>
11#include <string>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013#include "src/bit-vector.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/compiler/all-nodes.h"
15#include "src/compiler/common-operator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/compiler/graph.h"
17#include "src/compiler/node.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/compiler/node-properties.h"
19#include "src/compiler/opcodes.h"
20#include "src/compiler/operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022#include "src/compiler/schedule.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023#include "src/compiler/simplified-operator.h"
24#include "src/ostreams.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025
26namespace v8 {
27namespace internal {
28namespace compiler {
29
30
31static bool IsDefUseChainLinkPresent(Node* def, Node* use) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 auto const uses = def->uses();
33 return std::find(uses.begin(), uses.end(), use) != uses.end();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034}
35
36
37static bool IsUseDefChainLinkPresent(Node* def, Node* use) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 auto const inputs = use->inputs();
39 return std::find(inputs.begin(), inputs.end(), def) != inputs.end();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040}
41
42
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043class Verifier::Visitor {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040045 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 void Check(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048
Emily Bernierd0a1eb72015-03-24 16:35:39 -040049 Zone* zone;
50 Typing typing;
51
52 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053 void CheckNotTyped(Node* node) {
54 if (NodeProperties::IsTyped(node)) {
55 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 str << "TypeError: node #" << node->id() << ":" << *node->op()
57 << " should never have a type";
58 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040059 }
60 }
61 void CheckUpperIs(Node* node, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 if (typing == TYPED && !NodeProperties::GetType(node)->Is(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 str << "TypeError: node #" << node->id() << ":" << *node->op()
65 << " type ";
66 NodeProperties::GetType(node)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067 str << " is not ";
68 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040070 }
71 }
72 void CheckUpperMaybe(Node* node, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 if (typing == TYPED && !NodeProperties::GetType(node)->Maybe(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 str << "TypeError: node #" << node->id() << ":" << *node->op()
76 << " type ";
77 NodeProperties::GetType(node)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040078 str << " must intersect ";
79 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040081 }
82 }
83 void CheckValueInputIs(Node* node, int i, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 Node* input = NodeProperties::GetValueInput(node, i);
85 if (typing == TYPED && !NodeProperties::GetType(input)->Is(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 str << "TypeError: node #" << node->id() << ":" << *node->op()
88 << "(input @" << i << " = " << input->opcode() << ":"
89 << input->op()->mnemonic() << ") type ";
90 NodeProperties::GetType(input)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091 str << " is not ";
92 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 FATAL(str.str().c_str());
94 }
95 }
96 void CheckOutput(Node* node, Node* use, int count, const char* kind) {
97 if (count <= 0) {
98 std::ostringstream str;
99 str << "GraphError: node #" << node->id() << ":" << *node->op()
100 << " does not produce " << kind << " output used by node #"
101 << use->id() << ":" << *use->op();
102 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400103 }
104 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105};
106
107
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108void Verifier::Visitor::Check(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400109 int value_count = node->op()->ValueInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110 int context_count = OperatorProperties::GetContextInputCount(node->op());
111 int frame_state_count =
112 OperatorProperties::GetFrameStateInputCount(node->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400113 int effect_count = node->op()->EffectInputCount();
114 int control_count = node->op()->ControlInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115
116 // Verify number of inputs matches up.
117 int input_count = value_count + context_count + frame_state_count +
118 effect_count + control_count;
119 CHECK_EQ(input_count, node->InputCount());
120
121 // Verify that frame state has been inserted for the nodes that need it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 for (int i = 0; i < frame_state_count; i++) {
123 Node* frame_state = NodeProperties::GetFrameStateInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124 CHECK(frame_state->opcode() == IrOpcode::kFrameState ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 // kFrameState uses Start as a sentinel.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 (node->opcode() == IrOpcode::kFrameState &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 frame_state->opcode() == IrOpcode::kStart));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 CHECK(IsDefUseChainLinkPresent(frame_state, node));
129 CHECK(IsUseDefChainLinkPresent(frame_state, node));
130 }
131
132 // Verify all value inputs actually produce a value.
133 for (int i = 0; i < value_count; ++i) {
134 Node* value = NodeProperties::GetValueInput(node, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 CheckOutput(value, node, value->op()->ValueOutputCount(), "value");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 CHECK(IsDefUseChainLinkPresent(value, node));
137 CHECK(IsUseDefChainLinkPresent(value, node));
138 }
139
140 // Verify all context inputs are value nodes.
141 for (int i = 0; i < context_count; ++i) {
142 Node* context = NodeProperties::GetContextInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 CheckOutput(context, node, context->op()->ValueOutputCount(), "context");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 CHECK(IsDefUseChainLinkPresent(context, node));
145 CHECK(IsUseDefChainLinkPresent(context, node));
146 }
147
148 // Verify all effect inputs actually have an effect.
149 for (int i = 0; i < effect_count; ++i) {
150 Node* effect = NodeProperties::GetEffectInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152 CHECK(IsDefUseChainLinkPresent(effect, node));
153 CHECK(IsUseDefChainLinkPresent(effect, node));
154 }
155
156 // Verify all control inputs are control nodes.
157 for (int i = 0; i < control_count; ++i) {
158 Node* control = NodeProperties::GetControlInput(node, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159 CheckOutput(control, node, control->op()->ControlOutputCount(), "control");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000160 CHECK(IsDefUseChainLinkPresent(control, node));
161 CHECK(IsUseDefChainLinkPresent(control, node));
162 }
163
164 // Verify all successors are projections if multiple value outputs exist.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 if (node->op()->ValueOutputCount() > 1) {
166 for (Edge edge : node->use_edges()) {
167 Node* use = edge.from();
168 CHECK(!NodeProperties::IsValueEdge(edge) ||
169 use->opcode() == IrOpcode::kProjection ||
170 use->opcode() == IrOpcode::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 }
172 }
173
174 switch (node->opcode()) {
175 case IrOpcode::kStart:
176 // Start has no inputs.
177 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178 // Type is a tuple.
179 // TODO(rossberg): Multiple outputs are currently typed as Internal.
180 CheckUpperIs(node, Type::Internal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 break;
182 case IrOpcode::kEnd:
183 // End has no outputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400184 CHECK(node->op()->ValueOutputCount() == 0);
185 CHECK(node->op()->EffectOutputCount() == 0);
186 CHECK(node->op()->ControlOutputCount() == 0);
187 // Type is empty.
188 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 break;
190 case IrOpcode::kDead:
191 // Dead is never connected to the graph.
192 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 case IrOpcode::kBranch: {
195 // Branch uses are IfTrue and IfFalse.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 int count_true = 0, count_false = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 for (auto use : node->uses()) {
198 CHECK(use->opcode() == IrOpcode::kIfTrue ||
199 use->opcode() == IrOpcode::kIfFalse);
200 if (use->opcode() == IrOpcode::kIfTrue) ++count_true;
201 if (use->opcode() == IrOpcode::kIfFalse) ++count_false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 CHECK_EQ(1, count_true);
204 CHECK_EQ(1, count_false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400205 // Type is empty.
206 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 break;
208 }
209 case IrOpcode::kIfTrue:
210 case IrOpcode::kIfFalse:
211 CHECK_EQ(IrOpcode::kBranch,
212 NodeProperties::GetControlInput(node, 0)->opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 // Type is empty.
214 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 case IrOpcode::kIfSuccess: {
217 // IfSuccess and IfException continuation only on throwing nodes.
218 Node* input = NodeProperties::GetControlInput(node, 0);
219 CHECK(!input->op()->HasProperty(Operator::kNoThrow));
220 // Type is empty.
221 CheckNotTyped(node);
222 break;
223 }
224 case IrOpcode::kIfException: {
225 // IfSuccess and IfException continuation only on throwing nodes.
226 Node* input = NodeProperties::GetControlInput(node, 0);
227 CHECK(!input->op()->HasProperty(Operator::kNoThrow));
228 // Type can be anything.
229 CheckUpperIs(node, Type::Any());
230 break;
231 }
232 case IrOpcode::kSwitch: {
233 // Switch uses are Case and Default.
234 int count_case = 0, count_default = 0;
235 for (auto use : node->uses()) {
236 switch (use->opcode()) {
237 case IrOpcode::kIfValue: {
238 for (auto user : node->uses()) {
239 if (user != use && user->opcode() == IrOpcode::kIfValue) {
240 CHECK_NE(OpParameter<int32_t>(use->op()),
241 OpParameter<int32_t>(user->op()));
242 }
243 }
244 ++count_case;
245 break;
246 }
247 case IrOpcode::kIfDefault: {
248 ++count_default;
249 break;
250 }
251 default: {
252 V8_Fatal(__FILE__, __LINE__, "Switch #%d illegally used by #%d:%s",
253 node->id(), use->id(), use->op()->mnemonic());
254 break;
255 }
256 }
257 }
258 CHECK_EQ(1, count_default);
259 CHECK_EQ(node->op()->ControlOutputCount(), count_case + count_default);
260 // Type is empty.
261 CheckNotTyped(node);
262 break;
263 }
264 case IrOpcode::kIfValue:
265 case IrOpcode::kIfDefault:
266 CHECK_EQ(IrOpcode::kSwitch,
267 NodeProperties::GetControlInput(node)->opcode());
268 // Type is empty.
269 CheckNotTyped(node);
270 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 case IrOpcode::kLoop:
272 case IrOpcode::kMerge:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400273 CHECK_EQ(control_count, input_count);
274 // Type is empty.
275 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 case IrOpcode::kDeoptimize:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 case IrOpcode::kReturn:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 case IrOpcode::kThrow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 // Deoptimize, Return and Throw uses are End.
281 for (auto use : node->uses()) {
282 CHECK_EQ(IrOpcode::kEnd, use->opcode());
283 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400284 // Type is empty.
285 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400287 case IrOpcode::kTerminate:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 // Terminates take one loop and effect.
289 CHECK_EQ(1, control_count);
290 CHECK_EQ(1, effect_count);
291 CHECK_EQ(2, input_count);
292 CHECK_EQ(IrOpcode::kLoop,
293 NodeProperties::GetControlInput(node)->opcode());
294 // Terminate uses are End.
295 for (auto use : node->uses()) {
296 CHECK_EQ(IrOpcode::kEnd, use->opcode());
297 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400298 // Type is empty.
299 CheckNotTyped(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300 break;
301 case IrOpcode::kOsrNormalEntry:
302 case IrOpcode::kOsrLoopEntry:
303 // Osr entries take one control and effect.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304 CHECK_EQ(1, control_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 CHECK_EQ(1, effect_count);
306 CHECK_EQ(2, input_count);
307 // Type is empty.
308 CheckNotTyped(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400309 break;
310
311 // Common operators
312 // ----------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000313 case IrOpcode::kParameter: {
314 // Parameters have the start node as inputs.
315 CHECK_EQ(1, input_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316 // Parameter has an input that produces enough values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 int const index = ParameterIndexOf(node->op());
318 Node* const start = NodeProperties::GetValueInput(node, 0);
319 CHECK_EQ(IrOpcode::kStart, start->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 // Currently, parameter indices start at -1 instead of 0.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 CHECK_LE(-1, index);
322 CHECK_LT(index + 1, start->op()->ValueOutputCount());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400323 // Type can be anything.
324 CheckUpperIs(node, Type::Any());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 break;
326 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400327 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
328 // Constants have no inputs.
329 CHECK_EQ(0, input_count);
330 // Type is a 32 bit integer, signed or unsigned.
331 CheckUpperIs(node, Type::Integral32());
332 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 case IrOpcode::kInt64Constant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400334 // Constants have no inputs.
335 CHECK_EQ(0, input_count);
336 // Type is internal.
337 // TODO(rossberg): Introduce proper Int64 type.
338 CheckUpperIs(node, Type::Internal());
339 break;
340 case IrOpcode::kFloat32Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 case IrOpcode::kFloat64Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 case IrOpcode::kNumberConstant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400343 // Constants have no inputs.
344 CHECK_EQ(0, input_count);
345 // Type is a number.
346 CheckUpperIs(node, Type::Number());
347 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 case IrOpcode::kHeapConstant:
349 // Constants have no inputs.
350 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400351 // Type can be anything represented as a heap pointer.
352 CheckUpperIs(node, Type::TaggedPointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400354 case IrOpcode::kExternalConstant:
355 // Constants have no inputs.
356 CHECK_EQ(0, input_count);
357 // Type is considered internal.
358 CheckUpperIs(node, Type::Internal());
359 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 case IrOpcode::kOsrValue:
361 // OSR values have a value and a control input.
362 CHECK_EQ(1, control_count);
363 CHECK_EQ(1, input_count);
364 // Type is merged from other values in the graph and could be any.
365 CheckUpperIs(node, Type::Any());
366 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400367 case IrOpcode::kProjection: {
368 // Projection has an input that produces enough values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369 int index = static_cast<int>(ProjectionIndexOf(node->op()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400370 Node* input = NodeProperties::GetValueInput(node, 0);
371 CHECK_GT(input->op()->ValueOutputCount(), index);
372 // Type can be anything.
373 // TODO(rossberg): Introduce tuple types for this.
374 // TODO(titzer): Convince rossberg not to.
375 CheckUpperIs(node, Type::Any());
376 break;
377 }
378 case IrOpcode::kSelect: {
379 CHECK_EQ(0, effect_count);
380 CHECK_EQ(0, control_count);
381 CHECK_EQ(3, value_count);
382 break;
383 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384 case IrOpcode::kPhi: {
385 // Phi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400386 CHECK_EQ(0, effect_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387 CHECK_EQ(1, control_count);
388 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400389 CHECK_EQ(value_count, control->op()->ControlInputCount());
390 CHECK_EQ(input_count, 1 + value_count);
391 // Type must be subsumed by all input types.
392 // TODO(rossberg): for now at least, narrowing does not really hold.
393 /*
394 for (int i = 0; i < value_count; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395 CHECK(type_of(ValueInput(node, i))->Is(type_of(node)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400396 }
397 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 break;
399 }
400 case IrOpcode::kEffectPhi: {
401 // EffectPhi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400402 CHECK_EQ(0, value_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000403 CHECK_EQ(1, control_count);
404 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400405 CHECK_EQ(effect_count, control->op()->ControlInputCount());
406 CHECK_EQ(input_count, 1 + effect_count);
407 break;
408 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409 case IrOpcode::kEffectSet: {
410 CHECK_EQ(0, value_count);
411 CHECK_EQ(0, control_count);
412 CHECK_LT(1, effect_count);
413 break;
414 }
415 case IrOpcode::kGuard:
416 // TODO(bmeurer): what are the constraints on these?
417 break;
418 case IrOpcode::kBeginRegion:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400419 // TODO(rossberg): what are the constraints on these?
420 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 case IrOpcode::kFinishRegion: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400422 // TODO(rossberg): what are the constraints on these?
423 // Type must be subsumed by input type.
424 if (typing == TYPED) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 Node* val = NodeProperties::GetValueInput(node, 0);
426 CHECK(NodeProperties::GetType(val)->Is(NodeProperties::GetType(node)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400427 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000428 break;
429 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100430 case IrOpcode::kFrameState: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 // TODO(jarin): what are the constraints on these?
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432 CHECK_EQ(5, value_count);
433 CHECK_EQ(0, control_count);
434 CHECK_EQ(0, effect_count);
435 CHECK_EQ(6, input_count);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100436 for (int i = 0; i < 3; ++i) {
437 CHECK(NodeProperties::GetValueInput(node, i)->opcode() ==
438 IrOpcode::kStateValues ||
439 NodeProperties::GetValueInput(node, i)->opcode() ==
440 IrOpcode::kTypedStateValues);
441 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100443 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400444 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 case IrOpcode::kObjectState:
446 case IrOpcode::kTypedStateValues:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400447 // TODO(jarin): what are the constraints on these?
448 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449 case IrOpcode::kCall:
450 // TODO(rossberg): what are the constraints on these?
451 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 case IrOpcode::kTailCall:
453 // TODO(bmeurer): what are the constraints on these?
454 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400455
456 // JavaScript operators
457 // --------------------
458 case IrOpcode::kJSEqual:
459 case IrOpcode::kJSNotEqual:
460 case IrOpcode::kJSStrictEqual:
461 case IrOpcode::kJSStrictNotEqual:
462 case IrOpcode::kJSLessThan:
463 case IrOpcode::kJSGreaterThan:
464 case IrOpcode::kJSLessThanOrEqual:
465 case IrOpcode::kJSGreaterThanOrEqual:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400466 // Type is Boolean.
467 CheckUpperIs(node, Type::Boolean());
468 break;
469
470 case IrOpcode::kJSBitwiseOr:
471 case IrOpcode::kJSBitwiseXor:
472 case IrOpcode::kJSBitwiseAnd:
473 case IrOpcode::kJSShiftLeft:
474 case IrOpcode::kJSShiftRight:
475 case IrOpcode::kJSShiftRightLogical:
476 // Type is 32 bit integral.
477 CheckUpperIs(node, Type::Integral32());
478 break;
479 case IrOpcode::kJSAdd:
480 // Type is Number or String.
481 CheckUpperIs(node, Type::NumberOrString());
482 break;
483 case IrOpcode::kJSSubtract:
484 case IrOpcode::kJSMultiply:
485 case IrOpcode::kJSDivide:
486 case IrOpcode::kJSModulus:
487 // Type is Number.
488 CheckUpperIs(node, Type::Number());
489 break;
490
491 case IrOpcode::kJSToBoolean:
492 // Type is Boolean.
493 CheckUpperIs(node, Type::Boolean());
494 break;
495 case IrOpcode::kJSToNumber:
496 // Type is Number.
497 CheckUpperIs(node, Type::Number());
498 break;
499 case IrOpcode::kJSToString:
500 // Type is String.
501 CheckUpperIs(node, Type::String());
502 break;
503 case IrOpcode::kJSToName:
504 // Type is Name.
505 CheckUpperIs(node, Type::Name());
506 break;
507 case IrOpcode::kJSToObject:
508 // Type is Receiver.
509 CheckUpperIs(node, Type::Receiver());
510 break;
511
512 case IrOpcode::kJSCreate:
513 // Type is Object.
514 CheckUpperIs(node, Type::Object());
515 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516 case IrOpcode::kJSCreateArguments:
517 // Type is OtherObject.
518 CheckUpperIs(node, Type::OtherObject());
519 break;
520 case IrOpcode::kJSCreateArray:
521 // Type is OtherObject.
522 CheckUpperIs(node, Type::OtherObject());
523 break;
524 case IrOpcode::kJSCreateClosure:
525 // Type is Function.
526 CheckUpperIs(node, Type::Function());
527 break;
528 case IrOpcode::kJSCreateIterResultObject:
529 // Type is OtherObject.
530 CheckUpperIs(node, Type::OtherObject());
531 break;
532 case IrOpcode::kJSCreateLiteralArray:
533 case IrOpcode::kJSCreateLiteralObject:
534 case IrOpcode::kJSCreateLiteralRegExp:
535 // Type is OtherObject.
536 CheckUpperIs(node, Type::OtherObject());
537 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400538 case IrOpcode::kJSLoadProperty:
539 case IrOpcode::kJSLoadNamed:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 case IrOpcode::kJSLoadGlobal:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400541 // Type can be anything.
542 CheckUpperIs(node, Type::Any());
543 break;
544 case IrOpcode::kJSStoreProperty:
545 case IrOpcode::kJSStoreNamed:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546 case IrOpcode::kJSStoreGlobal:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400547 // Type is empty.
548 CheckNotTyped(node);
549 break;
550 case IrOpcode::kJSDeleteProperty:
551 case IrOpcode::kJSHasProperty:
552 case IrOpcode::kJSInstanceOf:
553 // Type is Boolean.
554 CheckUpperIs(node, Type::Boolean());
555 break;
556 case IrOpcode::kJSTypeOf:
557 // Type is String.
558 CheckUpperIs(node, Type::String());
559 break;
560
561 case IrOpcode::kJSLoadContext:
562 // Type can be anything.
563 CheckUpperIs(node, Type::Any());
564 break;
565 case IrOpcode::kJSStoreContext:
566 // Type is empty.
567 CheckNotTyped(node);
568 break;
569 case IrOpcode::kJSCreateFunctionContext:
570 case IrOpcode::kJSCreateCatchContext:
571 case IrOpcode::kJSCreateWithContext:
572 case IrOpcode::kJSCreateBlockContext:
573 case IrOpcode::kJSCreateModuleContext:
574 case IrOpcode::kJSCreateScriptContext: {
575 // Type is Context, and operand is Internal.
576 Node* context = NodeProperties::GetContextInput(node);
577 // TODO(rossberg): This should really be Is(Internal), but the typer
578 // currently can't do backwards propagation.
579 CheckUpperMaybe(context, Type::Internal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 if (typing == TYPED) CHECK(NodeProperties::GetType(node)->IsContext());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581 break;
582 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400583
584 case IrOpcode::kJSCallConstruct:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 case IrOpcode::kJSConvertReceiver:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400586 // Type is Receiver.
587 CheckUpperIs(node, Type::Receiver());
588 break;
589 case IrOpcode::kJSCallFunction:
590 case IrOpcode::kJSCallRuntime:
591 case IrOpcode::kJSYield:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400592 // Type can be anything.
593 CheckUpperIs(node, Type::Any());
594 break;
595
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 case IrOpcode::kJSForInPrepare: {
597 // TODO(bmeurer): What are the constraints on thse?
598 CheckUpperIs(node, Type::Any());
599 break;
600 }
601 case IrOpcode::kJSForInDone: {
602 // TODO(bmeurer): OSR breaks this invariant, although the node is not user
603 // visible, so we know it is safe (fullcodegen has an unsigned smi there).
604 // CheckValueInputIs(node, 0, Type::UnsignedSmall());
605 break;
606 }
607 case IrOpcode::kJSForInNext: {
608 CheckUpperIs(node, Type::Union(Type::Name(), Type::Undefined(), zone));
609 break;
610 }
611 case IrOpcode::kJSForInStep: {
612 // TODO(bmeurer): OSR breaks this invariant, although the node is not user
613 // visible, so we know it is safe (fullcodegen has an unsigned smi there).
614 // CheckValueInputIs(node, 0, Type::UnsignedSmall());
615 CheckUpperIs(node, Type::UnsignedSmall());
616 break;
617 }
618
619 case IrOpcode::kJSLoadMessage:
620 case IrOpcode::kJSStoreMessage:
621 break;
622
623 case IrOpcode::kJSStackCheck:
624 // Type is empty.
625 CheckNotTyped(node);
626 break;
627
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400628 // Simplified operators
629 // -------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400630 case IrOpcode::kBooleanNot:
631 // Boolean -> Boolean
632 CheckValueInputIs(node, 0, Type::Boolean());
633 CheckUpperIs(node, Type::Boolean());
634 break;
635 case IrOpcode::kBooleanToNumber:
636 // Boolean -> Number
637 CheckValueInputIs(node, 0, Type::Boolean());
638 CheckUpperIs(node, Type::Number());
639 break;
640 case IrOpcode::kNumberEqual:
641 case IrOpcode::kNumberLessThan:
642 case IrOpcode::kNumberLessThanOrEqual:
643 // (Number, Number) -> Boolean
644 CheckValueInputIs(node, 0, Type::Number());
645 CheckValueInputIs(node, 1, Type::Number());
646 CheckUpperIs(node, Type::Boolean());
647 break;
648 case IrOpcode::kNumberAdd:
649 case IrOpcode::kNumberSubtract:
650 case IrOpcode::kNumberMultiply:
651 case IrOpcode::kNumberDivide:
652 case IrOpcode::kNumberModulus:
653 // (Number, Number) -> Number
654 CheckValueInputIs(node, 0, Type::Number());
655 CheckValueInputIs(node, 1, Type::Number());
656 // TODO(rossberg): activate once we retype after opcode changes.
657 // CheckUpperIs(node, Type::Number());
658 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000659 case IrOpcode::kNumberBitwiseOr:
660 case IrOpcode::kNumberBitwiseXor:
661 case IrOpcode::kNumberBitwiseAnd:
662 // (Signed32, Signed32) -> Signed32
663 CheckValueInputIs(node, 0, Type::Signed32());
664 CheckValueInputIs(node, 1, Type::Signed32());
665 CheckUpperIs(node, Type::Signed32());
666 break;
667 case IrOpcode::kNumberShiftLeft:
668 case IrOpcode::kNumberShiftRight:
669 // (Signed32, Unsigned32) -> Signed32
670 CheckValueInputIs(node, 0, Type::Signed32());
671 CheckValueInputIs(node, 1, Type::Unsigned32());
672 CheckUpperIs(node, Type::Signed32());
673 break;
674 case IrOpcode::kNumberShiftRightLogical:
675 // (Unsigned32, Unsigned32) -> Unsigned32
676 CheckValueInputIs(node, 0, Type::Unsigned32());
677 CheckValueInputIs(node, 1, Type::Unsigned32());
678 CheckUpperIs(node, Type::Unsigned32());
679 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400680 case IrOpcode::kNumberToInt32:
681 // Number -> Signed32
682 CheckValueInputIs(node, 0, Type::Number());
683 CheckUpperIs(node, Type::Signed32());
684 break;
685 case IrOpcode::kNumberToUint32:
686 // Number -> Unsigned32
687 CheckValueInputIs(node, 0, Type::Number());
688 CheckUpperIs(node, Type::Unsigned32());
689 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000690 case IrOpcode::kNumberIsHoleNaN:
691 // Number -> Boolean
692 CheckValueInputIs(node, 0, Type::Number());
693 CheckUpperIs(node, Type::Boolean());
694 break;
695 case IrOpcode::kPlainPrimitiveToNumber:
696 // PlainPrimitive -> Number
697 CheckValueInputIs(node, 0, Type::PlainPrimitive());
698 CheckUpperIs(node, Type::Number());
699 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400700 case IrOpcode::kStringEqual:
701 case IrOpcode::kStringLessThan:
702 case IrOpcode::kStringLessThanOrEqual:
703 // (String, String) -> Boolean
704 CheckValueInputIs(node, 0, Type::String());
705 CheckValueInputIs(node, 1, Type::String());
706 CheckUpperIs(node, Type::Boolean());
707 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400708 case IrOpcode::kReferenceEqual: {
709 // (Unique, Any) -> Boolean and
710 // (Any, Unique) -> Boolean
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400711 CheckUpperIs(node, Type::Boolean());
712 break;
713 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 case IrOpcode::kObjectIsNumber:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100715 case IrOpcode::kObjectIsReceiver:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400716 case IrOpcode::kObjectIsSmi:
717 CheckValueInputIs(node, 0, Type::Any());
718 CheckUpperIs(node, Type::Boolean());
719 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 case IrOpcode::kAllocate:
721 CheckValueInputIs(node, 0, Type::PlainNumber());
722 CheckUpperIs(node, Type::TaggedPointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400723 break;
724
725 case IrOpcode::kChangeTaggedToInt32: {
726 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
727 // TODO(neis): Activate once ChangeRepresentation works in typer.
728 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
729 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
730 // CheckValueInputIs(node, 0, from));
731 // CheckUpperIs(node, to));
732 break;
733 }
734 case IrOpcode::kChangeTaggedToUint32: {
735 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
736 // TODO(neis): Activate once ChangeRepresentation works in typer.
737 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
738 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
739 // CheckValueInputIs(node, 0, from));
740 // CheckUpperIs(node, to));
741 break;
742 }
743 case IrOpcode::kChangeTaggedToFloat64: {
744 // Number /\ Tagged -> Number /\ UntaggedFloat64
745 // TODO(neis): Activate once ChangeRepresentation works in typer.
746 // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
747 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
748 // CheckValueInputIs(node, 0, from));
749 // CheckUpperIs(node, to));
750 break;
751 }
752 case IrOpcode::kChangeInt32ToTagged: {
753 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
754 // TODO(neis): Activate once ChangeRepresentation works in typer.
755 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
756 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
757 // CheckValueInputIs(node, 0, from));
758 // CheckUpperIs(node, to));
759 break;
760 }
761 case IrOpcode::kChangeUint32ToTagged: {
762 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
763 // TODO(neis): Activate once ChangeRepresentation works in typer.
764 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
765 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
766 // CheckValueInputIs(node, 0, from));
767 // CheckUpperIs(node, to));
768 break;
769 }
770 case IrOpcode::kChangeFloat64ToTagged: {
771 // Number /\ UntaggedFloat64 -> Number /\ Tagged
772 // TODO(neis): Activate once ChangeRepresentation works in typer.
773 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
774 // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
775 // CheckValueInputIs(node, 0, from));
776 // CheckUpperIs(node, to));
777 break;
778 }
779 case IrOpcode::kChangeBoolToBit: {
780 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
781 // TODO(neis): Activate once ChangeRepresentation works in typer.
782 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
783 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
784 // CheckValueInputIs(node, 0, from));
785 // CheckUpperIs(node, to));
786 break;
787 }
788 case IrOpcode::kChangeBitToBool: {
789 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
790 // TODO(neis): Activate once ChangeRepresentation works in typer.
791 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
792 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
793 // CheckValueInputIs(node, 0, from));
794 // CheckUpperIs(node, to));
795 break;
796 }
797
798 case IrOpcode::kLoadField:
799 // Object -> fieldtype
800 // TODO(rossberg): activate once machine ops are typed.
801 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 // CheckUpperIs(node, FieldAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400803 break;
804 case IrOpcode::kLoadBuffer:
805 break;
806 case IrOpcode::kLoadElement:
807 // Object -> elementtype
808 // TODO(rossberg): activate once machine ops are typed.
809 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810 // CheckUpperIs(node, ElementAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400811 break;
812 case IrOpcode::kStoreField:
813 // (Object, fieldtype) -> _|_
814 // TODO(rossberg): activate once machine ops are typed.
815 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 // CheckValueInputIs(node, 1, FieldAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400817 CheckNotTyped(node);
818 break;
819 case IrOpcode::kStoreBuffer:
820 break;
821 case IrOpcode::kStoreElement:
822 // (Object, elementtype) -> _|_
823 // TODO(rossberg): activate once machine ops are typed.
824 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 // CheckValueInputIs(node, 1, ElementAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400826 CheckNotTyped(node);
827 break;
828
829 // Machine operators
830 // -----------------------
831 case IrOpcode::kLoad:
832 case IrOpcode::kStore:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100833 case IrOpcode::kStackSlot:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400834 case IrOpcode::kWord32And:
835 case IrOpcode::kWord32Or:
836 case IrOpcode::kWord32Xor:
837 case IrOpcode::kWord32Shl:
838 case IrOpcode::kWord32Shr:
839 case IrOpcode::kWord32Sar:
840 case IrOpcode::kWord32Ror:
841 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 case IrOpcode::kWord32Clz:
843 case IrOpcode::kWord32Ctz:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100844 case IrOpcode::kWord32ReverseBits:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845 case IrOpcode::kWord32Popcnt:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400846 case IrOpcode::kWord64And:
847 case IrOpcode::kWord64Or:
848 case IrOpcode::kWord64Xor:
849 case IrOpcode::kWord64Shl:
850 case IrOpcode::kWord64Shr:
851 case IrOpcode::kWord64Sar:
852 case IrOpcode::kWord64Ror:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 case IrOpcode::kWord64Clz:
854 case IrOpcode::kWord64Popcnt:
855 case IrOpcode::kWord64Ctz:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100856 case IrOpcode::kWord64ReverseBits:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400857 case IrOpcode::kWord64Equal:
858 case IrOpcode::kInt32Add:
859 case IrOpcode::kInt32AddWithOverflow:
860 case IrOpcode::kInt32Sub:
861 case IrOpcode::kInt32SubWithOverflow:
862 case IrOpcode::kInt32Mul:
863 case IrOpcode::kInt32MulHigh:
864 case IrOpcode::kInt32Div:
865 case IrOpcode::kInt32Mod:
866 case IrOpcode::kInt32LessThan:
867 case IrOpcode::kInt32LessThanOrEqual:
868 case IrOpcode::kUint32Div:
869 case IrOpcode::kUint32Mod:
870 case IrOpcode::kUint32MulHigh:
871 case IrOpcode::kUint32LessThan:
872 case IrOpcode::kUint32LessThanOrEqual:
873 case IrOpcode::kInt64Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874 case IrOpcode::kInt64AddWithOverflow:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400875 case IrOpcode::kInt64Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 case IrOpcode::kInt64SubWithOverflow:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400877 case IrOpcode::kInt64Mul:
878 case IrOpcode::kInt64Div:
879 case IrOpcode::kInt64Mod:
880 case IrOpcode::kInt64LessThan:
881 case IrOpcode::kInt64LessThanOrEqual:
882 case IrOpcode::kUint64Div:
883 case IrOpcode::kUint64Mod:
884 case IrOpcode::kUint64LessThan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 case IrOpcode::kUint64LessThanOrEqual:
886 case IrOpcode::kFloat32Add:
887 case IrOpcode::kFloat32Sub:
888 case IrOpcode::kFloat32Mul:
889 case IrOpcode::kFloat32Div:
890 case IrOpcode::kFloat32Max:
891 case IrOpcode::kFloat32Min:
892 case IrOpcode::kFloat32Abs:
893 case IrOpcode::kFloat32Sqrt:
894 case IrOpcode::kFloat32Equal:
895 case IrOpcode::kFloat32LessThan:
896 case IrOpcode::kFloat32LessThanOrEqual:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400897 case IrOpcode::kFloat64Add:
898 case IrOpcode::kFloat64Sub:
899 case IrOpcode::kFloat64Mul:
900 case IrOpcode::kFloat64Div:
901 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 case IrOpcode::kFloat64Max:
903 case IrOpcode::kFloat64Min:
904 case IrOpcode::kFloat64Abs:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400905 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 case IrOpcode::kFloat32RoundDown:
907 case IrOpcode::kFloat64RoundDown:
908 case IrOpcode::kFloat32RoundUp:
909 case IrOpcode::kFloat64RoundUp:
910 case IrOpcode::kFloat32RoundTruncate:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400911 case IrOpcode::kFloat64RoundTruncate:
912 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000913 case IrOpcode::kFloat32RoundTiesEven:
914 case IrOpcode::kFloat64RoundTiesEven:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400915 case IrOpcode::kFloat64Equal:
916 case IrOpcode::kFloat64LessThan:
917 case IrOpcode::kFloat64LessThanOrEqual:
918 case IrOpcode::kTruncateInt64ToInt32:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100919 case IrOpcode::kRoundInt32ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 case IrOpcode::kRoundInt64ToFloat32:
921 case IrOpcode::kRoundInt64ToFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100922 case IrOpcode::kRoundUint32ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 case IrOpcode::kRoundUint64ToFloat64:
924 case IrOpcode::kRoundUint64ToFloat32:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400925 case IrOpcode::kTruncateFloat64ToFloat32:
926 case IrOpcode::kTruncateFloat64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927 case IrOpcode::kBitcastFloat32ToInt32:
928 case IrOpcode::kBitcastFloat64ToInt64:
929 case IrOpcode::kBitcastInt32ToFloat32:
930 case IrOpcode::kBitcastInt64ToFloat64:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400931 case IrOpcode::kChangeInt32ToInt64:
932 case IrOpcode::kChangeUint32ToUint64:
933 case IrOpcode::kChangeInt32ToFloat64:
934 case IrOpcode::kChangeUint32ToFloat64:
935 case IrOpcode::kChangeFloat32ToFloat64:
936 case IrOpcode::kChangeFloat64ToInt32:
937 case IrOpcode::kChangeFloat64ToUint32:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100938 case IrOpcode::kTruncateFloat32ToInt32:
939 case IrOpcode::kTruncateFloat32ToUint32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 case IrOpcode::kTryTruncateFloat32ToInt64:
941 case IrOpcode::kTryTruncateFloat64ToInt64:
942 case IrOpcode::kTryTruncateFloat32ToUint64:
943 case IrOpcode::kTryTruncateFloat64ToUint64:
944 case IrOpcode::kFloat64ExtractLowWord32:
945 case IrOpcode::kFloat64ExtractHighWord32:
946 case IrOpcode::kFloat64InsertLowWord32:
947 case IrOpcode::kFloat64InsertHighWord32:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400948 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 case IrOpcode::kLoadFramePointer:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100950 case IrOpcode::kLoadParentFramePointer:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400951 case IrOpcode::kCheckedLoad:
952 case IrOpcode::kCheckedStore:
953 // TODO(rossberg): Check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 break;
955 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000956} // NOLINT(readability/fn_size)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000957
958
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400959void Verifier::Run(Graph* graph, Typing typing) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 CHECK_NOT_NULL(graph->start());
961 CHECK_NOT_NULL(graph->end());
962 Zone zone;
963 Visitor visitor(&zone, typing);
964 AllNodes all(&zone, graph);
965 for (Node* node : all.live) visitor.Check(node);
966
967 // Check the uniqueness of projections.
968 for (Node* proj : all.live) {
969 if (proj->opcode() != IrOpcode::kProjection) continue;
970 Node* node = proj->InputAt(0);
971 for (Node* other : node->uses()) {
972 if (all.IsLive(other) && other != proj &&
973 other->opcode() == IrOpcode::kProjection &&
974 ProjectionIndexOf(other->op()) == ProjectionIndexOf(proj->op())) {
975 V8_Fatal(__FILE__, __LINE__,
976 "Node #%d:%s has duplicate projections #%d and #%d",
977 node->id(), node->op()->mnemonic(), proj->id(), other->id());
978 }
979 }
980 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000981}
982
983
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400984// -----------------------------------------------------------------------------
985
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986static bool HasDominatingDef(Schedule* schedule, Node* node,
987 BasicBlock* container, BasicBlock* use_block,
988 int use_pos) {
989 BasicBlock* block = use_block;
990 while (true) {
991 while (use_pos >= 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400992 if (block->NodeAt(use_pos) == node) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000993 use_pos--;
994 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400995 block = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000996 if (block == nullptr) break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400997 use_pos = static_cast<int>(block->NodeCount()) - 1;
998 if (node == block->control_input()) return true;
999 }
1000 return false;
1001}
1002
1003
1004static bool Dominates(Schedule* schedule, Node* dominator, Node* dominatee) {
1005 BasicBlock* dom = schedule->block(dominator);
1006 BasicBlock* sub = schedule->block(dominatee);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001007 while (sub != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001008 if (sub == dom) {
1009 return true;
1010 }
1011 sub = sub->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012 }
1013 return false;
1014}
1015
1016
1017static void CheckInputsDominate(Schedule* schedule, BasicBlock* block,
1018 Node* node, int use_pos) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001019 for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020 BasicBlock* use_block = block;
1021 if (node->opcode() == IrOpcode::kPhi) {
1022 use_block = use_block->PredecessorAt(j);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001023 use_pos = static_cast<int>(use_block->NodeCount()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024 }
1025 Node* input = node->InputAt(j);
1026 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block,
1027 use_pos)) {
1028 V8_Fatal(__FILE__, __LINE__,
1029 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001030 node->id(), node->op()->mnemonic(), block->rpo_number(), j,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001031 input->id(), input->op()->mnemonic());
1032 }
1033 }
1034 // Ensure that nodes are dominated by their control inputs;
1035 // kEnd is an exception, as unreachable blocks resulting from kMerge
1036 // are not in the RPO.
1037 if (node->op()->ControlInputCount() == 1 &&
1038 node->opcode() != IrOpcode::kEnd) {
1039 Node* ctl = NodeProperties::GetControlInput(node);
1040 if (!Dominates(schedule, ctl, node)) {
1041 V8_Fatal(__FILE__, __LINE__,
1042 "Node #%d:%s in B%d is not dominated by control input #%d:%s",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 node->id(), node->op()->mnemonic(), block->rpo_number(),
1044 ctl->id(), ctl->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001045 }
1046 }
1047}
1048
1049
1050void ScheduleVerifier::Run(Schedule* schedule) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001051 const size_t count = schedule->BasicBlockCount();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 Zone tmp_zone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001053 Zone* zone = &tmp_zone;
1054 BasicBlock* start = schedule->start();
1055 BasicBlockVector* rpo_order = schedule->rpo_order();
1056
1057 // Verify the RPO order contains only blocks from this schedule.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001058 CHECK_GE(count, rpo_order->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1060 ++b) {
1061 CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001062 // All predecessors and successors should be in rpo and in this schedule.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063 for (BasicBlock const* predecessor : (*b)->predecessors()) {
1064 CHECK_GE(predecessor->rpo_number(), 0);
1065 CHECK_EQ(predecessor, schedule->GetBlockById(predecessor->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001066 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 for (BasicBlock const* successor : (*b)->successors()) {
1068 CHECK_GE(successor->rpo_number(), 0);
1069 CHECK_EQ(successor, schedule->GetBlockById(successor->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001070 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071 }
1072
1073 // Verify RPO numbers of blocks.
1074 CHECK_EQ(start, rpo_order->at(0)); // Start should be first.
1075 for (size_t b = 0; b < rpo_order->size(); b++) {
1076 BasicBlock* block = rpo_order->at(b);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001077 CHECK_EQ(static_cast<int>(b), block->rpo_number());
1078 BasicBlock* dom = block->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001079 if (b == 0) {
1080 // All blocks except start should have a dominator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001081 CHECK_NULL(dom);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001082 } else {
1083 // Check that the immediate dominator appears somewhere before the block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 CHECK_NOT_NULL(dom);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001085 CHECK_LT(dom->rpo_number(), block->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086 }
1087 }
1088
1089 // Verify that all blocks reachable from start are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001090 BoolVector marked(static_cast<int>(count), false, zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001091 {
1092 ZoneQueue<BasicBlock*> queue(zone);
1093 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001094 marked[start->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001095 while (!queue.empty()) {
1096 BasicBlock* block = queue.front();
1097 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001098 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001099 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001100 if (!marked[succ->id().ToSize()]) {
1101 marked[succ->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 queue.push(succ);
1103 }
1104 }
1105 }
1106 }
1107 // Verify marked blocks are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001108 for (size_t i = 0; i < count; i++) {
1109 BasicBlock* block = schedule->GetBlockById(BasicBlock::Id::FromSize(i));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001110 if (marked[i]) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001111 CHECK_GE(block->rpo_number(), 0);
1112 CHECK_EQ(block, rpo_order->at(block->rpo_number()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001113 }
1114 }
1115 // Verify RPO blocks are marked.
1116 for (size_t b = 0; b < rpo_order->size(); b++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001117 CHECK(marked[rpo_order->at(b)->id().ToSize()]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 }
1119
1120 {
1121 // Verify the dominance relation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001122 ZoneVector<BitVector*> dominators(zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001123 dominators.resize(count, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124
1125 // Compute a set of all the nodes that dominate a given node by using
1126 // a forward fixpoint. O(n^2).
1127 ZoneQueue<BasicBlock*> queue(zone);
1128 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001129 dominators[start->id().ToSize()] =
1130 new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 while (!queue.empty()) {
1132 BasicBlock* block = queue.front();
1133 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001134 BitVector* block_doms = dominators[block->id().ToSize()];
1135 BasicBlock* idom = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 if (idom != nullptr && !block_doms->Contains(idom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 V8_Fatal(__FILE__, __LINE__, "Block B%d is not dominated by B%d",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001138 block->rpo_number(), idom->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001139 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001140 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001142 BitVector* succ_doms = dominators[succ->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001143
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001144 if (succ_doms == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001145 // First time visiting the node. S.doms = B U B.doms
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001146 succ_doms = new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147 succ_doms->CopyFrom(*block_doms);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001148 succ_doms->Add(block->id().ToInt());
1149 dominators[succ->id().ToSize()] = succ_doms;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150 queue.push(succ);
1151 } else {
1152 // Nth time visiting the successor. S.doms = S.doms ^ (B U B.doms)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001153 bool had = succ_doms->Contains(block->id().ToInt());
1154 if (had) succ_doms->Remove(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155 if (succ_doms->IntersectIsChanged(*block_doms)) queue.push(succ);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001156 if (had) succ_doms->Add(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157 }
1158 }
1159 }
1160
1161 // Verify the immediateness of dominators.
1162 for (BasicBlockVector::iterator b = rpo_order->begin();
1163 b != rpo_order->end(); ++b) {
1164 BasicBlock* block = *b;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001165 BasicBlock* idom = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166 if (idom == nullptr) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001167 BitVector* block_doms = dominators[block->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168
1169 for (BitVector::Iterator it(block_doms); !it.Done(); it.Advance()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001170 BasicBlock* dom =
1171 schedule->GetBlockById(BasicBlock::Id::FromInt(it.Current()));
1172 if (dom != idom &&
1173 !dominators[idom->id().ToSize()]->Contains(dom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 V8_Fatal(__FILE__, __LINE__,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001175 "Block B%d is not immediately dominated by B%d",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 block->rpo_number(), idom->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 }
1178 }
1179 }
1180 }
1181
1182 // Verify phis are placed in the block of their control input.
1183 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1184 ++b) {
1185 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) {
1186 Node* phi = *i;
1187 if (phi->opcode() != IrOpcode::kPhi) continue;
1188 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler
1189 // schedules don't have control inputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001190 if (phi->InputCount() > phi->op()->ValueInputCount()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 Node* control = NodeProperties::GetControlInput(phi);
1192 CHECK(control->opcode() == IrOpcode::kMerge ||
1193 control->opcode() == IrOpcode::kLoop);
1194 CHECK_EQ((*b), schedule->block(control));
1195 }
1196 }
1197 }
1198
1199 // Verify that all uses are dominated by their definitions.
1200 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1201 ++b) {
1202 BasicBlock* block = *b;
1203
1204 // Check inputs to control for this block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001205 Node* control = block->control_input();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 if (control != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207 CHECK_EQ(block, schedule->block(control));
1208 CheckInputsDominate(schedule, block, control,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001209 static_cast<int>(block->NodeCount()) - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 }
1211 // Check inputs for all nodes in the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001212 for (size_t i = 0; i < block->NodeCount(); i++) {
1213 Node* node = block->NodeAt(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1);
1215 }
1216 }
1217}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001218
1219
1220#ifdef DEBUG
1221
1222// static
1223void Verifier::VerifyNode(Node* node) {
1224 CHECK_EQ(OperatorProperties::GetTotalInputCount(node->op()),
1225 node->InputCount());
1226 // If this node has no effect or no control outputs,
1227 // we check that no its uses are effect or control inputs.
1228 bool check_no_control = node->op()->ControlOutputCount() == 0;
1229 bool check_no_effect = node->op()->EffectOutputCount() == 0;
1230 bool check_no_frame_state = node->opcode() != IrOpcode::kFrameState;
1231 if (check_no_effect || check_no_control) {
1232 for (Edge edge : node->use_edges()) {
1233 Node* const user = edge.from();
1234 CHECK(!user->IsDead());
1235 if (NodeProperties::IsControlEdge(edge)) {
1236 CHECK(!check_no_control);
1237 } else if (NodeProperties::IsEffectEdge(edge)) {
1238 CHECK(!check_no_effect);
1239 } else if (NodeProperties::IsFrameStateEdge(edge)) {
1240 CHECK(!check_no_frame_state);
1241 }
1242 }
1243 }
1244 // Frame state inputs should be frame states (or sentinels).
1245 for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(node->op());
1246 i++) {
1247 Node* input = NodeProperties::GetFrameStateInput(node, i);
1248 CHECK(input->opcode() == IrOpcode::kFrameState ||
1249 input->opcode() == IrOpcode::kStart ||
1250 input->opcode() == IrOpcode::kDead);
1251 }
1252 // Effect inputs should be effect-producing nodes (or sentinels).
1253 for (int i = 0; i < node->op()->EffectInputCount(); i++) {
1254 Node* input = NodeProperties::GetEffectInput(node, i);
1255 CHECK(input->op()->EffectOutputCount() > 0 ||
1256 input->opcode() == IrOpcode::kDead);
1257 }
1258 // Control inputs should be control-producing nodes (or sentinels).
1259 for (int i = 0; i < node->op()->ControlInputCount(); i++) {
1260 Node* input = NodeProperties::GetControlInput(node, i);
1261 CHECK(input->op()->ControlOutputCount() > 0 ||
1262 input->opcode() == IrOpcode::kDead);
1263 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001265
1266
1267void Verifier::VerifyEdgeInputReplacement(const Edge& edge,
1268 const Node* replacement) {
1269 // Check that the user does not misuse the replacement.
1270 DCHECK(!NodeProperties::IsControlEdge(edge) ||
1271 replacement->op()->ControlOutputCount() > 0);
1272 DCHECK(!NodeProperties::IsEffectEdge(edge) ||
1273 replacement->op()->EffectOutputCount() > 0);
1274 DCHECK(!NodeProperties::IsFrameStateEdge(edge) ||
1275 replacement->opcode() == IrOpcode::kFrameState);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001277
1278#endif // DEBUG
1279
1280} // namespace compiler
1281} // namespace internal
1282} // namespace v8