John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 1 | //===- subzero/src/IceInstX8664.cpp - X86-64 instruction implementation ---===// |
| 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 | /// \file |
Jim Stichnoth | 92a6e5b | 2015-12-02 16:52:44 -0800 | [diff] [blame] | 11 | /// \brief This file defines X8664 specific data related to X8664 Instructions |
| 12 | /// and Instruction traits. |
| 13 | /// |
| 14 | /// These are declared in the IceTargetLoweringX8664Traits.h header file. |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 15 | /// |
| 16 | /// This file also defines X8664 operand specific methods (dump and emit.) |
| 17 | /// |
| 18 | //===----------------------------------------------------------------------===// |
| 19 | #include "IceInstX8664.h" |
| 20 | |
| 21 | #include "IceAssemblerX8664.h" |
| 22 | #include "IceCfg.h" |
| 23 | #include "IceCfgNode.h" |
| 24 | #include "IceConditionCodesX8664.h" |
| 25 | #include "IceInst.h" |
| 26 | #include "IceRegistersX8664.h" |
| 27 | #include "IceTargetLoweringX8664.h" |
| 28 | #include "IceOperand.h" |
| 29 | |
| 30 | namespace Ice { |
| 31 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 32 | namespace X8664 { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 33 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 34 | const TargetX8664Traits::InstBrAttributesType |
| 35 | TargetX8664Traits::InstBrAttributes[] = { |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 36 | #define X(val, encode, opp, dump, emit) \ |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 37 | { X8664::Traits::Cond::opp, dump, emit } \ |
| 38 | , |
| 39 | ICEINSTX8664BR_TABLE |
| 40 | #undef X |
| 41 | }; |
| 42 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 43 | const TargetX8664Traits::InstCmppsAttributesType |
| 44 | TargetX8664Traits::InstCmppsAttributes[] = { |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 45 | #define X(val, emit) \ |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 46 | { emit } \ |
| 47 | , |
| 48 | ICEINSTX8664CMPPS_TABLE |
| 49 | #undef X |
| 50 | }; |
| 51 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 52 | const TargetX8664Traits::TypeAttributesType |
| 53 | TargetX8664Traits::TypeAttributes[] = { |
Nicolas Capens | 7638e27 | 2016-10-06 11:33:55 -0400 | [diff] [blame] | 54 | #define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld) \ |
| 55 | { cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld } \ |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 56 | , |
| 57 | ICETYPEX8664_TABLE |
| 58 | #undef X |
| 59 | }; |
| 60 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 61 | void TargetX8664Traits::X86Operand::dump(const Cfg *, Ostream &Str) const { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 62 | if (BuildDefs::dump()) |
| 63 | Str << "<OperandX8664>"; |
| 64 | } |
| 65 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 66 | TargetX8664Traits::X86OperandMem::X86OperandMem(Cfg *Func, Type Ty, |
| 67 | Variable *Base, |
| 68 | Constant *Offset, |
Jim Stichnoth | 8ff4b28 | 2016-01-04 15:39:06 -0800 | [diff] [blame] | 69 | Variable *Index, uint16_t Shift, |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 70 | bool IsRebased) |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 71 | : X86Operand(kMem, Ty), Base(Base), Offset(Offset), Index(Index), |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 72 | Shift(Shift), IsRebased(IsRebased) { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 73 | assert(Shift <= 3); |
| 74 | Vars = nullptr; |
| 75 | NumVars = 0; |
| 76 | if (Base) |
| 77 | ++NumVars; |
| 78 | if (Index) |
| 79 | ++NumVars; |
| 80 | if (NumVars) { |
| 81 | Vars = Func->allocateArrayOf<Variable *>(NumVars); |
| 82 | SizeT I = 0; |
| 83 | if (Base) |
| 84 | Vars[I++] = Base; |
| 85 | if (Index) |
| 86 | Vars[I++] = Index; |
| 87 | assert(I == NumVars); |
| 88 | } |
| 89 | } |
| 90 | |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 91 | namespace { |
Jim Stichnoth | 8aa3966 | 2016-02-10 11:20:30 -0800 | [diff] [blame] | 92 | int32_t getRematerializableOffset(Variable *Var, |
| 93 | const ::Ice::X8664::TargetX8664 *Target) { |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 94 | int32_t Disp = Var->getStackOffset(); |
Jim Stichnoth | 8aa3966 | 2016-02-10 11:20:30 -0800 | [diff] [blame] | 95 | const auto RegNum = Var->getRegNum(); |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 96 | if (RegNum == Target->getFrameReg()) { |
| 97 | Disp += Target->getFrameFixedAllocaOffset(); |
| 98 | } else if (RegNum != Target->getStackReg()) { |
| 99 | llvm::report_fatal_error("Unexpected rematerializable register type"); |
| 100 | } |
| 101 | return Disp; |
| 102 | } |
| 103 | } // end of anonymous namespace |
| 104 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 105 | void TargetX8664Traits::X86OperandMem::emit(const Cfg *Func) const { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 106 | if (!BuildDefs::dump()) |
| 107 | return; |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 108 | const auto *Target = |
| 109 | static_cast<const ::Ice::X8664::TargetX8664 *>(Func->getTarget()); |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 110 | // If the base is rematerializable, we need to replace it with the correct |
| 111 | // physical register (stack or base pointer), and update the Offset. |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 112 | const bool NeedSandboxing = Target->needSandboxing(); |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 113 | int32_t Disp = 0; |
| 114 | if (getBase() && getBase()->isRematerializable()) { |
| 115 | Disp += getRematerializableOffset(getBase(), Target); |
| 116 | } |
| 117 | // The index should never be rematerializable. But if we ever allow it, then |
| 118 | // we should make sure the rematerialization offset is shifted by the Shift |
| 119 | // value. |
| 120 | if (getIndex()) |
| 121 | assert(!getIndex()->isRematerializable()); |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 122 | Ostream &Str = Func->getContext()->getStrEmit(); |
Andrew Scull | 57e1268 | 2015-09-16 11:30:19 -0700 | [diff] [blame] | 123 | // Emit as Offset(Base,Index,1<<Shift). Offset is emitted without the leading |
| 124 | // '$'. Omit the (Base,Index,1<<Shift) part if Base==nullptr. |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 125 | if (getOffset() == nullptr && Disp == 0) { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 126 | // No offset, emit nothing. |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 127 | } else if (getOffset() == nullptr && Disp != 0) { |
| 128 | Str << Disp; |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 129 | } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 130 | if (Base == nullptr || CI->getValue() || Disp != 0) |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 131 | // Emit a non-zero offset without a leading '$'. |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 132 | Str << CI->getValue() + Disp; |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 133 | } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 134 | // TODO(sehr): ConstantRelocatable still needs updating for |
| 135 | // rematerializable base/index and Disp. |
| 136 | assert(Disp == 0); |
Karl Schimpf | d469994 | 2016-04-02 09:55:31 -0700 | [diff] [blame] | 137 | const bool UseNonsfi = getFlags().getUseNonsfi(); |
John Porto | d1bd1d3 | 2016-01-26 11:44:01 -0800 | [diff] [blame] | 138 | CR->emitWithoutPrefix(Target, UseNonsfi ? "@GOTOFF" : ""); |
| 139 | assert(!UseNonsfi); |
| 140 | if (Base == nullptr && Index == nullptr) { |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 141 | // rip-relative addressing. |
| 142 | if (NeedSandboxing) { |
| 143 | Str << "(%rip)"; |
| 144 | } else { |
| 145 | Str << "(%eip)"; |
John Porto | d1bd1d3 | 2016-01-26 11:44:01 -0800 | [diff] [blame] | 146 | } |
| 147 | } |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 148 | } else { |
| 149 | llvm_unreachable("Invalid offset type for x86 mem operand"); |
| 150 | } |
| 151 | |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 152 | if (Base == nullptr && Index == nullptr) { |
| 153 | return; |
| 154 | } |
| 155 | |
| 156 | Str << "("; |
| 157 | if (Base != nullptr) { |
| 158 | const Variable *B = Base; |
| 159 | if (!NeedSandboxing) { |
| 160 | // TODO(jpp): stop abusing the operand's type to identify LEAs. |
| 161 | const Type MemType = getType(); |
| 162 | if (Base->getType() != IceType_i32 && MemType != IceType_void) { |
John Porto | 008f4ce | 2015-12-24 13:22:18 -0800 | [diff] [blame] | 163 | // X86-64 is ILP32, but %rsp and %rbp are accessed as 64-bit registers. |
Manasij Mukherjee | fe2caab | 2016-06-27 15:42:12 -0700 | [diff] [blame] | 164 | // For filetype=asm, they need to be emitted as their 32-bit siblings. |
John Porto | 008f4ce | 2015-12-24 13:22:18 -0800 | [diff] [blame] | 165 | assert(Base->getType() == IceType_i64); |
Manasij Mukherjee | fe2caab | 2016-06-27 15:42:12 -0700 | [diff] [blame] | 166 | assert(getEncodedGPR(Base->getRegNum()) == RegX8664::Encoded_Reg_rsp || |
| 167 | getEncodedGPR(Base->getRegNum()) == RegX8664::Encoded_Reg_rbp || |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 168 | getType() == IceType_void); |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 169 | B = B->asType(Func, IceType_i32, X8664::Traits::getGprForType( |
| 170 | IceType_i32, Base->getRegNum())); |
John Porto | 008f4ce | 2015-12-24 13:22:18 -0800 | [diff] [blame] | 171 | } |
John Porto | 008f4ce | 2015-12-24 13:22:18 -0800 | [diff] [blame] | 172 | } |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 173 | |
| 174 | B->emit(Func); |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 175 | } |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 176 | |
| 177 | if (Index != nullptr) { |
| 178 | Variable *I = Index; |
| 179 | Str << ","; |
| 180 | I->emit(Func); |
| 181 | if (Shift) |
| 182 | Str << "," << (1u << Shift); |
| 183 | } |
| 184 | |
| 185 | Str << ")"; |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 186 | } |
| 187 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 188 | void TargetX8664Traits::X86OperandMem::dump(const Cfg *Func, |
| 189 | Ostream &Str) const { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 190 | if (!BuildDefs::dump()) |
| 191 | return; |
| 192 | bool Dumped = false; |
| 193 | Str << "["; |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 194 | int32_t Disp = 0; |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 195 | const auto *Target = |
| 196 | static_cast<const ::Ice::X8664::TargetX8664 *>(Func->getTarget()); |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 197 | if (getBase() && getBase()->isRematerializable()) { |
| 198 | Disp += getRematerializableOffset(getBase(), Target); |
| 199 | } |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 200 | if (Base) { |
| 201 | if (Func) |
| 202 | Base->dump(Func); |
| 203 | else |
| 204 | Base->dump(Str); |
| 205 | Dumped = true; |
| 206 | } |
| 207 | if (Index) { |
David Sehr | aa0b1a1 | 2015-10-27 16:55:40 -0700 | [diff] [blame] | 208 | if (Base) |
| 209 | Str << "+"; |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 210 | if (Shift > 0) |
| 211 | Str << (1u << Shift) << "*"; |
| 212 | if (Func) |
| 213 | Index->dump(Func); |
| 214 | else |
| 215 | Index->dump(Str); |
| 216 | Dumped = true; |
| 217 | } |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 218 | if (Disp) { |
| 219 | if (Disp > 0) |
| 220 | Str << "+"; |
| 221 | Str << Disp; |
| 222 | Dumped = true; |
| 223 | } |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 224 | // Pretty-print the Offset. |
| 225 | bool OffsetIsZero = false; |
| 226 | bool OffsetIsNegative = false; |
| 227 | if (!Offset) { |
| 228 | OffsetIsZero = true; |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 229 | } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 230 | OffsetIsZero = (CI->getValue() == 0); |
| 231 | OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0); |
| 232 | } else { |
| 233 | assert(llvm::isa<ConstantRelocatable>(Offset)); |
| 234 | } |
| 235 | if (Dumped) { |
| 236 | if (!OffsetIsZero) { // Suppress if Offset is known to be 0 |
| 237 | if (!OffsetIsNegative) // Suppress if Offset is known to be negative |
| 238 | Str << "+"; |
| 239 | Offset->dump(Func, Str); |
| 240 | } |
| 241 | } else { |
| 242 | // There is only the offset. |
| 243 | Offset->dump(Func, Str); |
| 244 | } |
| 245 | Str << "]"; |
| 246 | } |
| 247 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 248 | TargetX8664Traits::Address TargetX8664Traits::X86OperandMem::toAsmAddress( |
| 249 | TargetX8664Traits::Assembler *Asm, |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 250 | const Ice::TargetLowering *TargetLowering, bool IsLeaAddr) const { |
| 251 | (void)IsLeaAddr; |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 252 | const auto *Target = |
| 253 | static_cast<const ::Ice::X8664::TargetX8664 *>(TargetLowering); |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 254 | int32_t Disp = 0; |
| 255 | if (getBase() && getBase()->isRematerializable()) { |
| 256 | Disp += getRematerializableOffset(getBase(), Target); |
| 257 | } |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 258 | if (getIndex() != nullptr) { |
David Sehr | 4318a41 | 2015-11-11 15:01:55 -0800 | [diff] [blame] | 259 | assert(!getIndex()->isRematerializable()); |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 260 | } |
| 261 | |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 262 | AssemblerFixup *Fixup = nullptr; |
| 263 | // Determine the offset (is it relocatable?) |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 264 | if (getOffset() != nullptr) { |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 265 | if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) { |
John Porto | 3c275ce | 2015-12-22 08:14:00 -0800 | [diff] [blame] | 266 | Disp += static_cast<int32_t>(CI->getValue()); |
John Porto | d1bd1d3 | 2016-01-26 11:44:01 -0800 | [diff] [blame] | 267 | } else if (const auto *CR = |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 268 | llvm::dyn_cast<ConstantRelocatable>(getOffset())) { |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 269 | const auto FixupKind = |
| 270 | (getBase() != nullptr || getIndex() != nullptr) ? FK_Abs : FK_PcRel; |
| 271 | const RelocOffsetT DispAdjustment = FixupKind == FK_PcRel ? 4 : 0; |
| 272 | Fixup = Asm->createFixup(FixupKind, CR); |
| 273 | Fixup->set_addend(-DispAdjustment); |
John Porto | 6e8d3fa | 2016-02-04 10:35:20 -0800 | [diff] [blame] | 274 | Disp = CR->getOffset(); |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 275 | } else { |
| 276 | llvm_unreachable("Unexpected offset type"); |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | // Now convert to the various possible forms. |
| 281 | if (getBase() && getIndex()) { |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 282 | const bool NeedSandboxing = Target->needSandboxing(); |
| 283 | (void)NeedSandboxing; |
| 284 | assert(!NeedSandboxing || IsLeaAddr || |
John Porto | ac2388c | 2016-01-22 07:10:56 -0800 | [diff] [blame] | 285 | (getBase()->getRegNum() == Traits::RegisterSet::Reg_r15) || |
| 286 | (getBase()->getRegNum() == Traits::RegisterSet::Reg_rsp) || |
| 287 | (getBase()->getRegNum() == Traits::RegisterSet::Reg_rbp)); |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 288 | return X8664::Traits::Address(getEncodedGPR(getBase()->getRegNum()), |
| 289 | getEncodedGPR(getIndex()->getRegNum()), |
| 290 | X8664::Traits::ScaleFactor(getShift()), Disp, |
| 291 | Fixup); |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | if (getBase()) { |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 295 | return X8664::Traits::Address(getEncodedGPR(getBase()->getRegNum()), Disp, |
| 296 | Fixup); |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | if (getIndex()) { |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 300 | return X8664::Traits::Address(getEncodedGPR(getIndex()->getRegNum()), |
| 301 | X8664::Traits::ScaleFactor(getShift()), Disp, |
| 302 | Fixup); |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 303 | } |
John Porto | 56958cb | 2016-01-14 09:18:18 -0800 | [diff] [blame] | 304 | |
John Porto | d1bd1d3 | 2016-01-26 11:44:01 -0800 | [diff] [blame] | 305 | if (Fixup == nullptr) { |
| 306 | // Absolute addresses are not allowed in Nexes -- they must be rebased |
| 307 | // w.r.t. %r15. |
| 308 | // Exception: LEAs are fine because they do not touch memory. |
| 309 | assert(!Target->needSandboxing() || IsLeaAddr); |
| 310 | return X8664::Traits::Address::Absolute(Disp); |
| 311 | } |
| 312 | |
| 313 | return X8664::Traits::Address::RipRelative(Disp, Fixup); |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 314 | } |
| 315 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 316 | TargetX8664Traits::Address |
| 317 | TargetX8664Traits::VariableSplit::toAsmAddress(const Cfg *Func) const { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 318 | assert(!Var->hasReg()); |
| 319 | const ::Ice::TargetLowering *Target = Func->getTarget(); |
David Sehr | 26217e3 | 2015-11-26 13:03:50 -0800 | [diff] [blame] | 320 | int32_t Offset = Var->getStackOffset() + getOffset(); |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 321 | return X8664::Traits::Address(getEncodedGPR(Target->getFrameOrStackReg()), |
| 322 | Offset, AssemblerFixup::NoFixup); |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 323 | } |
| 324 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 325 | void TargetX8664Traits::VariableSplit::emit(const Cfg *Func) const { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 326 | if (!BuildDefs::dump()) |
| 327 | return; |
| 328 | Ostream &Str = Func->getContext()->getStrEmit(); |
| 329 | assert(!Var->hasReg()); |
| 330 | // The following is copied/adapted from TargetX8664::emitVariable(). |
| 331 | const ::Ice::TargetLowering *Target = Func->getTarget(); |
Jim Stichnoth | 5bff61c | 2015-10-28 09:26:00 -0700 | [diff] [blame] | 332 | constexpr Type Ty = IceType_i32; |
David Sehr | 26217e3 | 2015-11-26 13:03:50 -0800 | [diff] [blame] | 333 | int32_t Offset = Var->getStackOffset() + getOffset(); |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 334 | if (Offset) |
| 335 | Str << Offset; |
| 336 | Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; |
| 337 | } |
| 338 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 339 | void TargetX8664Traits::VariableSplit::dump(const Cfg *Func, |
| 340 | Ostream &Str) const { |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 341 | if (!BuildDefs::dump()) |
| 342 | return; |
| 343 | switch (Part) { |
| 344 | case Low: |
| 345 | Str << "low"; |
| 346 | break; |
| 347 | case High: |
| 348 | Str << "high"; |
| 349 | break; |
| 350 | } |
| 351 | Str << "("; |
| 352 | if (Func) |
| 353 | Var->dump(Func); |
| 354 | else |
| 355 | Var->dump(Str); |
| 356 | Str << ")"; |
| 357 | } |
| 358 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 359 | } // namespace X8664 |
John Porto | 453660f | 2015-07-31 14:52:52 -0700 | [diff] [blame] | 360 | } // end of namespace Ice |
| 361 | |
John Porto | 4a56686 | 2016-01-04 09:33:41 -0800 | [diff] [blame] | 362 | X86INSTS_DEFINE_STATIC_DATA(X8664, X8664::Traits) |