OSDN Git Service

Subzero: Cleanup Inst==>Instr.
[android-x86/external-swiftshader.git] / src / IceTargetLoweringX86Base.h
1 //===- 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 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Declares the TargetLoweringX86 template class, which implements the
12 /// TargetLowering base interface for the x86 architecture.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H
17 #define SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H
18
19 #include "IceDefs.h"
20 #include "IceInst.h"
21 #include "IceSwitchLowering.h"
22 #include "IceTargetLowering.h"
23 #include "IceTargetLoweringX86RegClass.h"
24 #include "IceUtils.h"
25
26 #include <array>
27 #include <type_traits>
28 #include <utility>
29
30 #ifndef X86NAMESPACE
31 #error "You must define the X86 Target namespace."
32 #endif
33
34 namespace Ice {
35 namespace X86NAMESPACE {
36
37 using namespace ::Ice::X86;
38
39 template <typename Traits> class BoolFolding;
40
41 /// 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 ///
51 ///  static_assert(std::is_base_of<TargetX86Base<TraitsType>,
52 ///  Machine>::value);
53 ///
54 /// but that does not work: the compiler does not know that Machine inherits
55 /// from TargetX86Base at this point in translation.
56 template <typename TraitsType> class TargetX86Base : public TargetLowering {
57   TargetX86Base() = delete;
58   TargetX86Base(const TargetX86Base &) = delete;
59   TargetX86Base &operator=(const TargetX86Base &) = delete;
60
61 public:
62   using Traits = TraitsType;
63   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;
73   using SpillVariable = typename Traits::SpillVariable;
74
75   using InstX86Br = typename Traits::Insts::Br;
76   using InstX86FakeRMW = typename Traits::Insts::FakeRMW;
77   using InstX86Label = typename Traits::Insts::Label;
78
79   ~TargetX86Base() override = default;
80
81   static void staticInit(GlobalContext *Ctx);
82   static TargetX86Base *create(Cfg *Func) { return new TargetX86Base(Func); }
83
84   static FixupKind getPcRelFixup() { return PcRelFixup; }
85   static FixupKind getAbsFixup() { return AbsFixup; }
86
87   bool needSandboxing() const { return NeedSandboxing; }
88
89   void translateOm1() override;
90   void translateO2() override;
91   void doLoadOpt();
92   bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
93
94   SizeT getNumRegisters() const override {
95     return Traits::RegisterSet::Reg_NUM;
96   }
97   Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
98   IceString getRegName(SizeT RegNum, Type Ty) const override;
99   static IceString getRegClassName(RegClass C) {
100     auto ClassNum = static_cast<RegClassX86>(C);
101     assert(ClassNum < RCX86_NUM);
102     switch (ClassNum) {
103     default:
104       assert(C < RC_Target);
105       return regClassString(C);
106     case RCX86_Is64To8:
107       return "i64to8"; // 64-bit GPR truncable to i8
108     case RCX86_Is32To8:
109       return "i32to8"; // 32-bit GPR truncable to i8
110     case RCX86_Is16To8:
111       return "i16to8"; // 16-bit GPR truncable to i8
112     case RCX86_IsTrunc8Rcvr:
113       return "i8from"; // 8-bit GPR truncable from wider GPRs
114     case RCX86_IsAhRcvr:
115       return "i8fromah"; // 8-bit GPR that ah can be assigned to
116     }
117   }
118   llvm::SmallBitVector getRegisterSet(RegSetMask Include,
119                                       RegSetMask Exclude) const override;
120   const llvm::SmallBitVector &
121   getRegistersForVariable(const Variable *Var) const override {
122     RegClass RC = Var->getRegClass();
123     assert(static_cast<RegClassX86>(RC) < RCX86_NUM);
124     return TypeToRegisterSet[RC];
125   }
126
127   const llvm::SmallBitVector &
128   getAllRegistersForVariable(const Variable *Var) const override {
129     RegClass RC = Var->getRegClass();
130     assert(static_cast<RegClassX86>(RC) < RCX86_NUM);
131     return TypeToRegisterSetUnfiltered[RC];
132   }
133
134   const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
135     assert(Reg < Traits::RegisterSet::Reg_NUM);
136     return RegisterAliases[Reg];
137   }
138
139   bool hasFramePointer() const override { return IsEbpBasedFrame; }
140   void setHasFramePointer() override { IsEbpBasedFrame = true; }
141   SizeT getStackReg() const override { return Traits::StackPtr; }
142   SizeT getFrameReg() const override { return Traits::FramePtr; }
143   SizeT getFrameOrStackReg() const override {
144     return IsEbpBasedFrame ? getFrameReg() : getStackReg();
145   }
146   size_t typeWidthInBytesOnStack(Type Ty) const override {
147     // Round up to the next multiple of WordType bytes.
148     const uint32_t WordSizeInBytes = typeWidthInBytes(Traits::WordType);
149     return Utils::applyAlignment(typeWidthInBytes(Ty), WordSizeInBytes);
150   }
151   uint32_t getStackAlignment() const override {
152     return Traits::X86_STACK_ALIGNMENT_BYTES;
153   }
154   void reserveFixedAllocaArea(size_t Size, size_t Align) override {
155     FixedAllocaSizeBytes = Size;
156     assert(llvm::isPowerOf2_32(Align));
157     FixedAllocaAlignBytes = Align;
158     PrologEmitsFixedAllocas = true;
159   }
160   /// Returns the (negative) offset from ebp/rbp where the fixed Allocas start.
161   int32_t getFrameFixedAllocaOffset() const override {
162     return FixedAllocaSizeBytes - (SpillAreaSizeBytes - maxOutArgsSizeBytes());
163   }
164   virtual uint32_t maxOutArgsSizeBytes() const override {
165     return MaxOutArgsSizeBytes;
166   }
167   virtual void updateMaxOutArgsSizeBytes(uint32_t Size) {
168     MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, Size);
169   }
170
171   bool shouldSplitToVariable64On32(Type Ty) const override {
172     return Traits::Is64Bit ? false : Ty == IceType_i64;
173   }
174
175   ConstantRelocatable *createGetIPForRegister(const Variable *Dest) {
176     assert(Dest->hasReg());
177     const IceString RegName = Traits::getRegName(Dest->getRegNum());
178     return llvm::cast<ConstantRelocatable>(
179         Ctx->getConstantExternSym(H_getIP_prefix + RegName));
180   }
181
182   SizeT getMinJumpTableSize() const override { return 4; }
183
184   void emitVariable(const Variable *Var) const override;
185
186   void emit(const ConstantInteger32 *C) const final;
187   void emit(const ConstantInteger64 *C) const final;
188   void emit(const ConstantFloat *C) const final;
189   void emit(const ConstantDouble *C) const final;
190   void emit(const ConstantUndef *C) const final;
191   void emit(const ConstantRelocatable *C) const final;
192
193   void initNodeForLowering(CfgNode *Node) override;
194
195   template <typename T = Traits>
196   typename std::enable_if<!T::Is64Bit, Operand>::type *
197   loOperand(Operand *Operand);
198   template <typename T = Traits>
199   typename std::enable_if<T::Is64Bit, Operand>::type *loOperand(Operand *) {
200     llvm::report_fatal_error(
201         "Hey, yo! This is x86-64. Watcha doin'? (loOperand)");
202   }
203
204   template <typename T = Traits>
205   typename std::enable_if<!T::Is64Bit, Operand>::type *
206   hiOperand(Operand *Operand);
207   template <typename T = Traits>
208   typename std::enable_if<T::Is64Bit, Operand>::type *hiOperand(Operand *) {
209     llvm::report_fatal_error(
210         "Hey, yo! This is x86-64. Watcha doin'? (hiOperand)");
211   }
212
213   void addProlog(CfgNode *Node) override;
214   void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
215                               size_t BasicFrameOffset, size_t StackAdjBytes,
216                               size_t &InArgsSizeBytes);
217   void addEpilog(CfgNode *Node) override;
218   X86Address stackVarToAsmOperand(const Variable *Var) const;
219
220   InstructionSetEnum getInstructionSet() const { return InstructionSet; }
221   Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
222
223 protected:
224   const bool NeedSandboxing;
225
226   explicit TargetX86Base(Cfg *Func);
227
228   void postLower() override;
229
230   /// Initializes the RebasePtr member variable -- if so required by
231   /// SandboxingType for the concrete Target.
232   void initRebasePtr() {
233     assert(SandboxingType != ST_None);
234     dispatchToConcrete(&Traits::ConcreteTarget::initRebasePtr);
235   }
236
237   /// Emit code that initializes the value of the RebasePtr near the start of
238   /// the function -- if so required by SandboxingType for the concrete type.
239   void initSandbox() {
240     assert(SandboxingType != ST_None);
241     dispatchToConcrete(&Traits::ConcreteTarget::initSandbox);
242   }
243
244   void lowerAlloca(const InstAlloca *Instr) override;
245   void lowerArguments() override;
246   void lowerArithmetic(const InstArithmetic *Instr) override;
247   void lowerAssign(const InstAssign *Instr) override;
248   void lowerBr(const InstBr *Instr) override;
249   void lowerCall(const InstCall *Instr) override;
250   void lowerCast(const InstCast *Instr) override;
251   void lowerExtractElement(const InstExtractElement *Instr) override;
252   void lowerFcmp(const InstFcmp *Instr) override;
253   void lowerIcmp(const InstIcmp *Instr) override;
254
255   void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
256   void lowerInsertElement(const InstInsertElement *Instr) override;
257   void lowerLoad(const InstLoad *Instr) override;
258   void lowerPhi(const InstPhi *Instr) override;
259   void lowerRet(const InstRet *Instr) override;
260   void lowerSelect(const InstSelect *Instr) override;
261   void lowerStore(const InstStore *Instr) override;
262   void lowerSwitch(const InstSwitch *Instr) override;
263   void lowerUnreachable(const InstUnreachable *Instr) override;
264   void lowerOther(const Inst *Instr) override;
265   void lowerRMW(const InstX86FakeRMW *RMW);
266   void prelowerPhis() override;
267   uint32_t getCallStackArgumentsSizeBytes(const std::vector<Type> &ArgTypes,
268                                           Type ReturnType);
269   uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
270   void genTargetHelperCallFor(Inst *Instr) override;
271
272   /// OptAddr wraps all the possible operands that an x86 address might have.
273   struct OptAddr {
274     Variable *Base = nullptr;
275     Variable *Index = nullptr;
276     uint16_t Shift = 0;
277     int32_t Offset = 0;
278     ConstantRelocatable *Relocatable = nullptr;
279   };
280   /// Legalizes Addr w.r.t. SandboxingType. The exact type of legalization
281   /// varies for different <Target, SandboxingType> tuples.
282   bool legalizeOptAddrForSandbox(OptAddr *Addr) {
283     return dispatchToConcrete(
284         &Traits::ConcreteTarget::legalizeOptAddrForSandbox, std::move(Addr));
285   }
286   // Builds information for a canonical address expresion:
287   //   <Relocatable + Offset>(Base, Index, Shift)
288   X86OperandMem *computeAddressOpt(const Inst *Instr, Type MemType,
289                                    Operand *Addr);
290   void doAddressOptLoad() override;
291   void doAddressOptStore() override;
292   void doMockBoundsCheck(Operand *Opnd) override;
293   void randomlyInsertNop(float Probability,
294                          RandomNumberGenerator &RNG) override;
295
296   /// Naive lowering of cmpxchg.
297   void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
298                           Operand *Desired);
299   /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
300   bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr,
301                                 Operand *Expected, Operand *Desired);
302   void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
303                       Operand *Val);
304   void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal,
305                        Operand *SecondVal);
306   /// Load from memory for a given type.
307   void typedLoad(Type Ty, Variable *Dest, Variable *Base, Constant *Offset);
308   /// Store to memory for a given type.
309   void typedStore(Type Ty, Variable *Value, Variable *Base, Constant *Offset);
310   /// Copy memory of given type from Src to Dest using OffsetAmt on both.
311   void copyMemory(Type Ty, Variable *Dest, Variable *Src, int32_t OffsetAmt);
312   /// Replace some calls to memcpy with inline instructions.
313   void lowerMemcpy(Operand *Dest, Operand *Src, Operand *Count);
314   /// Replace some calls to memmove with inline instructions.
315   void lowerMemmove(Operand *Dest, Operand *Src, Operand *Count);
316   /// Replace some calls to memset with inline instructions.
317   void lowerMemset(Operand *Dest, Operand *Val, Operand *Count);
318
319   /// Lower an indirect jump adding sandboxing when needed.
320   void lowerIndirectJump(Variable *JumpTarget) {
321     // Without std::move below, the compiler deduces that the argument to
322     // lowerIndirectJmp is a Variable *&, not a Variable *.
323     dispatchToConcrete(&Traits::ConcreteTarget::lowerIndirectJump,
324                        std::move(JumpTarget));
325   }
326
327   /// Check the comparison is in [Min,Max]. The flags register will be modified
328   /// with:
329   ///   - below equal, if in range
330   ///   - above, set if not in range
331   /// The index into the range is returned.
332   Operand *lowerCmpRange(Operand *Comparison, uint64_t Min, uint64_t Max);
333   /// Lowering of a cluster of switch cases. If the case is not matched control
334   /// will pass to the default label provided. If the default label is nullptr
335   /// then control will fall through to the next instruction. DoneCmp should be
336   /// true if the flags contain the result of a comparison with the Comparison.
337   void lowerCaseCluster(const CaseCluster &Case, Operand *Src0, bool DoneCmp,
338                         CfgNode *DefaultLabel = nullptr);
339
340   using LowerBinOp = void (TargetX86Base::*)(Variable *, Operand *);
341   void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi,
342                                 Variable *Dest, Operand *Ptr, Operand *Val);
343
344   void eliminateNextVectorSextInstruction(Variable *SignExtendedResult);
345
346   void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest,
347                            Operand *Src0, Operand *Src1);
348
349   void emitGetIP(CfgNode *Node) {
350     dispatchToConcrete(&Traits::ConcreteTarget::emitGetIP, std::move(Node));
351   }
352   /// Emit a sandboxed return sequence rather than a return.
353   void emitSandboxedReturn() {
354     dispatchToConcrete(&Traits::ConcreteTarget::emitSandboxedReturn);
355   }
356   /// Emit just the call instruction (without argument or return variable
357   /// processing), sandboxing if needed.
358   virtual Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) = 0;
359   /// Materialize the moves needed to return a value of the specified type.
360   virtual Variable *moveReturnValueToRegister(Operand *Value,
361                                               Type ReturnType) = 0;
362
363   /// Emit a jump table to the constant pool.
364   void emitJumpTable(const Cfg *Func,
365                      const InstJumpTable *JumpTable) const override;
366
367   /// Emit a fake use of esp to make sure esp stays alive for the entire
368   /// function. Otherwise some esp adjustments get dead-code eliminated.
369   void keepEspLiveAtExit() {
370     Variable *esp =
371         Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
372     Context.insert<InstFakeUse>(esp);
373   }
374
375   /// Operand legalization helpers. To deal with address mode constraints, the
376   /// helpers will create a new Operand and emit instructions that guarantee
377   /// that the Operand kind is one of those indicated by the LegalMask (a
378   /// bitmask of allowed kinds). If the input Operand is known to already meet
379   /// the constraints, it may be simply returned as the result, without creating
380   /// any new instructions or operands.
381   enum OperandLegalization {
382     Legal_None = 0,
383     Legal_Reg = 1 << 0, // physical register, not stack location
384     Legal_Imm = 1 << 1,
385     Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12]
386     Legal_Rematerializable = 1 << 3,
387     Legal_AddrAbs = 1 << 4, // ConstantRelocatable doesn't have to add RebasePtr
388     Legal_Default = ~(Legal_Rematerializable | Legal_AddrAbs)
389     // TODO(stichnot): Figure out whether this default works for x86-64.
390   };
391   using LegalMask = uint32_t;
392   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
393                     int32_t RegNum = Variable::NoRegister);
394   Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
395   /// Legalize the first source operand for use in the cmp instruction.
396   Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
397   /// Turn a pointer operand into a memory operand that can be used by a real
398   /// load/store operation. Legalizes the operand as well. This is a nop if the
399   /// operand is already a legal memory operand.
400   X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
401                                    bool DoLegalize = true);
402
403   Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
404   static Type stackSlotType();
405
406   static constexpr uint32_t NoSizeLimit = 0;
407   static const Type TypeForSize[];
408   /// Returns the largest type which is equal to or larger than Size bytes. The
409   /// type is suitable for copying memory i.e. a load and store will be a single
410   /// instruction (for example x86 will get f64 not i64).
411   static Type largestTypeInSize(uint32_t Size, uint32_t MaxSize = NoSizeLimit);
412   /// Returns the smallest type which is equal to or larger than Size bytes. If
413   /// one doesn't exist then the largest type smaller than Size bytes is
414   /// returned. The type is suitable for memory copies as described at
415   /// largestTypeInSize.
416   static Type firstTypeThatFitsSize(uint32_t Size,
417                                     uint32_t MaxSize = NoSizeLimit);
418
419   Variable *copyToReg8(Operand *Src, int32_t RegNum = Variable::NoRegister);
420   Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
421
422   /// Returns a register containing all zeros, without affecting the FLAGS
423   /// register, using the best instruction for the type.
424   Variable *makeZeroedRegister(Type Ty, int32_t RegNum = Variable::NoRegister);
425
426   /// \name Returns a vector in a register with the given constant entries.
427   /// @{
428   Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
429   Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister);
430   Variable *makeVectorOfMinusOnes(Type Ty,
431                                   int32_t RegNum = Variable::NoRegister);
432   Variable *makeVectorOfHighOrderBits(Type Ty,
433                                       int32_t RegNum = Variable::NoRegister);
434   Variable *makeVectorOfFabsMask(Type Ty,
435                                  int32_t RegNum = Variable::NoRegister);
436   /// @}
437
438   /// Return a memory operand corresponding to a stack allocated Variable.
439   X86OperandMem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
440                                               uint32_t Offset = 0);
441
442   void
443   makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
444                                 const llvm::SmallBitVector &ExcludeRegisters,
445                                 uint64_t Salt) const override;
446
447   /// AutoMemorySandboxer emits a bundle-lock/bundle-unlock pair if the
448   /// instruction's operand is a memory reference. This is only needed for
449   /// x86-64 NaCl sandbox.
450   template <InstBundleLock::Option BundleLockOpt = InstBundleLock::Opt_None>
451   class AutoMemorySandboxer {
452     AutoMemorySandboxer() = delete;
453     AutoMemorySandboxer(const AutoMemorySandboxer &) = delete;
454     AutoMemorySandboxer &operator=(const AutoMemorySandboxer &) = delete;
455
456   private:
457     typename Traits::TargetLowering *Target;
458
459     template <typename T, typename... Tail>
460     X86OperandMem **findMemoryReference(T **First, Tail... Others) {
461       if (llvm::isa<X86OperandMem>(*First)) {
462         return reinterpret_cast<X86OperandMem **>(First);
463       }
464       return findMemoryReference(Others...);
465     }
466
467     X86OperandMem **findMemoryReference() { return nullptr; }
468
469   public:
470     std::unique_ptr<AutoBundle> Bundler;
471     X86OperandMem **const MemOperand;
472
473     template <typename... T>
474     AutoMemorySandboxer(typename Traits::TargetLowering *Target, T... Args)
475         : Target(Target), MemOperand(Target->SandboxingType == ST_None
476                                          ? nullptr
477                                          : findMemoryReference(Args...)) {
478       if (MemOperand != nullptr) {
479         if (Traits::Is64Bit) {
480           Bundler = makeUnique<AutoBundle>(Target, BundleLockOpt);
481         }
482         *MemOperand = Target->_sandbox_mem_reference(*MemOperand);
483       }
484     }
485
486     ~AutoMemorySandboxer() {}
487   };
488
489   /// The following are helpers that insert lowered x86 instructions with
490   /// minimal syntactic overhead, so that the lowering code can look as close to
491   /// assembly as practical.
492   void _adc(Variable *Dest, Operand *Src0) {
493     AutoMemorySandboxer<> _(this, &Dest, &Src0);
494     Context.insert<typename Traits::Insts::Adc>(Dest, Src0);
495   }
496   void _adc_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
497     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
498     Context.insert<typename Traits::Insts::AdcRMW>(DestSrc0, Src1);
499   }
500   void _add(Variable *Dest, Operand *Src0) {
501     AutoMemorySandboxer<> _(this, &Dest, &Src0);
502     Context.insert<typename Traits::Insts::Add>(Dest, Src0);
503   }
504   void _add_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
505     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
506     Context.insert<typename Traits::Insts::AddRMW>(DestSrc0, Src1);
507   }
508   void _addps(Variable *Dest, Operand *Src0) {
509     AutoMemorySandboxer<> _(this, &Dest, &Src0);
510     Context.insert<typename Traits::Insts::Addps>(Dest, Src0);
511   }
512   void _addss(Variable *Dest, Operand *Src0) {
513     AutoMemorySandboxer<> _(this, &Dest, &Src0);
514     Context.insert<typename Traits::Insts::Addss>(Dest, Src0);
515   }
516   void _add_sp(Operand *Adjustment) {
517     dispatchToConcrete(&Traits::ConcreteTarget::_add_sp, std::move(Adjustment));
518   }
519   void _and(Variable *Dest, Operand *Src0) {
520     AutoMemorySandboxer<> _(this, &Dest, &Src0);
521     Context.insert<typename Traits::Insts::And>(Dest, Src0);
522   }
523   void _andnps(Variable *Dest, Operand *Src0) {
524     AutoMemorySandboxer<> _(this, &Dest, &Src0);
525     Context.insert<typename Traits::Insts::Andnps>(Dest, Src0);
526   }
527   void _andps(Variable *Dest, Operand *Src0) {
528     AutoMemorySandboxer<> _(this, &Dest, &Src0);
529     Context.insert<typename Traits::Insts::Andps>(Dest, Src0);
530   }
531   void _and_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
532     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
533     Context.insert<typename Traits::Insts::AndRMW>(DestSrc0, Src1);
534   }
535   void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
536     AutoMemorySandboxer<> _(this, &Dest, &Src0);
537     Context.insert<typename Traits::Insts::Blendvps>(Dest, Src0, Src1);
538   }
539   void _br(BrCond Condition, CfgNode *TargetTrue, CfgNode *TargetFalse) {
540     Context.insert<InstX86Br>(TargetTrue, TargetFalse, Condition,
541                               InstX86Br::Far);
542   }
543   void _br(CfgNode *Target) {
544     Context.insert<InstX86Br>(Target, InstX86Br::Far);
545   }
546   void _br(BrCond Condition, CfgNode *Target) {
547     Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far);
548   }
549   void _br(BrCond Condition, InstX86Label *Label,
550            typename InstX86Br::Mode Kind = InstX86Br::Near) {
551     Context.insert<InstX86Br>(Label, Condition, Kind);
552   }
553   void _bsf(Variable *Dest, Operand *Src0) {
554     AutoMemorySandboxer<> _(this, &Dest, &Src0);
555     Context.insert<typename Traits::Insts::Bsf>(Dest, Src0);
556   }
557   void _bsr(Variable *Dest, Operand *Src0) {
558     AutoMemorySandboxer<> _(this, &Dest, &Src0);
559     Context.insert<typename Traits::Insts::Bsr>(Dest, Src0);
560   }
561   void _bswap(Variable *SrcDest) {
562     AutoMemorySandboxer<> _(this, &SrcDest);
563     Context.insert<typename Traits::Insts::Bswap>(SrcDest);
564   }
565   void _cbwdq(Variable *Dest, Operand *Src0) {
566     AutoMemorySandboxer<> _(this, &Dest, &Src0);
567     Context.insert<typename Traits::Insts::Cbwdq>(Dest, Src0);
568   }
569   void _cmov(Variable *Dest, Operand *Src0, BrCond Condition) {
570     AutoMemorySandboxer<> _(this, &Dest, &Src0);
571     Context.insert<typename Traits::Insts::Cmov>(Dest, Src0, Condition);
572   }
573   void _cmp(Operand *Src0, Operand *Src1) {
574     AutoMemorySandboxer<> _(this, &Src0, &Src1);
575     Context.insert<typename Traits::Insts::Icmp>(Src0, Src1);
576   }
577   void _cmpps(Variable *Dest, Operand *Src0, CmppsCond Condition) {
578     AutoMemorySandboxer<> _(this, &Dest, &Src0);
579     Context.insert<typename Traits::Insts::Cmpps>(Dest, Src0, Condition);
580   }
581   void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
582                 bool Locked) {
583     AutoMemorySandboxer<> _(this, &DestOrAddr);
584     Context.insert<typename Traits::Insts::Cmpxchg>(DestOrAddr, Eax, Desired,
585                                                     Locked);
586     // Mark eax as possibly modified by cmpxchg.
587     Context.insert<InstFakeDef>(Eax, llvm::dyn_cast<Variable>(DestOrAddr));
588     _set_dest_redefined();
589     Context.insert<InstFakeUse>(Eax);
590   }
591   void _cmpxchg8b(X86OperandMem *Addr, Variable *Edx, Variable *Eax,
592                   Variable *Ecx, Variable *Ebx, bool Locked) {
593     AutoMemorySandboxer<> _(this, &Addr);
594     Context.insert<typename Traits::Insts::Cmpxchg8b>(Addr, Edx, Eax, Ecx, Ebx,
595                                                       Locked);
596     // Mark edx, and eax as possibly modified by cmpxchg8b.
597     Context.insert<InstFakeDef>(Edx);
598     _set_dest_redefined();
599     Context.insert<InstFakeUse>(Edx);
600     Context.insert<InstFakeDef>(Eax);
601     _set_dest_redefined();
602     Context.insert<InstFakeUse>(Eax);
603   }
604   void _cvt(Variable *Dest, Operand *Src0,
605             typename Traits::Insts::Cvt::CvtVariant Variant) {
606     AutoMemorySandboxer<> _(this, &Dest, &Src0);
607     Context.insert<typename Traits::Insts::Cvt>(Dest, Src0, Variant);
608   }
609   void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
610     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
611     Context.insert<typename Traits::Insts::Div>(Dest, Src0, Src1);
612   }
613   void _divps(Variable *Dest, Operand *Src0) {
614     AutoMemorySandboxer<> _(this, &Dest, &Src0);
615     Context.insert<typename Traits::Insts::Divps>(Dest, Src0);
616   }
617   void _divss(Variable *Dest, Operand *Src0) {
618     AutoMemorySandboxer<> _(this, &Dest, &Src0);
619     Context.insert<typename Traits::Insts::Divss>(Dest, Src0);
620   }
621   template <typename T = Traits>
622   typename std::enable_if<T::UsesX87, void>::type _fld(Operand *Src0) {
623     AutoMemorySandboxer<> _(this, &Src0);
624     Context.insert<typename Traits::Insts::template Fld<>>(Src0);
625   }
626   // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
627   // does not invoke this method, and remove it.
628   template <typename T = Traits>
629   typename std::enable_if<!T::UsesX87, void>::type _fld(Operand *) {
630     llvm::report_fatal_error("fld is not available in x86-64");
631   }
632   template <typename T = Traits>
633   typename std::enable_if<T::UsesX87, void>::type _fstp(Variable *Dest) {
634     AutoMemorySandboxer<> _(this, &Dest);
635     Context.insert<typename Traits::Insts::template Fstp<>>(Dest);
636   }
637   // TODO(jpp): when implementing the X8664 calling convention, make sure x8664
638   // does not invoke this method, and remove it.
639   template <typename T = Traits>
640   typename std::enable_if<!T::UsesX87, void>::type _fstp(Variable *) {
641     llvm::report_fatal_error("fstp is not available in x86-64");
642   }
643   void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) {
644     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
645     Context.insert<typename Traits::Insts::Idiv>(Dest, Src0, Src1);
646   }
647   void _imul(Variable *Dest, Operand *Src0) {
648     AutoMemorySandboxer<> _(this, &Dest, &Src0);
649     Context.insert<typename Traits::Insts::Imul>(Dest, Src0);
650   }
651   void _imul_imm(Variable *Dest, Operand *Src0, Constant *Imm) {
652     AutoMemorySandboxer<> _(this, &Dest, &Src0);
653     Context.insert<typename Traits::Insts::ImulImm>(Dest, Src0, Imm);
654   }
655   void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) {
656     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
657     Context.insert<typename Traits::Insts::Insertps>(Dest, Src0, Src1);
658   }
659   void _jmp(Operand *Target) {
660     AutoMemorySandboxer<> _(this, &Target);
661     Context.insert<typename Traits::Insts::Jmp>(Target);
662   }
663   void _lea(Variable *Dest, Operand *Src0) {
664     Context.insert<typename Traits::Insts::Lea>(Dest, Src0);
665   }
666   void _link_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_link_bp); }
667   void _push_reg(Variable *Reg) {
668     dispatchToConcrete(&Traits::ConcreteTarget::_push_reg, std::move(Reg));
669   }
670   void _mfence() { Context.insert<typename Traits::Insts::Mfence>(); }
671   /// Moves can be used to redefine registers, creating "partial kills" for
672   /// liveness.  Mark where moves are used in this way.
673   void _redefined(Inst *MovInst, bool IsRedefinition = true) {
674     if (IsRedefinition)
675       MovInst->setDestRedefined();
676   }
677   /// If Dest=nullptr is passed in, then a new variable is created, marked as
678   /// infinite register allocation weight, and returned through the in/out Dest
679   /// argument.
680   typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
681                                     int32_t RegNum = Variable::NoRegister) {
682     if (Dest == nullptr)
683       Dest = makeReg(Src0->getType(), RegNum);
684     AutoMemorySandboxer<> _(this, &Dest, &Src0);
685     return Context.insert<typename Traits::Insts::Mov>(Dest, Src0);
686   }
687   void _mov_sp(Operand *NewValue) {
688     dispatchToConcrete(&Traits::ConcreteTarget::_mov_sp, std::move(NewValue));
689   }
690   typename Traits::Insts::Movp *_movp(Variable *Dest, Operand *Src0) {
691     AutoMemorySandboxer<> _(this, &Dest, &Src0);
692     return Context.insert<typename Traits::Insts::Movp>(Dest, Src0);
693   }
694   void _movd(Variable *Dest, Operand *Src0) {
695     AutoMemorySandboxer<> _(this, &Dest, &Src0);
696     Context.insert<typename Traits::Insts::Movd>(Dest, Src0);
697   }
698   void _movq(Variable *Dest, Operand *Src0) {
699     AutoMemorySandboxer<> _(this, &Dest, &Src0);
700     Context.insert<typename Traits::Insts::Movq>(Dest, Src0);
701   }
702   void _movss(Variable *Dest, Variable *Src0) {
703     Context.insert<typename Traits::Insts::MovssRegs>(Dest, Src0);
704   }
705   void _movsx(Variable *Dest, Operand *Src0) {
706     AutoMemorySandboxer<> _(this, &Dest, &Src0);
707     Context.insert<typename Traits::Insts::Movsx>(Dest, Src0);
708   }
709   typename Traits::Insts::Movzx *_movzx(Variable *Dest, Operand *Src0) {
710     AutoMemorySandboxer<> _(this, &Dest, &Src0);
711     return Context.insert<typename Traits::Insts::Movzx>(Dest, Src0);
712   }
713   void _maxss(Variable *Dest, Operand *Src0) {
714     AutoMemorySandboxer<> _(this, &Dest, &Src0);
715     Context.insert<typename Traits::Insts::Maxss>(Dest, Src0);
716   }
717   void _minss(Variable *Dest, Operand *Src0) {
718     AutoMemorySandboxer<> _(this, &Dest, &Src0);
719     Context.insert<typename Traits::Insts::Minss>(Dest, Src0);
720   }
721   void _mul(Variable *Dest, Variable *Src0, Operand *Src1) {
722     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
723     Context.insert<typename Traits::Insts::Mul>(Dest, Src0, Src1);
724   }
725   void _mulps(Variable *Dest, Operand *Src0) {
726     AutoMemorySandboxer<> _(this, &Dest, &Src0);
727     Context.insert<typename Traits::Insts::Mulps>(Dest, Src0);
728   }
729   void _mulss(Variable *Dest, Operand *Src0) {
730     AutoMemorySandboxer<> _(this, &Dest, &Src0);
731     Context.insert<typename Traits::Insts::Mulss>(Dest, Src0);
732   }
733   void _neg(Variable *SrcDest) {
734     AutoMemorySandboxer<> _(this, &SrcDest);
735     Context.insert<typename Traits::Insts::Neg>(SrcDest);
736   }
737   void _nop(SizeT Variant) {
738     Context.insert<typename Traits::Insts::Nop>(Variant);
739   }
740   void _or(Variable *Dest, Operand *Src0) {
741     AutoMemorySandboxer<> _(this, &Dest, &Src0);
742     Context.insert<typename Traits::Insts::Or>(Dest, Src0);
743   }
744   void _orps(Variable *Dest, Operand *Src0) {
745     AutoMemorySandboxer<> _(this, &Dest, &Src0);
746     Context.insert<typename Traits::Insts::Orps>(Dest, Src0);
747   }
748   void _or_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
749     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
750     Context.insert<typename Traits::Insts::OrRMW>(DestSrc0, Src1);
751   }
752   void _padd(Variable *Dest, Operand *Src0) {
753     AutoMemorySandboxer<> _(this, &Dest, &Src0);
754     Context.insert<typename Traits::Insts::Padd>(Dest, Src0);
755   }
756   void _pand(Variable *Dest, Operand *Src0) {
757     AutoMemorySandboxer<> _(this, &Dest, &Src0);
758     Context.insert<typename Traits::Insts::Pand>(Dest, Src0);
759   }
760   void _pandn(Variable *Dest, Operand *Src0) {
761     AutoMemorySandboxer<> _(this, &Dest, &Src0);
762     Context.insert<typename Traits::Insts::Pandn>(Dest, Src0);
763   }
764   void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) {
765     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
766     Context.insert<typename Traits::Insts::Pblendvb>(Dest, Src0, Src1);
767   }
768   void _pcmpeq(Variable *Dest, Operand *Src0,
769                Type ArithmeticTypeOverride = IceType_void) {
770     AutoMemorySandboxer<> _(this, &Dest, &Src0);
771     Context.insert<typename Traits::Insts::Pcmpeq>(Dest, Src0,
772                                                    ArithmeticTypeOverride);
773   }
774   void _pcmpgt(Variable *Dest, Operand *Src0) {
775     AutoMemorySandboxer<> _(this, &Dest, &Src0);
776     Context.insert<typename Traits::Insts::Pcmpgt>(Dest, Src0);
777   }
778   void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) {
779     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
780     Context.insert<typename Traits::Insts::Pextr>(Dest, Src0, Src1);
781   }
782   void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) {
783     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
784     Context.insert<typename Traits::Insts::Pinsr>(Dest, Src0, Src1);
785   }
786   void _pmull(Variable *Dest, Operand *Src0) {
787     AutoMemorySandboxer<> _(this, &Dest, &Src0);
788     Context.insert<typename Traits::Insts::Pmull>(Dest, Src0);
789   }
790   void _pmuludq(Variable *Dest, Operand *Src0) {
791     AutoMemorySandboxer<> _(this, &Dest, &Src0);
792     Context.insert<typename Traits::Insts::Pmuludq>(Dest, Src0);
793   }
794   void _pop(Variable *Dest) {
795     Context.insert<typename Traits::Insts::Pop>(Dest);
796   }
797   void _por(Variable *Dest, Operand *Src0) {
798     AutoMemorySandboxer<> _(this, &Dest, &Src0);
799     Context.insert<typename Traits::Insts::Por>(Dest, Src0);
800   }
801   void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) {
802     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
803     Context.insert<typename Traits::Insts::Pshufd>(Dest, Src0, Src1);
804   }
805   void _psll(Variable *Dest, Operand *Src0) {
806     AutoMemorySandboxer<> _(this, &Dest, &Src0);
807     Context.insert<typename Traits::Insts::Psll>(Dest, Src0);
808   }
809   void _psra(Variable *Dest, Operand *Src0) {
810     AutoMemorySandboxer<> _(this, &Dest, &Src0);
811     Context.insert<typename Traits::Insts::Psra>(Dest, Src0);
812   }
813   void _psrl(Variable *Dest, Operand *Src0) {
814     AutoMemorySandboxer<> _(this, &Dest, &Src0);
815     Context.insert<typename Traits::Insts::Psrl>(Dest, Src0);
816   }
817   void _psub(Variable *Dest, Operand *Src0) {
818     AutoMemorySandboxer<> _(this, &Dest, &Src0);
819     Context.insert<typename Traits::Insts::Psub>(Dest, Src0);
820   }
821   void _push(Operand *Src0) {
822     Context.insert<typename Traits::Insts::Push>(Src0);
823   }
824   void _pxor(Variable *Dest, Operand *Src0) {
825     AutoMemorySandboxer<> _(this, &Dest, &Src0);
826     Context.insert<typename Traits::Insts::Pxor>(Dest, Src0);
827   }
828   void _ret(Variable *Src0 = nullptr) {
829     Context.insert<typename Traits::Insts::Ret>(Src0);
830   }
831   void _rol(Variable *Dest, Operand *Src0) {
832     AutoMemorySandboxer<> _(this, &Dest, &Src0);
833     Context.insert<typename Traits::Insts::Rol>(Dest, Src0);
834   }
835   X86OperandMem *_sandbox_mem_reference(X86OperandMem *Mem) {
836     return dispatchToConcrete(&Traits::ConcreteTarget::_sandbox_mem_reference,
837                               std::move(Mem));
838   }
839   void _sar(Variable *Dest, Operand *Src0) {
840     AutoMemorySandboxer<> _(this, &Dest, &Src0);
841     Context.insert<typename Traits::Insts::Sar>(Dest, Src0);
842   }
843   void _sbb(Variable *Dest, Operand *Src0) {
844     AutoMemorySandboxer<> _(this, &Dest, &Src0);
845     Context.insert<typename Traits::Insts::Sbb>(Dest, Src0);
846   }
847   void _sbb_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
848     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
849     Context.insert<typename Traits::Insts::SbbRMW>(DestSrc0, Src1);
850   }
851   void _setcc(Variable *Dest, BrCond Condition) {
852     Context.insert<typename Traits::Insts::Setcc>(Dest, Condition);
853   }
854   void _shl(Variable *Dest, Operand *Src0) {
855     AutoMemorySandboxer<> _(this, &Dest, &Src0);
856     Context.insert<typename Traits::Insts::Shl>(Dest, Src0);
857   }
858   void _shld(Variable *Dest, Variable *Src0, Operand *Src1) {
859     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
860     Context.insert<typename Traits::Insts::Shld>(Dest, Src0, Src1);
861   }
862   void _shr(Variable *Dest, Operand *Src0) {
863     AutoMemorySandboxer<> _(this, &Dest, &Src0);
864     Context.insert<typename Traits::Insts::Shr>(Dest, Src0);
865   }
866   void _shrd(Variable *Dest, Variable *Src0, Operand *Src1) {
867     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
868     Context.insert<typename Traits::Insts::Shrd>(Dest, Src0, Src1);
869   }
870   void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) {
871     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
872     Context.insert<typename Traits::Insts::Shufps>(Dest, Src0, Src1);
873   }
874   void _sqrtss(Variable *Dest, Operand *Src0) {
875     AutoMemorySandboxer<> _(this, &Dest, &Src0);
876     Context.insert<typename Traits::Insts::Sqrtss>(Dest, Src0);
877   }
878   void _store(Operand *Value, X86Operand *Mem) {
879     AutoMemorySandboxer<> _(this, &Value, &Mem);
880     Context.insert<typename Traits::Insts::Store>(Value, Mem);
881   }
882   void _storep(Variable *Value, X86OperandMem *Mem) {
883     AutoMemorySandboxer<> _(this, &Value, &Mem);
884     Context.insert<typename Traits::Insts::StoreP>(Value, Mem);
885   }
886   void _storeq(Variable *Value, X86OperandMem *Mem) {
887     AutoMemorySandboxer<> _(this, &Value, &Mem);
888     Context.insert<typename Traits::Insts::StoreQ>(Value, Mem);
889   }
890   void _sub(Variable *Dest, Operand *Src0) {
891     AutoMemorySandboxer<> _(this, &Dest, &Src0);
892     Context.insert<typename Traits::Insts::Sub>(Dest, Src0);
893   }
894   void _sub_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
895     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
896     Context.insert<typename Traits::Insts::SubRMW>(DestSrc0, Src1);
897   }
898   void _sub_sp(Operand *Adjustment) {
899     dispatchToConcrete(&Traits::ConcreteTarget::_sub_sp, std::move(Adjustment));
900   }
901   void _subps(Variable *Dest, Operand *Src0) {
902     AutoMemorySandboxer<> _(this, &Dest, &Src0);
903     Context.insert<typename Traits::Insts::Subps>(Dest, Src0);
904   }
905   void _subss(Variable *Dest, Operand *Src0) {
906     AutoMemorySandboxer<> _(this, &Dest, &Src0);
907     Context.insert<typename Traits::Insts::Subss>(Dest, Src0);
908   }
909   void _test(Operand *Src0, Operand *Src1) {
910     AutoMemorySandboxer<> _(this, &Src0, &Src1);
911     Context.insert<typename Traits::Insts::Test>(Src0, Src1);
912   }
913   void _ucomiss(Operand *Src0, Operand *Src1) {
914     AutoMemorySandboxer<> _(this, &Src0, &Src1);
915     Context.insert<typename Traits::Insts::Ucomiss>(Src0, Src1);
916   }
917   void _ud2() { Context.insert<typename Traits::Insts::UD2>(); }
918   void _unlink_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_unlink_bp); }
919   void _xadd(Operand *Dest, Variable *Src, bool Locked) {
920     AutoMemorySandboxer<> _(this, &Dest, &Src);
921     Context.insert<typename Traits::Insts::Xadd>(Dest, Src, Locked);
922     // The xadd exchanges Dest and Src (modifying Src). Model that update with
923     // a FakeDef followed by a FakeUse.
924     Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
925     _set_dest_redefined();
926     Context.insert<InstFakeUse>(Src);
927   }
928   void _xchg(Operand *Dest, Variable *Src) {
929     AutoMemorySandboxer<> _(this, &Dest, &Src);
930     Context.insert<typename Traits::Insts::Xchg>(Dest, Src);
931     // The xchg modifies Dest and Src -- model that update with a
932     // FakeDef/FakeUse.
933     Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
934     _set_dest_redefined();
935     Context.insert<InstFakeUse>(Src);
936   }
937   void _xor(Variable *Dest, Operand *Src0) {
938     AutoMemorySandboxer<> _(this, &Dest, &Src0);
939     Context.insert<typename Traits::Insts::Xor>(Dest, Src0);
940   }
941   void _xorps(Variable *Dest, Operand *Src0) {
942     AutoMemorySandboxer<> _(this, &Dest, &Src0);
943     Context.insert<typename Traits::Insts::Xorps>(Dest, Src0);
944   }
945   void _xor_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
946     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
947     Context.insert<typename Traits::Insts::XorRMW>(DestSrc0, Src1);
948   }
949
950   void _iaca_start() {
951     if (!BuildDefs::minimal())
952       Context.insert<typename Traits::Insts::IacaStart>();
953   }
954   void _iaca_end() {
955     if (!BuildDefs::minimal())
956       Context.insert<typename Traits::Insts::IacaEnd>();
957   }
958
959   /// This class helps wrap IACA markers around the code generated by the
960   /// current scope. It means you don't need to put an end before each return.
961   class ScopedIacaMark {
962     ScopedIacaMark(const ScopedIacaMark &) = delete;
963     ScopedIacaMark &operator=(const ScopedIacaMark &) = delete;
964
965   public:
966     ScopedIacaMark(TargetX86Base *Lowering) : Lowering(Lowering) {
967       Lowering->_iaca_start();
968     }
969     ~ScopedIacaMark() { end(); }
970     void end() {
971       if (!Lowering)
972         return;
973       Lowering->_iaca_end();
974       Lowering = nullptr;
975     }
976
977   private:
978     TargetX86Base *Lowering;
979   };
980
981   bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
982   void findRMW();
983
984   InstructionSetEnum InstructionSet = Traits::InstructionSet::Begin;
985   bool IsEbpBasedFrame = false;
986   bool NeedsStackAlignment = false;
987   size_t SpillAreaSizeBytes = 0;
988   size_t FixedAllocaSizeBytes = 0;
989   size_t FixedAllocaAlignBytes = 0;
990   bool PrologEmitsFixedAllocas = false;
991   uint32_t MaxOutArgsSizeBytes = 0;
992   static std::array<llvm::SmallBitVector, RCX86_NUM> TypeToRegisterSet;
993   static std::array<llvm::SmallBitVector, RCX86_NUM>
994       TypeToRegisterSetUnfiltered;
995   static std::array<llvm::SmallBitVector, Traits::RegisterSet::Reg_NUM>
996       RegisterAliases;
997   llvm::SmallBitVector RegsUsed;
998   std::array<VarList, IceType_NUM> PhysicalRegisters;
999   // RebasePtr is a Variable that holds the Rebasing pointer (if any) for the
1000   // current sandboxing type.
1001   Variable *RebasePtr = nullptr;
1002
1003   /// Randomize a given immediate operand
1004   Operand *randomizeOrPoolImmediate(Constant *Immediate,
1005                                     int32_t RegNum = Variable::NoRegister);
1006   X86OperandMem *
1007   randomizeOrPoolImmediate(X86OperandMem *MemOperand,
1008                            int32_t RegNum = Variable::NoRegister);
1009   bool RandomizationPoolingPaused = false;
1010
1011 private:
1012   /// dispatchToConcrete is the template voodoo that allows TargetX86Base to
1013   /// invoke methods in Machine (which inherits from TargetX86Base) without
1014   /// having to rely on virtual method calls. There are two overloads, one for
1015   /// non-void types, and one for void types. We need this becase, for non-void
1016   /// types, we need to return the method result, where as for void, we don't.
1017   /// While it is true that the code compiles without the void "version", there
1018   /// used to be a time when compilers would reject such code.
1019   ///
1020   /// This machinery is far from perfect. Note that, in particular, the
1021   /// arguments provided to dispatchToConcrete() need to match the arguments for
1022   /// Method **exactly** (i.e., no argument promotion is performed.)
1023   template <typename Ret, typename... Args>
1024   typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
1025   dispatchToConcrete(Ret (ConcreteTarget::*Method)(Args...), Args &&... args) {
1026     return (static_cast<ConcreteTarget *>(this)->*Method)(
1027         std::forward<Args>(args)...);
1028   }
1029
1030   template <typename... Args>
1031   void dispatchToConcrete(void (ConcreteTarget::*Method)(Args...),
1032                           Args &&... args) {
1033     (static_cast<ConcreteTarget *>(this)->*Method)(std::forward<Args>(args)...);
1034   }
1035
1036   void lowerShift64(InstArithmetic::OpKind Op, Operand *Src0Lo, Operand *Src0Hi,
1037                     Operand *Src1Lo, Variable *DestLo, Variable *DestHi);
1038
1039   /// Emit the code for a combined operation and consumer instruction, or set
1040   /// the destination variable of the operation if Consumer == nullptr.
1041   void lowerIcmpAndConsumer(const InstIcmp *Icmp, const Inst *Consumer);
1042   void lowerFcmpAndConsumer(const InstFcmp *Fcmp, const Inst *Consumer);
1043   void lowerArithAndConsumer(const InstArithmetic *Arith, const Inst *Consumer);
1044
1045   /// Emit a setcc instruction if Consumer == nullptr; otherwise emit a
1046   /// specialized version of Consumer.
1047   void setccOrConsumer(BrCond Condition, Variable *Dest, const Inst *Consumer);
1048
1049   /// Emit a mov [1|0] instruction if Consumer == nullptr; otherwise emit a
1050   /// specialized version of Consumer.
1051   void movOrConsumer(bool IcmpResult, Variable *Dest, const Inst *Consumer);
1052
1053   /// Emit the code for instructions with a vector type.
1054   void lowerIcmpVector(const InstIcmp *Icmp);
1055   void lowerFcmpVector(const InstFcmp *Icmp);
1056   void lowerSelectVector(const InstSelect *Instr);
1057
1058   /// Helpers for select lowering.
1059   void lowerSelectMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1060                        Operand *SrcF);
1061   void lowerSelectIntMove(Variable *Dest, BrCond Cond, Operand *SrcT,
1062                           Operand *SrcF);
1063   /// Generic helper to move an arbitrary type from Src to Dest.
1064   void lowerMove(Variable *Dest, Operand *Src, bool IsRedefinition);
1065
1066   /// Optimizations for idiom recognition.
1067   bool lowerOptimizeFcmpSelect(const InstFcmp *Fcmp, const InstSelect *Select);
1068
1069   /// Complains loudly if invoked because the cpu can handle 64-bit types
1070   /// natively.
1071   template <typename T = Traits>
1072   typename std::enable_if<T::Is64Bit, void>::type lowerIcmp64(const InstIcmp *,
1073                                                               const Inst *) {
1074     llvm::report_fatal_error(
1075         "Hey, yo! This is x86-64. Watcha doin'? (lowerIcmp64)");
1076   }
1077   /// x86lowerIcmp64 handles 64-bit icmp lowering.
1078   template <typename T = Traits>
1079   typename std::enable_if<!T::Is64Bit, void>::type
1080   lowerIcmp64(const InstIcmp *Icmp, const Inst *Consumer);
1081
1082   BoolFolding<Traits> FoldingInfo;
1083
1084   static FixupKind PcRelFixup;
1085   static FixupKind AbsFixup;
1086 };
1087
1088 template <typename TraitsType>
1089 class TargetDataX86 final : public TargetDataLowering {
1090   using Traits = TraitsType;
1091   TargetDataX86() = delete;
1092   TargetDataX86(const TargetDataX86 &) = delete;
1093   TargetDataX86 &operator=(const TargetDataX86 &) = delete;
1094
1095 public:
1096   ~TargetDataX86() override = default;
1097
1098   static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1099     return makeUnique<TargetDataX86>(Ctx);
1100   }
1101
1102   void lowerGlobals(const VariableDeclarationList &Vars,
1103                     const IceString &SectionSuffix) override;
1104   void lowerConstants() override;
1105   void lowerJumpTables() override;
1106
1107 private:
1108   ENABLE_MAKE_UNIQUE;
1109
1110   explicit TargetDataX86(GlobalContext *Ctx) : TargetDataLowering(Ctx){};
1111   template <typename T> static void emitConstantPool(GlobalContext *Ctx);
1112 };
1113
1114 class TargetHeaderX86 : public TargetHeaderLowering {
1115   TargetHeaderX86() = delete;
1116   TargetHeaderX86(const TargetHeaderX86 &) = delete;
1117   TargetHeaderX86 &operator=(const TargetHeaderX86 &) = delete;
1118
1119 public:
1120   ~TargetHeaderX86() = default;
1121
1122   static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1123     return makeUnique<TargetHeaderX86>(Ctx);
1124   }
1125
1126 private:
1127   ENABLE_MAKE_UNIQUE;
1128
1129   explicit TargetHeaderX86(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {}
1130 };
1131
1132 } // end of namespace X86NAMESPACE
1133 } // end of namespace Ice
1134
1135 #include "IceTargetLoweringX86BaseImpl.h"
1136
1137 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H