| Index: src/IceOperand.h
|
| diff --git a/src/IceOperand.h b/src/IceOperand.h
|
| index 67b1d231fbf4a2985d521c76797947db5b3cbb45..94bc8abe9e44c1bdd7e43f50fafbe8d9eddf00bd 100644
|
| --- a/src/IceOperand.h
|
| +++ b/src/IceOperand.h
|
| @@ -43,6 +43,7 @@ public:
|
| kConst_Target, // leave space for target-specific constant kinds
|
| kConst_Max = kConst_Target + MaxTargetKinds,
|
| kVariable,
|
| + kVariable64On32,
|
| kVariable_Target, // leave space for target-specific variable kinds
|
| kVariable_Max = kVariable_Target + MaxTargetKinds,
|
| // Target-specific operand classes use kTarget as the starting point for
|
| @@ -411,7 +412,7 @@ class Variable : public Operand {
|
| Variable(const Variable &) = delete;
|
| Variable &operator=(const Variable &) = delete;
|
|
|
| - enum RegRequirement {
|
| + enum RegRequirement : uint8_t {
|
| RR_MayHaveRegister,
|
| RR_MustHaveRegister,
|
| RR_MustNotHaveRegister,
|
| @@ -424,7 +425,7 @@ public:
|
|
|
| SizeT getIndex() const { return Number; }
|
| IceString getName(const Cfg *Func) const;
|
| - void setName(Cfg *Func, const IceString &NewName) {
|
| + virtual void setName(Cfg *Func, const IceString &NewName) {
|
| // Make sure that the name can only be set once.
|
| assert(NameIndex == Cfg::IdentifierIndexInvalid);
|
| if (!NewName.empty())
|
| @@ -432,7 +433,7 @@ public:
|
| }
|
|
|
| bool getIsArg() const { return IsArgument; }
|
| - void setIsArg(bool Val = true) { IsArgument = Val; }
|
| + virtual void setIsArg(bool Val = true) { IsArgument = Val; }
|
| bool getIsImplicitArg() const { return IsImplicitArgument; }
|
| void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
|
|
|
| @@ -485,14 +486,6 @@ public:
|
| return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
|
| }
|
|
|
| - Variable *getLo() const { return LoVar; }
|
| - Variable *getHi() const { return HiVar; }
|
| - void setLoHi(Variable *Lo, Variable *Hi) {
|
| - assert(LoVar == nullptr);
|
| - assert(HiVar == nullptr);
|
| - LoVar = Lo;
|
| - HiVar = Hi;
|
| - }
|
| /// Creates a temporary copy of the variable with a different type. Used
|
| /// primarily for syntactic correctness of textual assembly emission. Note
|
| /// that only basic information is copied, in particular not IsArgument,
|
| @@ -529,28 +522,84 @@ protected:
|
| /// and validating live ranges. This is usually reserved for the stack
|
| /// pointer.
|
| bool IgnoreLiveness = false;
|
| - /// StackOffset is the canonical location on stack (only if RegNum==NoRegister
|
| - /// || IsArgument).
|
| - int32_t StackOffset = 0;
|
| + RegRequirement RegRequirement = RR_MayHaveRegister;
|
| /// RegNum is the allocated register, or NoRegister if it isn't
|
| /// register-allocated.
|
| int32_t RegNum = NoRegister;
|
| /// RegNumTmp is the tentative assignment during register allocation.
|
| int32_t RegNumTmp = NoRegister;
|
| - RegRequirement RegRequirement = RR_MayHaveRegister;
|
| + /// StackOffset is the canonical location on stack (only if
|
| + /// RegNum==NoRegister || IsArgument).
|
| + int32_t StackOffset = 0;
|
| LiveRange Live;
|
| - // LoVar and HiVar are needed for lowering from 64 to 32 bits. When lowering
|
| - // from I64 to I32 on a 32-bit architecture, we split the variable into two
|
| - // machine-size pieces. LoVar is the low-order machine-size portion, and
|
| - // HiVar is the remaining high-order portion.
|
| - // TODO: It's wasteful to penalize all variables on all targets this way; use
|
| - // a sparser representation. It's also wasteful for a 64-bit target.
|
| - Variable *LoVar = nullptr;
|
| - Variable *HiVar = nullptr;
|
| /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
|
| Variable *VarsReal[1];
|
| };
|
|
|
| +// Variable64On32 represents a 64-bit variable on a 32-bit architecture. In
|
| +// this situation the variable must be split into a low and a high word.
|
| +class Variable64On32 : public Variable {
|
| + Variable64On32() = delete;
|
| + Variable64On32(const Variable64On32 &) = delete;
|
| + Variable64On32 &operator=(const Variable64On32 &) = delete;
|
| +
|
| +public:
|
| + static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) {
|
| + return new (Func->allocate<Variable64On32>()) Variable64On32(
|
| + kVariable64On32, Ty, Index);
|
| + }
|
| +
|
| + void setName(Cfg *Func, const IceString &NewName) override {
|
| + Variable::setName(Func, NewName);
|
| + if (LoVar && HiVar) {
|
| + LoVar->setName(Func, getName(Func) + "__lo");
|
| + HiVar->setName(Func, getName(Func) + "__hi");
|
| + }
|
| + }
|
| +
|
| + void setIsArg(bool Val = true) override {
|
| + Variable::setIsArg(Val);
|
| + if (LoVar && HiVar) {
|
| + LoVar->setIsArg(Val);
|
| + HiVar->setIsArg(Val);
|
| + }
|
| + }
|
| +
|
| + Variable *getLo() const {
|
| + assert(LoVar != nullptr);
|
| + return LoVar;
|
| + }
|
| + Variable *getHi() const {
|
| + assert(HiVar != nullptr);
|
| + return HiVar;
|
| + }
|
| +
|
| + void initHiLo(Cfg *Func) {
|
| + assert(LoVar == nullptr);
|
| + assert(HiVar == nullptr);
|
| + LoVar = Func->makeVariable(IceType_i32);
|
| + HiVar = Func->makeVariable(IceType_i32);
|
| + LoVar->setIsArg(getIsArg());
|
| + HiVar->setIsArg(getIsArg());
|
| + LoVar->setName(Func, getName(Func) + "__lo");
|
| + HiVar->setName(Func, getName(Func) + "__hi");
|
| + }
|
| +
|
| + static bool classof(const Operand *Operand) {
|
| + OperandKind Kind = Operand->getKind();
|
| + return Kind == kVariable64On32;
|
| + }
|
| +
|
| +protected:
|
| + Variable64On32(OperandKind K, Type Ty, SizeT Index)
|
| + : Variable(K, Ty, Index) {
|
| + assert(typeWidthInBytes(Ty) == 8);
|
| + }
|
| +
|
| + Variable *LoVar = nullptr;
|
| + Variable *HiVar = nullptr;
|
| +};
|
| +
|
| enum MetadataKind {
|
| VMK_Uses, /// Track only uses, not defs
|
| VMK_SingleDefs, /// Track uses+defs, but only record single def
|
|
|