blob: 9d606092365a85da5f1df4057134183b4f41c40e [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;
Nicolas Capense986b312017-01-27 00:56:42 -0800316 void doAddressOptLoadSubVector() override;
317 void doAddressOptStoreSubVector() override;
Jim Stichnothad2989b2015-09-15 10:21:42 -0700318 void doMockBoundsCheck(Operand *Opnd) override;
Qining Luaee5fa82015-08-20 14:59:03 -0700319 void randomlyInsertNop(float Probability,
320 RandomNumberGenerator &RNG) override;
John Porto7e93c622015-06-23 10:58:57 -0700321
Andrew Scull9612d322015-07-06 14:53:25 -0700322 /// Naive lowering of cmpxchg.
John Porto7e93c622015-06-23 10:58:57 -0700323 void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
324 Operand *Desired);
Andrew Scull9612d322015-07-06 14:53:25 -0700325 /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
John Porto7e93c622015-06-23 10:58:57 -0700326 bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr,
327 Operand *Expected, Operand *Desired);
328 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
329 Operand *Val);
330 void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal,
331 Operand *SecondVal);
Andrew Scullcfa628b2015-08-20 14:23:05 -0700332 /// Load from memory for a given type.
333 void typedLoad(Type Ty, Variable *Dest, Variable *Base, Constant *Offset);
334 /// Store to memory for a given type.
335 void typedStore(Type Ty, Variable *Value, Variable *Base, Constant *Offset);
336 /// Copy memory of given type from Src to Dest using OffsetAmt on both.
337 void copyMemory(Type Ty, Variable *Dest, Variable *Src, int32_t OffsetAmt);
338 /// Replace some calls to memcpy with inline instructions.
Andrew Scull9df4a372015-08-07 09:19:35 -0700339 void lowerMemcpy(Operand *Dest, Operand *Src, Operand *Count);
Andrew Scullcfa628b2015-08-20 14:23:05 -0700340 /// Replace some calls to memmove with inline instructions.
341 void lowerMemmove(Operand *Dest, Operand *Src, Operand *Count);
342 /// Replace some calls to memset with inline instructions.
Andrew Scull713dbde2015-08-04 14:25:27 -0700343 void lowerMemset(Operand *Dest, Operand *Val, Operand *Count);
344
Andrew Scull86df4e92015-07-30 13:54:44 -0700345 /// Lower an indirect jump adding sandboxing when needed.
John Porto56958cb2016-01-14 09:18:18 -0800346 void lowerIndirectJump(Variable *JumpTarget) {
347 // Without std::move below, the compiler deduces that the argument to
348 // lowerIndirectJmp is a Variable *&, not a Variable *.
349 dispatchToConcrete(&Traits::ConcreteTarget::lowerIndirectJump,
350 std::move(JumpTarget));
351 }
John Porto7e93c622015-06-23 10:58:57 -0700352
Andrew Scull87f80c12015-07-20 10:19:16 -0700353 /// Check the comparison is in [Min,Max]. The flags register will be modified
354 /// with:
355 /// - below equal, if in range
356 /// - above, set if not in range
357 /// The index into the range is returned.
358 Operand *lowerCmpRange(Operand *Comparison, uint64_t Min, uint64_t Max);
359 /// Lowering of a cluster of switch cases. If the case is not matched control
360 /// will pass to the default label provided. If the default label is nullptr
361 /// then control will fall through to the next instruction. DoneCmp should be
362 /// true if the flags contain the result of a comparison with the Comparison.
363 void lowerCaseCluster(const CaseCluster &Case, Operand *Src0, bool DoneCmp,
364 CfgNode *DefaultLabel = nullptr);
365
Andrew Scull8072bae2015-09-14 16:01:26 -0700366 using LowerBinOp = void (TargetX86Base::*)(Variable *, Operand *);
John Porto7e93c622015-06-23 10:58:57 -0700367 void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi,
368 Variable *Dest, Operand *Ptr, Operand *Val);
369
370 void eliminateNextVectorSextInstruction(Variable *SignExtendedResult);
371
David Sehrb9a404d2016-01-21 08:09:27 -0800372 void emitGetIP(CfgNode *Node) {
373 dispatchToConcrete(&Traits::ConcreteTarget::emitGetIP, std::move(Node));
374 }
375 /// Emit a sandboxed return sequence rather than a return.
376 void emitSandboxedReturn() {
377 dispatchToConcrete(&Traits::ConcreteTarget::emitSandboxedReturn);
378 }
David Sehr0c68bef2016-01-20 10:00:23 -0800379 /// Emit just the call instruction (without argument or return variable
380 /// processing), sandboxing if needed.
Jim Stichnothc10c1562016-03-10 08:19:34 -0800381 virtual Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) = 0;
David Sehr0c68bef2016-01-20 10:00:23 -0800382 /// Materialize the moves needed to return a value of the specified type.
Jim Stichnothc10c1562016-03-10 08:19:34 -0800383 virtual Variable *moveReturnValueToRegister(Operand *Value,
384 Type ReturnType) = 0;
David Sehr0c68bef2016-01-20 10:00:23 -0800385
David Sehr6b80cf12016-01-21 23:16:58 -0800386 /// Emit a jump table to the constant pool.
387 void emitJumpTable(const Cfg *Func,
388 const InstJumpTable *JumpTable) const override;
389
David Sehr21fd1032015-11-13 16:32:37 -0800390 /// Emit a fake use of esp to make sure esp stays alive for the entire
391 /// function. Otherwise some esp adjustments get dead-code eliminated.
392 void keepEspLiveAtExit() {
John Porto008f4ce2015-12-24 13:22:18 -0800393 Variable *esp =
394 Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
John Porto1d937a82015-12-17 06:19:34 -0800395 Context.insert<InstFakeUse>(esp);
David Sehr21fd1032015-11-13 16:32:37 -0800396 }
397
Andrew Scull57e12682015-09-16 11:30:19 -0700398 /// Operand legalization helpers. To deal with address mode constraints, the
399 /// helpers will create a new Operand and emit instructions that guarantee
400 /// that the Operand kind is one of those indicated by the LegalMask (a
401 /// bitmask of allowed kinds). If the input Operand is known to already meet
402 /// the constraints, it may be simply returned as the result, without creating
403 /// any new instructions or operands.
John Porto7e93c622015-06-23 10:58:57 -0700404 enum OperandLegalization {
405 Legal_None = 0,
406 Legal_Reg = 1 << 0, // physical register, not stack location
407 Legal_Imm = 1 << 1,
408 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12]
David Sehr4318a412015-11-11 15:01:55 -0800409 Legal_Rematerializable = 1 << 3,
John Portoac2388c2016-01-22 07:10:56 -0800410 Legal_AddrAbs = 1 << 4, // ConstantRelocatable doesn't have to add RebasePtr
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800411 Legal_Default = ~(Legal_Rematerializable | Legal_AddrAbs)
412 // TODO(stichnot): Figure out whether this default works for x86-64.
John Porto7e93c622015-06-23 10:58:57 -0700413 };
Andrew Scull8072bae2015-09-14 16:01:26 -0700414 using LegalMask = uint32_t;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800415 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800416 RegNumT RegNum = RegNumT());
417 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
Andrew Scull9612d322015-07-06 14:53:25 -0700418 /// Legalize the first source operand for use in the cmp instruction.
John Porto7e93c622015-06-23 10:58:57 -0700419 Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
Andrew Scull57e12682015-09-16 11:30:19 -0700420 /// Turn a pointer operand into a memory operand that can be used by a real
421 /// load/store operation. Legalizes the operand as well. This is a nop if the
422 /// operand is already a legal memory operand.
John Porto4a566862016-01-04 09:33:41 -0800423 X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
424 bool DoLegalize = true);
John Porto7e93c622015-06-23 10:58:57 -0700425
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800426 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700427 static Type stackSlotType();
428
Andrew Scullcfa628b2015-08-20 14:23:05 -0700429 static constexpr uint32_t NoSizeLimit = 0;
Andrew Scullcfa628b2015-08-20 14:23:05 -0700430 /// Returns the largest type which is equal to or larger than Size bytes. The
Andrew Scull57e12682015-09-16 11:30:19 -0700431 /// type is suitable for copying memory i.e. a load and store will be a single
432 /// instruction (for example x86 will get f64 not i64).
Andrew Scullcfa628b2015-08-20 14:23:05 -0700433 static Type largestTypeInSize(uint32_t Size, uint32_t MaxSize = NoSizeLimit);
434 /// Returns the smallest type which is equal to or larger than Size bytes. If
435 /// one doesn't exist then the largest type smaller than Size bytes is
436 /// returned. The type is suitable for memory copies as described at
437 /// largestTypeInSize.
438 static Type firstTypeThatFitsSize(uint32_t Size,
439 uint32_t MaxSize = NoSizeLimit);
440
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800441 Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT());
442 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -0700443
Jim Stichnoth99165662015-11-13 14:20:40 -0800444 /// Returns a register containing all zeros, without affecting the FLAGS
445 /// register, using the best instruction for the type.
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800446 Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT());
Jim Stichnoth99165662015-11-13 14:20:40 -0800447
Andrew Scull713dbde2015-08-04 14:25:27 -0700448 /// \name Returns a vector in a register with the given constant entries.
449 /// @{
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800450 Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
451 Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT());
452 Variable *makeVectorOfMinusOnes(Type Ty, RegNumT RegNum = RegNumT());
453 Variable *makeVectorOfHighOrderBits(Type Ty, RegNumT RegNum = RegNumT());
454 Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT());
Andrew Scull713dbde2015-08-04 14:25:27 -0700455 /// @}
John Porto7e93c622015-06-23 10:58:57 -0700456
Andrew Scull9612d322015-07-06 14:53:25 -0700457 /// Return a memory operand corresponding to a stack allocated Variable.
John Porto4a566862016-01-04 09:33:41 -0800458 X86OperandMem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
459 uint32_t Offset = 0);
John Porto7e93c622015-06-23 10:58:57 -0700460
Qining Luaee5fa82015-08-20 14:59:03 -0700461 void
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800462 makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
John Portoe82b5602016-02-24 15:58:55 -0800463 const SmallBitVector &ExcludeRegisters,
Qining Luaee5fa82015-08-20 14:59:03 -0700464 uint64_t Salt) const override;
John Porto7e93c622015-06-23 10:58:57 -0700465
John Porto56958cb2016-01-14 09:18:18 -0800466 /// AutoMemorySandboxer emits a bundle-lock/bundle-unlock pair if the
467 /// instruction's operand is a memory reference. This is only needed for
468 /// x86-64 NaCl sandbox.
469 template <InstBundleLock::Option BundleLockOpt = InstBundleLock::Opt_None>
470 class AutoMemorySandboxer {
471 AutoMemorySandboxer() = delete;
472 AutoMemorySandboxer(const AutoMemorySandboxer &) = delete;
473 AutoMemorySandboxer &operator=(const AutoMemorySandboxer &) = delete;
474
475 private:
476 typename Traits::TargetLowering *Target;
477
478 template <typename T, typename... Tail>
479 X86OperandMem **findMemoryReference(T **First, Tail... Others) {
480 if (llvm::isa<X86OperandMem>(*First)) {
481 return reinterpret_cast<X86OperandMem **>(First);
482 }
483 return findMemoryReference(Others...);
484 }
485
486 X86OperandMem **findMemoryReference() { return nullptr; }
487
488 public:
John Porto4abbb592016-03-10 10:59:02 -0800489 AutoBundle *Bundler = nullptr;
John Porto56958cb2016-01-14 09:18:18 -0800490 X86OperandMem **const MemOperand;
491
492 template <typename... T>
493 AutoMemorySandboxer(typename Traits::TargetLowering *Target, T... Args)
John Portoac2388c2016-01-22 07:10:56 -0800494 : Target(Target), MemOperand(Target->SandboxingType == ST_None
495 ? nullptr
496 : findMemoryReference(Args...)) {
John Porto56958cb2016-01-14 09:18:18 -0800497 if (MemOperand != nullptr) {
John Porto8347abd2016-02-04 09:12:02 -0800498 if (Traits::Is64Bit) {
John Porto4abbb592016-03-10 10:59:02 -0800499 Bundler = new (Target->Func->template allocate<AutoBundle>())
500 AutoBundle(Target, BundleLockOpt);
John Porto8347abd2016-02-04 09:12:02 -0800501 }
John Porto56958cb2016-01-14 09:18:18 -0800502 *MemOperand = Target->_sandbox_mem_reference(*MemOperand);
503 }
504 }
505
John Porto4abbb592016-03-10 10:59:02 -0800506 ~AutoMemorySandboxer() {
507 if (Bundler != nullptr) {
508 Bundler->~AutoBundle();
509 }
510 }
John Porto56958cb2016-01-14 09:18:18 -0800511 };
512
Andrew Scull57e12682015-09-16 11:30:19 -0700513 /// The following are helpers that insert lowered x86 instructions with
514 /// minimal syntactic overhead, so that the lowering code can look as close to
515 /// assembly as practical.
John Porto7e93c622015-06-23 10:58:57 -0700516 void _adc(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800517 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800518 Context.insert<typename Traits::Insts::Adc>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700519 }
John Porto4a566862016-01-04 09:33:41 -0800520 void _adc_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800521 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800522 Context.insert<typename Traits::Insts::AdcRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700523 }
524 void _add(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800525 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800526 Context.insert<typename Traits::Insts::Add>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700527 }
John Porto4a566862016-01-04 09:33:41 -0800528 void _add_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800529 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800530 Context.insert<typename Traits::Insts::AddRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700531 }
John Porto7e93c622015-06-23 10:58:57 -0700532 void _addps(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::Addps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700535 }
536 void _addss(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::Addss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700539 }
John Porto56958cb2016-01-14 09:18:18 -0800540 void _add_sp(Operand *Adjustment) {
541 dispatchToConcrete(&Traits::ConcreteTarget::_add_sp, std::move(Adjustment));
542 }
John Porto7e93c622015-06-23 10:58:57 -0700543 void _and(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800544 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800545 Context.insert<typename Traits::Insts::And>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700546 }
David Sehre3984282015-12-15 17:34:55 -0800547 void _andnps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800548 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800549 Context.insert<typename Traits::Insts::Andnps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800550 }
551 void _andps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800552 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800553 Context.insert<typename Traits::Insts::Andps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800554 }
John Porto4a566862016-01-04 09:33:41 -0800555 void _and_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800556 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800557 Context.insert<typename Traits::Insts::AndRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700558 }
559 void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800560 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800561 Context.insert<typename Traits::Insts::Blendvps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700562 }
John Porto4a566862016-01-04 09:33:41 -0800563 void _br(BrCond Condition, CfgNode *TargetTrue, CfgNode *TargetFalse) {
564 Context.insert<InstX86Br>(TargetTrue, TargetFalse, Condition,
565 InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700566 }
567 void _br(CfgNode *Target) {
John Porto4a566862016-01-04 09:33:41 -0800568 Context.insert<InstX86Br>(Target, InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700569 }
John Porto4a566862016-01-04 09:33:41 -0800570 void _br(BrCond Condition, CfgNode *Target) {
571 Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far);
John Porto7e93c622015-06-23 10:58:57 -0700572 }
John Porto4a566862016-01-04 09:33:41 -0800573 void _br(BrCond Condition, InstX86Label *Label,
574 typename InstX86Br::Mode Kind = InstX86Br::Near) {
575 Context.insert<InstX86Br>(Label, Condition, Kind);
John Porto7e93c622015-06-23 10:58:57 -0700576 }
577 void _bsf(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800578 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800579 Context.insert<typename Traits::Insts::Bsf>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700580 }
581 void _bsr(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800582 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800583 Context.insert<typename Traits::Insts::Bsr>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700584 }
585 void _bswap(Variable *SrcDest) {
John Porto56958cb2016-01-14 09:18:18 -0800586 AutoMemorySandboxer<> _(this, &SrcDest);
John Porto1d937a82015-12-17 06:19:34 -0800587 Context.insert<typename Traits::Insts::Bswap>(SrcDest);
John Porto7e93c622015-06-23 10:58:57 -0700588 }
589 void _cbwdq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800590 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800591 Context.insert<typename Traits::Insts::Cbwdq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700592 }
John Porto4a566862016-01-04 09:33:41 -0800593 void _cmov(Variable *Dest, Operand *Src0, BrCond Condition) {
John Porto56958cb2016-01-14 09:18:18 -0800594 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800595 Context.insert<typename Traits::Insts::Cmov>(Dest, Src0, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700596 }
597 void _cmp(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800598 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800599 Context.insert<typename Traits::Insts::Icmp>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700600 }
John Porto4a566862016-01-04 09:33:41 -0800601 void _cmpps(Variable *Dest, Operand *Src0, CmppsCond Condition) {
John Porto56958cb2016-01-14 09:18:18 -0800602 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800603 Context.insert<typename Traits::Insts::Cmpps>(Dest, Src0, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700604 }
605 void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
606 bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -0800607 AutoMemorySandboxer<> _(this, &DestOrAddr);
John Porto1d937a82015-12-17 06:19:34 -0800608 Context.insert<typename Traits::Insts::Cmpxchg>(DestOrAddr, Eax, Desired,
609 Locked);
John Porto7e93c622015-06-23 10:58:57 -0700610 // Mark eax as possibly modified by cmpxchg.
John Porto1d937a82015-12-17 06:19:34 -0800611 Context.insert<InstFakeDef>(Eax, llvm::dyn_cast<Variable>(DestOrAddr));
Jim Stichnoth230d4102015-09-25 17:40:32 -0700612 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800613 Context.insert<InstFakeUse>(Eax);
John Porto7e93c622015-06-23 10:58:57 -0700614 }
John Porto4a566862016-01-04 09:33:41 -0800615 void _cmpxchg8b(X86OperandMem *Addr, Variable *Edx, Variable *Eax,
616 Variable *Ecx, Variable *Ebx, bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -0800617 AutoMemorySandboxer<> _(this, &Addr);
John Porto1d937a82015-12-17 06:19:34 -0800618 Context.insert<typename Traits::Insts::Cmpxchg8b>(Addr, Edx, Eax, Ecx, Ebx,
619 Locked);
John Porto7e93c622015-06-23 10:58:57 -0700620 // Mark edx, and eax as possibly modified by cmpxchg8b.
John Porto1d937a82015-12-17 06:19:34 -0800621 Context.insert<InstFakeDef>(Edx);
Jim Stichnoth230d4102015-09-25 17:40:32 -0700622 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800623 Context.insert<InstFakeUse>(Edx);
624 Context.insert<InstFakeDef>(Eax);
Jim Stichnoth230d4102015-09-25 17:40:32 -0700625 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -0800626 Context.insert<InstFakeUse>(Eax);
John Porto7e93c622015-06-23 10:58:57 -0700627 }
John Porto921856d2015-07-07 11:56:26 -0700628 void _cvt(Variable *Dest, Operand *Src0,
629 typename Traits::Insts::Cvt::CvtVariant Variant) {
John Porto56958cb2016-01-14 09:18:18 -0800630 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800631 Context.insert<typename Traits::Insts::Cvt>(Dest, Src0, Variant);
John Porto7e93c622015-06-23 10:58:57 -0700632 }
Nicolas Capensf0d12c32016-10-27 15:17:41 -0400633 void _round(Variable *Dest, Operand *Src0, Operand *Imm) {
634 AutoMemorySandboxer<> _(this, &Dest, &Src0);
635 Context.insert<typename Traits::Insts::Round>(Dest, Src0, Imm);
636 }
John Porto7e93c622015-06-23 10:58:57 -0700637 void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800638 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800639 Context.insert<typename Traits::Insts::Div>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700640 }
641 void _divps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800642 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800643 Context.insert<typename Traits::Insts::Divps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700644 }
645 void _divss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800646 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800647 Context.insert<typename Traits::Insts::Divss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700648 }
John Porto453660f2015-07-31 14:52:52 -0700649 template <typename T = Traits>
650 typename std::enable_if<T::UsesX87, void>::type _fld(Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800651 AutoMemorySandboxer<> _(this, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800652 Context.insert<typename Traits::Insts::template Fld<>>(Src0);
John Porto921856d2015-07-07 11:56:26 -0700653 }
John Porto453660f2015-07-31 14:52:52 -0700654 // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
655 // does not invoke this method, and remove it.
656 template <typename T = Traits>
657 typename std::enable_if<!T::UsesX87, void>::type _fld(Operand *) {
658 llvm::report_fatal_error("fld is not available in x86-64");
659 }
660 template <typename T = Traits>
661 typename std::enable_if<T::UsesX87, void>::type _fstp(Variable *Dest) {
John Porto56958cb2016-01-14 09:18:18 -0800662 AutoMemorySandboxer<> _(this, &Dest);
John Porto1d937a82015-12-17 06:19:34 -0800663 Context.insert<typename Traits::Insts::template Fstp<>>(Dest);
John Porto453660f2015-07-31 14:52:52 -0700664 }
665 // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
666 // does not invoke this method, and remove it.
667 template <typename T = Traits>
668 typename std::enable_if<!T::UsesX87, void>::type _fstp(Variable *) {
669 llvm::report_fatal_error("fstp is not available in x86-64");
John Porto7e93c622015-06-23 10:58:57 -0700670 }
671 void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800672 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800673 Context.insert<typename Traits::Insts::Idiv>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700674 }
675 void _imul(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800676 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800677 Context.insert<typename Traits::Insts::Imul>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700678 }
David Sehre11f8782015-10-06 10:26:57 -0700679 void _imul_imm(Variable *Dest, Operand *Src0, Constant *Imm) {
John Porto56958cb2016-01-14 09:18:18 -0800680 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800681 Context.insert<typename Traits::Insts::ImulImm>(Dest, Src0, Imm);
David Sehre11f8782015-10-06 10:26:57 -0700682 }
John Porto7e93c622015-06-23 10:58:57 -0700683 void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800684 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800685 Context.insert<typename Traits::Insts::Insertps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700686 }
Eric Holk67c7c412016-04-15 13:05:37 -0700687 void _int3() { Context.insert<typename Traits::Insts::Int3>(); }
John Porto7e93c622015-06-23 10:58:57 -0700688 void _jmp(Operand *Target) {
John Porto56958cb2016-01-14 09:18:18 -0800689 AutoMemorySandboxer<> _(this, &Target);
John Porto1d937a82015-12-17 06:19:34 -0800690 Context.insert<typename Traits::Insts::Jmp>(Target);
John Porto7e93c622015-06-23 10:58:57 -0700691 }
692 void _lea(Variable *Dest, Operand *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800693 Context.insert<typename Traits::Insts::Lea>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700694 }
David Sehrb9a404d2016-01-21 08:09:27 -0800695 void _link_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_link_bp); }
Stephen White17078c72019-02-27 14:39:14 -0500696 void _push_reg(RegNumT RegNum) {
697 dispatchToConcrete(&Traits::ConcreteTarget::_push_reg, std::move(RegNum));
698 }
699 void _pop_reg(RegNumT RegNum) {
700 dispatchToConcrete(&Traits::ConcreteTarget::_pop_reg, std::move(RegNum));
David Sehrb9a404d2016-01-21 08:09:27 -0800701 }
John Porto1d937a82015-12-17 06:19:34 -0800702 void _mfence() { Context.insert<typename Traits::Insts::Mfence>(); }
David Sehre3984282015-12-15 17:34:55 -0800703 /// Moves can be used to redefine registers, creating "partial kills" for
704 /// liveness. Mark where moves are used in this way.
705 void _redefined(Inst *MovInst, bool IsRedefinition = true) {
706 if (IsRedefinition)
707 MovInst->setDestRedefined();
708 }
Andrew Scull57e12682015-09-16 11:30:19 -0700709 /// If Dest=nullptr is passed in, then a new variable is created, marked as
710 /// infinite register allocation weight, and returned through the in/out Dest
711 /// argument.
John Porto1d937a82015-12-17 06:19:34 -0800712 typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800713 RegNumT RegNum = RegNumT()) {
John Porto7e93c622015-06-23 10:58:57 -0700714 if (Dest == nullptr)
715 Dest = makeReg(Src0->getType(), RegNum);
John Porto56958cb2016-01-14 09:18:18 -0800716 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800717 return Context.insert<typename Traits::Insts::Mov>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800718 }
John Porto56958cb2016-01-14 09:18:18 -0800719 void _mov_sp(Operand *NewValue) {
720 dispatchToConcrete(&Traits::ConcreteTarget::_mov_sp, std::move(NewValue));
721 }
John Porto1d937a82015-12-17 06:19:34 -0800722 typename Traits::Insts::Movp *_movp(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800723 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800724 return Context.insert<typename Traits::Insts::Movp>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700725 }
726 void _movd(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800727 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800728 Context.insert<typename Traits::Insts::Movd>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700729 }
John Porto7e93c622015-06-23 10:58:57 -0700730 void _movq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800731 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800732 Context.insert<typename Traits::Insts::Movq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700733 }
734 void _movss(Variable *Dest, Variable *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800735 Context.insert<typename Traits::Insts::MovssRegs>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700736 }
737 void _movsx(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800738 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800739 Context.insert<typename Traits::Insts::Movsx>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700740 }
John Porto56958cb2016-01-14 09:18:18 -0800741 typename Traits::Insts::Movzx *_movzx(Variable *Dest, Operand *Src0) {
742 AutoMemorySandboxer<> _(this, &Dest, &Src0);
743 return Context.insert<typename Traits::Insts::Movzx>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700744 }
David Sehre3984282015-12-15 17:34:55 -0800745 void _maxss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800746 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800747 Context.insert<typename Traits::Insts::Maxss>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800748 }
749 void _minss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800750 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800751 Context.insert<typename Traits::Insts::Minss>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800752 }
Nicolas Capenseb568f52017-02-13 09:49:43 -0500753 void _maxps(Variable *Dest, Operand *Src0) {
754 AutoMemorySandboxer<> _(this, &Dest, &Src0);
755 Context.insert<typename Traits::Insts::Maxps>(Dest, Src0);
756 }
757 void _minps(Variable *Dest, Operand *Src0) {
758 AutoMemorySandboxer<> _(this, &Dest, &Src0);
759 Context.insert<typename Traits::Insts::Minps>(Dest, Src0);
760 }
John Porto7e93c622015-06-23 10:58:57 -0700761 void _mul(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800762 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800763 Context.insert<typename Traits::Insts::Mul>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700764 }
765 void _mulps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800766 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800767 Context.insert<typename Traits::Insts::Mulps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700768 }
769 void _mulss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800770 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800771 Context.insert<typename Traits::Insts::Mulss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700772 }
773 void _neg(Variable *SrcDest) {
John Porto56958cb2016-01-14 09:18:18 -0800774 AutoMemorySandboxer<> _(this, &SrcDest);
John Porto1d937a82015-12-17 06:19:34 -0800775 Context.insert<typename Traits::Insts::Neg>(SrcDest);
John Porto7e93c622015-06-23 10:58:57 -0700776 }
777 void _nop(SizeT Variant) {
John Porto1d937a82015-12-17 06:19:34 -0800778 Context.insert<typename Traits::Insts::Nop>(Variant);
John Porto7e93c622015-06-23 10:58:57 -0700779 }
780 void _or(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800781 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800782 Context.insert<typename Traits::Insts::Or>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700783 }
David Sehre3984282015-12-15 17:34:55 -0800784 void _orps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800785 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800786 Context.insert<typename Traits::Insts::Orps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -0800787 }
John Porto4a566862016-01-04 09:33:41 -0800788 void _or_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800789 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800790 Context.insert<typename Traits::Insts::OrRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700791 }
792 void _padd(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800793 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800794 Context.insert<typename Traits::Insts::Padd>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700795 }
Nicolas Capens67a49b52016-10-26 13:18:35 -0400796 void _padds(Variable *Dest, Operand *Src0) {
797 AutoMemorySandboxer<> _(this, &Dest, &Src0);
798 Context.insert<typename Traits::Insts::Padds>(Dest, Src0);
799 }
800 void _paddus(Variable *Dest, Operand *Src0) {
801 AutoMemorySandboxer<> _(this, &Dest, &Src0);
802 Context.insert<typename Traits::Insts::Paddus>(Dest, Src0);
803 }
John Porto7e93c622015-06-23 10:58:57 -0700804 void _pand(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800805 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800806 Context.insert<typename Traits::Insts::Pand>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700807 }
808 void _pandn(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::Pandn>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700811 }
812 void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800813 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800814 Context.insert<typename Traits::Insts::Pblendvb>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700815 }
David Sehrb19d39c2016-01-13 14:17:37 -0800816 void _pcmpeq(Variable *Dest, Operand *Src0,
817 Type ArithmeticTypeOverride = IceType_void) {
John Porto56958cb2016-01-14 09:18:18 -0800818 AutoMemorySandboxer<> _(this, &Dest, &Src0);
David Sehrb19d39c2016-01-13 14:17:37 -0800819 Context.insert<typename Traits::Insts::Pcmpeq>(Dest, Src0,
820 ArithmeticTypeOverride);
John Porto7e93c622015-06-23 10:58:57 -0700821 }
822 void _pcmpgt(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800823 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800824 Context.insert<typename Traits::Insts::Pcmpgt>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700825 }
826 void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800827 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800828 Context.insert<typename Traits::Insts::Pextr>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700829 }
830 void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800831 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800832 Context.insert<typename Traits::Insts::Pinsr>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700833 }
834 void _pmull(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800835 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800836 Context.insert<typename Traits::Insts::Pmull>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700837 }
Nicolas Capens13cde0f2016-10-26 10:36:11 -0400838 void _pmulhw(Variable *Dest, Operand *Src0) {
839 AutoMemorySandboxer<> _(this, &Dest, &Src0);
840 Context.insert<typename Traits::Insts::Pmulhw>(Dest, Src0);
841 }
842 void _pmulhuw(Variable *Dest, Operand *Src0) {
843 AutoMemorySandboxer<> _(this, &Dest, &Src0);
844 Context.insert<typename Traits::Insts::Pmulhuw>(Dest, Src0);
845 }
846 void _pmaddwd(Variable *Dest, Operand *Src0) {
847 AutoMemorySandboxer<> _(this, &Dest, &Src0);
848 Context.insert<typename Traits::Insts::Pmaddwd>(Dest, Src0);
849 }
John Porto7e93c622015-06-23 10:58:57 -0700850 void _pmuludq(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800851 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800852 Context.insert<typename Traits::Insts::Pmuludq>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700853 }
854 void _pop(Variable *Dest) {
John Porto1d937a82015-12-17 06:19:34 -0800855 Context.insert<typename Traits::Insts::Pop>(Dest);
John Porto7e93c622015-06-23 10:58:57 -0700856 }
857 void _por(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800858 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800859 Context.insert<typename Traits::Insts::Por>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700860 }
John Portoae15f0f2016-04-26 04:26:33 -0700861 void _punpckl(Variable *Dest, Operand *Src0) {
862 AutoMemorySandboxer<> _(this, &Dest, &Src0);
863 Context.insert<typename Traits::Insts::Punpckl>(Dest, Src0);
864 }
Nicolas Capens1448d952016-10-14 16:37:09 -0400865 void _punpckh(Variable *Dest, Operand *Src0) {
866 AutoMemorySandboxer<> _(this, &Dest, &Src0);
867 Context.insert<typename Traits::Insts::Punpckh>(Dest, Src0);
868 }
Nicolas Capens7638e272016-10-06 11:33:55 -0400869 void _packss(Variable *Dest, Operand *Src0) {
870 AutoMemorySandboxer<> _(this, &Dest, &Src0);
871 Context.insert<typename Traits::Insts::Packss>(Dest, Src0);
872 }
873 void _packus(Variable *Dest, Operand *Src0) {
874 AutoMemorySandboxer<> _(this, &Dest, &Src0);
875 Context.insert<typename Traits::Insts::Packus>(Dest, Src0);
876 }
John Portode29f122016-04-26 19:16:07 -0700877 void _pshufb(Variable *Dest, Operand *Src0) {
878 AutoMemorySandboxer<> _(this, &Dest, &Src0);
879 Context.insert<typename Traits::Insts::Pshufb>(Dest, Src0);
880 }
John Porto7e93c622015-06-23 10:58:57 -0700881 void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800882 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800883 Context.insert<typename Traits::Insts::Pshufd>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700884 }
885 void _psll(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800886 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800887 Context.insert<typename Traits::Insts::Psll>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700888 }
889 void _psra(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800890 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800891 Context.insert<typename Traits::Insts::Psra>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700892 }
893 void _psrl(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::Psrl>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700896 }
897 void _psub(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800898 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800899 Context.insert<typename Traits::Insts::Psub>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700900 }
Nicolas Capens67a49b52016-10-26 13:18:35 -0400901 void _psubs(Variable *Dest, Operand *Src0) {
902 AutoMemorySandboxer<> _(this, &Dest, &Src0);
903 Context.insert<typename Traits::Insts::Psubs>(Dest, Src0);
904 }
905 void _psubus(Variable *Dest, Operand *Src0) {
906 AutoMemorySandboxer<> _(this, &Dest, &Src0);
907 Context.insert<typename Traits::Insts::Psubus>(Dest, Src0);
908 }
John Porto56958cb2016-01-14 09:18:18 -0800909 void _push(Operand *Src0) {
John Porto1d937a82015-12-17 06:19:34 -0800910 Context.insert<typename Traits::Insts::Push>(Src0);
John Porto7e93c622015-06-23 10:58:57 -0700911 }
912 void _pxor(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800913 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800914 Context.insert<typename Traits::Insts::Pxor>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700915 }
916 void _ret(Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800917 Context.insert<typename Traits::Insts::Ret>(Src0);
John Porto7e93c622015-06-23 10:58:57 -0700918 }
919 void _rol(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800920 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800921 Context.insert<typename Traits::Insts::Rol>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700922 }
Nicolas Capensf0d12c32016-10-27 15:17:41 -0400923 void _round(Variable *Dest, Operand *Src, Constant *Imm) {
924 AutoMemorySandboxer<> _(this, &Dest, &Src);
925 Context.insert<typename Traits::Insts::Round>(Dest, Src, Imm);
926 }
John Porto56958cb2016-01-14 09:18:18 -0800927 X86OperandMem *_sandbox_mem_reference(X86OperandMem *Mem) {
928 return dispatchToConcrete(&Traits::ConcreteTarget::_sandbox_mem_reference,
929 std::move(Mem));
930 }
John Porto7e93c622015-06-23 10:58:57 -0700931 void _sar(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800932 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800933 Context.insert<typename Traits::Insts::Sar>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700934 }
935 void _sbb(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800936 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800937 Context.insert<typename Traits::Insts::Sbb>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700938 }
John Porto4a566862016-01-04 09:33:41 -0800939 void _sbb_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800940 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800941 Context.insert<typename Traits::Insts::SbbRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700942 }
John Porto4a566862016-01-04 09:33:41 -0800943 void _setcc(Variable *Dest, BrCond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800944 Context.insert<typename Traits::Insts::Setcc>(Dest, Condition);
John Porto7e93c622015-06-23 10:58:57 -0700945 }
946 void _shl(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800947 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800948 Context.insert<typename Traits::Insts::Shl>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700949 }
David Sehr55f2e6d2015-09-22 09:17:39 -0700950 void _shld(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800951 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800952 Context.insert<typename Traits::Insts::Shld>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700953 }
954 void _shr(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800955 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800956 Context.insert<typename Traits::Insts::Shr>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700957 }
David Sehr55f2e6d2015-09-22 09:17:39 -0700958 void _shrd(Variable *Dest, Variable *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800959 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800960 Context.insert<typename Traits::Insts::Shrd>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700961 }
962 void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800963 AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800964 Context.insert<typename Traits::Insts::Shufps>(Dest, Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700965 }
Nicolas Capense3cabda2016-10-18 16:27:27 -0400966 void _movmsk(Variable *Dest, Operand *Src0) {
967 AutoMemorySandboxer<> _(this, &Dest, &Src0);
968 Context.insert<typename Traits::Insts::Movmsk>(Dest, Src0);
969 }
Nicolas Capens956cfd62016-10-31 14:28:09 -0400970 void _sqrt(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800971 AutoMemorySandboxer<> _(this, &Dest, &Src0);
Nicolas Capens956cfd62016-10-31 14:28:09 -0400972 Context.insert<typename Traits::Insts::Sqrt>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700973 }
John Porto4a566862016-01-04 09:33:41 -0800974 void _store(Operand *Value, X86Operand *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800975 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800976 Context.insert<typename Traits::Insts::Store>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700977 }
John Porto4a566862016-01-04 09:33:41 -0800978 void _storep(Variable *Value, X86OperandMem *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800979 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800980 Context.insert<typename Traits::Insts::StoreP>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700981 }
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400982 void _storeq(Operand *Value, X86OperandMem *Mem) {
John Porto56958cb2016-01-14 09:18:18 -0800983 AutoMemorySandboxer<> _(this, &Value, &Mem);
John Porto1d937a82015-12-17 06:19:34 -0800984 Context.insert<typename Traits::Insts::StoreQ>(Value, Mem);
John Porto7e93c622015-06-23 10:58:57 -0700985 }
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400986 void _stored(Operand *Value, X86OperandMem *Mem) {
987 AutoMemorySandboxer<> _(this, &Value, &Mem);
988 Context.insert<typename Traits::Insts::StoreD>(Value, Mem);
989 }
John Porto7e93c622015-06-23 10:58:57 -0700990 void _sub(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -0800991 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -0800992 Context.insert<typename Traits::Insts::Sub>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -0700993 }
John Porto4a566862016-01-04 09:33:41 -0800994 void _sub_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -0800995 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -0800996 Context.insert<typename Traits::Insts::SubRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -0700997 }
John Porto56958cb2016-01-14 09:18:18 -0800998 void _sub_sp(Operand *Adjustment) {
999 dispatchToConcrete(&Traits::ConcreteTarget::_sub_sp, std::move(Adjustment));
1000 }
John Porto7e93c622015-06-23 10:58:57 -07001001 void _subps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001002 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001003 Context.insert<typename Traits::Insts::Subps>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -07001004 }
1005 void _subss(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001006 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001007 Context.insert<typename Traits::Insts::Subss>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -07001008 }
1009 void _test(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -08001010 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -08001011 Context.insert<typename Traits::Insts::Test>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -07001012 }
1013 void _ucomiss(Operand *Src0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -08001014 AutoMemorySandboxer<> _(this, &Src0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -08001015 Context.insert<typename Traits::Insts::Ucomiss>(Src0, Src1);
John Porto7e93c622015-06-23 10:58:57 -07001016 }
John Porto1d937a82015-12-17 06:19:34 -08001017 void _ud2() { Context.insert<typename Traits::Insts::UD2>(); }
David Sehrb9a404d2016-01-21 08:09:27 -08001018 void _unlink_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_unlink_bp); }
John Porto7e93c622015-06-23 10:58:57 -07001019 void _xadd(Operand *Dest, Variable *Src, bool Locked) {
John Porto56958cb2016-01-14 09:18:18 -08001020 AutoMemorySandboxer<> _(this, &Dest, &Src);
John Porto1d937a82015-12-17 06:19:34 -08001021 Context.insert<typename Traits::Insts::Xadd>(Dest, Src, Locked);
Andrew Scull57e12682015-09-16 11:30:19 -07001022 // The xadd exchanges Dest and Src (modifying Src). Model that update with
1023 // a FakeDef followed by a FakeUse.
John Porto1d937a82015-12-17 06:19:34 -08001024 Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
Jim Stichnoth230d4102015-09-25 17:40:32 -07001025 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -08001026 Context.insert<InstFakeUse>(Src);
John Porto7e93c622015-06-23 10:58:57 -07001027 }
1028 void _xchg(Operand *Dest, Variable *Src) {
John Porto56958cb2016-01-14 09:18:18 -08001029 AutoMemorySandboxer<> _(this, &Dest, &Src);
John Porto1d937a82015-12-17 06:19:34 -08001030 Context.insert<typename Traits::Insts::Xchg>(Dest, Src);
John Porto7e93c622015-06-23 10:58:57 -07001031 // The xchg modifies Dest and Src -- model that update with a
1032 // FakeDef/FakeUse.
John Porto1d937a82015-12-17 06:19:34 -08001033 Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
Jim Stichnoth230d4102015-09-25 17:40:32 -07001034 _set_dest_redefined();
John Porto1d937a82015-12-17 06:19:34 -08001035 Context.insert<InstFakeUse>(Src);
John Porto7e93c622015-06-23 10:58:57 -07001036 }
1037 void _xor(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001038 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001039 Context.insert<typename Traits::Insts::Xor>(Dest, Src0);
John Porto7e93c622015-06-23 10:58:57 -07001040 }
David Sehre3984282015-12-15 17:34:55 -08001041 void _xorps(Variable *Dest, Operand *Src0) {
John Porto56958cb2016-01-14 09:18:18 -08001042 AutoMemorySandboxer<> _(this, &Dest, &Src0);
John Porto1d937a82015-12-17 06:19:34 -08001043 Context.insert<typename Traits::Insts::Xorps>(Dest, Src0);
David Sehre3984282015-12-15 17:34:55 -08001044 }
John Porto4a566862016-01-04 09:33:41 -08001045 void _xor_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
John Porto56958cb2016-01-14 09:18:18 -08001046 AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
John Porto1d937a82015-12-17 06:19:34 -08001047 Context.insert<typename Traits::Insts::XorRMW>(DestSrc0, Src1);
John Porto7e93c622015-06-23 10:58:57 -07001048 }
John Porto7e93c622015-06-23 10:58:57 -07001049
Andrew Scull2c862522015-08-06 08:41:53 -07001050 void _iaca_start() {
1051 if (!BuildDefs::minimal())
John Porto1d937a82015-12-17 06:19:34 -08001052 Context.insert<typename Traits::Insts::IacaStart>();
Andrew Scull2c862522015-08-06 08:41:53 -07001053 }
1054 void _iaca_end() {
1055 if (!BuildDefs::minimal())
John Porto1d937a82015-12-17 06:19:34 -08001056 Context.insert<typename Traits::Insts::IacaEnd>();
Andrew Scull2c862522015-08-06 08:41:53 -07001057 }
1058
1059 /// This class helps wrap IACA markers around the code generated by the
1060 /// current scope. It means you don't need to put an end before each return.
1061 class ScopedIacaMark {
1062 ScopedIacaMark(const ScopedIacaMark &) = delete;
1063 ScopedIacaMark &operator=(const ScopedIacaMark &) = delete;
1064
1065 public:
1066 ScopedIacaMark(TargetX86Base *Lowering) : Lowering(Lowering) {
1067 Lowering->_iaca_start();
1068 }
1069 ~ScopedIacaMark() { end(); }
1070 void end() {
1071 if (!Lowering)
1072 return;
1073 Lowering->_iaca_end();
1074 Lowering = nullptr;
1075 }
1076
1077 private:
1078 TargetX86Base *Lowering;
1079 };
1080
John Porto7e93c622015-06-23 10:58:57 -07001081 bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
1082 void findRMW();
1083
John Porto4a566862016-01-04 09:33:41 -08001084 InstructionSetEnum InstructionSet = Traits::InstructionSet::Begin;
John Porto7e93c622015-06-23 10:58:57 -07001085 bool IsEbpBasedFrame = false;
Nicolas Capensa551dfc2016-12-14 17:37:10 -05001086 size_t RequiredStackAlignment = sizeof(Traits::WordType);
John Porto7e93c622015-06-23 10:58:57 -07001087 size_t SpillAreaSizeBytes = 0;
Jim Stichnoth55f931f2015-09-23 16:33:08 -07001088 size_t FixedAllocaSizeBytes = 0;
David Sehr2f3b8ec2015-11-16 16:51:39 -08001089 size_t FixedAllocaAlignBytes = 0;
1090 bool PrologEmitsFixedAllocas = false;
David Sehr26217e32015-11-26 13:03:50 -08001091 uint32_t MaxOutArgsSizeBytes = 0;
John Portoe82b5602016-02-24 15:58:55 -08001092 static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSet;
1093 static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSetUnfiltered;
1094 static std::array<SmallBitVector, Traits::RegisterSet::Reg_NUM>
John Portobb0a5fe2015-09-04 11:23:41 -07001095 RegisterAliases;
John Portoe82b5602016-02-24 15:58:55 -08001096 SmallBitVector RegsUsed;
John Portobb0a5fe2015-09-04 11:23:41 -07001097 std::array<VarList, IceType_NUM> PhysicalRegisters;
John Portoac2388c2016-01-22 07:10:56 -08001098 // RebasePtr is a Variable that holds the Rebasing pointer (if any) for the
1099 // current sandboxing type.
1100 Variable *RebasePtr = nullptr;
John Porto7e93c622015-06-23 10:58:57 -07001101
Andrew Scull9612d322015-07-06 14:53:25 -07001102 /// Randomize a given immediate operand
John Porto7e93c622015-06-23 10:58:57 -07001103 Operand *randomizeOrPoolImmediate(Constant *Immediate,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -08001104 RegNumT RegNum = RegNumT());
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001105 X86OperandMem *randomizeOrPoolImmediate(X86OperandMem *MemOperand,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -08001106 RegNumT RegNum = RegNumT());
John Porto7e93c622015-06-23 10:58:57 -07001107 bool RandomizationPoolingPaused = false;
1108
1109private:
John Porto5aeed952015-07-21 13:39:09 -07001110 /// dispatchToConcrete is the template voodoo that allows TargetX86Base to
1111 /// invoke methods in Machine (which inherits from TargetX86Base) without
1112 /// having to rely on virtual method calls. There are two overloads, one for
1113 /// non-void types, and one for void types. We need this becase, for non-void
1114 /// types, we need to return the method result, where as for void, we don't.
1115 /// While it is true that the code compiles without the void "version", there
1116 /// used to be a time when compilers would reject such code.
1117 ///
1118 /// This machinery is far from perfect. Note that, in particular, the
1119 /// arguments provided to dispatchToConcrete() need to match the arguments for
1120 /// Method **exactly** (i.e., no argument promotion is performed.)
1121 template <typename Ret, typename... Args>
1122 typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
John Porto4a566862016-01-04 09:33:41 -08001123 dispatchToConcrete(Ret (ConcreteTarget::*Method)(Args...), Args &&... args) {
1124 return (static_cast<ConcreteTarget *>(this)->*Method)(
1125 std::forward<Args>(args)...);
John Porto5aeed952015-07-21 13:39:09 -07001126 }
1127
1128 template <typename... Args>
John Porto4a566862016-01-04 09:33:41 -08001129 void dispatchToConcrete(void (ConcreteTarget::*Method)(Args...),
1130 Args &&... args) {
1131 (static_cast<ConcreteTarget *>(this)->*Method)(std::forward<Args>(args)...);
John Porto5aeed952015-07-21 13:39:09 -07001132 }
1133
David Sehr188eae52015-09-24 11:42:55 -07001134 void lowerShift64(InstArithmetic::OpKind Op, Operand *Src0Lo, Operand *Src0Hi,
1135 Operand *Src1Lo, Variable *DestLo, Variable *DestHi);
1136
David Sehre3984282015-12-15 17:34:55 -08001137 /// Emit the code for a combined operation and consumer instruction, or set
1138 /// the destination variable of the operation if Consumer == nullptr.
1139 void lowerIcmpAndConsumer(const InstIcmp *Icmp, const Inst *Consumer);
1140 void lowerFcmpAndConsumer(const InstFcmp *Fcmp, const Inst *Consumer);
1141 void lowerArithAndConsumer(const InstArithmetic *Arith, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001142
David Sehre3984282015-12-15 17:34:55 -08001143 /// Emit a setcc instruction if Consumer == nullptr; otherwise emit a
1144 /// specialized version of Consumer.
John Porto4a566862016-01-04 09:33:41 -08001145 void setccOrConsumer(BrCond Condition, Variable *Dest, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001146
David Sehre3984282015-12-15 17:34:55 -08001147 /// Emit a mov [1|0] instruction if Consumer == nullptr; otherwise emit a
1148 /// specialized version of Consumer.
1149 void movOrConsumer(bool IcmpResult, Variable *Dest, const Inst *Consumer);
1150
1151 /// Emit the code for instructions with a vector type.
1152 void lowerIcmpVector(const InstIcmp *Icmp);
1153 void lowerFcmpVector(const InstFcmp *Icmp);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001154 void lowerSelectVector(const InstSelect *Instr);
David Sehre3984282015-12-15 17:34:55 -08001155
1156 /// Helpers for select lowering.
John Porto4a566862016-01-04 09:33:41 -08001157 void lowerSelectMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1158 Operand *SrcF);
1159 void lowerSelectIntMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1160 Operand *SrcF);
David Sehre3984282015-12-15 17:34:55 -08001161 /// Generic helper to move an arbitrary type from Src to Dest.
1162 void lowerMove(Variable *Dest, Operand *Src, bool IsRedefinition);
1163
1164 /// Optimizations for idiom recognition.
1165 bool lowerOptimizeFcmpSelect(const InstFcmp *Fcmp, const InstSelect *Select);
David Sehrd9810252015-10-16 13:23:17 -07001166
1167 /// Complains loudly if invoked because the cpu can handle 64-bit types
1168 /// natively.
1169 template <typename T = Traits>
1170 typename std::enable_if<T::Is64Bit, void>::type lowerIcmp64(const InstIcmp *,
David Sehre3984282015-12-15 17:34:55 -08001171 const Inst *) {
David Sehrd9810252015-10-16 13:23:17 -07001172 llvm::report_fatal_error(
1173 "Hey, yo! This is x86-64. Watcha doin'? (lowerIcmp64)");
1174 }
1175 /// x86lowerIcmp64 handles 64-bit icmp lowering.
1176 template <typename T = Traits>
1177 typename std::enable_if<!T::Is64Bit, void>::type
David Sehre3984282015-12-15 17:34:55 -08001178 lowerIcmp64(const InstIcmp *Icmp, const Inst *Consumer);
David Sehrd9810252015-10-16 13:23:17 -07001179
Jim Stichnothcaeaa272016-01-10 12:53:44 -08001180 BoolFolding<Traits> FoldingInfo;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -08001181
John Portoae15f0f2016-04-26 04:26:33 -07001182 /// Helpers for lowering ShuffleVector
1183 /// @{
Nicolas Capens579b1b32016-12-09 14:56:03 -05001184 Variable *lowerShuffleVector_AllFromSameSrc(Operand *Src, SizeT Index0,
John Portoae15f0f2016-04-26 04:26:33 -07001185 SizeT Index1, SizeT Index2,
1186 SizeT Index3);
1187 static constexpr SizeT IGNORE_INDEX = 0x80000000u;
Nicolas Capens579b1b32016-12-09 14:56:03 -05001188 Variable *lowerShuffleVector_TwoFromSameSrc(Operand *Src0, SizeT Index0,
1189 SizeT Index1, Operand *Src1,
John Portoae15f0f2016-04-26 04:26:33 -07001190 SizeT Index2, SizeT Index3);
1191 static constexpr SizeT UNIFIED_INDEX_0 = 0;
1192 static constexpr SizeT UNIFIED_INDEX_1 = 2;
Nicolas Capens579b1b32016-12-09 14:56:03 -05001193 Variable *lowerShuffleVector_UnifyFromDifferentSrcs(Operand *Src0,
John Portoae15f0f2016-04-26 04:26:33 -07001194 SizeT Index0,
Nicolas Capens579b1b32016-12-09 14:56:03 -05001195 Operand *Src1,
John Portoae15f0f2016-04-26 04:26:33 -07001196 SizeT Index1);
John Portode29f122016-04-26 19:16:07 -07001197 static constexpr SizeT CLEAR_ALL_BITS = 0x80;
1198 SizeT PshufbMaskCount = 0;
1199 GlobalString lowerShuffleVector_NewMaskName();
1200 ConstantRelocatable *lowerShuffleVector_CreatePshufbMask(
1201 int8_t Idx0, int8_t Idx1, int8_t Idx2, int8_t Idx3, int8_t Idx4,
1202 int8_t Idx5, int8_t Idx6, int8_t Idx7, int8_t Idx8, int8_t Idx9,
1203 int8_t Idx10, int8_t Idx11, int8_t Idx12, int8_t Idx13, int8_t Idx14,
1204 int8_t Idx15);
1205 void lowerShuffleVector_UsingPshufb(Variable *Dest, Operand *Src0,
1206 Operand *Src1, int8_t Idx0, int8_t Idx1,
1207 int8_t Idx2, int8_t Idx3, int8_t Idx4,
1208 int8_t Idx5, int8_t Idx6, int8_t Idx7,
1209 int8_t Idx8, int8_t Idx9, int8_t Idx10,
1210 int8_t Idx11, int8_t Idx12, int8_t Idx13,
1211 int8_t Idx14, int8_t Idx15);
John Portoae15f0f2016-04-26 04:26:33 -07001212 /// @}
1213
Jim Stichnoth8ff4b282016-01-04 15:39:06 -08001214 static FixupKind PcRelFixup;
1215 static FixupKind AbsFixup;
John Porto7e93c622015-06-23 10:58:57 -07001216};
David Sehr6b80cf12016-01-21 23:16:58 -08001217
1218template <typename TraitsType>
1219class TargetDataX86 final : public TargetDataLowering {
1220 using Traits = TraitsType;
1221 TargetDataX86() = delete;
1222 TargetDataX86(const TargetDataX86 &) = delete;
1223 TargetDataX86 &operator=(const TargetDataX86 &) = delete;
1224
1225public:
1226 ~TargetDataX86() override = default;
1227
1228 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1229 return makeUnique<TargetDataX86>(Ctx);
1230 }
1231
1232 void lowerGlobals(const VariableDeclarationList &Vars,
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001233 const std::string &SectionSuffix) override;
David Sehr6b80cf12016-01-21 23:16:58 -08001234 void lowerConstants() override;
1235 void lowerJumpTables() override;
1236
1237private:
1238 ENABLE_MAKE_UNIQUE;
1239
Ben Clayton2a582382019-04-24 12:11:36 +01001240 explicit TargetDataX86(GlobalContext *Ctx) : TargetDataLowering(Ctx){}
David Sehr6b80cf12016-01-21 23:16:58 -08001241 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
1242};
1243
1244class TargetHeaderX86 : public TargetHeaderLowering {
1245 TargetHeaderX86() = delete;
1246 TargetHeaderX86(const TargetHeaderX86 &) = delete;
1247 TargetHeaderX86 &operator=(const TargetHeaderX86 &) = delete;
1248
1249public:
1250 ~TargetHeaderX86() = default;
1251
1252 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1253 return makeUnique<TargetHeaderX86>(Ctx);
1254 }
1255
1256private:
1257 ENABLE_MAKE_UNIQUE;
1258
1259 explicit TargetHeaderX86(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {}
1260};
1261
John Porto4a566862016-01-04 09:33:41 -08001262} // end of namespace X86NAMESPACE
John Porto7e93c622015-06-23 10:58:57 -07001263} // end of namespace Ice
1264
1265#include "IceTargetLoweringX86BaseImpl.h"
1266
1267#endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H