OLD | NEW |
(Empty) | |
| 1 //===- subzero/src/IceTargetLoweringX8632.h - x86-32 lowering ---*- C++ -*-===// |
| 2 // |
| 3 // The Subzero Code Generator |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // This file declares the TargetLoweringX8632 class, which |
| 11 // implements the TargetLowering interface for the x86-32 |
| 12 // architecture. |
| 13 // |
| 14 //===----------------------------------------------------------------------===// |
| 15 |
| 16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632_H |
| 17 #define SUBZERO_SRC_ICETARGETLOWERINGX8632_H |
| 18 |
| 19 #include "IceDefs.h" |
| 20 #include "IceTargetLowering.h" |
| 21 #include "IceInstX8632.h" |
| 22 |
| 23 namespace Ice { |
| 24 |
| 25 class TargetX8632 : public TargetLowering { |
| 26 public: |
| 27 static TargetX8632 *create(Cfg *Func) { return new TargetX8632(Func); } |
| 28 |
| 29 virtual void translateOm1(); |
| 30 |
| 31 virtual Variable *getPhysicalRegister(SizeT RegNum); |
| 32 virtual IceString getRegName(SizeT RegNum, Type Ty) const; |
| 33 virtual llvm::SmallBitVector getRegisterSet(RegSetMask Include, |
| 34 RegSetMask Exclude) const; |
| 35 virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const { |
| 36 return TypeToRegisterSet[Ty]; |
| 37 } |
| 38 virtual bool hasFramePointer() const { return IsEbpBasedFrame; } |
| 39 virtual SizeT getFrameOrStackReg() const { |
| 40 return IsEbpBasedFrame ? Reg_ebp : Reg_esp; |
| 41 } |
| 42 virtual size_t typeWidthInBytesOnStack(Type Ty) { |
| 43 // Round up to the next multiple of 4 bytes. In particular, i1, |
| 44 // i8, and i16 are rounded up to 4 bytes. |
| 45 return (typeWidthInBytes(Ty) + 3) & ~3; |
| 46 } |
| 47 virtual void emitVariable(const Variable *Var, const Cfg *Func) const; |
| 48 virtual void addProlog(CfgNode *Node); |
| 49 virtual void addEpilog(CfgNode *Node); |
| 50 SizeT makeNextLabelNumber() { return NextLabelNumber++; } |
| 51 // Ensure that a 64-bit Variable has been split into 2 32-bit |
| 52 // Variables, creating them if necessary. This is needed for all |
| 53 // I64 operations, and it is needed for pushing F64 arguments for |
| 54 // function calls using the 32-bit push instruction (though the |
| 55 // latter could be done by directly writing to the stack). |
| 56 void split64(Variable *Var); |
| 57 void setArgOffsetAndCopy(Variable *Arg, Variable *FramePtr, |
| 58 int32_t BasicFrameOffset, int32_t &InArgsSizeBytes); |
| 59 Operand *loOperand(Operand *Operand); |
| 60 Operand *hiOperand(Operand *Operand); |
| 61 |
| 62 enum Registers { |
| 63 #define X(val, init, name, name16, name8, scratch, preserved, stackptr, \ |
| 64 frameptr, isI8, isInt, isFP) \ |
| 65 val init, |
| 66 REGX8632_TABLE |
| 67 #undef X |
| 68 Reg_NUM |
| 69 }; |
| 70 |
| 71 protected: |
| 72 TargetX8632(Cfg *Func); |
| 73 |
| 74 virtual void postLower(); |
| 75 |
| 76 virtual void lowerAlloca(const InstAlloca *Inst); |
| 77 virtual void lowerArithmetic(const InstArithmetic *Inst); |
| 78 virtual void lowerAssign(const InstAssign *Inst); |
| 79 virtual void lowerBr(const InstBr *Inst); |
| 80 virtual void lowerCall(const InstCall *Inst); |
| 81 virtual void lowerCast(const InstCast *Inst); |
| 82 virtual void lowerFcmp(const InstFcmp *Inst); |
| 83 virtual void lowerIcmp(const InstIcmp *Inst); |
| 84 virtual void lowerLoad(const InstLoad *Inst); |
| 85 virtual void lowerPhi(const InstPhi *Inst); |
| 86 virtual void lowerRet(const InstRet *Inst); |
| 87 virtual void lowerSelect(const InstSelect *Inst); |
| 88 virtual void lowerStore(const InstStore *Inst); |
| 89 virtual void lowerSwitch(const InstSwitch *Inst); |
| 90 virtual void lowerUnreachable(const InstUnreachable *Inst); |
| 91 |
| 92 // Operand legalization helpers. To deal with address mode |
| 93 // constraints, the helpers will create a new Operand and emit |
| 94 // instructions that guarantee that the Operand kind is one of those |
| 95 // indicated by the LegalMask (a bitmask of allowed kinds). If the |
| 96 // input Operand is known to already meet the constraints, it may be |
| 97 // simply returned as the result, without creating any new |
| 98 // instructions or operands. |
| 99 enum OperandLegalization { |
| 100 Legal_None = 0, |
| 101 Legal_Reg = 1 << 0, // physical register, not stack location |
| 102 Legal_Imm = 1 << 1, |
| 103 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12] |
| 104 Legal_All = ~Legal_None |
| 105 }; |
| 106 typedef uint32_t LegalMask; |
| 107 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, |
| 108 bool AllowOverlap = false, |
| 109 int32_t RegNum = Variable::NoRegister); |
| 110 Variable *legalizeToVar(Operand *From, bool AllowOverlap = false, |
| 111 int32_t RegNum = Variable::NoRegister); |
| 112 |
| 113 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 114 InstCall *makeHelperCall(const IceString &Name, Variable *Dest, |
| 115 SizeT MaxSrcs) { |
| 116 bool SuppressMangling = true; |
| 117 Type Ty = Dest ? Dest->getType() : IceType_void; |
| 118 Constant *CallTarget = Ctx->getConstantSym(Ty, 0, Name, SuppressMangling); |
| 119 InstCall *Call = InstCall::create(Func, MaxSrcs, Dest, CallTarget); |
| 120 return Call; |
| 121 } |
| 122 |
| 123 // The following are helpers that insert lowered x86 instructions |
| 124 // with minimal syntactic overhead, so that the lowering code can |
| 125 // look as close to assembly as practical. |
| 126 void _adc(Variable *Dest, Operand *Src0) { |
| 127 Context.insert(InstX8632Adc::create(Func, Dest, Src0)); |
| 128 } |
| 129 void _add(Variable *Dest, Operand *Src0) { |
| 130 Context.insert(InstX8632Add::create(Func, Dest, Src0)); |
| 131 } |
| 132 void _addss(Variable *Dest, Operand *Src0) { |
| 133 Context.insert(InstX8632Addss::create(Func, Dest, Src0)); |
| 134 } |
| 135 void _and(Variable *Dest, Operand *Src0) { |
| 136 Context.insert(InstX8632And::create(Func, Dest, Src0)); |
| 137 } |
| 138 void _br(InstX8632Br::BrCond Condition, CfgNode *TargetTrue, |
| 139 CfgNode *TargetFalse) { |
| 140 Context.insert( |
| 141 InstX8632Br::create(Func, TargetTrue, TargetFalse, Condition)); |
| 142 } |
| 143 void _br(CfgNode *Target) { |
| 144 Context.insert(InstX8632Br::create(Func, Target)); |
| 145 } |
| 146 void _br(InstX8632Br::BrCond Condition, CfgNode *Target) { |
| 147 Context.insert(InstX8632Br::create(Func, Target, Condition)); |
| 148 } |
| 149 void _br(InstX8632Br::BrCond Condition, InstX8632Label *Label) { |
| 150 Context.insert(InstX8632Br::create(Func, Label, Condition)); |
| 151 } |
| 152 void _cdq(Variable *Dest, Operand *Src0) { |
| 153 Context.insert(InstX8632Cdq::create(Func, Dest, Src0)); |
| 154 } |
| 155 void _cmp(Operand *Src0, Operand *Src1) { |
| 156 Context.insert(InstX8632Icmp::create(Func, Src0, Src1)); |
| 157 } |
| 158 void _cvt(Variable *Dest, Operand *Src0) { |
| 159 Context.insert(InstX8632Cvt::create(Func, Dest, Src0)); |
| 160 } |
| 161 void _div(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 162 Context.insert(InstX8632Div::create(Func, Dest, Src0, Src1)); |
| 163 } |
| 164 void _divss(Variable *Dest, Operand *Src0) { |
| 165 Context.insert(InstX8632Divss::create(Func, Dest, Src0)); |
| 166 } |
| 167 void _fld(Operand *Src0) { Context.insert(InstX8632Fld::create(Func, Src0)); } |
| 168 void _fstp(Variable *Dest) { |
| 169 Context.insert(InstX8632Fstp::create(Func, Dest)); |
| 170 } |
| 171 void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 172 Context.insert(InstX8632Idiv::create(Func, Dest, Src0, Src1)); |
| 173 } |
| 174 void _imul(Variable *Dest, Operand *Src0) { |
| 175 Context.insert(InstX8632Imul::create(Func, Dest, Src0)); |
| 176 } |
| 177 // If Dest=NULL is passed in, then a new variable is created, marked |
| 178 // as infinite register allocation weight, and returned through the |
| 179 // in/out Dest argument. |
| 180 void _mov(Variable *&Dest, Operand *Src0, |
| 181 int32_t RegNum = Variable::NoRegister) { |
| 182 if (Dest == NULL) { |
| 183 Dest = legalizeToVar(Src0, false, RegNum); |
| 184 } else { |
| 185 Context.insert(InstX8632Mov::create(Func, Dest, Src0)); |
| 186 } |
| 187 } |
| 188 void _movsx(Variable *Dest, Operand *Src0) { |
| 189 Context.insert(InstX8632Movsx::create(Func, Dest, Src0)); |
| 190 } |
| 191 void _movzx(Variable *Dest, Operand *Src0) { |
| 192 Context.insert(InstX8632Movzx::create(Func, Dest, Src0)); |
| 193 } |
| 194 void _mul(Variable *Dest, Variable *Src0, Operand *Src1) { |
| 195 Context.insert(InstX8632Mul::create(Func, Dest, Src0, Src1)); |
| 196 } |
| 197 void _mulss(Variable *Dest, Operand *Src0) { |
| 198 Context.insert(InstX8632Mulss::create(Func, Dest, Src0)); |
| 199 } |
| 200 void _or(Variable *Dest, Operand *Src0) { |
| 201 Context.insert(InstX8632Or::create(Func, Dest, Src0)); |
| 202 } |
| 203 void _pop(Variable *Dest) { |
| 204 Context.insert(InstX8632Pop::create(Func, Dest)); |
| 205 } |
| 206 void _push(Operand *Src0, bool SuppressStackAdjustment = false) { |
| 207 Context.insert(InstX8632Push::create(Func, Src0, SuppressStackAdjustment)); |
| 208 } |
| 209 void _ret(Variable *Src0 = NULL) { |
| 210 Context.insert(InstX8632Ret::create(Func, Src0)); |
| 211 } |
| 212 void _sar(Variable *Dest, Operand *Src0) { |
| 213 Context.insert(InstX8632Sar::create(Func, Dest, Src0)); |
| 214 } |
| 215 void _sbb(Variable *Dest, Operand *Src0) { |
| 216 Context.insert(InstX8632Sbb::create(Func, Dest, Src0)); |
| 217 } |
| 218 void _shl(Variable *Dest, Operand *Src0) { |
| 219 Context.insert(InstX8632Shl::create(Func, Dest, Src0)); |
| 220 } |
| 221 void _shld(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 222 Context.insert(InstX8632Shld::create(Func, Dest, Src0, Src1)); |
| 223 } |
| 224 void _shr(Variable *Dest, Operand *Src0) { |
| 225 Context.insert(InstX8632Shr::create(Func, Dest, Src0)); |
| 226 } |
| 227 void _shrd(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 228 Context.insert(InstX8632Shrd::create(Func, Dest, Src0, Src1)); |
| 229 } |
| 230 void _store(Operand *Value, OperandX8632 *Mem) { |
| 231 Context.insert(InstX8632Store::create(Func, Value, Mem)); |
| 232 } |
| 233 void _sub(Variable *Dest, Operand *Src0) { |
| 234 Context.insert(InstX8632Sub::create(Func, Dest, Src0)); |
| 235 } |
| 236 void _subss(Variable *Dest, Operand *Src0) { |
| 237 Context.insert(InstX8632Subss::create(Func, Dest, Src0)); |
| 238 } |
| 239 void _test(Operand *Src0, Operand *Src1) { |
| 240 Context.insert(InstX8632Test::create(Func, Src0, Src1)); |
| 241 } |
| 242 void _ucomiss(Operand *Src0, Operand *Src1) { |
| 243 Context.insert(InstX8632Ucomiss::create(Func, Src0, Src1)); |
| 244 } |
| 245 void _xor(Variable *Dest, Operand *Src0) { |
| 246 Context.insert(InstX8632Xor::create(Func, Dest, Src0)); |
| 247 } |
| 248 |
| 249 bool IsEbpBasedFrame; |
| 250 int32_t FrameSizeLocals; |
| 251 int32_t LocalsSizeBytes; |
| 252 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; |
| 253 llvm::SmallBitVector ScratchRegs; |
| 254 llvm::SmallBitVector RegsUsed; |
| 255 SizeT NextLabelNumber; |
| 256 bool ComputedLiveRanges; |
| 257 VarList PhysicalRegisters; |
| 258 static IceString RegNames[]; |
| 259 |
| 260 private: |
| 261 TargetX8632(const TargetX8632 &) LLVM_DELETED_FUNCTION; |
| 262 TargetX8632 &operator=(const TargetX8632 &) LLVM_DELETED_FUNCTION; |
| 263 virtual ~TargetX8632() {} |
| 264 }; |
| 265 |
| 266 } // end of namespace Ice |
| 267 |
| 268 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632_H |
OLD | NEW |