blob: 19e745f394d376a47d643cca519bb7b2c9474460 [file] [log] [blame]
John Porto7e93c622015-06-23 10:58:57 -07001//===- subzero/src/IceTargetLoweringX86Base.h - x86 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the TargetLoweringX86 template class, which implements the
12/// TargetLowering base interface for the x86 architecture.
Andrew Scull9612d322015-07-06 14:53:25 -070013///
John Porto7e93c622015-06-23 10:58:57 -070014//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H
17#define SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H
18
John Porto7e93c622015-06-23 10:58:57 -070019#include "IceDefs.h"
20#include "IceInst.h"
Andrew Scull87f80c12015-07-20 10:19:16 -070021#include "IceSwitchLowering.h"
John Porto7e93c622015-06-23 10:58:57 -070022#include "IceTargetLowering.h"
Jim Stichnothc59288b2015-11-09 11:38:40 -080023#include "IceTargetLoweringX86RegClass.h"
John Porto1d235422015-08-12 12:37:53 -070024#include "IceUtils.h"
John Porto7e93c622015-06-23 10:58:57 -070025
John Portobb0a5fe2015-09-04 11:23:41 -070026#include <array>
John Porto67f8de92015-06-25 10:14:17 -070027#include <type_traits>
John Porto5aeed952015-07-21 13:39:09 -070028#include <utility>
John Porto67f8de92015-06-25 10:14:17 -070029
John Porto4a566862016-01-04 09:33:41 -080030#ifndef X86NAMESPACE
31#error "You must define the X86 Target namespace."
32#endif
33
John Porto7e93c622015-06-23 10:58:57 -070034namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080035namespace X86NAMESPACE {
John Porto7e93c622015-06-23 10:58:57 -070036
John Porto4a566862016-01-04 09:33:41 -080037using namespace ::Ice::X86;
John Porto7e93c622015-06-23 10:58:57 -070038
John Porto4a566862016-01-04 09:33:41 -080039template <typename Traits> class BoolFolding;
John Porto7e93c622015-06-23 10:58:57 -070040
John Porto5aeed952015-07-21 13:39:09 -070041/// TargetX86Base is a template for all X86 Targets, and it relies on the CRT
42/// pattern for generating code, delegating to actual backends target-specific
43/// lowerings (e.g., call, ret, and intrinsics.) Backends are expected to
44/// implement the following methods (which should be accessible from
45/// TargetX86Base):
46///
47/// Operand *createNaClReadTPSrcOperand()
48///
49/// Note: Ideally, we should be able to
50///
John Porto4a566862016-01-04 09:33:41 -080051/// static_assert(std::is_base_of<TargetX86Base<TraitsType>,
52/// Machine>::value);
John Porto5aeed952015-07-21 13:39:09 -070053///
54/// but that does not work: the compiler does not know that Machine inherits
55/// from TargetX86Base at this point in translation.
John Porto4a566862016-01-04 09:33:41 -080056template <typename TraitsType> class TargetX86Base : public TargetLowering {
John Porto7e93c622015-06-23 10:58:57 -070057 TargetX86Base() = delete;
58 TargetX86Base(const TargetX86Base &) = delete;
59 TargetX86Base &operator=(const TargetX86Base &) = delete;
60
John Porto7e93c622015-06-23 10:58:57 -070061public:
John Porto4a566862016-01-04 09:33:41 -080062 using Traits = TraitsType;
John Porto4a566862016-01-04 09:33:41 -080063 using ConcreteTarget = typename Traits::ConcreteTarget;
64 using InstructionSetEnum = typename Traits::InstructionSet;
65
66 using BrCond = typename Traits::Cond::BrCond;
67 using CmppsCond = typename Traits::Cond::CmppsCond;
68
69 using X86Address = typename Traits::Address;
70 using X86Operand = typename Traits::X86Operand;
71 using X86OperandMem = typename Traits::X86OperandMem;
72 using SegmentRegisters = typename Traits::X86OperandMem::SegmentRegisters;
John Porto4a566862016-01-04 09:33:41 -080073
74 using InstX86Br = typename Traits::Insts::Br;
75 using InstX86FakeRMW = typename Traits::Insts::FakeRMW;
76 using InstX86Label = typename Traits::Insts::Label;
John Porto7e93c622015-06-23 10:58:57 -070077
John Porto5aeed952015-07-21 13:39:09 -070078 ~TargetX86Base() override = default;
John Porto7e93c622015-06-23 10:58:57 -070079
Karl Schimpf5403f5d2016-01-15 11:07:46 -080080 static void staticInit(GlobalContext *Ctx);
Jim Stichnoth467ffe52016-03-29 15:01:06 -070081 static bool shouldBePooled(const Constant *C);
Nicolas Capens32f9cce2016-10-19 01:24:27 -040082 static ::Ice::Type getPointerType();
John Porto7e93c622015-06-23 10:58:57 -070083
Jim Stichnoth8ff4b282016-01-04 15:39:06 -080084 static FixupKind getPcRelFixup() { return PcRelFixup; }
85 static FixupKind getAbsFixup() { return AbsFixup; }
86
John Porto56958cb2016-01-14 09:18:18 -080087 bool needSandboxing() const { return NeedSandboxing; }
88
John Porto7e93c622015-06-23 10:58:57 -070089 void translateOm1() override;
90 void translateO2() override;
91 void doLoadOpt();
92 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
93
John Porto5d0acff2015-06-30 15:29:21 -070094 SizeT getNumRegisters() const override {
95 return Traits::RegisterSet::Reg_NUM;
96 }
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -070097
98 Inst *createLoweredMove(Variable *Dest, Variable *SrcVar) override {
99 if (isVectorType(Dest->getType())) {
100 return Traits::Insts::Movp::create(Func, Dest, SrcVar);
101 }
102 return Traits::Insts::Mov::create(Func, Dest, SrcVar);
103 (void)Dest;
104 (void)SrcVar;
105 return nullptr;
106 }
107
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800108 Variable *getPhysicalRegister(RegNumT RegNum,
109 Type Ty = IceType_void) override;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700110 const char *getRegName(RegNumT RegNum, Type Ty) const override;
111 static const char *getRegClassName(RegClass C) {
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800112 auto ClassNum = static_cast<RegClassX86>(C);
113 assert(ClassNum < RCX86_NUM);
114 switch (ClassNum) {
115 default:
116 assert(C < RC_Target);
117 return regClassString(C);
118 case RCX86_Is64To8:
119 return "i64to8"; // 64-bit GPR truncable to i8
120 case RCX86_Is32To8:
121 return "i32to8"; // 32-bit GPR truncable to i8
122 case RCX86_Is16To8:
123 return "i16to8"; // 16-bit GPR truncable to i8
124 case RCX86_IsTrunc8Rcvr:
125 return "i8from"; // 8-bit GPR truncable from wider GPRs
126 case RCX86_IsAhRcvr:
127 return "i8fromah"; // 8-bit GPR that ah can be assigned to
128 }
129 }
John Portoe82b5602016-02-24 15:58:55 -0800130 SmallBitVector getRegisterSet(RegSetMask Include,
131 RegSetMask Exclude) const override;
132 const SmallBitVector &
Jim Stichnothc59288b2015-11-09 11:38:40 -0800133 getRegistersForVariable(const Variable *Var) const override {
134 RegClass RC = Var->getRegClass();
135 assert(static_cast<RegClassX86>(RC) < RCX86_NUM);
136 return TypeToRegisterSet[RC];
John Porto7e93c622015-06-23 10:58:57 -0700137 }
John Portobb0a5fe2015-09-04 11:23:41 -0700138
John Portoe82b5602016-02-24 15:58:55 -0800139 const SmallBitVector &
Jim Stichnothb40595a2016-01-29 06:14:31 -0800140 getAllRegistersForVariable(const Variable *Var) const override {
141 RegClass RC = Var->getRegClass();
142 assert(static_cast<RegClassX86>(RC) < RCX86_NUM);
143 return TypeToRegisterSetUnfiltered[RC];
144 }
145
John Portoe82b5602016-02-24 15:58:55 -0800146 const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800147 Reg.assertIsValid();
John Portobb0a5fe2015-09-04 11:23:41 -0700148 return RegisterAliases[Reg];
149 }
150
John Porto7e93c622015-06-23 10:58:57 -0700151 bool hasFramePointer() const override { return IsEbpBasedFrame; }
David Sehre39d0ca2015-11-06 11:25:41 -0800152 void setHasFramePointer() override { IsEbpBasedFrame = true; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800153 RegNumT getStackReg() const override { return Traits::StackPtr; }
154 RegNumT getFrameReg() const override { return Traits::FramePtr; }
155 RegNumT getFrameOrStackReg() const override {
Nicolas Capens4e679e52017-01-12 17:01:06 -0500156 // If the stack pointer needs to be aligned, then the frame pointer is
157 // unaligned, so always use the stack pointer.
158 if (needsStackPointerAlignment())
159 return getStackReg();
David Sehr2f3b8ec2015-11-16 16:51:39 -0800160 return IsEbpBasedFrame ? getFrameReg() : getStackReg();
John Porto7e93c622015-06-23 10:58:57 -0700161 }
162 size_t typeWidthInBytesOnStack(Type Ty) const override {
John Porto1d235422015-08-12 12:37:53 -0700163 // Round up to the next multiple of WordType bytes.
164 const uint32_t WordSizeInBytes = typeWidthInBytes(Traits::WordType);
165 return Utils::applyAlignment(typeWidthInBytes(Ty), WordSizeInBytes);
John Porto7e93c622015-06-23 10:58:57 -0700166 }
David Sehre39d0ca2015-11-06 11:25:41 -0800167 uint32_t getStackAlignment() const override {
168 return Traits::X86_STACK_ALIGNMENT_BYTES;
169 }
Nicolas Capens4e679e52017-01-12 17:01:06 -0500170 bool needsStackPointerAlignment() const override {
171 // If the ABI's stack alignment is smaller than the vector size (16 bytes),
172 // use the (realigned) stack pointer for addressing any stack variables.
173 return Traits::X86_STACK_ALIGNMENT_BYTES < 16;
174 }
David Sehr2f3b8ec2015-11-16 16:51:39 -0800175 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
176 FixedAllocaSizeBytes = Size;
177 assert(llvm::isPowerOf2_32(Align));
178 FixedAllocaAlignBytes = Align;
179 PrologEmitsFixedAllocas = true;
180 }
181 /// Returns the (negative) offset from ebp/rbp where the fixed Allocas start.
182 int32_t getFrameFixedAllocaOffset() const override {
David Sehr26217e32015-11-26 13:03:50 -0800183 return FixedAllocaSizeBytes - (SpillAreaSizeBytes - maxOutArgsSizeBytes());
184 }
185 virtual uint32_t maxOutArgsSizeBytes() const override {
186 return MaxOutArgsSizeBytes;
187 }
188 virtual void updateMaxOutArgsSizeBytes(uint32_t Size) {
189 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, Size);
David Sehr2f3b8ec2015-11-16 16:51:39 -0800190 }
John Porto7e93c622015-06-23 10:58:57 -0700191
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700192 bool shouldSplitToVariable64On32(Type Ty) const override {
193 return Traits::Is64Bit ? false : Ty == IceType_i64;
194 }
195
John Porto6e8d3fa2016-02-04 10:35:20 -0800196 ConstantRelocatable *createGetIPForRegister(const Variable *Dest) {
197 assert(Dest->hasReg());
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700198 const std::string RegName = Traits::getRegName(Dest->getRegNum());
199 return llvm::cast<ConstantRelocatable>(Ctx->getConstantExternSym(
200 Ctx->getGlobalString(H_getIP_prefix + RegName)));
John Porto6e8d3fa2016-02-04 10:35:20 -0800201 }
202
Andrew Scull87f80c12015-07-20 10:19:16 -0700203 SizeT getMinJumpTableSize() const override { return 4; }
204
John Porto7e93c622015-06-23 10:58:57 -0700205 void emitVariable(const Variable *Var) const override;
206
John Porto7e93c622015-06-23 10:58:57 -0700207 void emit(const ConstantInteger32 *C) const final;
208 void emit(const ConstantInteger64 *C) const final;
209 void emit(const ConstantFloat *C) const final;
210 void emit(const ConstantDouble *C) const final;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800211 void emit(const ConstantUndef *C) const final;
212 void emit(const ConstantRelocatable *C) const final;
John Porto7e93c622015-06-23 10:58:57 -0700213
John Porto7e93c622015-06-23 10:58:57 -0700214 void initNodeForLowering(CfgNode *Node) override;
John Porto1d235422015-08-12 12:37:53 -0700215
216 template <typename T = Traits>
217 typename std::enable_if<!T::Is64Bit, Operand>::type *
218 loOperand(Operand *Operand);
219 template <typename T = Traits>
220 typename std::enable_if<T::Is64Bit, Operand>::type *loOperand(Operand *) {
221 llvm::report_fatal_error(
222 "Hey, yo! This is x86-64. Watcha doin'? (loOperand)");
223 }
224
225 template <typename T = Traits>
226 typename std::enable_if<!T::Is64Bit, Operand>::type *
227 hiOperand(Operand *Operand);
228 template <typename T = Traits>
229 typename std::enable_if<T::Is64Bit, Operand>::type *hiOperand(Operand *) {
230 llvm::report_fatal_error(
231 "Hey, yo! This is x86-64. Watcha doin'? (hiOperand)");
232 }
233
David Sehrb9a404d2016-01-21 08:09:27 -0800234 void addProlog(CfgNode *Node) override;
John Porto7e93c622015-06-23 10:58:57 -0700235 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
Jim Stichnoth55f931f2015-09-23 16:33:08 -0700236 size_t BasicFrameOffset, size_t StackAdjBytes,
237 size_t &InArgsSizeBytes);
David Sehrb9a404d2016-01-21 08:09:27 -0800238 void addEpilog(CfgNode *Node) override;
John Porto4a566862016-01-04 09:33:41 -0800239 X86Address stackVarToAsmOperand(const Variable *Var) const;
John Porto7e93c622015-06-23 10:58:57 -0700240
John Porto4a566862016-01-04 09:33:41 -0800241 InstructionSetEnum getInstructionSet() const { return InstructionSet; }
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800242 Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700243
244protected:
John Porto56958cb2016-01-14 09:18:18 -0800245 const bool NeedSandboxing;
246
John Porto7e93c622015-06-23 10:58:57 -0700247 explicit TargetX86Base(Cfg *Func);
248
249 void postLower() override;
250
John Portoac2388c2016-01-22 07:10:56 -0800251 /// Initializes the RebasePtr member variable -- if so required by
252 /// SandboxingType for the concrete Target.
253 void initRebasePtr() {
254 assert(SandboxingType != ST_None);
255 dispatchToConcrete(&Traits::ConcreteTarget::initRebasePtr);
256 }
257
258 /// Emit code that initializes the value of the RebasePtr near the start of
259 /// the function -- if so required by SandboxingType for the concrete type.
John Porto56958cb2016-01-14 09:18:18 -0800260 void initSandbox() {
John Portoac2388c2016-01-22 07:10:56 -0800261 assert(SandboxingType != ST_None);
John Porto56958cb2016-01-14 09:18:18 -0800262 dispatchToConcrete(&Traits::ConcreteTarget::initSandbox);
263 }
264
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800265 void lowerAlloca(const InstAlloca *Instr) override;
David Sehr0c68bef2016-01-20 10:00:23 -0800266 void lowerArguments() override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800267 void lowerArithmetic(const InstArithmetic *Instr) override;
268 void lowerAssign(const InstAssign *Instr) override;
269 void lowerBr(const InstBr *Instr) override;
Eric Holk67c7c412016-04-15 13:05:37 -0700270 void lowerBreakpoint(const InstBreakpoint *Instr) override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800271 void lowerCall(const InstCall *Instr) override;
272 void lowerCast(const InstCast *Instr) override;
273 void lowerExtractElement(const InstExtractElement *Instr) override;
274 void lowerFcmp(const InstFcmp *Instr) override;
275 void lowerIcmp(const InstIcmp *Instr) override;
John Porto1d235422015-08-12 12:37:53 -0700276
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800277 void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
278 void lowerInsertElement(const InstInsertElement *Instr) override;
279 void lowerLoad(const InstLoad *Instr) override;
280 void lowerPhi(const InstPhi *Instr) override;
281 void lowerRet(const InstRet *Instr) override;
282 void lowerSelect(const InstSelect *Instr) override;
John Portoa47c11c2016-04-21 05:53:42 -0700283 void lowerShuffleVector(const InstShuffleVector *Instr) override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800284 void lowerStore(const InstStore *Instr) override;
285 void lowerSwitch(const InstSwitch *Instr) override;
286 void lowerUnreachable(const InstUnreachable *Instr) override;
John Porto7e93c622015-06-23 10:58:57 -0700287 void lowerOther(const Inst *Instr) override;
John Porto4a566862016-01-04 09:33:41 -0800288 void lowerRMW(const InstX86FakeRMW *RMW);
John Porto7e93c622015-06-23 10:58:57 -0700289 void prelowerPhis() override;
John Portoe82b5602016-02-24 15:58:55 -0800290 uint32_t getCallStackArgumentsSizeBytes(const CfgVector<Type> &ArgTypes,
David Sehr26217e32015-11-26 13:03:50 -0800291 Type ReturnType);
David Sehr4163b9f2015-11-20 21:09:31 -0800292 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
David Sehr26217e32015-11-26 13:03:50 -0800293 void genTargetHelperCallFor(Inst *Instr) override;
John Portoac2388c2016-01-22 07:10:56 -0800294
295 /// OptAddr wraps all the possible operands that an x86 address might have.
296 struct OptAddr {
297 Variable *Base = nullptr;
298 Variable *Index = nullptr;
299 uint16_t Shift = 0;
300 int32_t Offset = 0;
301 ConstantRelocatable *Relocatable = nullptr;
302 };
303 /// Legalizes Addr w.r.t. SandboxingType. The exact type of legalization
304 /// varies for different <Target, SandboxingType> tuples.
305 bool legalizeOptAddrForSandbox(OptAddr *Addr) {
306 return dispatchToConcrete(
307 &Traits::ConcreteTarget::legalizeOptAddrForSandbox, std::move(Addr));
308 }
309 // Builds information for a canonical address expresion:
310 // <Relocatable + Offset>(Base, Index, Shift)
311 X86OperandMem *computeAddressOpt(const Inst *Instr, Type MemType,
312 Operand *Addr);
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700313 void doAddressOptOther() override;
John Porto7e93c622015-06-23 10:58:57 -0700314 void doAddressOptLoad() override;
315 void doAddressOptStore() override;
Jim Stichnothad2989b2015-09-15 10:21:42 -0700316 void doMockBoundsCheck(Operand *Opnd) override;
Qining Luaee5fa82015-08-20 14:59:03 -0700317 void randomlyInsertNop(float Probability,
318 RandomNumberGenerator &RNG) override;
John Porto7e93c622015-06-23 10:58:57 -0700319
Andrew Scull9612d322015-07-06 14:53:25 -0700320 /// Naive lowering of cmpxchg.
John Porto7e93c622015-06-23 10:58:57 -0700321 void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
322 Operand *Desired);
Andrew Scull9612d322015-07-06 14:53:25 -0700323 /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
John Porto7e93c622015-06-23 10:58:57 -0700324 bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr,
325 Operand *Expected, Operand *Desired);
326 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
327 Operand *Val);
328 void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal,
329 Operand *SecondVal);
Andrew Scullcfa628b2015-08-20 14:23:05 -0700330 /// Load from memory for a given type.
331 void typedLoad(Type Ty, Variable *Dest, Variable *Base, Constant *Offset);
332 /// Store to memory for a given type.
333 void typedStore(Type Ty, Variable *Value, Variable *Base, Constant *Offset);
334 /// Copy memory of given type from Src to Dest using OffsetAmt on both.
335 void copyMemory(Type Ty, Variable *Dest, Variable *Src, int32_t OffsetAmt);
336 /// Replace some calls to memcpy with inline instructions.
Andrew Scull9df4a372015-08-07 09:19:35 -0700337 void lowerMemcpy(Operand *Dest, Operand *Src, Operand *Count);
Andrew Scullcfa628b2015-08-20 14:23:05 -0700338 /// Replace some calls to memmove with inline instructions.
339 void lowerMemmove(Operand *Dest, Operand *Src, Operand *Count);
340 /// Replace some calls to memset with inline instructions.
Andrew Scull713dbde2015-08-04 14:25:27 -0700341 void lowerMemset(Operand *Dest, Operand *Val, Operand *Count);
342
Andrew Scull86df4e92015-07-30 13:54:44 -0700343 /// Lower an indirect jump adding sandboxing when needed.
John Porto56958cb2016-01-14 09:18:18 -0800344 void lowerIndirectJump(Variable *JumpTarget) {
345 // Without std::move below, the compiler deduces that the argument to
346 // lowerIndirectJmp is a Variable *&, not a Variable *.
347 dispatchToConcrete(&Traits::ConcreteTarget::lowerIndirectJump,
348 std::move(JumpTarget));
349 }
John Porto7e93c622015-06-23 10:58:57 -0700350
Andrew Scull87f80c12015-07-20 10:19:16 -0700351 /// Check the comparison is in [Min,Max]. The flags register will be modified
352 /// with:
353 /// - below equal, if in range
354 /// - above, set if not in range
355 /// The index into the range is returned.
356 Operand *lowerCmpRange(Operand *Comparison, uint64_t Min, uint64_t Max);
357 /// Lowering of a cluster of switch cases. If the case is not matched control
358 /// will pass to the default label provided. If the default label is nullptr
359 /// then control will fall through to the next instruction. DoneCmp should be
360 /// true if the flags contain the result of a comparison with the Comparison.
361 void lowerCaseCluster(const CaseCluster &Case, Operand *Src0, bool DoneCmp,
362 CfgNode *DefaultLabel = nullptr);
363
Andrew Scull8072bae2015-09-14 16:01:26 -0700364 using LowerBinOp = void (TargetX86Base::*)(Variable *, Operand *);
John Porto7e93c622015-06-23 10:58:57 -0700365 void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi,
366 Variable *Dest, Operand *Ptr, Operand *Val);
367
368 void eliminateNextVectorSextInstruction(Variable *SignExtendedResult);
369
David Sehrb9a404d2016-01-21 08:09:27 -0800370 void emitGetIP(CfgNode *Node) {
371 dispatchToConcrete(&Traits::ConcreteTarget::emitGetIP, std::move(Node));
372 }
373 /// Emit a sandboxed return sequence rather than a return.
374 void emitSandboxedReturn() {
375 dispatchToConcrete(&Traits::ConcreteTarget::emitSandboxedReturn);
376 }
David Sehr0c68bef2016-01-20 10:00:23 -0800377 /// Emit just the call instruction (without argument or return variable
378 /// processing), sandboxing if needed.
Jim Stichnothc10c1562016-03-10 08:19:34 -0800379 virtual Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) = 0;
David Sehr0c68bef2016-01-20 10:00:23 -0800380 /// Materialize the moves needed to return a value of the specified type.
Jim Stichnothc10c1562016-03-10 08:19:34 -0800381 virtual Variable *moveReturnValueToRegister(Operand *Value,
382 Type ReturnType) = 0;
David Sehr0c68bef2016-01-20 10:00:23 -0800383
David Sehr6b80cf12016-01-21 23:16:58 -0800384 /// Emit a jump table to the constant pool.
385 void emitJumpTable(const Cfg *Func,
386 const InstJumpTable *JumpTable) const override;
387
David Sehr21fd1032015-11-13 16:32:37 -0800388 /// Emit a fake use of esp to make sure esp stays alive for the entire
389 /// function. Otherwise some esp adjustments get dead-code eliminated.
390 void keepEspLiveAtExit() {
John Porto008f4ce2015-12-24 13:22:18 -0800391 Variable *esp =
392 Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
John Porto1d937a82015-12-17 06:19:34 -0800393 Context.insert<InstFakeUse>(esp);
David Sehr21fd1032015-11-13 16:32:37 -0800394 }
395
Andrew Scull57e12682015-09-16 11:30:19 -0700396 /// Operand legalization helpers. To deal with address mode constraints, the
397 /// helpers will create a new Operand and emit instructions that guarantee
398 /// that the Operand kind is one of those indicated by the LegalMask (a
399 /// bitmask of allowed kinds). If the input Operand is known to already meet
400 /// the constraints, it may be simply returned as the result, without creating
401 /// any new instructions or operands.
John Porto7e93c622015-06-23 10:58:57 -0700402 enum OperandLegalization {
403 Legal_None = 0,
404 Legal_Reg = 1 << 0, // physical register, not stack location
405 Legal_Imm = 1 << 1,
406 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12]
David Sehr4318a412015-11-11 15:01:55 -0800407 Legal_Rematerializable = 1 << 3,
John Portoac2388c2016-01-22 07:10:56 -0800408 Legal_AddrAbs = 1 << 4, // ConstantRelocatable doesn't have to add RebasePtr
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800409 Legal_Default = ~(Legal_Rematerializable | Legal_AddrAbs)
410 // TODO(stichnot): Figure out whether this default works for x86-64.
John Porto7e93c622015-06-23 10:58:57 -0700411 };
Andrew Scull8072bae2015-09-14 16:01:26 -0700412 using LegalMask = uint32_t;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800413 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800414 RegNumT RegNum = RegNumT());
415 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
Andrew Scull9612d322015-07-06 14:53:25 -0700416 /// Legalize the first source operand for use in the cmp instruction.
John Porto7e93c622015-06-23 10:58:57 -0700417 Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
Andrew Scull57e12682015-09-16 11:30:19 -0700418 /// Turn a pointer operand into a memory operand that can be used by a real
419 /// load/store operation. Legalizes the operand as well. This is a nop if the
420 /// operand is already a legal memory operand.
John Porto4a566862016-01-04 09:33:41 -0800421 X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
422 bool DoLegalize = true);
John Porto7e93c622015-06-23 10:58:57 -0700423
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800424 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700425 static Type stackSlotType();
426
Andrew Scullcfa628b2015-08-20 14:23:05 -0700427 static constexpr uint32_t NoSizeLimit = 0;
Andrew Scullcfa628b2015-08-20 14:23:05 -0700428 /// Returns the largest type which is equal to or larger than Size bytes. The
Andrew Scull57e12682015-09-16 11:30:19 -0700429 /// type is suitable for copying memory i.e. a load and store will be a single
430 /// instruction (for example x86 will get f64 not i64).
Andrew Scullcfa628b2015-08-20 14:23:05 -0700431 static Type largestTypeInSize(uint32_t Size, uint32_t MaxSize = NoSizeLimit);
432 /// Returns the smallest type which is equal to or larger than Size bytes. If
433 /// one doesn't exist then the largest type smaller than Size bytes is
434 /// returned. The type is suitable for memory copies as described at
435 /// largestTypeInSize.
436 static Type firstTypeThatFitsSize(uint32_t Size,
437 uint32_t MaxSize = NoSizeLimit);
438
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800439 Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT());
440 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700441
Jim Stichnoth99165662015-11-13 14:20:40 -0800442 /// Returns a register containing all zeros, without affecting the FLAGS
443 /// register, using the best instruction for the type.
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800444 Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT());
Jim Stichnoth99165662015-11-13 14:20:40 -0800445
Andrew Scull713dbde2015-08-04 14:25:27 -0700446 /// \name Returns a vector in a register with the given constant entries.
447 /// @{
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800448 Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
449 Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT());
450 Variable *makeVectorOfMinusOnes(Type Ty, RegNumT RegNum = RegNumT());
451 Variable *makeVectorOfHighOrderBits(Type Ty, RegNumT RegNum = RegNumT());
452 Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT());
Andrew Scull713dbde2015-08-04 14:25:27 -0700453 /// @}
John Porto7e93c622015-06-23 10:58:57 -0700454
Andrew Scull9612d322015-07-06 14:53:25 -0700455 /// Return a memory operand corresponding to a stack allocated Variable.
John Porto4a566862016-01-04 09:33:41 -0800456 X86OperandMem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
457 uint32_t Offset = 0);
John Porto7e93c622015-06-23 10:58:57 -0700458
Qining Luaee5fa82015-08-20 14:59:03 -0700459 void
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800460 makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
John Portoe82b5602016-02-24 15:58:55 -0800461 const SmallBitVector &ExcludeRegisters,
Qining Luaee5fa82015-08-20 14:59:03 -0700462 uint64_t Salt) const override;
John Porto7e93c622015-06-23 10:58:57 -0700463
John Porto56958cb2016-01-14 09:18:18 -0800464 /// AutoMemorySandboxer emits a bundle-lock/bundle-unlock pair if the
465 /// instruction's operand is a memory reference. This is only needed for
466 /// x86-64 NaCl sandbox.
467 template <InstBundleLock::Option BundleLockOpt = InstBundleLock::Opt_None>
468 class AutoMemorySandboxer {
469 AutoMemorySandboxer() = delete;
470 AutoMemorySandboxer(const AutoMemorySandboxer &) = delete;
471 AutoMemorySandboxer &operator=(const AutoMemorySandboxer &) = delete;
472
473 private:
474 typename Traits::TargetLowering *Target;
475
476 template <typename T, typename... Tail>
477 X86OperandMem **findMemoryReference(T **First, Tail... Others) {
478 if (llvm::isa<X86OperandMem>(*First)) {
479 return reinterpret_cast<X86OperandMem **>(First);
480 }
481 return findMemoryReference(Others...);
482 }
483
484 X86OperandMem **findMemoryReference() { return nullptr; }
485
486 public:
John Porto4abbb592016-03-10 10:59:02 -0800487 AutoBundle *Bundler = nullptr;
John Porto56958cb2016-01-14 09:18:18 -0800488 X86OperandMem **const MemOperand;
489
490 template <typename... T>
491 AutoMemorySandboxer(typename Traits::TargetLowering *Target, T... Args)
John Portoac2388c2016-01-22 07:10:56 -0800492 : Target(Target), MemOperand(Target->SandboxingType == ST_None
493 ? nullptr
494 : findMemoryReference(Args...)) {
John Porto56958cb2016-01-14 09:18:18 -0800495 if (MemOperand != nullptr) {
John Porto8347abd2016-02-04 09:12:02 -0800496 if (Traits::Is64Bit) {
John Porto4abbb592016-03-10 10:59:02 -0800497 Bundler = new (Target->Func->template allocate<AutoBundle>())
498 AutoBundle(Target, BundleLockOpt);
John Porto8347abd2016-02-04 09:12:02 -0800499 }
John Porto56958cb2016-01-14 09:18:18 -0800500 *MemOperand = Target->_sandbox_mem_reference(*MemOperand);
501 }
502 }
503
John Porto4abbb592016-03-10 10:59:02 -0800504 ~AutoMemorySandboxer() {
505 if (Bundler != nullptr) {
506 Bundler->~AutoBundle();
507 }
508 }
John Porto56958cb2016-01-14 09:18:18 -0800509 };
510
Andrew Scull57e12682015-09-16 11:30:19 -0700511 /// The following are helpers that insert lowered x86 instructions with
512 /// minimal syntactic overhead, so that the lowering code can look as close to
513 /// assembly as practical.
John Porto7e93c622015-06-23 10:58:57 -0700514 void _adc(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800515 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800516 Context.insert<typename Traits::Insts::Adc>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700517 }
John Porto4a566862016-01-04 09:33:41 -0800518 void _adc_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800519 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800520 Context.insert<typename Traits::Insts::AdcRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700521 }
522 void _add(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800523 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800524 Context.insert<typename Traits::Insts::Add>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700525 }
John Porto4a566862016-01-04 09:33:41 -0800526 void _add_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800527 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800528 Context.insert<typename Traits::Insts::AddRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700529 }
John Porto7e93c622015-06-23 10:58:57 -0700530 void _addps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800531 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800532 Context.insert<typename Traits::Insts::Addps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700533 }
534 void _addss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800535 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800536 Context.insert<typename Traits::Insts::Addss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700537 }
John Porto56958cb2016-01-14 09:18:18 -0800538 void _add_sp(Operand *Adjustment) {
539 dispatchToConcrete(&Traits::ConcreteTarget::_add_sp, std::move(Adjustment));
540 }
John Porto7e93c622015-06-23 10:58:57 -0700541 void _and(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800542 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800543 Context.insert<typename Traits::Insts::And>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700544 }
David Sehre3984282015-12-15 17:34:55 -0800545 void _andnps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800546 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800547 Context.insert<typename Traits::Insts::Andnps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800548 }
549 void _andps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800550 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800551 Context.insert<typename Traits::Insts::Andps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800552 }
John Porto4a566862016-01-04 09:33:41 -0800553 void _and_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800554 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800555 Context.insert<typename Traits::Insts::AndRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700556 }
557 void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800558 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800559 Context.insert<typename Traits::Insts::Blendvps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700560 }
John Porto4a566862016-01-04 09:33:41 -0800561 void _br(BrCond Condition, CfgNode *TargetTrue, CfgNode *TargetFalse) {
562 Context.insert<InstX86Br>(TargetTrue, TargetFalse, Condition,
563 InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700564 }
565 void _br(CfgNode *Target) {
John Porto4a566862016-01-04 09:33:41 -0800566 Context.insert<InstX86Br>(Target, InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700567 }
John Porto4a566862016-01-04 09:33:41 -0800568 void _br(BrCond Condition, CfgNode *Target) {
569 Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700570 }
John Porto4a566862016-01-04 09:33:41 -0800571 void _br(BrCond Condition, InstX86Label *Label,
572 typename InstX86Br::Mode Kind = InstX86Br::Near) {
573 Context.insert<InstX86Br>(Label, Condition, Kind);
John Porto7e93c622015-06-23 10:58:57 -0700574 }
575 void _bsf(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800576 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800577 Context.insert<typename Traits::Insts::Bsf>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700578 }
579 void _bsr(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800580 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800581 Context.insert<typename Traits::Insts::Bsr>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700582 }
583 void _bswap(Variable *SrcDest) {
John Porto56958cb2016-01-14 09:18:18 -0800584 AutoMemorySandboxer<> _(this, &SrcDest);
John Porto1d937a82015-12-17 06:19:34 -0800585 Context.insert<typename Traits::Insts::Bswap>(SrcDest);
John Porto7e93c622015-06-23 10:58:57 -0700586 }
587 void _cbwdq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800588 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800589 Context.insert<typename Traits::Insts::Cbwdq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700590 }
John Porto4a566862016-01-04 09:33:41 -0800591 void _cmov(Variable *Dest, Operand *Src0, BrCond Condition) {
John Porto56958cb2016-01-14 09:18:18 -0800592 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800593 Context.insert<typename Traits::Insts::Cmov>(Dest, Src0, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700594 }
595 void _cmp(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800596 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800597 Context.insert<typename Traits::Insts::Icmp>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700598 }
John Porto4a566862016-01-04 09:33:41 -0800599 void _cmpps(Variable *Dest, Operand *Src0, CmppsCond Condition) {
John Porto56958cb2016-01-14 09:18:18 -0800600 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800601 Context.insert<typename Traits::Insts::Cmpps>(Dest, Src0, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700602 }
603 void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
604 bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -0800605 AutoMemorySandboxer<> _(this, &DestOrAddr);
John Porto1d937a82015-12-17 06:19:34 -0800606 Context.insert<typename Traits::Insts::Cmpxchg>(DestOrAddr, Eax, Desired,
607 Locked);
John Porto7e93c622015-06-23 10:58:57 -0700608 // Mark eax as possibly modified by cmpxchg.
John Porto1d937a82015-12-17 06:19:34 -0800609 Context.insert<InstFakeDef>(Eax, llvm::dyn_cast<Variable>(DestOrAddr));
Jim Stichnoth230d4102015-09-25 17:40:32 -0700610 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800611 Context.insert<InstFakeUse>(Eax);
John Porto7e93c622015-06-23 10:58:57 -0700612 }
John Porto4a566862016-01-04 09:33:41 -0800613 void _cmpxchg8b(X86OperandMem *Addr, Variable *Edx, Variable *Eax,
614 Variable *Ecx, Variable *Ebx, bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -0800615 AutoMemorySandboxer<> _(this, &Addr);
John Porto1d937a82015-12-17 06:19:34 -0800616 Context.insert<typename Traits::Insts::Cmpxchg8b>(Addr, Edx, Eax, Ecx, Ebx,
617 Locked);
John Porto7e93c622015-06-23 10:58:57 -0700618 // Mark edx, and eax as possibly modified by cmpxchg8b.
John Porto1d937a82015-12-17 06:19:34 -0800619 Context.insert<InstFakeDef>(Edx);
Jim Stichnoth230d4102015-09-25 17:40:32 -0700620 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800621 Context.insert<InstFakeUse>(Edx);
622 Context.insert<InstFakeDef>(Eax);
Jim Stichnoth230d4102015-09-25 17:40:32 -0700623 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800624 Context.insert<InstFakeUse>(Eax);
John Porto7e93c622015-06-23 10:58:57 -0700625 }
John Porto921856d2015-07-07 11:56:26 -0700626 void _cvt(Variable *Dest, Operand *Src0,
627 typename Traits::Insts::Cvt::CvtVariant Variant) {
John Porto56958cb2016-01-14 09:18:18 -0800628 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800629 Context.insert<typename Traits::Insts::Cvt>(Dest, Src0, Variant);
John Porto7e93c622015-06-23 10:58:57 -0700630 }
Nicolas Capensf0d12c32016-10-27 15:17:41 -0400631 void _round(Variable *Dest, Operand *Src0, Operand *Imm) {
632 AutoMemorySandboxer<> _(this, &Dest, &Src0);
633 Context.insert<typename Traits::Insts::Round>(Dest, Src0, Imm);
634 }
John Porto7e93c622015-06-23 10:58:57 -0700635 void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800636 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800637 Context.insert<typename Traits::Insts::Div>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700638 }
639 void _divps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800640 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800641 Context.insert<typename Traits::Insts::Divps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700642 }
643 void _divss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800644 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800645 Context.insert<typename Traits::Insts::Divss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700646 }
John Porto453660f2015-07-31 14:52:52 -0700647 template <typename T = Traits>
648 typename std::enable_if<T::UsesX87, void>::type _fld(Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800649 AutoMemorySandboxer<> _(this, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800650 Context.insert<typename Traits::Insts::template Fld<>>(Src0);
John Porto921856d2015-07-07 11:56:26 -0700651 }
John Porto453660f2015-07-31 14:52:52 -0700652 // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
653 // does not invoke this method, and remove it.
654 template <typename T = Traits>
655 typename std::enable_if<!T::UsesX87, void>::type _fld(Operand *) {
656 llvm::report_fatal_error("fld is not available in x86-64");
657 }
658 template <typename T = Traits>
659 typename std::enable_if<T::UsesX87, void>::type _fstp(Variable *Dest) {
John Porto56958cb2016-01-14 09:18:18 -0800660 AutoMemorySandboxer<> _(this, &Dest);
John Porto1d937a82015-12-17 06:19:34 -0800661 Context.insert<typename Traits::Insts::template Fstp<>>(Dest);
John Porto453660f2015-07-31 14:52:52 -0700662 }
663 // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
664 // does not invoke this method, and remove it.
665 template <typename T = Traits>
666 typename std::enable_if<!T::UsesX87, void>::type _fstp(Variable *) {
667 llvm::report_fatal_error("fstp is not available in x86-64");
John Porto7e93c622015-06-23 10:58:57 -0700668 }
669 void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800670 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800671 Context.insert<typename Traits::Insts::Idiv>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700672 }
673 void _imul(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800674 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800675 Context.insert<typename Traits::Insts::Imul>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700676 }
David Sehre11f8782015-10-06 10:26:57 -0700677 void _imul_imm(Variable *Dest, Operand *Src0, Constant *Imm) {
John Porto56958cb2016-01-14 09:18:18 -0800678 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800679 Context.insert<typename Traits::Insts::ImulImm>(Dest, Src0, Imm);
David Sehre11f8782015-10-06 10:26:57 -0700680 }
John Porto7e93c622015-06-23 10:58:57 -0700681 void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800682 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800683 Context.insert<typename Traits::Insts::Insertps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700684 }
Eric Holk67c7c412016-04-15 13:05:37 -0700685 void _int3() { Context.insert<typename Traits::Insts::Int3>(); }
John Porto7e93c622015-06-23 10:58:57 -0700686 void _jmp(Operand *Target) {
John Porto56958cb2016-01-14 09:18:18 -0800687 AutoMemorySandboxer<> _(this, &Target);
John Porto1d937a82015-12-17 06:19:34 -0800688 Context.insert<typename Traits::Insts::Jmp>(Target);
John Porto7e93c622015-06-23 10:58:57 -0700689 }
690 void _lea(Variable *Dest, Operand *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800691 Context.insert<typename Traits::Insts::Lea>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700692 }
David Sehrb9a404d2016-01-21 08:09:27 -0800693 void _link_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_link_bp); }
694 void _push_reg(Variable *Reg) {
695 dispatchToConcrete(&Traits::ConcreteTarget::_push_reg, std::move(Reg));
696 }
John Porto1d937a82015-12-17 06:19:34 -0800697 void _mfence() { Context.insert<typename Traits::Insts::Mfence>(); }
David Sehre3984282015-12-15 17:34:55 -0800698 /// Moves can be used to redefine registers, creating "partial kills" for
699 /// liveness. Mark where moves are used in this way.
700 void _redefined(Inst *MovInst, bool IsRedefinition = true) {
701 if (IsRedefinition)
702 MovInst->setDestRedefined();
703 }
Andrew Scull57e12682015-09-16 11:30:19 -0700704 /// If Dest=nullptr is passed in, then a new variable is created, marked as
705 /// infinite register allocation weight, and returned through the in/out Dest
706 /// argument.
John Porto1d937a82015-12-17 06:19:34 -0800707 typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800708 RegNumT RegNum = RegNumT()) {
John Porto7e93c622015-06-23 10:58:57 -0700709 if (Dest == nullptr)
710 Dest = makeReg(Src0->getType(), RegNum);
John Porto56958cb2016-01-14 09:18:18 -0800711 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800712 return Context.insert<typename Traits::Insts::Mov>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800713 }
John Porto56958cb2016-01-14 09:18:18 -0800714 void _mov_sp(Operand *NewValue) {
715 dispatchToConcrete(&Traits::ConcreteTarget::_mov_sp, std::move(NewValue));
716 }
John Porto1d937a82015-12-17 06:19:34 -0800717 typename Traits::Insts::Movp *_movp(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800718 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800719 return Context.insert<typename Traits::Insts::Movp>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700720 }
721 void _movd(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800722 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800723 Context.insert<typename Traits::Insts::Movd>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700724 }
John Porto7e93c622015-06-23 10:58:57 -0700725 void _movq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800726 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800727 Context.insert<typename Traits::Insts::Movq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700728 }
729 void _movss(Variable *Dest, Variable *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800730 Context.insert<typename Traits::Insts::MovssRegs>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700731 }
732 void _movsx(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800733 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800734 Context.insert<typename Traits::Insts::Movsx>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700735 }
John Porto56958cb2016-01-14 09:18:18 -0800736 typename Traits::Insts::Movzx *_movzx(Variable *Dest, Operand *Src0) {
737 AutoMemorySandboxer<> _(this, &Dest, &Src0);
738 return Context.insert<typename Traits::Insts::Movzx>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700739 }
David Sehre3984282015-12-15 17:34:55 -0800740 void _maxss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800741 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800742 Context.insert<typename Traits::Insts::Maxss>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800743 }
744 void _minss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800745 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800746 Context.insert<typename Traits::Insts::Minss>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800747 }
John Porto7e93c622015-06-23 10:58:57 -0700748 void _mul(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800749 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800750 Context.insert<typename Traits::Insts::Mul>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700751 }
752 void _mulps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800753 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800754 Context.insert<typename Traits::Insts::Mulps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700755 }
756 void _mulss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800757 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800758 Context.insert<typename Traits::Insts::Mulss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700759 }
760 void _neg(Variable *SrcDest) {
John Porto56958cb2016-01-14 09:18:18 -0800761 AutoMemorySandboxer<> _(this, &SrcDest);
John Porto1d937a82015-12-17 06:19:34 -0800762 Context.insert<typename Traits::Insts::Neg>(SrcDest);
John Porto7e93c622015-06-23 10:58:57 -0700763 }
764 void _nop(SizeT Variant) {
John Porto1d937a82015-12-17 06:19:34 -0800765 Context.insert<typename Traits::Insts::Nop>(Variant);
John Porto7e93c622015-06-23 10:58:57 -0700766 }
767 void _or(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800768 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800769 Context.insert<typename Traits::Insts::Or>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700770 }
David Sehre3984282015-12-15 17:34:55 -0800771 void _orps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800772 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800773 Context.insert<typename Traits::Insts::Orps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800774 }
John Porto4a566862016-01-04 09:33:41 -0800775 void _or_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800776 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800777 Context.insert<typename Traits::Insts::OrRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700778 }
779 void _padd(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800780 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800781 Context.insert<typename Traits::Insts::Padd>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700782 }
Nicolas Capens67a49b52016-10-26 13:18:35 -0400783 void _padds(Variable *Dest, Operand *Src0) {
784 AutoMemorySandboxer<> _(this, &Dest, &Src0);
785 Context.insert<typename Traits::Insts::Padds>(Dest, Src0);
786 }
787 void _paddus(Variable *Dest, Operand *Src0) {
788 AutoMemorySandboxer<> _(this, &Dest, &Src0);
789 Context.insert<typename Traits::Insts::Paddus>(Dest, Src0);
790 }
John Porto7e93c622015-06-23 10:58:57 -0700791 void _pand(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800792 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800793 Context.insert<typename Traits::Insts::Pand>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700794 }
795 void _pandn(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800796 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800797 Context.insert<typename Traits::Insts::Pandn>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700798 }
799 void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800800 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800801 Context.insert<typename Traits::Insts::Pblendvb>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700802 }
David Sehrb19d39c2016-01-13 14:17:37 -0800803 void _pcmpeq(Variable *Dest, Operand *Src0,
804 Type ArithmeticTypeOverride = IceType_void) {
John Porto56958cb2016-01-14 09:18:18 -0800805 AutoMemorySandboxer<> _(this, &Dest, &Src0);
David Sehrb19d39c2016-01-13 14:17:37 -0800806 Context.insert<typename Traits::Insts::Pcmpeq>(Dest, Src0,
807 ArithmeticTypeOverride);
John Porto7e93c622015-06-23 10:58:57 -0700808 }
809 void _pcmpgt(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800810 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800811 Context.insert<typename Traits::Insts::Pcmpgt>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700812 }
813 void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800814 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800815 Context.insert<typename Traits::Insts::Pextr>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700816 }
817 void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800818 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800819 Context.insert<typename Traits::Insts::Pinsr>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700820 }
821 void _pmull(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800822 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800823 Context.insert<typename Traits::Insts::Pmull>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700824 }
Nicolas Capens13cde0f2016-10-26 10:36:11 -0400825 void _pmulhw(Variable *Dest, Operand *Src0) {
826 AutoMemorySandboxer<> _(this, &Dest, &Src0);
827 Context.insert<typename Traits::Insts::Pmulhw>(Dest, Src0);
828 }
829 void _pmulhuw(Variable *Dest, Operand *Src0) {
830 AutoMemorySandboxer<> _(this, &Dest, &Src0);
831 Context.insert<typename Traits::Insts::Pmulhuw>(Dest, Src0);
832 }
833 void _pmaddwd(Variable *Dest, Operand *Src0) {
834 AutoMemorySandboxer<> _(this, &Dest, &Src0);
835 Context.insert<typename Traits::Insts::Pmaddwd>(Dest, Src0);
836 }
John Porto7e93c622015-06-23 10:58:57 -0700837 void _pmuludq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800838 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800839 Context.insert<typename Traits::Insts::Pmuludq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700840 }
841 void _pop(Variable *Dest) {
John Porto1d937a82015-12-17 06:19:34 -0800842 Context.insert<typename Traits::Insts::Pop>(Dest);
John Porto7e93c622015-06-23 10:58:57 -0700843 }
844 void _por(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800845 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800846 Context.insert<typename Traits::Insts::Por>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700847 }
John Portoae15f0f2016-04-26 04:26:33 -0700848 void _punpckl(Variable *Dest, Operand *Src0) {
849 AutoMemorySandboxer<> _(this, &Dest, &Src0);
850 Context.insert<typename Traits::Insts::Punpckl>(Dest, Src0);
851 }
Nicolas Capens1448d952016-10-14 16:37:09 -0400852 void _punpckh(Variable *Dest, Operand *Src0) {
853 AutoMemorySandboxer<> _(this, &Dest, &Src0);
854 Context.insert<typename Traits::Insts::Punpckh>(Dest, Src0);
855 }
Nicolas Capens7638e272016-10-06 11:33:55 -0400856 void _packss(Variable *Dest, Operand *Src0) {
857 AutoMemorySandboxer<> _(this, &Dest, &Src0);
858 Context.insert<typename Traits::Insts::Packss>(Dest, Src0);
859 }
860 void _packus(Variable *Dest, Operand *Src0) {
861 AutoMemorySandboxer<> _(this, &Dest, &Src0);
862 Context.insert<typename Traits::Insts::Packus>(Dest, Src0);
863 }
John Portode29f122016-04-26 19:16:07 -0700864 void _pshufb(Variable *Dest, Operand *Src0) {
865 AutoMemorySandboxer<> _(this, &Dest, &Src0);
866 Context.insert<typename Traits::Insts::Pshufb>(Dest, Src0);
867 }
John Porto7e93c622015-06-23 10:58:57 -0700868 void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800869 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800870 Context.insert<typename Traits::Insts::Pshufd>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700871 }
872 void _psll(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800873 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800874 Context.insert<typename Traits::Insts::Psll>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700875 }
876 void _psra(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800877 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800878 Context.insert<typename Traits::Insts::Psra>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700879 }
880 void _psrl(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800881 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800882 Context.insert<typename Traits::Insts::Psrl>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700883 }
884 void _psub(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800885 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800886 Context.insert<typename Traits::Insts::Psub>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700887 }
Nicolas Capens67a49b52016-10-26 13:18:35 -0400888 void _psubs(Variable *Dest, Operand *Src0) {
889 AutoMemorySandboxer<> _(this, &Dest, &Src0);
890 Context.insert<typename Traits::Insts::Psubs>(Dest, Src0);
891 }
892 void _psubus(Variable *Dest, Operand *Src0) {
893 AutoMemorySandboxer<> _(this, &Dest, &Src0);
894 Context.insert<typename Traits::Insts::Psubus>(Dest, Src0);
895 }
John Porto56958cb2016-01-14 09:18:18 -0800896 void _push(Operand *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800897 Context.insert<typename Traits::Insts::Push>(Src0);
John Porto7e93c622015-06-23 10:58:57 -0700898 }
899 void _pxor(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800900 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800901 Context.insert<typename Traits::Insts::Pxor>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700902 }
903 void _ret(Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800904 Context.insert<typename Traits::Insts::Ret>(Src0);
John Porto7e93c622015-06-23 10:58:57 -0700905 }
906 void _rol(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800907 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800908 Context.insert<typename Traits::Insts::Rol>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700909 }
Nicolas Capensf0d12c32016-10-27 15:17:41 -0400910 void _round(Variable *Dest, Operand *Src, Constant *Imm) {
911 AutoMemorySandboxer<> _(this, &Dest, &Src);
912 Context.insert<typename Traits::Insts::Round>(Dest, Src, Imm);
913 }
John Porto56958cb2016-01-14 09:18:18 -0800914 X86OperandMem *_sandbox_mem_reference(X86OperandMem *Mem) {
915 return dispatchToConcrete(&Traits::ConcreteTarget::_sandbox_mem_reference,
916 std::move(Mem));
917 }
John Porto7e93c622015-06-23 10:58:57 -0700918 void _sar(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800919 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800920 Context.insert<typename Traits::Insts::Sar>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700921 }
922 void _sbb(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800923 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800924 Context.insert<typename Traits::Insts::Sbb>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700925 }
John Porto4a566862016-01-04 09:33:41 -0800926 void _sbb_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800927 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800928 Context.insert<typename Traits::Insts::SbbRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700929 }
John Porto4a566862016-01-04 09:33:41 -0800930 void _setcc(Variable *Dest, BrCond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800931 Context.insert<typename Traits::Insts::Setcc>(Dest, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700932 }
933 void _shl(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800934 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800935 Context.insert<typename Traits::Insts::Shl>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700936 }
David Sehr55f2e6d2015-09-22 09:17:39 -0700937 void _shld(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800938 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800939 Context.insert<typename Traits::Insts::Shld>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700940 }
941 void _shr(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800942 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800943 Context.insert<typename Traits::Insts::Shr>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700944 }
David Sehr55f2e6d2015-09-22 09:17:39 -0700945 void _shrd(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800946 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800947 Context.insert<typename Traits::Insts::Shrd>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700948 }
949 void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800950 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800951 Context.insert<typename Traits::Insts::Shufps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700952 }
Nicolas Capense3cabda2016-10-18 16:27:27 -0400953 void _movmsk(Variable *Dest, Operand *Src0) {
954 AutoMemorySandboxer<> _(this, &Dest, &Src0);
955 Context.insert<typename Traits::Insts::Movmsk>(Dest, Src0);
956 }
Nicolas Capens956cfd62016-10-31 14:28:09 -0400957 void _sqrt(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800958 AutoMemorySandboxer<> _(this, &Dest, &Src0);
Nicolas Capens956cfd62016-10-31 14:28:09 -0400959 Context.insert<typename Traits::Insts::Sqrt>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700960 }
John Porto4a566862016-01-04 09:33:41 -0800961 void _store(Operand *Value, X86Operand *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800962 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800963 Context.insert<typename Traits::Insts::Store>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700964 }
John Porto4a566862016-01-04 09:33:41 -0800965 void _storep(Variable *Value, X86OperandMem *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800966 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800967 Context.insert<typename Traits::Insts::StoreP>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700968 }
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400969 void _storeq(Operand *Value, X86OperandMem *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800970 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800971 Context.insert<typename Traits::Insts::StoreQ>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700972 }
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400973 void _stored(Operand *Value, X86OperandMem *Mem) {
974 AutoMemorySandboxer<> _(this, &Value, &Mem);
975 Context.insert<typename Traits::Insts::StoreD>(Value, Mem);
976 }
John Porto7e93c622015-06-23 10:58:57 -0700977 void _sub(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800978 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800979 Context.insert<typename Traits::Insts::Sub>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700980 }
John Porto4a566862016-01-04 09:33:41 -0800981 void _sub_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800982 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800983 Context.insert<typename Traits::Insts::SubRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700984 }
John Porto56958cb2016-01-14 09:18:18 -0800985 void _sub_sp(Operand *Adjustment) {
986 dispatchToConcrete(&Traits::ConcreteTarget::_sub_sp, std::move(Adjustment));
987 }
John Porto7e93c622015-06-23 10:58:57 -0700988 void _subps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800989 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800990 Context.insert<typename Traits::Insts::Subps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700991 }
992 void _subss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800993 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800994 Context.insert<typename Traits::Insts::Subss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700995 }
996 void _test(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800997 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800998 Context.insert<typename Traits::Insts::Test>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700999 }
1000 void _ucomiss(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -08001001 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -08001002 Context.insert<typename Traits::Insts::Ucomiss>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -07001003 }
John Porto1d937a82015-12-17 06:19:34 -08001004 void _ud2() { Context.insert<typename Traits::Insts::UD2>(); }
David Sehrb9a404d2016-01-21 08:09:27 -08001005 void _unlink_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_unlink_bp); }
John Porto7e93c622015-06-23 10:58:57 -07001006 void _xadd(Operand *Dest, Variable *Src, bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -08001007 AutoMemorySandboxer<> _(this, &Dest, &Src);
John Porto1d937a82015-12-17 06:19:34 -08001008 Context.insert<typename Traits::Insts::Xadd>(Dest, Src, Locked);
Andrew Scull57e12682015-09-16 11:30:19 -07001009 // The xadd exchanges Dest and Src (modifying Src). Model that update with
1010 // a FakeDef followed by a FakeUse.
John Porto1d937a82015-12-17 06:19:34 -08001011 Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
Jim Stichnoth230d4102015-09-25 17:40:32 -07001012 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -08001013 Context.insert<InstFakeUse>(Src);
John Porto7e93c622015-06-23 10:58:57 -07001014 }
1015 void _xchg(Operand *Dest, Variable *Src) {
John Porto56958cb2016-01-14 09:18:18 -08001016 AutoMemorySandboxer<> _(this, &Dest, &Src);
John Porto1d937a82015-12-17 06:19:34 -08001017 Context.insert<typename Traits::Insts::Xchg>(Dest, Src);
John Porto7e93c622015-06-23 10:58:57 -07001018 // The xchg modifies Dest and Src -- model that update with a
1019 // FakeDef/FakeUse.
John Porto1d937a82015-12-17 06:19:34 -08001020 Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
Jim Stichnoth230d4102015-09-25 17:40:32 -07001021 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -08001022 Context.insert<InstFakeUse>(Src);
John Porto7e93c622015-06-23 10:58:57 -07001023 }
1024 void _xor(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001025 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001026 Context.insert<typename Traits::Insts::Xor>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -07001027 }
David Sehre3984282015-12-15 17:34:55 -08001028 void _xorps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001029 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001030 Context.insert<typename Traits::Insts::Xorps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -08001031 }
John Porto4a566862016-01-04 09:33:41 -08001032 void _xor_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -08001033 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -08001034 Context.insert<typename Traits::Insts::XorRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -07001035 }
John Porto7e93c622015-06-23 10:58:57 -07001036
Andrew Scull2c862522015-08-06 08:41:53 -07001037 void _iaca_start() {
1038 if (!BuildDefs::minimal())
John Porto1d937a82015-12-17 06:19:34 -08001039 Context.insert<typename Traits::Insts::IacaStart>();
Andrew Scull2c862522015-08-06 08:41:53 -07001040 }
1041 void _iaca_end() {
1042 if (!BuildDefs::minimal())
John Porto1d937a82015-12-17 06:19:34 -08001043 Context.insert<typename Traits::Insts::IacaEnd>();
Andrew Scull2c862522015-08-06 08:41:53 -07001044 }
1045
1046 /// This class helps wrap IACA markers around the code generated by the
1047 /// current scope. It means you don't need to put an end before each return.
1048 class ScopedIacaMark {
1049 ScopedIacaMark(const ScopedIacaMark &) = delete;
1050 ScopedIacaMark &operator=(const ScopedIacaMark &) = delete;
1051
1052 public:
1053 ScopedIacaMark(TargetX86Base *Lowering) : Lowering(Lowering) {
1054 Lowering->_iaca_start();
1055 }
1056 ~ScopedIacaMark() { end(); }
1057 void end() {
1058 if (!Lowering)
1059 return;
1060 Lowering->_iaca_end();
1061 Lowering = nullptr;
1062 }
1063
1064 private:
1065 TargetX86Base *Lowering;
1066 };
1067
John Porto7e93c622015-06-23 10:58:57 -07001068 bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
1069 void findRMW();
1070
John Porto4a566862016-01-04 09:33:41 -08001071 InstructionSetEnum InstructionSet = Traits::InstructionSet::Begin;
John Porto7e93c622015-06-23 10:58:57 -07001072 bool IsEbpBasedFrame = false;
Nicolas Capensa551dfc2016-12-14 17:37:10 -05001073 size_t RequiredStackAlignment = sizeof(Traits::WordType);
John Porto7e93c622015-06-23 10:58:57 -07001074 size_t SpillAreaSizeBytes = 0;
Jim Stichnoth55f931f2015-09-23 16:33:08 -07001075 size_t FixedAllocaSizeBytes = 0;
David Sehr2f3b8ec2015-11-16 16:51:39 -08001076 size_t FixedAllocaAlignBytes = 0;
1077 bool PrologEmitsFixedAllocas = false;
David Sehr26217e32015-11-26 13:03:50 -08001078 uint32_t MaxOutArgsSizeBytes = 0;
John Portoe82b5602016-02-24 15:58:55 -08001079 static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSet;
1080 static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSetUnfiltered;
1081 static std::array<SmallBitVector, Traits::RegisterSet::Reg_NUM>
John Portobb0a5fe2015-09-04 11:23:41 -07001082 RegisterAliases;
John Portoe82b5602016-02-24 15:58:55 -08001083 SmallBitVector RegsUsed;
John Portobb0a5fe2015-09-04 11:23:41 -07001084 std::array<VarList, IceType_NUM> PhysicalRegisters;
John Portoac2388c2016-01-22 07:10:56 -08001085 // RebasePtr is a Variable that holds the Rebasing pointer (if any) for the
1086 // current sandboxing type.
1087 Variable *RebasePtr = nullptr;
John Porto7e93c622015-06-23 10:58:57 -07001088
Andrew Scull9612d322015-07-06 14:53:25 -07001089 /// Randomize a given immediate operand
John Porto7e93c622015-06-23 10:58:57 -07001090 Operand *randomizeOrPoolImmediate(Constant *Immediate,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -08001091 RegNumT RegNum = RegNumT());
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001092 X86OperandMem *randomizeOrPoolImmediate(X86OperandMem *MemOperand,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -08001093 RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -07001094 bool RandomizationPoolingPaused = false;
1095
1096private:
John Porto5aeed952015-07-21 13:39:09 -07001097 /// dispatchToConcrete is the template voodoo that allows TargetX86Base to
1098 /// invoke methods in Machine (which inherits from TargetX86Base) without
1099 /// having to rely on virtual method calls. There are two overloads, one for
1100 /// non-void types, and one for void types. We need this becase, for non-void
1101 /// types, we need to return the method result, where as for void, we don't.
1102 /// While it is true that the code compiles without the void "version", there
1103 /// used to be a time when compilers would reject such code.
1104 ///
1105 /// This machinery is far from perfect. Note that, in particular, the
1106 /// arguments provided to dispatchToConcrete() need to match the arguments for
1107 /// Method **exactly** (i.e., no argument promotion is performed.)
1108 template <typename Ret, typename... Args>
1109 typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
John Porto4a566862016-01-04 09:33:41 -08001110 dispatchToConcrete(Ret (ConcreteTarget::*Method)(Args...), Args &&... args) {
1111 return (static_cast<ConcreteTarget *>(this)->*Method)(
1112 std::forward<Args>(args)...);
John Porto5aeed952015-07-21 13:39:09 -07001113 }
1114
1115 template <typename... Args>
John Porto4a566862016-01-04 09:33:41 -08001116 void dispatchToConcrete(void (ConcreteTarget::*Method)(Args...),
1117 Args &&... args) {
1118 (static_cast<ConcreteTarget *>(this)->*Method)(std::forward<Args>(args)...);
John Porto5aeed952015-07-21 13:39:09 -07001119 }
1120
David Sehr188eae52015-09-24 11:42:55 -07001121 void lowerShift64(InstArithmetic::OpKind Op, Operand *Src0Lo, Operand *Src0Hi,
1122 Operand *Src1Lo, Variable *DestLo, Variable *DestHi);
1123
David Sehre3984282015-12-15 17:34:55 -08001124 /// Emit the code for a combined operation and consumer instruction, or set
1125 /// the destination variable of the operation if Consumer == nullptr.
1126 void lowerIcmpAndConsumer(const InstIcmp *Icmp, const Inst *Consumer);
1127 void lowerFcmpAndConsumer(const InstFcmp *Fcmp, const Inst *Consumer);
1128 void lowerArithAndConsumer(const InstArithmetic *Arith, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001129
David Sehre3984282015-12-15 17:34:55 -08001130 /// Emit a setcc instruction if Consumer == nullptr; otherwise emit a
1131 /// specialized version of Consumer.
John Porto4a566862016-01-04 09:33:41 -08001132 void setccOrConsumer(BrCond Condition, Variable *Dest, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001133
David Sehre3984282015-12-15 17:34:55 -08001134 /// Emit a mov [1|0] instruction if Consumer == nullptr; otherwise emit a
1135 /// specialized version of Consumer.
1136 void movOrConsumer(bool IcmpResult, Variable *Dest, const Inst *Consumer);
1137
1138 /// Emit the code for instructions with a vector type.
1139 void lowerIcmpVector(const InstIcmp *Icmp);
1140 void lowerFcmpVector(const InstFcmp *Icmp);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001141 void lowerSelectVector(const InstSelect *Instr);
David Sehre3984282015-12-15 17:34:55 -08001142
1143 /// Helpers for select lowering.
John Porto4a566862016-01-04 09:33:41 -08001144 void lowerSelectMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1145 Operand *SrcF);
1146 void lowerSelectIntMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1147 Operand *SrcF);
David Sehre3984282015-12-15 17:34:55 -08001148 /// Generic helper to move an arbitrary type from Src to Dest.
1149 void lowerMove(Variable *Dest, Operand *Src, bool IsRedefinition);
1150
1151 /// Optimizations for idiom recognition.
1152 bool lowerOptimizeFcmpSelect(const InstFcmp *Fcmp, const InstSelect *Select);
David Sehrd9810252015-10-16 13:23:17 -07001153
1154 /// Complains loudly if invoked because the cpu can handle 64-bit types
1155 /// natively.
1156 template <typename T = Traits>
1157 typename std::enable_if<T::Is64Bit, void>::type lowerIcmp64(const InstIcmp *,
David Sehre3984282015-12-15 17:34:55 -08001158 const Inst *) {
David Sehrd9810252015-10-16 13:23:17 -07001159 llvm::report_fatal_error(
1160 "Hey, yo! This is x86-64. Watcha doin'? (lowerIcmp64)");
1161 }
1162 /// x86lowerIcmp64 handles 64-bit icmp lowering.
1163 template <typename T = Traits>
1164 typename std::enable_if<!T::Is64Bit, void>::type
David Sehre3984282015-12-15 17:34:55 -08001165 lowerIcmp64(const InstIcmp *Icmp, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001166
Jim Stichnothcaeaa272016-01-10 12:53:44 -08001167 BoolFolding<Traits> FoldingInfo;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -08001168
John Portoae15f0f2016-04-26 04:26:33 -07001169 /// Helpers for lowering ShuffleVector
1170 /// @{
Nicolas Capens579b1b32016-12-09 14:56:03 -05001171 Variable *lowerShuffleVector_AllFromSameSrc(Operand *Src, SizeT Index0,
John Portoae15f0f2016-04-26 04:26:33 -07001172 SizeT Index1, SizeT Index2,
1173 SizeT Index3);
1174 static constexpr SizeT IGNORE_INDEX = 0x80000000u;
Nicolas Capens579b1b32016-12-09 14:56:03 -05001175 Variable *lowerShuffleVector_TwoFromSameSrc(Operand *Src0, SizeT Index0,
1176 SizeT Index1, Operand *Src1,
John Portoae15f0f2016-04-26 04:26:33 -07001177 SizeT Index2, SizeT Index3);
1178 static constexpr SizeT UNIFIED_INDEX_0 = 0;
1179 static constexpr SizeT UNIFIED_INDEX_1 = 2;
Nicolas Capens579b1b32016-12-09 14:56:03 -05001180 Variable *lowerShuffleVector_UnifyFromDifferentSrcs(Operand *Src0,
John Portoae15f0f2016-04-26 04:26:33 -07001181 SizeT Index0,
Nicolas Capens579b1b32016-12-09 14:56:03 -05001182 Operand *Src1,
John Portoae15f0f2016-04-26 04:26:33 -07001183 SizeT Index1);
John Portode29f122016-04-26 19:16:07 -07001184 static constexpr SizeT CLEAR_ALL_BITS = 0x80;
1185 SizeT PshufbMaskCount = 0;
1186 GlobalString lowerShuffleVector_NewMaskName();
1187 ConstantRelocatable *lowerShuffleVector_CreatePshufbMask(
1188 int8_t Idx0, int8_t Idx1, int8_t Idx2, int8_t Idx3, int8_t Idx4,
1189 int8_t Idx5, int8_t Idx6, int8_t Idx7, int8_t Idx8, int8_t Idx9,
1190 int8_t Idx10, int8_t Idx11, int8_t Idx12, int8_t Idx13, int8_t Idx14,
1191 int8_t Idx15);
1192 void lowerShuffleVector_UsingPshufb(Variable *Dest, Operand *Src0,
1193 Operand *Src1, int8_t Idx0, int8_t Idx1,
1194 int8_t Idx2, int8_t Idx3, int8_t Idx4,
1195 int8_t Idx5, int8_t Idx6, int8_t Idx7,
1196 int8_t Idx8, int8_t Idx9, int8_t Idx10,
1197 int8_t Idx11, int8_t Idx12, int8_t Idx13,
1198 int8_t Idx14, int8_t Idx15);
John Portoae15f0f2016-04-26 04:26:33 -07001199 /// @}
1200
Jim Stichnoth8ff4b282016-01-04 15:39:06 -08001201 static FixupKind PcRelFixup;
1202 static FixupKind AbsFixup;
John Porto7e93c622015-06-23 10:58:57 -07001203};
David Sehr6b80cf12016-01-21 23:16:58 -08001204
1205template <typename TraitsType>
1206class TargetDataX86 final : public TargetDataLowering {
1207 using Traits = TraitsType;
1208 TargetDataX86() = delete;
1209 TargetDataX86(const TargetDataX86 &) = delete;
1210 TargetDataX86 &operator=(const TargetDataX86 &) = delete;
1211
1212public:
1213 ~TargetDataX86() override = default;
1214
1215 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1216 return makeUnique<TargetDataX86>(Ctx);
1217 }
1218
1219 void lowerGlobals(const VariableDeclarationList &Vars,
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001220 const std::string &SectionSuffix) override;
David Sehr6b80cf12016-01-21 23:16:58 -08001221 void lowerConstants() override;
1222 void lowerJumpTables() override;
1223
1224private:
1225 ENABLE_MAKE_UNIQUE;
1226
1227 explicit TargetDataX86(GlobalContext *Ctx) : TargetDataLowering(Ctx){};
1228 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
1229};
1230
1231class TargetHeaderX86 : public TargetHeaderLowering {
1232 TargetHeaderX86() = delete;
1233 TargetHeaderX86(const TargetHeaderX86 &) = delete;
1234 TargetHeaderX86 &operator=(const TargetHeaderX86 &) = delete;
1235
1236public:
1237 ~TargetHeaderX86() = default;
1238
1239 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1240 return makeUnique<TargetHeaderX86>(Ctx);
1241 }
1242
1243private:
1244 ENABLE_MAKE_UNIQUE;
1245
1246 explicit TargetHeaderX86(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {}
1247};
1248
John Porto4a566862016-01-04 09:33:41 -08001249} // end of namespace X86NAMESPACE
John Porto7e93c622015-06-23 10:58:57 -07001250} // end of namespace Ice
1251
1252#include "IceTargetLoweringX86BaseImpl.h"
1253
1254#endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H