blob: e6276cefb5ffaa2d897c2bd6314ac616df92c497 [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 {
David Sehr2f3b8ec2015-11-16 16:51:39 -0800156 return IsEbpBasedFrame ? getFrameReg() : getStackReg();
John Porto7e93c622015-06-23 10:58:57 -0700157 }
158 size_t typeWidthInBytesOnStack(Type Ty) const override {
John Porto1d235422015-08-12 12:37:53 -0700159 // Round up to the next multiple of WordType bytes.
160 const uint32_t WordSizeInBytes = typeWidthInBytes(Traits::WordType);
161 return Utils::applyAlignment(typeWidthInBytes(Ty), WordSizeInBytes);
John Porto7e93c622015-06-23 10:58:57 -0700162 }
David Sehre39d0ca2015-11-06 11:25:41 -0800163 uint32_t getStackAlignment() const override {
164 return Traits::X86_STACK_ALIGNMENT_BYTES;
165 }
David Sehr2f3b8ec2015-11-16 16:51:39 -0800166 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
167 FixedAllocaSizeBytes = Size;
168 assert(llvm::isPowerOf2_32(Align));
169 FixedAllocaAlignBytes = Align;
170 PrologEmitsFixedAllocas = true;
171 }
172 /// Returns the (negative) offset from ebp/rbp where the fixed Allocas start.
173 int32_t getFrameFixedAllocaOffset() const override {
David Sehr26217e32015-11-26 13:03:50 -0800174 return FixedAllocaSizeBytes - (SpillAreaSizeBytes - maxOutArgsSizeBytes());
175 }
176 virtual uint32_t maxOutArgsSizeBytes() const override {
177 return MaxOutArgsSizeBytes;
178 }
179 virtual void updateMaxOutArgsSizeBytes(uint32_t Size) {
180 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, Size);
David Sehr2f3b8ec2015-11-16 16:51:39 -0800181 }
John Porto7e93c622015-06-23 10:58:57 -0700182
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700183 bool shouldSplitToVariable64On32(Type Ty) const override {
184 return Traits::Is64Bit ? false : Ty == IceType_i64;
185 }
186
John Porto6e8d3fa2016-02-04 10:35:20 -0800187 ConstantRelocatable *createGetIPForRegister(const Variable *Dest) {
188 assert(Dest->hasReg());
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700189 const std::string RegName = Traits::getRegName(Dest->getRegNum());
190 return llvm::cast<ConstantRelocatable>(Ctx->getConstantExternSym(
191 Ctx->getGlobalString(H_getIP_prefix + RegName)));
John Porto6e8d3fa2016-02-04 10:35:20 -0800192 }
193
Andrew Scull87f80c12015-07-20 10:19:16 -0700194 SizeT getMinJumpTableSize() const override { return 4; }
195
John Porto7e93c622015-06-23 10:58:57 -0700196 void emitVariable(const Variable *Var) const override;
197
John Porto7e93c622015-06-23 10:58:57 -0700198 void emit(const ConstantInteger32 *C) const final;
199 void emit(const ConstantInteger64 *C) const final;
200 void emit(const ConstantFloat *C) const final;
201 void emit(const ConstantDouble *C) const final;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800202 void emit(const ConstantUndef *C) const final;
203 void emit(const ConstantRelocatable *C) const final;
John Porto7e93c622015-06-23 10:58:57 -0700204
John Porto7e93c622015-06-23 10:58:57 -0700205 void initNodeForLowering(CfgNode *Node) override;
John Porto1d235422015-08-12 12:37:53 -0700206
207 template <typename T = Traits>
208 typename std::enable_if<!T::Is64Bit, Operand>::type *
209 loOperand(Operand *Operand);
210 template <typename T = Traits>
211 typename std::enable_if<T::Is64Bit, Operand>::type *loOperand(Operand *) {
212 llvm::report_fatal_error(
213 "Hey, yo! This is x86-64. Watcha doin'? (loOperand)");
214 }
215
216 template <typename T = Traits>
217 typename std::enable_if<!T::Is64Bit, Operand>::type *
218 hiOperand(Operand *Operand);
219 template <typename T = Traits>
220 typename std::enable_if<T::Is64Bit, Operand>::type *hiOperand(Operand *) {
221 llvm::report_fatal_error(
222 "Hey, yo! This is x86-64. Watcha doin'? (hiOperand)");
223 }
224
David Sehrb9a404d2016-01-21 08:09:27 -0800225 void addProlog(CfgNode *Node) override;
John Porto7e93c622015-06-23 10:58:57 -0700226 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
Jim Stichnoth55f931f2015-09-23 16:33:08 -0700227 size_t BasicFrameOffset, size_t StackAdjBytes,
228 size_t &InArgsSizeBytes);
David Sehrb9a404d2016-01-21 08:09:27 -0800229 void addEpilog(CfgNode *Node) override;
John Porto4a566862016-01-04 09:33:41 -0800230 X86Address stackVarToAsmOperand(const Variable *Var) const;
John Porto7e93c622015-06-23 10:58:57 -0700231
John Porto4a566862016-01-04 09:33:41 -0800232 InstructionSetEnum getInstructionSet() const { return InstructionSet; }
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800233 Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700234
235protected:
John Porto56958cb2016-01-14 09:18:18 -0800236 const bool NeedSandboxing;
237
John Porto7e93c622015-06-23 10:58:57 -0700238 explicit TargetX86Base(Cfg *Func);
239
240 void postLower() override;
241
John Portoac2388c2016-01-22 07:10:56 -0800242 /// Initializes the RebasePtr member variable -- if so required by
243 /// SandboxingType for the concrete Target.
244 void initRebasePtr() {
245 assert(SandboxingType != ST_None);
246 dispatchToConcrete(&Traits::ConcreteTarget::initRebasePtr);
247 }
248
249 /// Emit code that initializes the value of the RebasePtr near the start of
250 /// the function -- if so required by SandboxingType for the concrete type.
John Porto56958cb2016-01-14 09:18:18 -0800251 void initSandbox() {
John Portoac2388c2016-01-22 07:10:56 -0800252 assert(SandboxingType != ST_None);
John Porto56958cb2016-01-14 09:18:18 -0800253 dispatchToConcrete(&Traits::ConcreteTarget::initSandbox);
254 }
255
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800256 void lowerAlloca(const InstAlloca *Instr) override;
David Sehr0c68bef2016-01-20 10:00:23 -0800257 void lowerArguments() override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800258 void lowerArithmetic(const InstArithmetic *Instr) override;
259 void lowerAssign(const InstAssign *Instr) override;
260 void lowerBr(const InstBr *Instr) override;
Eric Holk67c7c412016-04-15 13:05:37 -0700261 void lowerBreakpoint(const InstBreakpoint *Instr) override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800262 void lowerCall(const InstCall *Instr) override;
263 void lowerCast(const InstCast *Instr) override;
264 void lowerExtractElement(const InstExtractElement *Instr) override;
265 void lowerFcmp(const InstFcmp *Instr) override;
266 void lowerIcmp(const InstIcmp *Instr) override;
John Porto1d235422015-08-12 12:37:53 -0700267
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800268 void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
269 void lowerInsertElement(const InstInsertElement *Instr) override;
270 void lowerLoad(const InstLoad *Instr) override;
271 void lowerPhi(const InstPhi *Instr) override;
272 void lowerRet(const InstRet *Instr) override;
273 void lowerSelect(const InstSelect *Instr) override;
John Portoa47c11c2016-04-21 05:53:42 -0700274 void lowerShuffleVector(const InstShuffleVector *Instr) override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800275 void lowerStore(const InstStore *Instr) override;
276 void lowerSwitch(const InstSwitch *Instr) override;
277 void lowerUnreachable(const InstUnreachable *Instr) override;
John Porto7e93c622015-06-23 10:58:57 -0700278 void lowerOther(const Inst *Instr) override;
John Porto4a566862016-01-04 09:33:41 -0800279 void lowerRMW(const InstX86FakeRMW *RMW);
John Porto7e93c622015-06-23 10:58:57 -0700280 void prelowerPhis() override;
John Portoe82b5602016-02-24 15:58:55 -0800281 uint32_t getCallStackArgumentsSizeBytes(const CfgVector<Type> &ArgTypes,
David Sehr26217e32015-11-26 13:03:50 -0800282 Type ReturnType);
David Sehr4163b9f2015-11-20 21:09:31 -0800283 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
David Sehr26217e32015-11-26 13:03:50 -0800284 void genTargetHelperCallFor(Inst *Instr) override;
John Portoac2388c2016-01-22 07:10:56 -0800285
286 /// OptAddr wraps all the possible operands that an x86 address might have.
287 struct OptAddr {
288 Variable *Base = nullptr;
289 Variable *Index = nullptr;
290 uint16_t Shift = 0;
291 int32_t Offset = 0;
292 ConstantRelocatable *Relocatable = nullptr;
293 };
294 /// Legalizes Addr w.r.t. SandboxingType. The exact type of legalization
295 /// varies for different <Target, SandboxingType> tuples.
296 bool legalizeOptAddrForSandbox(OptAddr *Addr) {
297 return dispatchToConcrete(
298 &Traits::ConcreteTarget::legalizeOptAddrForSandbox, std::move(Addr));
299 }
300 // Builds information for a canonical address expresion:
301 // <Relocatable + Offset>(Base, Index, Shift)
302 X86OperandMem *computeAddressOpt(const Inst *Instr, Type MemType,
303 Operand *Addr);
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700304 void doAddressOptOther() override;
John Porto7e93c622015-06-23 10:58:57 -0700305 void doAddressOptLoad() override;
306 void doAddressOptStore() override;
Jim Stichnothad2989b2015-09-15 10:21:42 -0700307 void doMockBoundsCheck(Operand *Opnd) override;
Qining Luaee5fa82015-08-20 14:59:03 -0700308 void randomlyInsertNop(float Probability,
309 RandomNumberGenerator &RNG) override;
John Porto7e93c622015-06-23 10:58:57 -0700310
Andrew Scull9612d322015-07-06 14:53:25 -0700311 /// Naive lowering of cmpxchg.
John Porto7e93c622015-06-23 10:58:57 -0700312 void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
313 Operand *Desired);
Andrew Scull9612d322015-07-06 14:53:25 -0700314 /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
John Porto7e93c622015-06-23 10:58:57 -0700315 bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr,
316 Operand *Expected, Operand *Desired);
317 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
318 Operand *Val);
319 void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal,
320 Operand *SecondVal);
Andrew Scullcfa628b2015-08-20 14:23:05 -0700321 /// Load from memory for a given type.
322 void typedLoad(Type Ty, Variable *Dest, Variable *Base, Constant *Offset);
323 /// Store to memory for a given type.
324 void typedStore(Type Ty, Variable *Value, Variable *Base, Constant *Offset);
325 /// Copy memory of given type from Src to Dest using OffsetAmt on both.
326 void copyMemory(Type Ty, Variable *Dest, Variable *Src, int32_t OffsetAmt);
327 /// Replace some calls to memcpy with inline instructions.
Andrew Scull9df4a372015-08-07 09:19:35 -0700328 void lowerMemcpy(Operand *Dest, Operand *Src, Operand *Count);
Andrew Scullcfa628b2015-08-20 14:23:05 -0700329 /// Replace some calls to memmove with inline instructions.
330 void lowerMemmove(Operand *Dest, Operand *Src, Operand *Count);
331 /// Replace some calls to memset with inline instructions.
Andrew Scull713dbde2015-08-04 14:25:27 -0700332 void lowerMemset(Operand *Dest, Operand *Val, Operand *Count);
333
Andrew Scull86df4e92015-07-30 13:54:44 -0700334 /// Lower an indirect jump adding sandboxing when needed.
John Porto56958cb2016-01-14 09:18:18 -0800335 void lowerIndirectJump(Variable *JumpTarget) {
336 // Without std::move below, the compiler deduces that the argument to
337 // lowerIndirectJmp is a Variable *&, not a Variable *.
338 dispatchToConcrete(&Traits::ConcreteTarget::lowerIndirectJump,
339 std::move(JumpTarget));
340 }
John Porto7e93c622015-06-23 10:58:57 -0700341
Andrew Scull87f80c12015-07-20 10:19:16 -0700342 /// Check the comparison is in [Min,Max]. The flags register will be modified
343 /// with:
344 /// - below equal, if in range
345 /// - above, set if not in range
346 /// The index into the range is returned.
347 Operand *lowerCmpRange(Operand *Comparison, uint64_t Min, uint64_t Max);
348 /// Lowering of a cluster of switch cases. If the case is not matched control
349 /// will pass to the default label provided. If the default label is nullptr
350 /// then control will fall through to the next instruction. DoneCmp should be
351 /// true if the flags contain the result of a comparison with the Comparison.
352 void lowerCaseCluster(const CaseCluster &Case, Operand *Src0, bool DoneCmp,
353 CfgNode *DefaultLabel = nullptr);
354
Andrew Scull8072bae2015-09-14 16:01:26 -0700355 using LowerBinOp = void (TargetX86Base::*)(Variable *, Operand *);
John Porto7e93c622015-06-23 10:58:57 -0700356 void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi,
357 Variable *Dest, Operand *Ptr, Operand *Val);
358
359 void eliminateNextVectorSextInstruction(Variable *SignExtendedResult);
360
David Sehrb9a404d2016-01-21 08:09:27 -0800361 void emitGetIP(CfgNode *Node) {
362 dispatchToConcrete(&Traits::ConcreteTarget::emitGetIP, std::move(Node));
363 }
364 /// Emit a sandboxed return sequence rather than a return.
365 void emitSandboxedReturn() {
366 dispatchToConcrete(&Traits::ConcreteTarget::emitSandboxedReturn);
367 }
David Sehr0c68bef2016-01-20 10:00:23 -0800368 /// Emit just the call instruction (without argument or return variable
369 /// processing), sandboxing if needed.
Jim Stichnothc10c1562016-03-10 08:19:34 -0800370 virtual Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) = 0;
David Sehr0c68bef2016-01-20 10:00:23 -0800371 /// Materialize the moves needed to return a value of the specified type.
Jim Stichnothc10c1562016-03-10 08:19:34 -0800372 virtual Variable *moveReturnValueToRegister(Operand *Value,
373 Type ReturnType) = 0;
David Sehr0c68bef2016-01-20 10:00:23 -0800374
David Sehr6b80cf12016-01-21 23:16:58 -0800375 /// Emit a jump table to the constant pool.
376 void emitJumpTable(const Cfg *Func,
377 const InstJumpTable *JumpTable) const override;
378
David Sehr21fd1032015-11-13 16:32:37 -0800379 /// Emit a fake use of esp to make sure esp stays alive for the entire
380 /// function. Otherwise some esp adjustments get dead-code eliminated.
381 void keepEspLiveAtExit() {
John Porto008f4ce2015-12-24 13:22:18 -0800382 Variable *esp =
383 Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
John Porto1d937a82015-12-17 06:19:34 -0800384 Context.insert<InstFakeUse>(esp);
David Sehr21fd1032015-11-13 16:32:37 -0800385 }
386
Andrew Scull57e12682015-09-16 11:30:19 -0700387 /// Operand legalization helpers. To deal with address mode constraints, the
388 /// helpers will create a new Operand and emit instructions that guarantee
389 /// that the Operand kind is one of those indicated by the LegalMask (a
390 /// bitmask of allowed kinds). If the input Operand is known to already meet
391 /// the constraints, it may be simply returned as the result, without creating
392 /// any new instructions or operands.
John Porto7e93c622015-06-23 10:58:57 -0700393 enum OperandLegalization {
394 Legal_None = 0,
395 Legal_Reg = 1 << 0, // physical register, not stack location
396 Legal_Imm = 1 << 1,
397 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12]
David Sehr4318a412015-11-11 15:01:55 -0800398 Legal_Rematerializable = 1 << 3,
John Portoac2388c2016-01-22 07:10:56 -0800399 Legal_AddrAbs = 1 << 4, // ConstantRelocatable doesn't have to add RebasePtr
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800400 Legal_Default = ~(Legal_Rematerializable | Legal_AddrAbs)
401 // TODO(stichnot): Figure out whether this default works for x86-64.
John Porto7e93c622015-06-23 10:58:57 -0700402 };
Andrew Scull8072bae2015-09-14 16:01:26 -0700403 using LegalMask = uint32_t;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800404 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800405 RegNumT RegNum = RegNumT());
406 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
Andrew Scull9612d322015-07-06 14:53:25 -0700407 /// Legalize the first source operand for use in the cmp instruction.
John Porto7e93c622015-06-23 10:58:57 -0700408 Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
Andrew Scull57e12682015-09-16 11:30:19 -0700409 /// Turn a pointer operand into a memory operand that can be used by a real
410 /// load/store operation. Legalizes the operand as well. This is a nop if the
411 /// operand is already a legal memory operand.
John Porto4a566862016-01-04 09:33:41 -0800412 X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
413 bool DoLegalize = true);
John Porto7e93c622015-06-23 10:58:57 -0700414
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800415 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700416 static Type stackSlotType();
417
Andrew Scullcfa628b2015-08-20 14:23:05 -0700418 static constexpr uint32_t NoSizeLimit = 0;
Andrew Scullcfa628b2015-08-20 14:23:05 -0700419 /// Returns the largest type which is equal to or larger than Size bytes. The
Andrew Scull57e12682015-09-16 11:30:19 -0700420 /// type is suitable for copying memory i.e. a load and store will be a single
421 /// instruction (for example x86 will get f64 not i64).
Andrew Scullcfa628b2015-08-20 14:23:05 -0700422 static Type largestTypeInSize(uint32_t Size, uint32_t MaxSize = NoSizeLimit);
423 /// Returns the smallest type which is equal to or larger than Size bytes. If
424 /// one doesn't exist then the largest type smaller than Size bytes is
425 /// returned. The type is suitable for memory copies as described at
426 /// largestTypeInSize.
427 static Type firstTypeThatFitsSize(uint32_t Size,
428 uint32_t MaxSize = NoSizeLimit);
429
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800430 Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT());
431 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700432
Jim Stichnoth99165662015-11-13 14:20:40 -0800433 /// Returns a register containing all zeros, without affecting the FLAGS
434 /// register, using the best instruction for the type.
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800435 Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT());
Jim Stichnoth99165662015-11-13 14:20:40 -0800436
Andrew Scull713dbde2015-08-04 14:25:27 -0700437 /// \name Returns a vector in a register with the given constant entries.
438 /// @{
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800439 Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
440 Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT());
441 Variable *makeVectorOfMinusOnes(Type Ty, RegNumT RegNum = RegNumT());
442 Variable *makeVectorOfHighOrderBits(Type Ty, RegNumT RegNum = RegNumT());
443 Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT());
Andrew Scull713dbde2015-08-04 14:25:27 -0700444 /// @}
John Porto7e93c622015-06-23 10:58:57 -0700445
Andrew Scull9612d322015-07-06 14:53:25 -0700446 /// Return a memory operand corresponding to a stack allocated Variable.
John Porto4a566862016-01-04 09:33:41 -0800447 X86OperandMem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
448 uint32_t Offset = 0);
John Porto7e93c622015-06-23 10:58:57 -0700449
Qining Luaee5fa82015-08-20 14:59:03 -0700450 void
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800451 makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
John Portoe82b5602016-02-24 15:58:55 -0800452 const SmallBitVector &ExcludeRegisters,
Qining Luaee5fa82015-08-20 14:59:03 -0700453 uint64_t Salt) const override;
John Porto7e93c622015-06-23 10:58:57 -0700454
John Porto56958cb2016-01-14 09:18:18 -0800455 /// AutoMemorySandboxer emits a bundle-lock/bundle-unlock pair if the
456 /// instruction's operand is a memory reference. This is only needed for
457 /// x86-64 NaCl sandbox.
458 template <InstBundleLock::Option BundleLockOpt = InstBundleLock::Opt_None>
459 class AutoMemorySandboxer {
460 AutoMemorySandboxer() = delete;
461 AutoMemorySandboxer(const AutoMemorySandboxer &) = delete;
462 AutoMemorySandboxer &operator=(const AutoMemorySandboxer &) = delete;
463
464 private:
465 typename Traits::TargetLowering *Target;
466
467 template <typename T, typename... Tail>
468 X86OperandMem **findMemoryReference(T **First, Tail... Others) {
469 if (llvm::isa<X86OperandMem>(*First)) {
470 return reinterpret_cast<X86OperandMem **>(First);
471 }
472 return findMemoryReference(Others...);
473 }
474
475 X86OperandMem **findMemoryReference() { return nullptr; }
476
477 public:
John Porto4abbb592016-03-10 10:59:02 -0800478 AutoBundle *Bundler = nullptr;
John Porto56958cb2016-01-14 09:18:18 -0800479 X86OperandMem **const MemOperand;
480
481 template <typename... T>
482 AutoMemorySandboxer(typename Traits::TargetLowering *Target, T... Args)
John Portoac2388c2016-01-22 07:10:56 -0800483 : Target(Target), MemOperand(Target->SandboxingType == ST_None
484 ? nullptr
485 : findMemoryReference(Args...)) {
John Porto56958cb2016-01-14 09:18:18 -0800486 if (MemOperand != nullptr) {
John Porto8347abd2016-02-04 09:12:02 -0800487 if (Traits::Is64Bit) {
John Porto4abbb592016-03-10 10:59:02 -0800488 Bundler = new (Target->Func->template allocate<AutoBundle>())
489 AutoBundle(Target, BundleLockOpt);
John Porto8347abd2016-02-04 09:12:02 -0800490 }
John Porto56958cb2016-01-14 09:18:18 -0800491 *MemOperand = Target->_sandbox_mem_reference(*MemOperand);
492 }
493 }
494
John Porto4abbb592016-03-10 10:59:02 -0800495 ~AutoMemorySandboxer() {
496 if (Bundler != nullptr) {
497 Bundler->~AutoBundle();
498 }
499 }
John Porto56958cb2016-01-14 09:18:18 -0800500 };
501
Andrew Scull57e12682015-09-16 11:30:19 -0700502 /// The following are helpers that insert lowered x86 instructions with
503 /// minimal syntactic overhead, so that the lowering code can look as close to
504 /// assembly as practical.
John Porto7e93c622015-06-23 10:58:57 -0700505 void _adc(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800506 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800507 Context.insert<typename Traits::Insts::Adc>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700508 }
John Porto4a566862016-01-04 09:33:41 -0800509 void _adc_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800510 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800511 Context.insert<typename Traits::Insts::AdcRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700512 }
513 void _add(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800514 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800515 Context.insert<typename Traits::Insts::Add>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700516 }
John Porto4a566862016-01-04 09:33:41 -0800517 void _add_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800518 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800519 Context.insert<typename Traits::Insts::AddRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700520 }
John Porto7e93c622015-06-23 10:58:57 -0700521 void _addps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800522 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800523 Context.insert<typename Traits::Insts::Addps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700524 }
525 void _addss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800526 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800527 Context.insert<typename Traits::Insts::Addss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700528 }
John Porto56958cb2016-01-14 09:18:18 -0800529 void _add_sp(Operand *Adjustment) {
530 dispatchToConcrete(&Traits::ConcreteTarget::_add_sp, std::move(Adjustment));
531 }
John Porto7e93c622015-06-23 10:58:57 -0700532 void _and(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800533 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800534 Context.insert<typename Traits::Insts::And>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700535 }
David Sehre3984282015-12-15 17:34:55 -0800536 void _andnps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800537 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800538 Context.insert<typename Traits::Insts::Andnps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800539 }
540 void _andps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800541 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800542 Context.insert<typename Traits::Insts::Andps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800543 }
John Porto4a566862016-01-04 09:33:41 -0800544 void _and_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800545 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800546 Context.insert<typename Traits::Insts::AndRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700547 }
548 void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800549 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800550 Context.insert<typename Traits::Insts::Blendvps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700551 }
John Porto4a566862016-01-04 09:33:41 -0800552 void _br(BrCond Condition, CfgNode *TargetTrue, CfgNode *TargetFalse) {
553 Context.insert<InstX86Br>(TargetTrue, TargetFalse, Condition,
554 InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700555 }
556 void _br(CfgNode *Target) {
John Porto4a566862016-01-04 09:33:41 -0800557 Context.insert<InstX86Br>(Target, InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700558 }
John Porto4a566862016-01-04 09:33:41 -0800559 void _br(BrCond Condition, CfgNode *Target) {
560 Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700561 }
John Porto4a566862016-01-04 09:33:41 -0800562 void _br(BrCond Condition, InstX86Label *Label,
563 typename InstX86Br::Mode Kind = InstX86Br::Near) {
564 Context.insert<InstX86Br>(Label, Condition, Kind);
John Porto7e93c622015-06-23 10:58:57 -0700565 }
566 void _bsf(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800567 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800568 Context.insert<typename Traits::Insts::Bsf>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700569 }
570 void _bsr(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800571 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800572 Context.insert<typename Traits::Insts::Bsr>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700573 }
574 void _bswap(Variable *SrcDest) {
John Porto56958cb2016-01-14 09:18:18 -0800575 AutoMemorySandboxer<> _(this, &SrcDest);
John Porto1d937a82015-12-17 06:19:34 -0800576 Context.insert<typename Traits::Insts::Bswap>(SrcDest);
John Porto7e93c622015-06-23 10:58:57 -0700577 }
578 void _cbwdq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800579 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800580 Context.insert<typename Traits::Insts::Cbwdq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700581 }
John Porto4a566862016-01-04 09:33:41 -0800582 void _cmov(Variable *Dest, Operand *Src0, BrCond Condition) {
John Porto56958cb2016-01-14 09:18:18 -0800583 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800584 Context.insert<typename Traits::Insts::Cmov>(Dest, Src0, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700585 }
586 void _cmp(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800587 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800588 Context.insert<typename Traits::Insts::Icmp>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700589 }
John Porto4a566862016-01-04 09:33:41 -0800590 void _cmpps(Variable *Dest, Operand *Src0, CmppsCond Condition) {
John Porto56958cb2016-01-14 09:18:18 -0800591 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800592 Context.insert<typename Traits::Insts::Cmpps>(Dest, Src0, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700593 }
594 void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
595 bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -0800596 AutoMemorySandboxer<> _(this, &DestOrAddr);
John Porto1d937a82015-12-17 06:19:34 -0800597 Context.insert<typename Traits::Insts::Cmpxchg>(DestOrAddr, Eax, Desired,
598 Locked);
John Porto7e93c622015-06-23 10:58:57 -0700599 // Mark eax as possibly modified by cmpxchg.
John Porto1d937a82015-12-17 06:19:34 -0800600 Context.insert<InstFakeDef>(Eax, llvm::dyn_cast<Variable>(DestOrAddr));
Jim Stichnoth230d4102015-09-25 17:40:32 -0700601 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800602 Context.insert<InstFakeUse>(Eax);
John Porto7e93c622015-06-23 10:58:57 -0700603 }
John Porto4a566862016-01-04 09:33:41 -0800604 void _cmpxchg8b(X86OperandMem *Addr, Variable *Edx, Variable *Eax,
605 Variable *Ecx, Variable *Ebx, bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -0800606 AutoMemorySandboxer<> _(this, &Addr);
John Porto1d937a82015-12-17 06:19:34 -0800607 Context.insert<typename Traits::Insts::Cmpxchg8b>(Addr, Edx, Eax, Ecx, Ebx,
608 Locked);
John Porto7e93c622015-06-23 10:58:57 -0700609 // Mark edx, and eax as possibly modified by cmpxchg8b.
John Porto1d937a82015-12-17 06:19:34 -0800610 Context.insert<InstFakeDef>(Edx);
Jim Stichnoth230d4102015-09-25 17:40:32 -0700611 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800612 Context.insert<InstFakeUse>(Edx);
613 Context.insert<InstFakeDef>(Eax);
Jim Stichnoth230d4102015-09-25 17:40:32 -0700614 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800615 Context.insert<InstFakeUse>(Eax);
John Porto7e93c622015-06-23 10:58:57 -0700616 }
John Porto921856d2015-07-07 11:56:26 -0700617 void _cvt(Variable *Dest, Operand *Src0,
618 typename Traits::Insts::Cvt::CvtVariant Variant) {
John Porto56958cb2016-01-14 09:18:18 -0800619 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800620 Context.insert<typename Traits::Insts::Cvt>(Dest, Src0, Variant);
John Porto7e93c622015-06-23 10:58:57 -0700621 }
622 void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800623 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800624 Context.insert<typename Traits::Insts::Div>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700625 }
626 void _divps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800627 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800628 Context.insert<typename Traits::Insts::Divps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700629 }
630 void _divss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800631 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800632 Context.insert<typename Traits::Insts::Divss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700633 }
John Porto453660f2015-07-31 14:52:52 -0700634 template <typename T = Traits>
635 typename std::enable_if<T::UsesX87, void>::type _fld(Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800636 AutoMemorySandboxer<> _(this, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800637 Context.insert<typename Traits::Insts::template Fld<>>(Src0);
John Porto921856d2015-07-07 11:56:26 -0700638 }
John Porto453660f2015-07-31 14:52:52 -0700639 // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
640 // does not invoke this method, and remove it.
641 template <typename T = Traits>
642 typename std::enable_if<!T::UsesX87, void>::type _fld(Operand *) {
643 llvm::report_fatal_error("fld is not available in x86-64");
644 }
645 template <typename T = Traits>
646 typename std::enable_if<T::UsesX87, void>::type _fstp(Variable *Dest) {
John Porto56958cb2016-01-14 09:18:18 -0800647 AutoMemorySandboxer<> _(this, &Dest);
John Porto1d937a82015-12-17 06:19:34 -0800648 Context.insert<typename Traits::Insts::template Fstp<>>(Dest);
John Porto453660f2015-07-31 14:52:52 -0700649 }
650 // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
651 // does not invoke this method, and remove it.
652 template <typename T = Traits>
653 typename std::enable_if<!T::UsesX87, void>::type _fstp(Variable *) {
654 llvm::report_fatal_error("fstp is not available in x86-64");
John Porto7e93c622015-06-23 10:58:57 -0700655 }
656 void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800657 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800658 Context.insert<typename Traits::Insts::Idiv>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700659 }
660 void _imul(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800661 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800662 Context.insert<typename Traits::Insts::Imul>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700663 }
David Sehre11f8782015-10-06 10:26:57 -0700664 void _imul_imm(Variable *Dest, Operand *Src0, Constant *Imm) {
John Porto56958cb2016-01-14 09:18:18 -0800665 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800666 Context.insert<typename Traits::Insts::ImulImm>(Dest, Src0, Imm);
David Sehre11f8782015-10-06 10:26:57 -0700667 }
John Porto7e93c622015-06-23 10:58:57 -0700668 void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800669 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800670 Context.insert<typename Traits::Insts::Insertps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700671 }
Eric Holk67c7c412016-04-15 13:05:37 -0700672 void _int3() { Context.insert<typename Traits::Insts::Int3>(); }
John Porto7e93c622015-06-23 10:58:57 -0700673 void _jmp(Operand *Target) {
John Porto56958cb2016-01-14 09:18:18 -0800674 AutoMemorySandboxer<> _(this, &Target);
John Porto1d937a82015-12-17 06:19:34 -0800675 Context.insert<typename Traits::Insts::Jmp>(Target);
John Porto7e93c622015-06-23 10:58:57 -0700676 }
677 void _lea(Variable *Dest, Operand *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800678 Context.insert<typename Traits::Insts::Lea>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700679 }
David Sehrb9a404d2016-01-21 08:09:27 -0800680 void _link_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_link_bp); }
681 void _push_reg(Variable *Reg) {
682 dispatchToConcrete(&Traits::ConcreteTarget::_push_reg, std::move(Reg));
683 }
John Porto1d937a82015-12-17 06:19:34 -0800684 void _mfence() { Context.insert<typename Traits::Insts::Mfence>(); }
David Sehre3984282015-12-15 17:34:55 -0800685 /// Moves can be used to redefine registers, creating "partial kills" for
686 /// liveness. Mark where moves are used in this way.
687 void _redefined(Inst *MovInst, bool IsRedefinition = true) {
688 if (IsRedefinition)
689 MovInst->setDestRedefined();
690 }
Andrew Scull57e12682015-09-16 11:30:19 -0700691 /// If Dest=nullptr is passed in, then a new variable is created, marked as
692 /// infinite register allocation weight, and returned through the in/out Dest
693 /// argument.
John Porto1d937a82015-12-17 06:19:34 -0800694 typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800695 RegNumT RegNum = RegNumT()) {
John Porto7e93c622015-06-23 10:58:57 -0700696 if (Dest == nullptr)
697 Dest = makeReg(Src0->getType(), RegNum);
John Porto56958cb2016-01-14 09:18:18 -0800698 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800699 return Context.insert<typename Traits::Insts::Mov>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800700 }
John Porto56958cb2016-01-14 09:18:18 -0800701 void _mov_sp(Operand *NewValue) {
702 dispatchToConcrete(&Traits::ConcreteTarget::_mov_sp, std::move(NewValue));
703 }
John Porto1d937a82015-12-17 06:19:34 -0800704 typename Traits::Insts::Movp *_movp(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800705 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800706 return Context.insert<typename Traits::Insts::Movp>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700707 }
708 void _movd(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800709 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800710 Context.insert<typename Traits::Insts::Movd>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700711 }
John Porto7e93c622015-06-23 10:58:57 -0700712 void _movq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800713 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800714 Context.insert<typename Traits::Insts::Movq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700715 }
716 void _movss(Variable *Dest, Variable *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800717 Context.insert<typename Traits::Insts::MovssRegs>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700718 }
719 void _movsx(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800720 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800721 Context.insert<typename Traits::Insts::Movsx>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700722 }
John Porto56958cb2016-01-14 09:18:18 -0800723 typename Traits::Insts::Movzx *_movzx(Variable *Dest, Operand *Src0) {
724 AutoMemorySandboxer<> _(this, &Dest, &Src0);
725 return Context.insert<typename Traits::Insts::Movzx>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700726 }
David Sehre3984282015-12-15 17:34:55 -0800727 void _maxss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800728 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800729 Context.insert<typename Traits::Insts::Maxss>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800730 }
731 void _minss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800732 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800733 Context.insert<typename Traits::Insts::Minss>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800734 }
John Porto7e93c622015-06-23 10:58:57 -0700735 void _mul(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800736 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800737 Context.insert<typename Traits::Insts::Mul>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700738 }
739 void _mulps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800740 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800741 Context.insert<typename Traits::Insts::Mulps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700742 }
743 void _mulss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800744 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800745 Context.insert<typename Traits::Insts::Mulss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700746 }
747 void _neg(Variable *SrcDest) {
John Porto56958cb2016-01-14 09:18:18 -0800748 AutoMemorySandboxer<> _(this, &SrcDest);
John Porto1d937a82015-12-17 06:19:34 -0800749 Context.insert<typename Traits::Insts::Neg>(SrcDest);
John Porto7e93c622015-06-23 10:58:57 -0700750 }
751 void _nop(SizeT Variant) {
John Porto1d937a82015-12-17 06:19:34 -0800752 Context.insert<typename Traits::Insts::Nop>(Variant);
John Porto7e93c622015-06-23 10:58:57 -0700753 }
754 void _or(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800755 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800756 Context.insert<typename Traits::Insts::Or>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700757 }
David Sehre3984282015-12-15 17:34:55 -0800758 void _orps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800759 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800760 Context.insert<typename Traits::Insts::Orps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800761 }
John Porto4a566862016-01-04 09:33:41 -0800762 void _or_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800763 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800764 Context.insert<typename Traits::Insts::OrRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700765 }
766 void _padd(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800767 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800768 Context.insert<typename Traits::Insts::Padd>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700769 }
Nicolas Capens67a49b52016-10-26 13:18:35 -0400770 void _padds(Variable *Dest, Operand *Src0) {
771 AutoMemorySandboxer<> _(this, &Dest, &Src0);
772 Context.insert<typename Traits::Insts::Padds>(Dest, Src0);
773 }
774 void _paddus(Variable *Dest, Operand *Src0) {
775 AutoMemorySandboxer<> _(this, &Dest, &Src0);
776 Context.insert<typename Traits::Insts::Paddus>(Dest, Src0);
777 }
John Porto7e93c622015-06-23 10:58:57 -0700778 void _pand(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800779 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800780 Context.insert<typename Traits::Insts::Pand>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700781 }
782 void _pandn(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800783 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800784 Context.insert<typename Traits::Insts::Pandn>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700785 }
786 void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800787 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800788 Context.insert<typename Traits::Insts::Pblendvb>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700789 }
David Sehrb19d39c2016-01-13 14:17:37 -0800790 void _pcmpeq(Variable *Dest, Operand *Src0,
791 Type ArithmeticTypeOverride = IceType_void) {
John Porto56958cb2016-01-14 09:18:18 -0800792 AutoMemorySandboxer<> _(this, &Dest, &Src0);
David Sehrb19d39c2016-01-13 14:17:37 -0800793 Context.insert<typename Traits::Insts::Pcmpeq>(Dest, Src0,
794 ArithmeticTypeOverride);
John Porto7e93c622015-06-23 10:58:57 -0700795 }
796 void _pcmpgt(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800797 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800798 Context.insert<typename Traits::Insts::Pcmpgt>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700799 }
800 void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800801 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800802 Context.insert<typename Traits::Insts::Pextr>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700803 }
804 void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800805 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800806 Context.insert<typename Traits::Insts::Pinsr>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700807 }
808 void _pmull(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800809 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800810 Context.insert<typename Traits::Insts::Pmull>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700811 }
Nicolas Capens13cde0f2016-10-26 10:36:11 -0400812 void _pmulhw(Variable *Dest, Operand *Src0) {
813 AutoMemorySandboxer<> _(this, &Dest, &Src0);
814 Context.insert<typename Traits::Insts::Pmulhw>(Dest, Src0);
815 }
816 void _pmulhuw(Variable *Dest, Operand *Src0) {
817 AutoMemorySandboxer<> _(this, &Dest, &Src0);
818 Context.insert<typename Traits::Insts::Pmulhuw>(Dest, Src0);
819 }
820 void _pmaddwd(Variable *Dest, Operand *Src0) {
821 AutoMemorySandboxer<> _(this, &Dest, &Src0);
822 Context.insert<typename Traits::Insts::Pmaddwd>(Dest, Src0);
823 }
John Porto7e93c622015-06-23 10:58:57 -0700824 void _pmuludq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800825 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800826 Context.insert<typename Traits::Insts::Pmuludq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700827 }
828 void _pop(Variable *Dest) {
John Porto1d937a82015-12-17 06:19:34 -0800829 Context.insert<typename Traits::Insts::Pop>(Dest);
John Porto7e93c622015-06-23 10:58:57 -0700830 }
831 void _por(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800832 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800833 Context.insert<typename Traits::Insts::Por>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700834 }
John Portoae15f0f2016-04-26 04:26:33 -0700835 void _punpckl(Variable *Dest, Operand *Src0) {
836 AutoMemorySandboxer<> _(this, &Dest, &Src0);
837 Context.insert<typename Traits::Insts::Punpckl>(Dest, Src0);
838 }
Nicolas Capens1448d952016-10-14 16:37:09 -0400839 void _punpckh(Variable *Dest, Operand *Src0) {
840 AutoMemorySandboxer<> _(this, &Dest, &Src0);
841 Context.insert<typename Traits::Insts::Punpckh>(Dest, Src0);
842 }
Nicolas Capens7638e272016-10-06 11:33:55 -0400843 void _packss(Variable *Dest, Operand *Src0) {
844 AutoMemorySandboxer<> _(this, &Dest, &Src0);
845 Context.insert<typename Traits::Insts::Packss>(Dest, Src0);
846 }
847 void _packus(Variable *Dest, Operand *Src0) {
848 AutoMemorySandboxer<> _(this, &Dest, &Src0);
849 Context.insert<typename Traits::Insts::Packus>(Dest, Src0);
850 }
John Portode29f122016-04-26 19:16:07 -0700851 void _pshufb(Variable *Dest, Operand *Src0) {
852 AutoMemorySandboxer<> _(this, &Dest, &Src0);
853 Context.insert<typename Traits::Insts::Pshufb>(Dest, Src0);
854 }
John Porto7e93c622015-06-23 10:58:57 -0700855 void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800856 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800857 Context.insert<typename Traits::Insts::Pshufd>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700858 }
859 void _psll(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800860 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800861 Context.insert<typename Traits::Insts::Psll>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700862 }
863 void _psra(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800864 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800865 Context.insert<typename Traits::Insts::Psra>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700866 }
867 void _psrl(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800868 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800869 Context.insert<typename Traits::Insts::Psrl>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700870 }
871 void _psub(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800872 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800873 Context.insert<typename Traits::Insts::Psub>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700874 }
Nicolas Capens67a49b52016-10-26 13:18:35 -0400875 void _psubs(Variable *Dest, Operand *Src0) {
876 AutoMemorySandboxer<> _(this, &Dest, &Src0);
877 Context.insert<typename Traits::Insts::Psubs>(Dest, Src0);
878 }
879 void _psubus(Variable *Dest, Operand *Src0) {
880 AutoMemorySandboxer<> _(this, &Dest, &Src0);
881 Context.insert<typename Traits::Insts::Psubus>(Dest, Src0);
882 }
John Porto56958cb2016-01-14 09:18:18 -0800883 void _push(Operand *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800884 Context.insert<typename Traits::Insts::Push>(Src0);
John Porto7e93c622015-06-23 10:58:57 -0700885 }
886 void _pxor(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800887 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800888 Context.insert<typename Traits::Insts::Pxor>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700889 }
890 void _ret(Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800891 Context.insert<typename Traits::Insts::Ret>(Src0);
John Porto7e93c622015-06-23 10:58:57 -0700892 }
893 void _rol(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800894 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800895 Context.insert<typename Traits::Insts::Rol>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700896 }
John Porto56958cb2016-01-14 09:18:18 -0800897 X86OperandMem *_sandbox_mem_reference(X86OperandMem *Mem) {
898 return dispatchToConcrete(&Traits::ConcreteTarget::_sandbox_mem_reference,
899 std::move(Mem));
900 }
John Porto7e93c622015-06-23 10:58:57 -0700901 void _sar(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800902 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800903 Context.insert<typename Traits::Insts::Sar>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700904 }
905 void _sbb(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800906 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800907 Context.insert<typename Traits::Insts::Sbb>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700908 }
John Porto4a566862016-01-04 09:33:41 -0800909 void _sbb_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800910 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800911 Context.insert<typename Traits::Insts::SbbRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700912 }
John Porto4a566862016-01-04 09:33:41 -0800913 void _setcc(Variable *Dest, BrCond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800914 Context.insert<typename Traits::Insts::Setcc>(Dest, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700915 }
916 void _shl(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800917 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800918 Context.insert<typename Traits::Insts::Shl>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700919 }
David Sehr55f2e6d2015-09-22 09:17:39 -0700920 void _shld(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800921 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800922 Context.insert<typename Traits::Insts::Shld>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700923 }
924 void _shr(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800925 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800926 Context.insert<typename Traits::Insts::Shr>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700927 }
David Sehr55f2e6d2015-09-22 09:17:39 -0700928 void _shrd(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800929 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800930 Context.insert<typename Traits::Insts::Shrd>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700931 }
932 void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800933 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800934 Context.insert<typename Traits::Insts::Shufps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700935 }
Nicolas Capense3cabda2016-10-18 16:27:27 -0400936 void _movmsk(Variable *Dest, Operand *Src0) {
937 AutoMemorySandboxer<> _(this, &Dest, &Src0);
938 Context.insert<typename Traits::Insts::Movmsk>(Dest, Src0);
939 }
Nicolas Capens956cfd62016-10-31 14:28:09 -0400940 void _sqrt(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800941 AutoMemorySandboxer<> _(this, &Dest, &Src0);
Nicolas Capens956cfd62016-10-31 14:28:09 -0400942 Context.insert<typename Traits::Insts::Sqrt>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700943 }
John Porto4a566862016-01-04 09:33:41 -0800944 void _store(Operand *Value, X86Operand *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800945 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800946 Context.insert<typename Traits::Insts::Store>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700947 }
John Porto4a566862016-01-04 09:33:41 -0800948 void _storep(Variable *Value, X86OperandMem *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800949 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800950 Context.insert<typename Traits::Insts::StoreP>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700951 }
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400952 void _storeq(Operand *Value, X86OperandMem *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800953 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800954 Context.insert<typename Traits::Insts::StoreQ>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700955 }
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400956 void _stored(Operand *Value, X86OperandMem *Mem) {
957 AutoMemorySandboxer<> _(this, &Value, &Mem);
958 Context.insert<typename Traits::Insts::StoreD>(Value, Mem);
959 }
John Porto7e93c622015-06-23 10:58:57 -0700960 void _sub(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800961 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800962 Context.insert<typename Traits::Insts::Sub>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700963 }
John Porto4a566862016-01-04 09:33:41 -0800964 void _sub_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800965 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800966 Context.insert<typename Traits::Insts::SubRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700967 }
John Porto56958cb2016-01-14 09:18:18 -0800968 void _sub_sp(Operand *Adjustment) {
969 dispatchToConcrete(&Traits::ConcreteTarget::_sub_sp, std::move(Adjustment));
970 }
John Porto7e93c622015-06-23 10:58:57 -0700971 void _subps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800972 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800973 Context.insert<typename Traits::Insts::Subps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700974 }
975 void _subss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800976 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800977 Context.insert<typename Traits::Insts::Subss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700978 }
979 void _test(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800980 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800981 Context.insert<typename Traits::Insts::Test>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700982 }
983 void _ucomiss(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800984 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800985 Context.insert<typename Traits::Insts::Ucomiss>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700986 }
John Porto1d937a82015-12-17 06:19:34 -0800987 void _ud2() { Context.insert<typename Traits::Insts::UD2>(); }
David Sehrb9a404d2016-01-21 08:09:27 -0800988 void _unlink_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_unlink_bp); }
John Porto7e93c622015-06-23 10:58:57 -0700989 void _xadd(Operand *Dest, Variable *Src, bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -0800990 AutoMemorySandboxer<> _(this, &Dest, &Src);
John Porto1d937a82015-12-17 06:19:34 -0800991 Context.insert<typename Traits::Insts::Xadd>(Dest, Src, Locked);
Andrew Scull57e12682015-09-16 11:30:19 -0700992 // The xadd exchanges Dest and Src (modifying Src). Model that update with
993 // a FakeDef followed by a FakeUse.
John Porto1d937a82015-12-17 06:19:34 -0800994 Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
Jim Stichnoth230d4102015-09-25 17:40:32 -0700995 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800996 Context.insert<InstFakeUse>(Src);
John Porto7e93c622015-06-23 10:58:57 -0700997 }
998 void _xchg(Operand *Dest, Variable *Src) {
John Porto56958cb2016-01-14 09:18:18 -0800999 AutoMemorySandboxer<> _(this, &Dest, &Src);
John Porto1d937a82015-12-17 06:19:34 -08001000 Context.insert<typename Traits::Insts::Xchg>(Dest, Src);
John Porto7e93c622015-06-23 10:58:57 -07001001 // The xchg modifies Dest and Src -- model that update with a
1002 // FakeDef/FakeUse.
John Porto1d937a82015-12-17 06:19:34 -08001003 Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
Jim Stichnoth230d4102015-09-25 17:40:32 -07001004 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -08001005 Context.insert<InstFakeUse>(Src);
John Porto7e93c622015-06-23 10:58:57 -07001006 }
1007 void _xor(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001008 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001009 Context.insert<typename Traits::Insts::Xor>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -07001010 }
David Sehre3984282015-12-15 17:34:55 -08001011 void _xorps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001012 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001013 Context.insert<typename Traits::Insts::Xorps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -08001014 }
John Porto4a566862016-01-04 09:33:41 -08001015 void _xor_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -08001016 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -08001017 Context.insert<typename Traits::Insts::XorRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -07001018 }
John Porto7e93c622015-06-23 10:58:57 -07001019
Andrew Scull2c862522015-08-06 08:41:53 -07001020 void _iaca_start() {
1021 if (!BuildDefs::minimal())
John Porto1d937a82015-12-17 06:19:34 -08001022 Context.insert<typename Traits::Insts::IacaStart>();
Andrew Scull2c862522015-08-06 08:41:53 -07001023 }
1024 void _iaca_end() {
1025 if (!BuildDefs::minimal())
John Porto1d937a82015-12-17 06:19:34 -08001026 Context.insert<typename Traits::Insts::IacaEnd>();
Andrew Scull2c862522015-08-06 08:41:53 -07001027 }
1028
1029 /// This class helps wrap IACA markers around the code generated by the
1030 /// current scope. It means you don't need to put an end before each return.
1031 class ScopedIacaMark {
1032 ScopedIacaMark(const ScopedIacaMark &) = delete;
1033 ScopedIacaMark &operator=(const ScopedIacaMark &) = delete;
1034
1035 public:
1036 ScopedIacaMark(TargetX86Base *Lowering) : Lowering(Lowering) {
1037 Lowering->_iaca_start();
1038 }
1039 ~ScopedIacaMark() { end(); }
1040 void end() {
1041 if (!Lowering)
1042 return;
1043 Lowering->_iaca_end();
1044 Lowering = nullptr;
1045 }
1046
1047 private:
1048 TargetX86Base *Lowering;
1049 };
1050
John Porto7e93c622015-06-23 10:58:57 -07001051 bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
1052 void findRMW();
1053
John Porto4a566862016-01-04 09:33:41 -08001054 InstructionSetEnum InstructionSet = Traits::InstructionSet::Begin;
John Porto7e93c622015-06-23 10:58:57 -07001055 bool IsEbpBasedFrame = false;
1056 bool NeedsStackAlignment = false;
1057 size_t SpillAreaSizeBytes = 0;
Jim Stichnoth55f931f2015-09-23 16:33:08 -07001058 size_t FixedAllocaSizeBytes = 0;
David Sehr2f3b8ec2015-11-16 16:51:39 -08001059 size_t FixedAllocaAlignBytes = 0;
1060 bool PrologEmitsFixedAllocas = false;
David Sehr26217e32015-11-26 13:03:50 -08001061 uint32_t MaxOutArgsSizeBytes = 0;
John Portoe82b5602016-02-24 15:58:55 -08001062 static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSet;
1063 static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSetUnfiltered;
1064 static std::array<SmallBitVector, Traits::RegisterSet::Reg_NUM>
John Portobb0a5fe2015-09-04 11:23:41 -07001065 RegisterAliases;
John Portoe82b5602016-02-24 15:58:55 -08001066 SmallBitVector RegsUsed;
John Portobb0a5fe2015-09-04 11:23:41 -07001067 std::array<VarList, IceType_NUM> PhysicalRegisters;
John Portoac2388c2016-01-22 07:10:56 -08001068 // RebasePtr is a Variable that holds the Rebasing pointer (if any) for the
1069 // current sandboxing type.
1070 Variable *RebasePtr = nullptr;
John Porto7e93c622015-06-23 10:58:57 -07001071
Andrew Scull9612d322015-07-06 14:53:25 -07001072 /// Randomize a given immediate operand
John Porto7e93c622015-06-23 10:58:57 -07001073 Operand *randomizeOrPoolImmediate(Constant *Immediate,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -08001074 RegNumT RegNum = RegNumT());
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001075 X86OperandMem *randomizeOrPoolImmediate(X86OperandMem *MemOperand,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -08001076 RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -07001077 bool RandomizationPoolingPaused = false;
1078
1079private:
John Porto5aeed952015-07-21 13:39:09 -07001080 /// dispatchToConcrete is the template voodoo that allows TargetX86Base to
1081 /// invoke methods in Machine (which inherits from TargetX86Base) without
1082 /// having to rely on virtual method calls. There are two overloads, one for
1083 /// non-void types, and one for void types. We need this becase, for non-void
1084 /// types, we need to return the method result, where as for void, we don't.
1085 /// While it is true that the code compiles without the void "version", there
1086 /// used to be a time when compilers would reject such code.
1087 ///
1088 /// This machinery is far from perfect. Note that, in particular, the
1089 /// arguments provided to dispatchToConcrete() need to match the arguments for
1090 /// Method **exactly** (i.e., no argument promotion is performed.)
1091 template <typename Ret, typename... Args>
1092 typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
John Porto4a566862016-01-04 09:33:41 -08001093 dispatchToConcrete(Ret (ConcreteTarget::*Method)(Args...), Args &&... args) {
1094 return (static_cast<ConcreteTarget *>(this)->*Method)(
1095 std::forward<Args>(args)...);
John Porto5aeed952015-07-21 13:39:09 -07001096 }
1097
1098 template <typename... Args>
John Porto4a566862016-01-04 09:33:41 -08001099 void dispatchToConcrete(void (ConcreteTarget::*Method)(Args...),
1100 Args &&... args) {
1101 (static_cast<ConcreteTarget *>(this)->*Method)(std::forward<Args>(args)...);
John Porto5aeed952015-07-21 13:39:09 -07001102 }
1103
David Sehr188eae52015-09-24 11:42:55 -07001104 void lowerShift64(InstArithmetic::OpKind Op, Operand *Src0Lo, Operand *Src0Hi,
1105 Operand *Src1Lo, Variable *DestLo, Variable *DestHi);
1106
David Sehre3984282015-12-15 17:34:55 -08001107 /// Emit the code for a combined operation and consumer instruction, or set
1108 /// the destination variable of the operation if Consumer == nullptr.
1109 void lowerIcmpAndConsumer(const InstIcmp *Icmp, const Inst *Consumer);
1110 void lowerFcmpAndConsumer(const InstFcmp *Fcmp, const Inst *Consumer);
1111 void lowerArithAndConsumer(const InstArithmetic *Arith, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001112
David Sehre3984282015-12-15 17:34:55 -08001113 /// Emit a setcc instruction if Consumer == nullptr; otherwise emit a
1114 /// specialized version of Consumer.
John Porto4a566862016-01-04 09:33:41 -08001115 void setccOrConsumer(BrCond Condition, Variable *Dest, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001116
David Sehre3984282015-12-15 17:34:55 -08001117 /// Emit a mov [1|0] instruction if Consumer == nullptr; otherwise emit a
1118 /// specialized version of Consumer.
1119 void movOrConsumer(bool IcmpResult, Variable *Dest, const Inst *Consumer);
1120
1121 /// Emit the code for instructions with a vector type.
1122 void lowerIcmpVector(const InstIcmp *Icmp);
1123 void lowerFcmpVector(const InstFcmp *Icmp);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001124 void lowerSelectVector(const InstSelect *Instr);
David Sehre3984282015-12-15 17:34:55 -08001125
1126 /// Helpers for select lowering.
John Porto4a566862016-01-04 09:33:41 -08001127 void lowerSelectMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1128 Operand *SrcF);
1129 void lowerSelectIntMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1130 Operand *SrcF);
David Sehre3984282015-12-15 17:34:55 -08001131 /// Generic helper to move an arbitrary type from Src to Dest.
1132 void lowerMove(Variable *Dest, Operand *Src, bool IsRedefinition);
1133
1134 /// Optimizations for idiom recognition.
1135 bool lowerOptimizeFcmpSelect(const InstFcmp *Fcmp, const InstSelect *Select);
David Sehrd9810252015-10-16 13:23:17 -07001136
1137 /// Complains loudly if invoked because the cpu can handle 64-bit types
1138 /// natively.
1139 template <typename T = Traits>
1140 typename std::enable_if<T::Is64Bit, void>::type lowerIcmp64(const InstIcmp *,
David Sehre3984282015-12-15 17:34:55 -08001141 const Inst *) {
David Sehrd9810252015-10-16 13:23:17 -07001142 llvm::report_fatal_error(
1143 "Hey, yo! This is x86-64. Watcha doin'? (lowerIcmp64)");
1144 }
1145 /// x86lowerIcmp64 handles 64-bit icmp lowering.
1146 template <typename T = Traits>
1147 typename std::enable_if<!T::Is64Bit, void>::type
David Sehre3984282015-12-15 17:34:55 -08001148 lowerIcmp64(const InstIcmp *Icmp, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001149
Jim Stichnothcaeaa272016-01-10 12:53:44 -08001150 BoolFolding<Traits> FoldingInfo;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -08001151
John Portoae15f0f2016-04-26 04:26:33 -07001152 /// Helpers for lowering ShuffleVector
1153 /// @{
1154 Variable *lowerShuffleVector_AllFromSameSrc(Variable *Src, SizeT Index0,
1155 SizeT Index1, SizeT Index2,
1156 SizeT Index3);
1157 static constexpr SizeT IGNORE_INDEX = 0x80000000u;
1158 Variable *lowerShuffleVector_TwoFromSameSrc(Variable *Src0, SizeT Index0,
1159 SizeT Index1, Variable *Src1,
1160 SizeT Index2, SizeT Index3);
1161 static constexpr SizeT UNIFIED_INDEX_0 = 0;
1162 static constexpr SizeT UNIFIED_INDEX_1 = 2;
1163 Variable *lowerShuffleVector_UnifyFromDifferentSrcs(Variable *Src0,
1164 SizeT Index0,
1165 Variable *Src1,
1166 SizeT Index1);
John Portode29f122016-04-26 19:16:07 -07001167 static constexpr SizeT CLEAR_ALL_BITS = 0x80;
1168 SizeT PshufbMaskCount = 0;
1169 GlobalString lowerShuffleVector_NewMaskName();
1170 ConstantRelocatable *lowerShuffleVector_CreatePshufbMask(
1171 int8_t Idx0, int8_t Idx1, int8_t Idx2, int8_t Idx3, int8_t Idx4,
1172 int8_t Idx5, int8_t Idx6, int8_t Idx7, int8_t Idx8, int8_t Idx9,
1173 int8_t Idx10, int8_t Idx11, int8_t Idx12, int8_t Idx13, int8_t Idx14,
1174 int8_t Idx15);
1175 void lowerShuffleVector_UsingPshufb(Variable *Dest, Operand *Src0,
1176 Operand *Src1, int8_t Idx0, int8_t Idx1,
1177 int8_t Idx2, int8_t Idx3, int8_t Idx4,
1178 int8_t Idx5, int8_t Idx6, int8_t Idx7,
1179 int8_t Idx8, int8_t Idx9, int8_t Idx10,
1180 int8_t Idx11, int8_t Idx12, int8_t Idx13,
1181 int8_t Idx14, int8_t Idx15);
John Portoae15f0f2016-04-26 04:26:33 -07001182 /// @}
1183
Jim Stichnoth8ff4b282016-01-04 15:39:06 -08001184 static FixupKind PcRelFixup;
1185 static FixupKind AbsFixup;
John Porto7e93c622015-06-23 10:58:57 -07001186};
David Sehr6b80cf12016-01-21 23:16:58 -08001187
1188template <typename TraitsType>
1189class TargetDataX86 final : public TargetDataLowering {
1190 using Traits = TraitsType;
1191 TargetDataX86() = delete;
1192 TargetDataX86(const TargetDataX86 &) = delete;
1193 TargetDataX86 &operator=(const TargetDataX86 &) = delete;
1194
1195public:
1196 ~TargetDataX86() override = default;
1197
1198 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1199 return makeUnique<TargetDataX86>(Ctx);
1200 }
1201
1202 void lowerGlobals(const VariableDeclarationList &Vars,
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001203 const std::string &SectionSuffix) override;
David Sehr6b80cf12016-01-21 23:16:58 -08001204 void lowerConstants() override;
1205 void lowerJumpTables() override;
1206
1207private:
1208 ENABLE_MAKE_UNIQUE;
1209
1210 explicit TargetDataX86(GlobalContext *Ctx) : TargetDataLowering(Ctx){};
1211 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
1212};
1213
1214class TargetHeaderX86 : public TargetHeaderLowering {
1215 TargetHeaderX86() = delete;
1216 TargetHeaderX86(const TargetHeaderX86 &) = delete;
1217 TargetHeaderX86 &operator=(const TargetHeaderX86 &) = delete;
1218
1219public:
1220 ~TargetHeaderX86() = default;
1221
1222 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1223 return makeUnique<TargetHeaderX86>(Ctx);
1224 }
1225
1226private:
1227 ENABLE_MAKE_UNIQUE;
1228
1229 explicit TargetHeaderX86(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {}
1230};
1231
John Porto4a566862016-01-04 09:33:41 -08001232} // end of namespace X86NAMESPACE
John Porto7e93c622015-06-23 10:58:57 -07001233} // end of namespace Ice
1234
1235#include "IceTargetLoweringX86BaseImpl.h"
1236
1237#endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H