Index: src/compiler/instruction.h |
diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h |
index 3615e37affcc9053f029df2f67b34c36e949d893..4d6538c828acc26ea6757a84a9c1fd94b8c337fe 100644 |
--- a/src/compiler/instruction.h |
+++ b/src/compiler/instruction.h |
@@ -27,26 +27,13 @@ class Schedule; |
// A couple of reserved opcodes are used for internal use. |
const InstructionCode kSourcePositionInstruction = -1; |
-#define ALLOCATED_OPERAND_LIST(V) \ |
- V(StackSlot, STACK_SLOT) \ |
- V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ |
- V(Register, REGISTER) \ |
- V(DoubleRegister, DOUBLE_REGISTER) |
- |
class InstructionOperand { |
public: |
static const int kInvalidVirtualRegister = -1; |
- enum Kind { |
- INVALID, |
- UNALLOCATED, |
- CONSTANT, |
- IMMEDIATE, |
- STACK_SLOT, |
- DOUBLE_STACK_SLOT, |
- REGISTER, |
- DOUBLE_REGISTER |
- }; |
+ // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with |
+ // kInvalidVirtualRegister and some DCHECKS. |
+ enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, ALLOCATED }; |
InstructionOperand() |
: InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {} |
@@ -55,13 +42,18 @@ class InstructionOperand { |
#define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |
bool Is##name() const { return kind() == type; } |
- ALLOCATED_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
+ INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
+ INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |
INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) |
INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) |
- INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |
- INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
+ INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) |
#undef INSTRUCTION_OPERAND_PREDICATE |
+ inline bool IsRegister() const; |
+ inline bool IsDoubleRegister() const; |
+ inline bool IsStackSlot() const; |
+ inline bool IsDoubleStackSlot() const; |
+ |
bool Equals(const InstructionOperand* other) const { |
return value_ == other->value_; |
} |
@@ -84,7 +76,6 @@ class InstructionOperand { |
protected: |
InstructionOperand(Kind kind, int index, int virtual_register) { |
- if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
if (kind != UNALLOCATED && kind != CONSTANT) { |
DCHECK(virtual_register == kInvalidVirtualRegister); |
} |
@@ -109,6 +100,23 @@ struct PrintableInstructionOperand { |
std::ostream& operator<<(std::ostream& os, |
const PrintableInstructionOperand& op); |
+#define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind) \ |
+ \ |
+ static OperandType* cast(InstructionOperand* op) { \ |
+ DCHECK_EQ(OperandKind, op->kind()); \ |
+ return static_cast<OperandType*>(op); \ |
+ } \ |
+ \ |
+ static const OperandType* cast(const InstructionOperand* op) { \ |
+ DCHECK_EQ(OperandKind, op->kind()); \ |
+ return static_cast<const OperandType*>(op); \ |
+ } \ |
+ \ |
+ static OperandType cast(const InstructionOperand& op) { \ |
+ DCHECK_EQ(OperandKind, op.kind()); \ |
+ return *static_cast<const OperandType*>(&op); \ |
+ } |
+ |
class UnallocatedOperand : public InstructionOperand { |
public: |
enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY }; |
@@ -175,21 +183,6 @@ class UnallocatedOperand : public InstructionOperand { |
return New(zone, UnallocatedOperand(ANY, virtual_register())); |
} |
- static const UnallocatedOperand* cast(const InstructionOperand* op) { |
- DCHECK(op->IsUnallocated()); |
- return static_cast<const UnallocatedOperand*>(op); |
- } |
- |
- static UnallocatedOperand* cast(InstructionOperand* op) { |
- DCHECK(op->IsUnallocated()); |
- return static_cast<UnallocatedOperand*>(op); |
- } |
- |
- static UnallocatedOperand cast(const InstructionOperand& op) { |
- DCHECK(op.IsUnallocated()); |
- return *static_cast<const UnallocatedOperand*>(&op); |
- } |
- |
// The encoding used for UnallocatedOperand operands depends on the policy |
// that is |
// stored within the operand. The FIXED_SLOT policy uses a compact encoding |
@@ -297,6 +290,8 @@ class UnallocatedOperand : public InstructionOperand { |
DCHECK(basic_policy() == EXTENDED_POLICY); |
return LifetimeField::decode(value_) == USED_AT_START; |
} |
+ |
+ INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED); |
}; |
@@ -313,20 +308,7 @@ class ConstantOperand : public InstructionOperand { |
return InstructionOperand::New(zone, ConstantOperand(virtual_register)); |
} |
- static ConstantOperand* cast(InstructionOperand* op) { |
- DCHECK(op->kind() == CONSTANT); |
- return static_cast<ConstantOperand*>(op); |
- } |
- |
- static const ConstantOperand* cast(const InstructionOperand* op) { |
- DCHECK(op->kind() == CONSTANT); |
- return static_cast<const ConstantOperand*>(op); |
- } |
- |
- static ConstantOperand cast(const InstructionOperand& op) { |
- DCHECK(op.kind() == CONSTANT); |
- return *static_cast<const ConstantOperand*>(&op); |
- } |
+ INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT); |
}; |
@@ -343,93 +325,91 @@ class ImmediateOperand : public InstructionOperand { |
return InstructionOperand::New(zone, ImmediateOperand(index)); |
} |
- static ImmediateOperand* cast(InstructionOperand* op) { |
- DCHECK(op->kind() == IMMEDIATE); |
- return static_cast<ImmediateOperand*>(op); |
- } |
- |
- static const ImmediateOperand* cast(const InstructionOperand* op) { |
- DCHECK(op->kind() == IMMEDIATE); |
- return static_cast<const ImmediateOperand*>(op); |
- } |
- |
- static ImmediateOperand cast(const InstructionOperand& op) { |
- DCHECK(op.kind() == IMMEDIATE); |
- return *static_cast<const ImmediateOperand*>(&op); |
- } |
+ INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE); |
}; |
class AllocatedOperand : public InstructionOperand { |
-#define ALLOCATED_OPERAND_CHECK(Name, Kind) || kind == Kind |
-#define CHECK_ALLOCATED_KIND() \ |
- DCHECK(false ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CHECK)); \ |
- USE(kind); |
- |
public: |
+ enum AllocatedKind { |
+ STACK_SLOT, |
+ DOUBLE_STACK_SLOT, |
+ REGISTER, |
+ DOUBLE_REGISTER |
+ }; |
+ |
+ AllocatedOperand(AllocatedKind kind, int index) |
+ : InstructionOperand(ALLOCATED, index, kInvalidVirtualRegister) { |
+ if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
+ value_ = AllocatedKindField::update(value_, kind); |
+ } |
+ |
int index() const { |
return static_cast<int64_t>(value_) >> IndexField::kShift; |
} |
- AllocatedOperand(Kind kind, int index) |
- : InstructionOperand(kind, index, kInvalidVirtualRegister) { |
- CHECK_ALLOCATED_KIND(); |
+ AllocatedKind allocated_kind() const { |
+ return AllocatedKindField::decode(value_); |
} |
- static AllocatedOperand* New(Zone* zone, Kind kind, int index) { |
+ static AllocatedOperand* New(Zone* zone, AllocatedKind kind, int index) { |
return InstructionOperand::New(zone, AllocatedOperand(kind, index)); |
} |
- static AllocatedOperand* cast(InstructionOperand* op) { |
- Kind kind = op->kind(); |
- CHECK_ALLOCATED_KIND(); |
- return static_cast<AllocatedOperand*>(op); |
- } |
+ INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); |
- static const AllocatedOperand* cast(const InstructionOperand* op) { |
- Kind kind = op->kind(); |
- CHECK_ALLOCATED_KIND(); |
- return static_cast<const AllocatedOperand*>(op); |
- } |
+ private: |
+ typedef BitField64<AllocatedKind, 3, 2> AllocatedKindField; |
+}; |
- static AllocatedOperand cast(const InstructionOperand& op) { |
- Kind kind = op.kind(); |
- CHECK_ALLOCATED_KIND(); |
- return *static_cast<const AllocatedOperand*>(&op); |
- } |
-#undef CHECK_ALLOCATED_KIND |
-#undef ALLOCATED_OPERAND_CAST_CHECK |
-}; |
+#undef INSTRUCTION_OPERAND_CASTS |
+ |
+ |
+#define ALLOCATED_OPERAND_LIST(V) \ |
+ V(StackSlot, STACK_SLOT) \ |
+ V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ |
+ V(Register, REGISTER) \ |
+ V(DoubleRegister, DOUBLE_REGISTER) |
-#define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ |
- class SubKind##Operand FINAL : public AllocatedOperand { \ |
- public: \ |
- explicit SubKind##Operand(int index) \ |
- : AllocatedOperand(kOperandKind, index) {} \ |
- \ |
- static SubKind##Operand* New(Zone* zone, int index) { \ |
- return InstructionOperand::New(zone, SubKind##Operand(index)); \ |
- } \ |
- \ |
- static SubKind##Operand* cast(InstructionOperand* op) { \ |
- DCHECK(op->kind() == kOperandKind); \ |
- return reinterpret_cast<SubKind##Operand*>(op); \ |
- } \ |
- \ |
- static const SubKind##Operand* cast(const InstructionOperand* op) { \ |
- DCHECK(op->kind() == kOperandKind); \ |
- return reinterpret_cast<const SubKind##Operand*>(op); \ |
- } \ |
- \ |
- static SubKind##Operand cast(const InstructionOperand& op) { \ |
- DCHECK(op.kind() == kOperandKind); \ |
- return *static_cast<const SubKind##Operand*>(&op); \ |
- } \ |
+#define ALLOCATED_OPERAND_IS(SubKind, kOperandKind) \ |
+ bool InstructionOperand::Is##SubKind() const { \ |
+ return IsAllocated() && \ |
+ AllocatedOperand::cast(this)->allocated_kind() == \ |
+ AllocatedOperand::kOperandKind; \ |
+ } |
+ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_IS) |
+#undef ALLOCATED_OPERAND_IS |
+ |
+ |
+#define ALLOCATED_OPERAND_CLASS(SubKind, kOperandKind) \ |
+ class SubKind##Operand FINAL : public AllocatedOperand { \ |
+ public: \ |
+ explicit SubKind##Operand(int index) \ |
+ : AllocatedOperand(kOperandKind, index) {} \ |
+ \ |
+ static SubKind##Operand* New(Zone* zone, int index) { \ |
+ return InstructionOperand::New(zone, SubKind##Operand(index)); \ |
+ } \ |
+ \ |
+ static SubKind##Operand* cast(InstructionOperand* op) { \ |
+ DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \ |
+ return reinterpret_cast<SubKind##Operand*>(op); \ |
+ } \ |
+ \ |
+ static const SubKind##Operand* cast(const InstructionOperand* op) { \ |
+ DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \ |
+ return reinterpret_cast<const SubKind##Operand*>(op); \ |
+ } \ |
+ \ |
+ static SubKind##Operand cast(const InstructionOperand& op) { \ |
+ DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op).allocated_kind()); \ |
+ return *static_cast<const SubKind##Operand*>(&op); \ |
+ } \ |
}; |
-ALLOCATED_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS) |
-#undef INSTRUCTION_SUBKIND_OPERAND_CLASS |
+ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CLASS) |
+#undef ALLOCATED_OPERAND_CLASS |
class MoveOperands FINAL { |