| Index: src/compiler/verifier.cc
|
| diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc
|
| index f2ad4bae70c330b8960c96ff2b01d496c23fb9d6..6887d5c465a05bfb8be0fdb800460cc750eeb262 100644
|
| --- a/src/compiler/verifier.cc
|
| +++ b/src/compiler/verifier.cc
|
| @@ -56,10 +56,8 @@ class Verifier::Visitor : public NullNodeVisitor {
|
|
|
| private:
|
| // TODO(rossberg): Get rid of these once we got rid of NodeProperties.
|
| - Bounds bounds(Node* node) {
|
| - return NodeProperties::GetBounds(node);
|
| - }
|
| - Node* Operand(Node* node, int i = 0) {
|
| + Bounds bounds(Node* node) { return NodeProperties::GetBounds(node); }
|
| + Node* ValueInput(Node* node, int i = 0) {
|
| return NodeProperties::GetValueInput(node, i);
|
| }
|
| FieldAccess Field(Node* node) {
|
| @@ -72,6 +70,16 @@ class Verifier::Visitor : public NullNodeVisitor {
|
| node->opcode() == IrOpcode::kStoreElement);
|
| return OpParameter<ElementAccess>(node);
|
| }
|
| + void CheckNotTyped(Node* node) { CHECK(!NodeProperties::IsTyped(node)); }
|
| + void CheckUpperIs(Node* node, Type* type) {
|
| + if (typing == TYPED) CHECK(bounds(node).upper->Is(type));
|
| + }
|
| + void CheckUpperMaybe(Node* node, Type* type) {
|
| + if (typing == TYPED) CHECK(bounds(node).upper->Maybe(type));
|
| + }
|
| + void CheckValueInputIs(Node* node, int i, Type* type) {
|
| + if (typing == TYPED) CHECK(bounds(ValueInput(node, i)).upper->Is(type));
|
| + }
|
| };
|
|
|
|
|
| @@ -141,527 +149,532 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
|
| }
|
| }
|
|
|
| - if (typing == TYPED) {
|
| - switch (node->opcode()) {
|
| - // Control operators
|
| - // -----------------
|
| - case IrOpcode::kStart:
|
| - // Start has no inputs.
|
| - CHECK_EQ(0, input_count);
|
| - // Type is a tuple.
|
| - // TODO(rossberg): Multiple outputs are currently typed as Internal.
|
| - CHECK(bounds(node).upper->Is(Type::Internal()));
|
| - break;
|
| - case IrOpcode::kEnd:
|
| - // End has no outputs.
|
| - CHECK(!OperatorProperties::HasValueOutput(node->op()));
|
| - CHECK(!OperatorProperties::HasEffectOutput(node->op()));
|
| - CHECK(!OperatorProperties::HasControlOutput(node->op()));
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - case IrOpcode::kDead:
|
| - // Dead is never connected to the graph.
|
| - UNREACHABLE();
|
| - case IrOpcode::kBranch: {
|
| - // Branch uses are IfTrue and IfFalse.
|
| - Node::Uses uses = node->uses();
|
| - int count_true = 0, count_false = 0;
|
| - for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
|
| - CHECK((*it)->opcode() == IrOpcode::kIfTrue ||
|
| - (*it)->opcode() == IrOpcode::kIfFalse);
|
| - if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true;
|
| - if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false;
|
| - }
|
| - CHECK(count_true == 1 && count_false == 1);
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - }
|
| - case IrOpcode::kIfTrue:
|
| - case IrOpcode::kIfFalse:
|
| - CHECK_EQ(IrOpcode::kBranch,
|
| - NodeProperties::GetControlInput(node, 0)->opcode());
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - case IrOpcode::kLoop:
|
| - case IrOpcode::kMerge:
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - case IrOpcode::kReturn:
|
| - // TODO(rossberg): check successor is End
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - case IrOpcode::kThrow:
|
| - // TODO(rossberg): what are the constraints on these?
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| -
|
| - // Common operators
|
| - // ----------------
|
| - case IrOpcode::kParameter: {
|
| - // Parameters have the start node as inputs.
|
| - CHECK_EQ(1, input_count);
|
| - CHECK_EQ(IrOpcode::kStart,
|
| - NodeProperties::GetValueInput(node, 0)->opcode());
|
| - // Parameter has an input that produces enough values.
|
| - int index = OpParameter<int>(node);
|
| - Node* input = NodeProperties::GetValueInput(node, 0);
|
| - // Currently, parameter indices start at -1 instead of 0.
|
| - CHECK_GT(
|
| - OperatorProperties::GetValueOutputCount(input->op()), index + 1);
|
| - // Type can be anything.
|
| - CHECK(bounds(node).upper->Is(Type::Any()));
|
| - break;
|
| - }
|
| - case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
|
| - // Constants have no inputs.
|
| - CHECK_EQ(0, input_count);
|
| - // Type is a 32 bit integer, signed or unsigned.
|
| - CHECK(bounds(node).upper->Is(Type::Integral32()));
|
| - break;
|
| - case IrOpcode::kInt64Constant:
|
| - // Constants have no inputs.
|
| - CHECK_EQ(0, input_count);
|
| - // Type is internal.
|
| - // TODO(rossberg): Introduce proper Int64 type.
|
| - CHECK(bounds(node).upper->Is(Type::Internal()));
|
| - break;
|
| - case IrOpcode::kFloat32Constant:
|
| - case IrOpcode::kFloat64Constant:
|
| - case IrOpcode::kNumberConstant:
|
| - // Constants have no inputs.
|
| - CHECK_EQ(0, input_count);
|
| - // Type is a number.
|
| - CHECK(bounds(node).upper->Is(Type::Number()));
|
| - break;
|
| - case IrOpcode::kHeapConstant:
|
| - // Constants have no inputs.
|
| - CHECK_EQ(0, input_count);
|
| - // Type can be anything represented as a heap pointer.
|
| - CHECK(bounds(node).upper->Is(Type::TaggedPtr()));
|
| - break;
|
| - case IrOpcode::kExternalConstant:
|
| - // Constants have no inputs.
|
| - CHECK_EQ(0, input_count);
|
| - // Type is considered internal.
|
| - CHECK(bounds(node).upper->Is(Type::Internal()));
|
| - break;
|
| - case IrOpcode::kProjection: {
|
| - // Projection has an input that produces enough values.
|
| - int index = OpParameter<int>(node->op());
|
| - Node* input = NodeProperties::GetValueInput(node, 0);
|
| - CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index);
|
| - // Type can be anything.
|
| - // TODO(rossberg): Introduce tuple types for this.
|
| - CHECK(bounds(node).upper->Is(Type::Any()));
|
| - break;
|
| - }
|
| - case IrOpcode::kPhi: {
|
| - // Phi input count matches parent control node.
|
| - CHECK_EQ(1, control_count);
|
| - Node* control = NodeProperties::GetControlInput(node, 0);
|
| - CHECK_EQ(value_count,
|
| - OperatorProperties::GetControlInputCount(control->op()));
|
| - // Type must be subsumed by all input types.
|
| - // TODO(rossberg): for now at least, narrowing does not really hold.
|
| - /*
|
| - for (int i = 0; i < value_count; ++i) {
|
| - // TODO(rossberg, jarin): Figure out what to do about lower bounds.
|
| - // CHECK(bounds(node).lower->Is(bounds(Operand(node, i)).lower));
|
| - CHECK(bounds(Operand(node, i)).upper->Is(bounds(node).upper));
|
| - }
|
| - */
|
| - break;
|
| + switch (node->opcode()) {
|
| + case IrOpcode::kStart:
|
| + // Start has no inputs.
|
| + CHECK_EQ(0, input_count);
|
| + // Type is a tuple.
|
| + // TODO(rossberg): Multiple outputs are currently typed as Internal.
|
| + CheckUpperIs(node, Type::Internal());
|
| + break;
|
| + case IrOpcode::kEnd:
|
| + // End has no outputs.
|
| + CHECK(!OperatorProperties::HasValueOutput(node->op()));
|
| + CHECK(!OperatorProperties::HasEffectOutput(node->op()));
|
| + CHECK(!OperatorProperties::HasControlOutput(node->op()));
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| + case IrOpcode::kDead:
|
| + // Dead is never connected to the graph.
|
| + UNREACHABLE();
|
| + case IrOpcode::kBranch: {
|
| + // Branch uses are IfTrue and IfFalse.
|
| + Node::Uses uses = node->uses();
|
| + int count_true = 0, count_false = 0;
|
| + for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) {
|
| + CHECK((*it)->opcode() == IrOpcode::kIfTrue ||
|
| + (*it)->opcode() == IrOpcode::kIfFalse);
|
| + if ((*it)->opcode() == IrOpcode::kIfTrue) ++count_true;
|
| + if ((*it)->opcode() == IrOpcode::kIfFalse) ++count_false;
|
| }
|
| - case IrOpcode::kEffectPhi: {
|
| - // EffectPhi input count matches parent control node.
|
| - CHECK_EQ(1, control_count);
|
| - Node* control = NodeProperties::GetControlInput(node, 0);
|
| - CHECK_EQ(effect_count,
|
| - OperatorProperties::GetControlInputCount(control->op()));
|
| - break;
|
| - }
|
| - case IrOpcode::kValueEffect:
|
| - // TODO(rossberg): what are the constraints on these?
|
| - break;
|
| - case IrOpcode::kFinish: {
|
| - // TODO(rossberg): what are the constraints on these?
|
| - // Type must be subsumed by input type.
|
| - CHECK(bounds(Operand(node)).lower->Is(bounds(node).lower));
|
| - CHECK(bounds(Operand(node)).upper->Is(bounds(node).upper));
|
| - break;
|
| + CHECK(count_true == 1 && count_false == 1);
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| + }
|
| + case IrOpcode::kIfTrue:
|
| + case IrOpcode::kIfFalse:
|
| + CHECK_EQ(IrOpcode::kBranch,
|
| + NodeProperties::GetControlInput(node, 0)->opcode());
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| + case IrOpcode::kLoop:
|
| + case IrOpcode::kMerge:
|
| + CHECK_EQ(control_count, input_count);
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| + case IrOpcode::kReturn:
|
| + // TODO(rossberg): check successor is End
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| + case IrOpcode::kThrow:
|
| + // TODO(rossberg): what are the constraints on these?
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| +
|
| + // Common operators
|
| + // ----------------
|
| + case IrOpcode::kParameter: {
|
| + // Parameters have the start node as inputs.
|
| + CHECK_EQ(1, input_count);
|
| + CHECK_EQ(IrOpcode::kStart,
|
| + NodeProperties::GetValueInput(node, 0)->opcode());
|
| + // Parameter has an input that produces enough values.
|
| + int index = OpParameter<int>(node);
|
| + Node* input = NodeProperties::GetValueInput(node, 0);
|
| + // Currently, parameter indices start at -1 instead of 0.
|
| + CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index + 1);
|
| + // Type can be anything.
|
| + CheckUpperIs(node, Type::Any());
|
| + break;
|
| + }
|
| + case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
|
| + // Constants have no inputs.
|
| + CHECK_EQ(0, input_count);
|
| + // Type is a 32 bit integer, signed or unsigned.
|
| + CheckUpperIs(node, Type::Integral32());
|
| + break;
|
| + case IrOpcode::kInt64Constant:
|
| + // Constants have no inputs.
|
| + CHECK_EQ(0, input_count);
|
| + // Type is internal.
|
| + // TODO(rossberg): Introduce proper Int64 type.
|
| + CheckUpperIs(node, Type::Internal());
|
| + break;
|
| + case IrOpcode::kFloat32Constant:
|
| + case IrOpcode::kFloat64Constant:
|
| + case IrOpcode::kNumberConstant:
|
| + // Constants have no inputs.
|
| + CHECK_EQ(0, input_count);
|
| + // Type is a number.
|
| + CheckUpperIs(node, Type::Number());
|
| + break;
|
| + case IrOpcode::kHeapConstant:
|
| + // Constants have no inputs.
|
| + CHECK_EQ(0, input_count);
|
| + // Type can be anything represented as a heap pointer.
|
| + CheckUpperIs(node, Type::TaggedPtr());
|
| + break;
|
| + case IrOpcode::kExternalConstant:
|
| + // Constants have no inputs.
|
| + CHECK_EQ(0, input_count);
|
| + // Type is considered internal.
|
| + CheckUpperIs(node, Type::Internal());
|
| + break;
|
| + case IrOpcode::kProjection: {
|
| + // Projection has an input that produces enough values.
|
| + int index = OpParameter<int>(node->op());
|
| + Node* input = NodeProperties::GetValueInput(node, 0);
|
| + CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index);
|
| + // Type can be anything.
|
| + // TODO(rossberg): Introduce tuple types for this.
|
| + // TODO(titzer): Convince rossberg not to.
|
| + CheckUpperIs(node, Type::Any());
|
| + break;
|
| + }
|
| + case IrOpcode::kPhi: {
|
| + // Phi input count matches parent control node.
|
| + CHECK_EQ(0, effect_count);
|
| + CHECK_EQ(1, control_count);
|
| + Node* control = NodeProperties::GetControlInput(node, 0);
|
| + CHECK_EQ(value_count,
|
| + OperatorProperties::GetControlInputCount(control->op()));
|
| + CHECK_EQ(input_count, 1 + value_count);
|
| + // Type must be subsumed by all input types.
|
| + // TODO(rossberg): for now at least, narrowing does not really hold.
|
| + /*
|
| + for (int i = 0; i < value_count; ++i) {
|
| + // TODO(rossberg, jarin): Figure out what to do about lower bounds.
|
| + // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower));
|
| + CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper));
|
| }
|
| - case IrOpcode::kFrameState:
|
| - // TODO(jarin): what are the constraints on these?
|
| - break;
|
| - case IrOpcode::kStateValues:
|
| - // TODO(jarin): what are the constraints on these?
|
| - break;
|
| - case IrOpcode::kCall:
|
| - // TODO(rossberg): what are the constraints on these?
|
| - break;
|
| -
|
| - // JavaScript operators
|
| - // --------------------
|
| - case IrOpcode::kJSEqual:
|
| - case IrOpcode::kJSNotEqual:
|
| - case IrOpcode::kJSStrictEqual:
|
| - case IrOpcode::kJSStrictNotEqual:
|
| - case IrOpcode::kJSLessThan:
|
| - case IrOpcode::kJSGreaterThan:
|
| - case IrOpcode::kJSLessThanOrEqual:
|
| - case IrOpcode::kJSGreaterThanOrEqual:
|
| - case IrOpcode::kJSUnaryNot:
|
| - // Type is Boolean.
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| -
|
| - case IrOpcode::kJSBitwiseOr:
|
| - case IrOpcode::kJSBitwiseXor:
|
| - case IrOpcode::kJSBitwiseAnd:
|
| - case IrOpcode::kJSShiftLeft:
|
| - case IrOpcode::kJSShiftRight:
|
| - case IrOpcode::kJSShiftRightLogical:
|
| - // Type is 32 bit integral.
|
| - CHECK(bounds(node).upper->Is(Type::Integral32()));
|
| - break;
|
| - case IrOpcode::kJSAdd:
|
| - // Type is Number or String.
|
| - CHECK(bounds(node).upper->Is(Type::NumberOrString()));
|
| - break;
|
| - case IrOpcode::kJSSubtract:
|
| - case IrOpcode::kJSMultiply:
|
| - case IrOpcode::kJSDivide:
|
| - case IrOpcode::kJSModulus:
|
| - // Type is Number.
|
| - CHECK(bounds(node).upper->Is(Type::Number()));
|
| - break;
|
| -
|
| - case IrOpcode::kJSToBoolean:
|
| - // Type is Boolean.
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| - case IrOpcode::kJSToNumber:
|
| - // Type is Number.
|
| - CHECK(bounds(node).upper->Is(Type::Number()));
|
| - break;
|
| - case IrOpcode::kJSToString:
|
| - // Type is String.
|
| - CHECK(bounds(node).upper->Is(Type::String()));
|
| - break;
|
| - case IrOpcode::kJSToName:
|
| - // Type is Name.
|
| - CHECK(bounds(node).upper->Is(Type::Name()));
|
| - break;
|
| - case IrOpcode::kJSToObject:
|
| - // Type is Receiver.
|
| - CHECK(bounds(node).upper->Is(Type::Receiver()));
|
| - break;
|
| -
|
| - case IrOpcode::kJSCreate:
|
| - // Type is Object.
|
| - CHECK(bounds(node).upper->Is(Type::Object()));
|
| - break;
|
| - case IrOpcode::kJSLoadProperty:
|
| - case IrOpcode::kJSLoadNamed:
|
| - // Type can be anything.
|
| - CHECK(bounds(node).upper->Is(Type::Any()));
|
| - break;
|
| - case IrOpcode::kJSStoreProperty:
|
| - case IrOpcode::kJSStoreNamed:
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - case IrOpcode::kJSDeleteProperty:
|
| - case IrOpcode::kJSHasProperty:
|
| - case IrOpcode::kJSInstanceOf:
|
| - // Type is Boolean.
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| - case IrOpcode::kJSTypeOf:
|
| - // Type is String.
|
| - CHECK(bounds(node).upper->Is(Type::String()));
|
| - break;
|
| -
|
| - case IrOpcode::kJSLoadContext:
|
| - // Type can be anything.
|
| - CHECK(bounds(node).upper->Is(Type::Any()));
|
| - break;
|
| - case IrOpcode::kJSStoreContext:
|
| - // Type is empty.
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - case IrOpcode::kJSCreateFunctionContext:
|
| - case IrOpcode::kJSCreateCatchContext:
|
| - case IrOpcode::kJSCreateWithContext:
|
| - case IrOpcode::kJSCreateBlockContext:
|
| - case IrOpcode::kJSCreateModuleContext:
|
| - case IrOpcode::kJSCreateGlobalContext: {
|
| - // Type is Context, and operand is Internal.
|
| - Bounds outer = bounds(NodeProperties::GetContextInput(node));
|
| - // TODO(rossberg): This should really be Is(Internal), but the typer
|
| - // currently can't do backwards propagation.
|
| - CHECK(outer.upper->Maybe(Type::Internal()));
|
| - CHECK(bounds(node).upper->IsContext());
|
| - break;
|
| + */
|
| + break;
|
| + }
|
| + case IrOpcode::kEffectPhi: {
|
| + // EffectPhi input count matches parent control node.
|
| + CHECK_EQ(0, value_count);
|
| + CHECK_EQ(1, control_count);
|
| + Node* control = NodeProperties::GetControlInput(node, 0);
|
| + CHECK_EQ(effect_count,
|
| + OperatorProperties::GetControlInputCount(control->op()));
|
| + CHECK_EQ(input_count, 1 + effect_count);
|
| + break;
|
| + }
|
| + case IrOpcode::kValueEffect:
|
| + // TODO(rossberg): what are the constraints on these?
|
| + break;
|
| + case IrOpcode::kFinish: {
|
| + // TODO(rossberg): what are the constraints on these?
|
| + // Type must be subsumed by input type.
|
| + if (typing == TYPED) {
|
| + CHECK(bounds(ValueInput(node)).lower->Is(bounds(node).lower));
|
| + CHECK(bounds(ValueInput(node)).upper->Is(bounds(node).upper));
|
| }
|
| + break;
|
| + }
|
| + case IrOpcode::kFrameState:
|
| + // TODO(jarin): what are the constraints on these?
|
| + break;
|
| + case IrOpcode::kStateValues:
|
| + // TODO(jarin): what are the constraints on these?
|
| + break;
|
| + case IrOpcode::kCall:
|
| + // TODO(rossberg): what are the constraints on these?
|
| + break;
|
| +
|
| + // JavaScript operators
|
| + // --------------------
|
| + case IrOpcode::kJSEqual:
|
| + case IrOpcode::kJSNotEqual:
|
| + case IrOpcode::kJSStrictEqual:
|
| + case IrOpcode::kJSStrictNotEqual:
|
| + case IrOpcode::kJSLessThan:
|
| + case IrOpcode::kJSGreaterThan:
|
| + case IrOpcode::kJSLessThanOrEqual:
|
| + case IrOpcode::kJSGreaterThanOrEqual:
|
| + case IrOpcode::kJSUnaryNot:
|
| + // Type is Boolean.
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| +
|
| + case IrOpcode::kJSBitwiseOr:
|
| + case IrOpcode::kJSBitwiseXor:
|
| + case IrOpcode::kJSBitwiseAnd:
|
| + case IrOpcode::kJSShiftLeft:
|
| + case IrOpcode::kJSShiftRight:
|
| + case IrOpcode::kJSShiftRightLogical:
|
| + // Type is 32 bit integral.
|
| + CheckUpperIs(node, Type::Integral32());
|
| + break;
|
| + case IrOpcode::kJSAdd:
|
| + // Type is Number or String.
|
| + CheckUpperIs(node, Type::NumberOrString());
|
| + break;
|
| + case IrOpcode::kJSSubtract:
|
| + case IrOpcode::kJSMultiply:
|
| + case IrOpcode::kJSDivide:
|
| + case IrOpcode::kJSModulus:
|
| + // Type is Number.
|
| + CheckUpperIs(node, Type::Number());
|
| + break;
|
| +
|
| + case IrOpcode::kJSToBoolean:
|
| + // Type is Boolean.
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| + case IrOpcode::kJSToNumber:
|
| + // Type is Number.
|
| + CheckUpperIs(node, Type::Number());
|
| + break;
|
| + case IrOpcode::kJSToString:
|
| + // Type is String.
|
| + CheckUpperIs(node, Type::String());
|
| + break;
|
| + case IrOpcode::kJSToName:
|
| + // Type is Name.
|
| + CheckUpperIs(node, Type::Name());
|
| + break;
|
| + case IrOpcode::kJSToObject:
|
| + // Type is Receiver.
|
| + CheckUpperIs(node, Type::Receiver());
|
| + break;
|
| +
|
| + case IrOpcode::kJSCreate:
|
| + // Type is Object.
|
| + CheckUpperIs(node, Type::Object());
|
| + break;
|
| + case IrOpcode::kJSLoadProperty:
|
| + case IrOpcode::kJSLoadNamed:
|
| + // Type can be anything.
|
| + CheckUpperIs(node, Type::Any());
|
| + break;
|
| + case IrOpcode::kJSStoreProperty:
|
| + case IrOpcode::kJSStoreNamed:
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| + case IrOpcode::kJSDeleteProperty:
|
| + case IrOpcode::kJSHasProperty:
|
| + case IrOpcode::kJSInstanceOf:
|
| + // Type is Boolean.
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| + case IrOpcode::kJSTypeOf:
|
| + // Type is String.
|
| + CheckUpperIs(node, Type::String());
|
| + break;
|
| +
|
| + case IrOpcode::kJSLoadContext:
|
| + // Type can be anything.
|
| + CheckUpperIs(node, Type::Any());
|
| + break;
|
| + case IrOpcode::kJSStoreContext:
|
| + // Type is empty.
|
| + CheckNotTyped(node);
|
| + break;
|
| + case IrOpcode::kJSCreateFunctionContext:
|
| + case IrOpcode::kJSCreateCatchContext:
|
| + case IrOpcode::kJSCreateWithContext:
|
| + case IrOpcode::kJSCreateBlockContext:
|
| + case IrOpcode::kJSCreateModuleContext:
|
| + case IrOpcode::kJSCreateGlobalContext: {
|
| + // Type is Context, and operand is Internal.
|
| + Node* context = NodeProperties::GetContextInput(node);
|
| + // TODO(rossberg): This should really be Is(Internal), but the typer
|
| + // currently can't do backwards propagation.
|
| + CheckUpperMaybe(context, Type::Internal());
|
| + if (typing == TYPED) CHECK(bounds(node).upper->IsContext());
|
| + break;
|
| + }
|
|
|
| - case IrOpcode::kJSCallConstruct:
|
| - // Type is Receiver.
|
| - CHECK(bounds(node).upper->Is(Type::Receiver()));
|
| - break;
|
| - case IrOpcode::kJSCallFunction:
|
| - case IrOpcode::kJSCallRuntime:
|
| - case IrOpcode::kJSYield:
|
| - case IrOpcode::kJSDebugger:
|
| - // Type can be anything.
|
| - CHECK(bounds(node).upper->Is(Type::Any()));
|
| - break;
|
| -
|
| - // Simplified operators
|
| - // -------------------------------
|
| - case IrOpcode::kBooleanNot:
|
| - // Boolean -> Boolean
|
| - CHECK(bounds(Operand(node)).upper->Is(Type::Boolean()));
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| - case IrOpcode::kBooleanToNumber:
|
| - // Boolean -> Number
|
| - CHECK(bounds(Operand(node)).upper->Is(Type::Boolean()));
|
| - CHECK(bounds(node).upper->Is(Type::Number()));
|
| - break;
|
| - case IrOpcode::kNumberEqual:
|
| - case IrOpcode::kNumberLessThan:
|
| - case IrOpcode::kNumberLessThanOrEqual:
|
| - // (Number, Number) -> Boolean
|
| - CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number()));
|
| - CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number()));
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| - case IrOpcode::kNumberAdd:
|
| - case IrOpcode::kNumberSubtract:
|
| - case IrOpcode::kNumberMultiply:
|
| - case IrOpcode::kNumberDivide:
|
| - case IrOpcode::kNumberModulus:
|
| - // (Number, Number) -> Number
|
| - CHECK(bounds(Operand(node, 0)).upper->Is(Type::Number()));
|
| - CHECK(bounds(Operand(node, 1)).upper->Is(Type::Number()));
|
| - // TODO(rossberg): activate once we retype after opcode changes.
|
| - // CHECK(bounds(node).upper->Is(Type::Number()));
|
| - break;
|
| - case IrOpcode::kNumberToInt32:
|
| - // Number -> Signed32
|
| - CHECK(bounds(Operand(node)).upper->Is(Type::Number()));
|
| - CHECK(bounds(node).upper->Is(Type::Signed32()));
|
| - break;
|
| - case IrOpcode::kNumberToUint32:
|
| - // Number -> Unsigned32
|
| - CHECK(bounds(Operand(node)).upper->Is(Type::Number()));
|
| - CHECK(bounds(node).upper->Is(Type::Unsigned32()));
|
| - break;
|
| - case IrOpcode::kStringEqual:
|
| - case IrOpcode::kStringLessThan:
|
| - case IrOpcode::kStringLessThanOrEqual:
|
| - // (String, String) -> Boolean
|
| - CHECK(bounds(Operand(node, 0)).upper->Is(Type::String()));
|
| - CHECK(bounds(Operand(node, 1)).upper->Is(Type::String()));
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| - case IrOpcode::kStringAdd:
|
| - // (String, String) -> String
|
| - CHECK(bounds(Operand(node, 0)).upper->Is(Type::String()));
|
| - CHECK(bounds(Operand(node, 1)).upper->Is(Type::String()));
|
| - CHECK(bounds(node).upper->Is(Type::String()));
|
| - break;
|
| - case IrOpcode::kReferenceEqual: {
|
| - // (Unique, Any) -> Boolean and
|
| - // (Any, Unique) -> Boolean
|
| - CHECK(bounds(Operand(node, 0)).upper->Is(Type::Unique()) ||
|
| - bounds(Operand(node, 1)).upper->Is(Type::Unique()));
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| - }
|
| - case IrOpcode::kObjectIsSmi:
|
| - CHECK(bounds(Operand(node)).upper->Is(Type::Any()));
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| - case IrOpcode::kObjectIsNonNegativeSmi:
|
| - CHECK(bounds(Operand(node)).upper->Is(Type::Any()));
|
| - CHECK(bounds(node).upper->Is(Type::Boolean()));
|
| - break;
|
| -
|
| - case IrOpcode::kChangeTaggedToInt32: {
|
| - // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
|
| - // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| + case IrOpcode::kJSCallConstruct:
|
| + // Type is Receiver.
|
| + CheckUpperIs(node, Type::Receiver());
|
| + break;
|
| + case IrOpcode::kJSCallFunction:
|
| + case IrOpcode::kJSCallRuntime:
|
| + case IrOpcode::kJSYield:
|
| + case IrOpcode::kJSDebugger:
|
| + // Type can be anything.
|
| + CheckUpperIs(node, Type::Any());
|
| + break;
|
| +
|
| + // Simplified operators
|
| + // -------------------------------
|
| + case IrOpcode::kBooleanNot:
|
| + // Boolean -> Boolean
|
| + CheckValueInputIs(node, 0, Type::Boolean());
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| + case IrOpcode::kBooleanToNumber:
|
| + // Boolean -> Number
|
| + CheckValueInputIs(node, 0, Type::Boolean());
|
| + CheckUpperIs(node, Type::Number());
|
| + break;
|
| + case IrOpcode::kNumberEqual:
|
| + case IrOpcode::kNumberLessThan:
|
| + case IrOpcode::kNumberLessThanOrEqual:
|
| + // (Number, Number) -> Boolean
|
| + CheckValueInputIs(node, 0, Type::Number());
|
| + CheckValueInputIs(node, 1, Type::Number());
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| + case IrOpcode::kNumberAdd:
|
| + case IrOpcode::kNumberSubtract:
|
| + case IrOpcode::kNumberMultiply:
|
| + case IrOpcode::kNumberDivide:
|
| + case IrOpcode::kNumberModulus:
|
| + // (Number, Number) -> Number
|
| + CheckValueInputIs(node, 0, Type::Number());
|
| + CheckValueInputIs(node, 1, Type::Number());
|
| + // TODO(rossberg): activate once we retype after opcode changes.
|
| + // CheckUpperIs(node, Type::Number());
|
| + break;
|
| + case IrOpcode::kNumberToInt32:
|
| + // Number -> Signed32
|
| + CheckValueInputIs(node, 0, Type::Number());
|
| + CheckUpperIs(node, Type::Signed32());
|
| + break;
|
| + case IrOpcode::kNumberToUint32:
|
| + // Number -> Unsigned32
|
| + CheckValueInputIs(node, 0, Type::Number());
|
| + CheckUpperIs(node, Type::Unsigned32());
|
| + break;
|
| + case IrOpcode::kStringEqual:
|
| + case IrOpcode::kStringLessThan:
|
| + case IrOpcode::kStringLessThanOrEqual:
|
| + // (String, String) -> Boolean
|
| + CheckValueInputIs(node, 0, Type::String());
|
| + CheckValueInputIs(node, 1, Type::String());
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| + case IrOpcode::kStringAdd:
|
| + // (String, String) -> String
|
| + CheckValueInputIs(node, 0, Type::String());
|
| + CheckValueInputIs(node, 1, Type::String());
|
| + CheckUpperIs(node, Type::String());
|
| + break;
|
| + case IrOpcode::kReferenceEqual: {
|
| + // (Unique, Any) -> Boolean and
|
| + // (Any, Unique) -> Boolean
|
| + if (typing == TYPED) {
|
| + CHECK(bounds(ValueInput(node, 0)).upper->Is(Type::Unique()) ||
|
| + bounds(ValueInput(node, 1)).upper->Is(Type::Unique()));
|
| }
|
| - case IrOpcode::kChangeTaggedToUint32: {
|
| - // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
|
| - // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| - }
|
| - case IrOpcode::kChangeTaggedToFloat64: {
|
| - // Number /\ Tagged -> Number /\ UntaggedFloat64
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
|
| - // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| - }
|
| - case IrOpcode::kChangeInt32ToTagged: {
|
| - // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
|
| - // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| - }
|
| - case IrOpcode::kChangeUint32ToTagged: {
|
| - // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
|
| - // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| - }
|
| - case IrOpcode::kChangeFloat64ToTagged: {
|
| - // Number /\ UntaggedFloat64 -> Number /\ Tagged
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
|
| - // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| - }
|
| - case IrOpcode::kChangeBoolToBit: {
|
| - // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
|
| - // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| - }
|
| - case IrOpcode::kChangeBitToBool: {
|
| - // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
|
| - // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| - // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
|
| - // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
|
| - // CHECK(bounds(Operand(node)).upper->Is(from));
|
| - // CHECK(bounds(node).upper->Is(to));
|
| - break;
|
| - }
|
| -
|
| - case IrOpcode::kLoadField:
|
| - // Object -> fieldtype
|
| - // TODO(rossberg): activate once machine ops are typed.
|
| - // CHECK(bounds(Operand(node)).upper->Is(Type::Object()));
|
| - // CHECK(bounds(node).upper->Is(Field(node).type));
|
| - break;
|
| - case IrOpcode::kLoadElement:
|
| - // Object -> elementtype
|
| - // TODO(rossberg): activate once machine ops are typed.
|
| - // CHECK(bounds(Operand(node)).upper->Is(Type::Object()));
|
| - // CHECK(bounds(node).upper->Is(Element(node).type));
|
| - break;
|
| - case IrOpcode::kStoreField:
|
| - // (Object, fieldtype) -> _|_
|
| - // TODO(rossberg): activate once machine ops are typed.
|
| - // CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object()));
|
| - // CHECK(bounds(Operand(node, 1)).upper->Is(Field(node).type));
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| - case IrOpcode::kStoreElement:
|
| - // (Object, elementtype) -> _|_
|
| - // TODO(rossberg): activate once machine ops are typed.
|
| - // CHECK(bounds(Operand(node, 0)).upper->Is(Type::Object()));
|
| - // CHECK(bounds(Operand(node, 1)).upper->Is(Element(node).type));
|
| - CHECK(!NodeProperties::IsTyped(node));
|
| - break;
|
| -
|
| - // Machine operators
|
| - // -----------------------
|
| - case IrOpcode::kLoad:
|
| - case IrOpcode::kStore:
|
| - case IrOpcode::kWord32And:
|
| - case IrOpcode::kWord32Or:
|
| - case IrOpcode::kWord32Xor:
|
| - case IrOpcode::kWord32Shl:
|
| - case IrOpcode::kWord32Shr:
|
| - case IrOpcode::kWord32Sar:
|
| - case IrOpcode::kWord32Ror:
|
| - case IrOpcode::kWord32Equal:
|
| - case IrOpcode::kWord64And:
|
| - case IrOpcode::kWord64Or:
|
| - case IrOpcode::kWord64Xor:
|
| - case IrOpcode::kWord64Shl:
|
| - case IrOpcode::kWord64Shr:
|
| - case IrOpcode::kWord64Sar:
|
| - case IrOpcode::kWord64Ror:
|
| - case IrOpcode::kWord64Equal:
|
| - case IrOpcode::kInt32Add:
|
| - case IrOpcode::kInt32AddWithOverflow:
|
| - case IrOpcode::kInt32Sub:
|
| - case IrOpcode::kInt32SubWithOverflow:
|
| - case IrOpcode::kInt32Mul:
|
| - case IrOpcode::kInt32MulHigh:
|
| - case IrOpcode::kInt32Div:
|
| - case IrOpcode::kInt32Mod:
|
| - case IrOpcode::kInt32LessThan:
|
| - case IrOpcode::kInt32LessThanOrEqual:
|
| - case IrOpcode::kUint32Div:
|
| - case IrOpcode::kUint32Mod:
|
| - case IrOpcode::kUint32LessThan:
|
| - case IrOpcode::kUint32LessThanOrEqual:
|
| - case IrOpcode::kInt64Add:
|
| - case IrOpcode::kInt64Sub:
|
| - case IrOpcode::kInt64Mul:
|
| - case IrOpcode::kInt64Div:
|
| - case IrOpcode::kInt64Mod:
|
| - case IrOpcode::kInt64LessThan:
|
| - case IrOpcode::kInt64LessThanOrEqual:
|
| - case IrOpcode::kUint64Div:
|
| - case IrOpcode::kUint64Mod:
|
| - case IrOpcode::kUint64LessThan:
|
| - case IrOpcode::kFloat64Add:
|
| - case IrOpcode::kFloat64Sub:
|
| - case IrOpcode::kFloat64Mul:
|
| - case IrOpcode::kFloat64Div:
|
| - case IrOpcode::kFloat64Mod:
|
| - case IrOpcode::kFloat64Sqrt:
|
| - case IrOpcode::kFloat64Equal:
|
| - case IrOpcode::kFloat64LessThan:
|
| - case IrOpcode::kFloat64LessThanOrEqual:
|
| - case IrOpcode::kTruncateInt64ToInt32:
|
| - case IrOpcode::kTruncateFloat64ToFloat32:
|
| - case IrOpcode::kTruncateFloat64ToInt32:
|
| - case IrOpcode::kChangeInt32ToInt64:
|
| - case IrOpcode::kChangeUint32ToUint64:
|
| - case IrOpcode::kChangeInt32ToFloat64:
|
| - case IrOpcode::kChangeUint32ToFloat64:
|
| - case IrOpcode::kChangeFloat32ToFloat64:
|
| - case IrOpcode::kChangeFloat64ToInt32:
|
| - case IrOpcode::kChangeFloat64ToUint32:
|
| - case IrOpcode::kLoadStackPointer:
|
| - // TODO(rossberg): Check.
|
| - break;
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| + }
|
| + case IrOpcode::kObjectIsSmi:
|
| + CheckValueInputIs(node, 0, Type::Any());
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| + case IrOpcode::kObjectIsNonNegativeSmi:
|
| + CheckValueInputIs(node, 0, Type::Any());
|
| + CheckUpperIs(node, Type::Boolean());
|
| + break;
|
| +
|
| + case IrOpcode::kChangeTaggedToInt32: {
|
| + // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
|
| + // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| }
|
| + case IrOpcode::kChangeTaggedToUint32: {
|
| + // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
|
| + // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| + }
|
| + case IrOpcode::kChangeTaggedToFloat64: {
|
| + // Number /\ Tagged -> Number /\ UntaggedFloat64
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
|
| + // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| + }
|
| + case IrOpcode::kChangeInt32ToTagged: {
|
| + // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
|
| + // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| + }
|
| + case IrOpcode::kChangeUint32ToTagged: {
|
| + // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
|
| + // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| + }
|
| + case IrOpcode::kChangeFloat64ToTagged: {
|
| + // Number /\ UntaggedFloat64 -> Number /\ Tagged
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
|
| + // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| + }
|
| + case IrOpcode::kChangeBoolToBit: {
|
| + // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
|
| + // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| + }
|
| + case IrOpcode::kChangeBitToBool: {
|
| + // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
|
| + // TODO(neis): Activate once ChangeRepresentation works in typer.
|
| + // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
|
| + // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
|
| + // CheckValueInputIs(node, 0, from));
|
| + // CheckUpperIs(node, to));
|
| + break;
|
| + }
|
| +
|
| + case IrOpcode::kLoadField:
|
| + // Object -> fieldtype
|
| + // TODO(rossberg): activate once machine ops are typed.
|
| + // CheckValueInputIs(node, 0, Type::Object());
|
| + // CheckUpperIs(node, Field(node).type));
|
| + break;
|
| + case IrOpcode::kLoadElement:
|
| + // Object -> elementtype
|
| + // TODO(rossberg): activate once machine ops are typed.
|
| + // CheckValueInputIs(node, 0, Type::Object());
|
| + // CheckUpperIs(node, Element(node).type));
|
| + break;
|
| + case IrOpcode::kStoreField:
|
| + // (Object, fieldtype) -> _|_
|
| + // TODO(rossberg): activate once machine ops are typed.
|
| + // CheckValueInputIs(node, 0, Type::Object());
|
| + // CheckValueInputIs(node, 1, Field(node).type));
|
| + CheckNotTyped(node);
|
| + break;
|
| + case IrOpcode::kStoreElement:
|
| + // (Object, elementtype) -> _|_
|
| + // TODO(rossberg): activate once machine ops are typed.
|
| + // CheckValueInputIs(node, 0, Type::Object());
|
| + // CheckValueInputIs(node, 1, Element(node).type));
|
| + CheckNotTyped(node);
|
| + break;
|
| +
|
| + // Machine operators
|
| + // -----------------------
|
| + case IrOpcode::kLoad:
|
| + case IrOpcode::kStore:
|
| + case IrOpcode::kWord32And:
|
| + case IrOpcode::kWord32Or:
|
| + case IrOpcode::kWord32Xor:
|
| + case IrOpcode::kWord32Shl:
|
| + case IrOpcode::kWord32Shr:
|
| + case IrOpcode::kWord32Sar:
|
| + case IrOpcode::kWord32Ror:
|
| + case IrOpcode::kWord32Equal:
|
| + case IrOpcode::kWord64And:
|
| + case IrOpcode::kWord64Or:
|
| + case IrOpcode::kWord64Xor:
|
| + case IrOpcode::kWord64Shl:
|
| + case IrOpcode::kWord64Shr:
|
| + case IrOpcode::kWord64Sar:
|
| + case IrOpcode::kWord64Ror:
|
| + case IrOpcode::kWord64Equal:
|
| + case IrOpcode::kInt32Add:
|
| + case IrOpcode::kInt32AddWithOverflow:
|
| + case IrOpcode::kInt32Sub:
|
| + case IrOpcode::kInt32SubWithOverflow:
|
| + case IrOpcode::kInt32Mul:
|
| + case IrOpcode::kInt32MulHigh:
|
| + case IrOpcode::kInt32Div:
|
| + case IrOpcode::kInt32Mod:
|
| + case IrOpcode::kInt32LessThan:
|
| + case IrOpcode::kInt32LessThanOrEqual:
|
| + case IrOpcode::kUint32Div:
|
| + case IrOpcode::kUint32Mod:
|
| + case IrOpcode::kUint32LessThan:
|
| + case IrOpcode::kUint32LessThanOrEqual:
|
| + case IrOpcode::kInt64Add:
|
| + case IrOpcode::kInt64Sub:
|
| + case IrOpcode::kInt64Mul:
|
| + case IrOpcode::kInt64Div:
|
| + case IrOpcode::kInt64Mod:
|
| + case IrOpcode::kInt64LessThan:
|
| + case IrOpcode::kInt64LessThanOrEqual:
|
| + case IrOpcode::kUint64Div:
|
| + case IrOpcode::kUint64Mod:
|
| + case IrOpcode::kUint64LessThan:
|
| + case IrOpcode::kFloat64Add:
|
| + case IrOpcode::kFloat64Sub:
|
| + case IrOpcode::kFloat64Mul:
|
| + case IrOpcode::kFloat64Div:
|
| + case IrOpcode::kFloat64Mod:
|
| + case IrOpcode::kFloat64Sqrt:
|
| + case IrOpcode::kFloat64Equal:
|
| + case IrOpcode::kFloat64LessThan:
|
| + case IrOpcode::kFloat64LessThanOrEqual:
|
| + case IrOpcode::kTruncateInt64ToInt32:
|
| + case IrOpcode::kTruncateFloat64ToFloat32:
|
| + case IrOpcode::kTruncateFloat64ToInt32:
|
| + case IrOpcode::kChangeInt32ToInt64:
|
| + case IrOpcode::kChangeUint32ToUint64:
|
| + case IrOpcode::kChangeInt32ToFloat64:
|
| + case IrOpcode::kChangeUint32ToFloat64:
|
| + case IrOpcode::kChangeFloat32ToFloat64:
|
| + case IrOpcode::kChangeFloat64ToInt32:
|
| + case IrOpcode::kChangeFloat64ToUint32:
|
| + case IrOpcode::kLoadStackPointer:
|
| + // TODO(rossberg): Check.
|
| + break;
|
| }
|
|
|
| return GenericGraphVisit::CONTINUE;
|
|
|