Home | History | Annotate | Download | only in src
      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 
     74   using InstX86Br = typename Traits::Insts::Br;
     75   using InstX86FakeRMW = typename Traits::Insts::FakeRMW;
     76   using InstX86Label = typename Traits::Insts::Label;
     77 
     78   ~TargetX86Base() override = default;
     79 
     80   static void staticInit(GlobalContext *Ctx);
     81   static bool shouldBePooled(const Constant *C);
     82   static ::Ice::Type getPointerType();
     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 
     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 
    108   Variable *getPhysicalRegister(RegNumT RegNum,
    109                                 Type Ty = IceType_void) override;
    110   const char *getRegName(RegNumT RegNum, Type Ty) const override;
    111   static const char *getRegClassName(RegClass C) {
    112     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   }
    130   SmallBitVector getRegisterSet(RegSetMask Include,
    131                                 RegSetMask Exclude) const override;
    132   const SmallBitVector &
    133   getRegistersForVariable(const Variable *Var) const override {
    134     RegClass RC = Var->getRegClass();
    135     assert(static_cast<RegClassX86>(RC) < RCX86_NUM);
    136     return TypeToRegisterSet[RC];
    137   }
    138 
    139   const SmallBitVector &
    140   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 
    146   const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
    147     Reg.assertIsValid();
    148     return RegisterAliases[Reg];
    149   }
    150 
    151   bool hasFramePointer() const override { return IsEbpBasedFrame; }
    152   void setHasFramePointer() override { IsEbpBasedFrame = true; }
    153   RegNumT getStackReg() const override { return Traits::StackPtr; }
    154   RegNumT getFrameReg() const override { return Traits::FramePtr; }
    155   RegNumT getFrameOrStackReg() const override {
    156     // 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();
    160     return IsEbpBasedFrame ? getFrameReg() : getStackReg();
    161   }
    162   size_t typeWidthInBytesOnStack(Type Ty) const override {
    163     // Round up to the next multiple of WordType bytes.
    164     const uint32_t WordSizeInBytes = typeWidthInBytes(Traits::WordType);
    165     return Utils::applyAlignment(typeWidthInBytes(Ty), WordSizeInBytes);
    166   }
    167   uint32_t getStackAlignment() const override {
    168     return Traits::X86_STACK_ALIGNMENT_BYTES;
    169   }
    170   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   }
    175   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 {
    183     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);
    190   }
    191 
    192   bool shouldSplitToVariable64On32(Type Ty) const override {
    193     return Traits::Is64Bit ? false : Ty == IceType_i64;
    194   }
    195 
    196   ConstantRelocatable *createGetIPForRegister(const Variable *Dest) {
    197     assert(Dest->hasReg());
    198     const std::string RegName = Traits::getRegName(Dest->getRegNum());
    199     return llvm::cast<ConstantRelocatable>(Ctx->getConstantExternSym(
    200         Ctx->getGlobalString(H_getIP_prefix + RegName)));
    201   }
    202 
    203   SizeT getMinJumpTableSize() const override { return 4; }
    204 
    205   void emitVariable(const Variable *Var) const override;
    206 
    207   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;
    211   void emit(const ConstantUndef *C) const final;
    212   void emit(const ConstantRelocatable *C) const final;
    213 
    214   void initNodeForLowering(CfgNode *Node) override;
    215 
    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 
    234   void addProlog(CfgNode *Node) override;
    235   void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
    236                               size_t BasicFrameOffset, size_t StackAdjBytes,
    237                               size_t &InArgsSizeBytes);
    238   void addEpilog(CfgNode *Node) override;
    239   X86Address stackVarToAsmOperand(const Variable *Var) const;
    240 
    241   InstructionSetEnum getInstructionSet() const { return InstructionSet; }
    242   Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
    243 
    244 protected:
    245   const bool NeedSandboxing;
    246 
    247   explicit TargetX86Base(Cfg *Func);
    248 
    249   void postLower() override;
    250 
    251   /// 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.
    260   void initSandbox() {
    261     assert(SandboxingType != ST_None);
    262     dispatchToConcrete(&Traits::ConcreteTarget::initSandbox);
    263   }
    264 
    265   void lowerAlloca(const InstAlloca *Instr) override;
    266   void lowerArguments() override;
    267   void lowerArithmetic(const InstArithmetic *Instr) override;
    268   void lowerAssign(const InstAssign *Instr) override;
    269   void lowerBr(const InstBr *Instr) override;
    270   void lowerBreakpoint(const InstBreakpoint *Instr) override;
    271   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;
    276 
    277   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;
    283   void lowerShuffleVector(const InstShuffleVector *Instr) override;
    284   void lowerStore(const InstStore *Instr) override;
    285   void lowerSwitch(const InstSwitch *Instr) override;
    286   void lowerUnreachable(const InstUnreachable *Instr) override;
    287   void lowerOther(const Inst *Instr) override;
    288   void lowerRMW(const InstX86FakeRMW *RMW);
    289   void prelowerPhis() override;
    290   uint32_t getCallStackArgumentsSizeBytes(const CfgVector<Type> &ArgTypes,
    291                                           Type ReturnType);
    292   uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
    293   void genTargetHelperCallFor(Inst *Instr) override;
    294 
    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);
    313   void doAddressOptOther() override;
    314   void doAddressOptLoad() override;
    315   void doAddressOptStore() override;
    316   void doAddressOptLoadSubVector() override;
    317   void doAddressOptStoreSubVector() override;
    318   void doMockBoundsCheck(Operand *Opnd) override;
    319   void randomlyInsertNop(float Probability,
    320                          RandomNumberGenerator &RNG) override;
    321 
    322   /// Naive lowering of cmpxchg.
    323   void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
    324                           Operand *Desired);
    325   /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
    326   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);
    332   /// 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.
    339   void lowerMemcpy(Operand *Dest, Operand *Src, Operand *Count);
    340   /// 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.
    343   void lowerMemset(Operand *Dest, Operand *Val, Operand *Count);
    344 
    345   /// Lower an indirect jump adding sandboxing when needed.
    346   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   }
    352 
    353   /// 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 
    366   using LowerBinOp = void (TargetX86Base::*)(Variable *, Operand *);
    367   void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi,
    368                                 Variable *Dest, Operand *Ptr, Operand *Val);
    369 
    370   void eliminateNextVectorSextInstruction(Variable *SignExtendedResult);
    371 
    372   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   }
    379   /// Emit just the call instruction (without argument or return variable
    380   /// processing), sandboxing if needed.
    381   virtual Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) = 0;
    382   /// Materialize the moves needed to return a value of the specified type.
    383   virtual Variable *moveReturnValueToRegister(Operand *Value,
    384                                               Type ReturnType) = 0;
    385 
    386   /// Emit a jump table to the constant pool.
    387   void emitJumpTable(const Cfg *Func,
    388                      const InstJumpTable *JumpTable) const override;
    389 
    390   /// 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() {
    393     Variable *esp =
    394         Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
    395     Context.insert<InstFakeUse>(esp);
    396   }
    397 
    398   /// 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.
    404   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]
    409     Legal_Rematerializable = 1 << 3,
    410     Legal_AddrAbs = 1 << 4, // ConstantRelocatable doesn't have to add RebasePtr
    411     Legal_Default = ~(Legal_Rematerializable | Legal_AddrAbs)
    412     // TODO(stichnot): Figure out whether this default works for x86-64.
    413   };
    414   using LegalMask = uint32_t;
    415   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
    416                     RegNumT RegNum = RegNumT());
    417   Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
    418   /// Legalize the first source operand for use in the cmp instruction.
    419   Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
    420   /// 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.
    423   X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
    424                                    bool DoLegalize = true);
    425 
    426   Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
    427   static Type stackSlotType();
    428 
    429   static constexpr uint32_t NoSizeLimit = 0;
    430   /// Returns the largest type which is equal to or larger than Size bytes. The
    431   /// 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).
    433   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 
    441   Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT());
    442   Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
    443 
    444   /// Returns a register containing all zeros, without affecting the FLAGS
    445   /// register, using the best instruction for the type.
    446   Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT());
    447 
    448   /// \name Returns a vector in a register with the given constant entries.
    449   /// @{
    450   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());
    455   /// @}
    456 
    457   /// Return a memory operand corresponding to a stack allocated Variable.
    458   X86OperandMem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
    459                                               uint32_t Offset = 0);
    460 
    461   void
    462   makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
    463                                 const SmallBitVector &ExcludeRegisters,
    464                                 uint64_t Salt) const override;
    465 
    466   /// 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:
    489     AutoBundle *Bundler = nullptr;
    490     X86OperandMem **const MemOperand;
    491 
    492     template <typename... T>
    493     AutoMemorySandboxer(typename Traits::TargetLowering *Target, T... Args)
    494         : Target(Target), MemOperand(Target->SandboxingType == ST_None
    495                                          ? nullptr
    496                                          : findMemoryReference(Args...)) {
    497       if (MemOperand != nullptr) {
    498         if (Traits::Is64Bit) {
    499           Bundler = new (Target->Func->template allocate<AutoBundle>())
    500               AutoBundle(Target, BundleLockOpt);
    501         }
    502         *MemOperand = Target->_sandbox_mem_reference(*MemOperand);
    503       }
    504     }
    505 
    506     ~AutoMemorySandboxer() {
    507       if (Bundler != nullptr) {
    508         Bundler->~AutoBundle();
    509       }
    510     }
    511   };
    512 
    513   /// 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.
    516   void _adc(Variable *Dest, Operand *Src0) {
    517     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    518     Context.insert<typename Traits::Insts::Adc>(Dest, Src0);
    519   }
    520   void _adc_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
    521     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
    522     Context.insert<typename Traits::Insts::AdcRMW>(DestSrc0, Src1);
    523   }
    524   void _add(Variable *Dest, Operand *Src0) {
    525     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    526     Context.insert<typename Traits::Insts::Add>(Dest, Src0);
    527   }
    528   void _add_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
    529     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
    530     Context.insert<typename Traits::Insts::AddRMW>(DestSrc0, Src1);
    531   }
    532   void _addps(Variable *Dest, Operand *Src0) {
    533     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    534     Context.insert<typename Traits::Insts::Addps>(Dest, Src0);
    535   }
    536   void _addss(Variable *Dest, Operand *Src0) {
    537     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    538     Context.insert<typename Traits::Insts::Addss>(Dest, Src0);
    539   }
    540   void _add_sp(Operand *Adjustment) {
    541     dispatchToConcrete(&Traits::ConcreteTarget::_add_sp, std::move(Adjustment));
    542   }
    543   void _and(Variable *Dest, Operand *Src0) {
    544     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    545     Context.insert<typename Traits::Insts::And>(Dest, Src0);
    546   }
    547   void _andnps(Variable *Dest, Operand *Src0) {
    548     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    549     Context.insert<typename Traits::Insts::Andnps>(Dest, Src0);
    550   }
    551   void _andps(Variable *Dest, Operand *Src0) {
    552     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    553     Context.insert<typename Traits::Insts::Andps>(Dest, Src0);
    554   }
    555   void _and_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
    556     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
    557     Context.insert<typename Traits::Insts::AndRMW>(DestSrc0, Src1);
    558   }
    559   void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
    560     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    561     Context.insert<typename Traits::Insts::Blendvps>(Dest, Src0, Src1);
    562   }
    563   void _br(BrCond Condition, CfgNode *TargetTrue, CfgNode *TargetFalse) {
    564     Context.insert<InstX86Br>(TargetTrue, TargetFalse, Condition,
    565                               InstX86Br::Far);
    566   }
    567   void _br(CfgNode *Target) {
    568     Context.insert<InstX86Br>(Target, InstX86Br::Far);
    569   }
    570   void _br(BrCond Condition, CfgNode *Target) {
    571     Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far);
    572   }
    573   void _br(BrCond Condition, InstX86Label *Label,
    574            typename InstX86Br::Mode Kind = InstX86Br::Near) {
    575     Context.insert<InstX86Br>(Label, Condition, Kind);
    576   }
    577   void _bsf(Variable *Dest, Operand *Src0) {
    578     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    579     Context.insert<typename Traits::Insts::Bsf>(Dest, Src0);
    580   }
    581   void _bsr(Variable *Dest, Operand *Src0) {
    582     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    583     Context.insert<typename Traits::Insts::Bsr>(Dest, Src0);
    584   }
    585   void _bswap(Variable *SrcDest) {
    586     AutoMemorySandboxer<> _(this, &SrcDest);
    587     Context.insert<typename Traits::Insts::Bswap>(SrcDest);
    588   }
    589   void _cbwdq(Variable *Dest, Operand *Src0) {
    590     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    591     Context.insert<typename Traits::Insts::Cbwdq>(Dest, Src0);
    592   }
    593   void _cmov(Variable *Dest, Operand *Src0, BrCond Condition) {
    594     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    595     Context.insert<typename Traits::Insts::Cmov>(Dest, Src0, Condition);
    596   }
    597   void _cmp(Operand *Src0, Operand *Src1) {
    598     AutoMemorySandboxer<> _(this, &Src0, &Src1);
    599     Context.insert<typename Traits::Insts::Icmp>(Src0, Src1);
    600   }
    601   void _cmpps(Variable *Dest, Operand *Src0, CmppsCond Condition) {
    602     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    603     Context.insert<typename Traits::Insts::Cmpps>(Dest, Src0, Condition);
    604   }
    605   void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
    606                 bool Locked) {
    607     AutoMemorySandboxer<> _(this, &DestOrAddr);
    608     Context.insert<typename Traits::Insts::Cmpxchg>(DestOrAddr, Eax, Desired,
    609                                                     Locked);
    610     // Mark eax as possibly modified by cmpxchg.
    611     Context.insert<InstFakeDef>(Eax, llvm::dyn_cast<Variable>(DestOrAddr));
    612     _set_dest_redefined();
    613     Context.insert<InstFakeUse>(Eax);
    614   }
    615   void _cmpxchg8b(X86OperandMem *Addr, Variable *Edx, Variable *Eax,
    616                   Variable *Ecx, Variable *Ebx, bool Locked) {
    617     AutoMemorySandboxer<> _(this, &Addr);
    618     Context.insert<typename Traits::Insts::Cmpxchg8b>(Addr, Edx, Eax, Ecx, Ebx,
    619                                                       Locked);
    620     // Mark edx, and eax as possibly modified by cmpxchg8b.
    621     Context.insert<InstFakeDef>(Edx);
    622     _set_dest_redefined();
    623     Context.insert<InstFakeUse>(Edx);
    624     Context.insert<InstFakeDef>(Eax);
    625     _set_dest_redefined();
    626     Context.insert<InstFakeUse>(Eax);
    627   }
    628   void _cvt(Variable *Dest, Operand *Src0,
    629             typename Traits::Insts::Cvt::CvtVariant Variant) {
    630     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    631     Context.insert<typename Traits::Insts::Cvt>(Dest, Src0, Variant);
    632   }
    633   void _round(Variable *Dest, Operand *Src0, Operand *Imm) {
    634     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    635     Context.insert<typename Traits::Insts::Round>(Dest, Src0, Imm);
    636   }
    637   void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
    638     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    639     Context.insert<typename Traits::Insts::Div>(Dest, Src0, Src1);
    640   }
    641   void _divps(Variable *Dest, Operand *Src0) {
    642     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    643     Context.insert<typename Traits::Insts::Divps>(Dest, Src0);
    644   }
    645   void _divss(Variable *Dest, Operand *Src0) {
    646     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    647     Context.insert<typename Traits::Insts::Divss>(Dest, Src0);
    648   }
    649   template <typename T = Traits>
    650   typename std::enable_if<T::UsesX87, void>::type _fld(Operand *Src0) {
    651     AutoMemorySandboxer<> _(this, &Src0);
    652     Context.insert<typename Traits::Insts::template Fld<>>(Src0);
    653   }
    654   // 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) {
    662     AutoMemorySandboxer<> _(this, &Dest);
    663     Context.insert<typename Traits::Insts::template Fstp<>>(Dest);
    664   }
    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");
    670   }
    671   void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) {
    672     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    673     Context.insert<typename Traits::Insts::Idiv>(Dest, Src0, Src1);
    674   }
    675   void _imul(Variable *Dest, Operand *Src0) {
    676     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    677     Context.insert<typename Traits::Insts::Imul>(Dest, Src0);
    678   }
    679   void _imul_imm(Variable *Dest, Operand *Src0, Constant *Imm) {
    680     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    681     Context.insert<typename Traits::Insts::ImulImm>(Dest, Src0, Imm);
    682   }
    683   void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) {
    684     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    685     Context.insert<typename Traits::Insts::Insertps>(Dest, Src0, Src1);
    686   }
    687   void _int3() { Context.insert<typename Traits::Insts::Int3>(); }
    688   void _jmp(Operand *Target) {
    689     AutoMemorySandboxer<> _(this, &Target);
    690     Context.insert<typename Traits::Insts::Jmp>(Target);
    691   }
    692   void _lea(Variable *Dest, Operand *Src0) {
    693     Context.insert<typename Traits::Insts::Lea>(Dest, Src0);
    694   }
    695   void _link_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_link_bp); }
    696   void _push_reg(Variable *Reg) {
    697     dispatchToConcrete(&Traits::ConcreteTarget::_push_reg, std::move(Reg));
    698   }
    699   void _mfence() { Context.insert<typename Traits::Insts::Mfence>(); }
    700   /// Moves can be used to redefine registers, creating "partial kills" for
    701   /// liveness.  Mark where moves are used in this way.
    702   void _redefined(Inst *MovInst, bool IsRedefinition = true) {
    703     if (IsRedefinition)
    704       MovInst->setDestRedefined();
    705   }
    706   /// If Dest=nullptr is passed in, then a new variable is created, marked as
    707   /// infinite register allocation weight, and returned through the in/out Dest
    708   /// argument.
    709   typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
    710                                     RegNumT RegNum = RegNumT()) {
    711     if (Dest == nullptr)
    712       Dest = makeReg(Src0->getType(), RegNum);
    713     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    714     return Context.insert<typename Traits::Insts::Mov>(Dest, Src0);
    715   }
    716   void _mov_sp(Operand *NewValue) {
    717     dispatchToConcrete(&Traits::ConcreteTarget::_mov_sp, std::move(NewValue));
    718   }
    719   typename Traits::Insts::Movp *_movp(Variable *Dest, Operand *Src0) {
    720     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    721     return Context.insert<typename Traits::Insts::Movp>(Dest, Src0);
    722   }
    723   void _movd(Variable *Dest, Operand *Src0) {
    724     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    725     Context.insert<typename Traits::Insts::Movd>(Dest, Src0);
    726   }
    727   void _movq(Variable *Dest, Operand *Src0) {
    728     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    729     Context.insert<typename Traits::Insts::Movq>(Dest, Src0);
    730   }
    731   void _movss(Variable *Dest, Variable *Src0) {
    732     Context.insert<typename Traits::Insts::MovssRegs>(Dest, Src0);
    733   }
    734   void _movsx(Variable *Dest, Operand *Src0) {
    735     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    736     Context.insert<typename Traits::Insts::Movsx>(Dest, Src0);
    737   }
    738   typename Traits::Insts::Movzx *_movzx(Variable *Dest, Operand *Src0) {
    739     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    740     return Context.insert<typename Traits::Insts::Movzx>(Dest, Src0);
    741   }
    742   void _maxss(Variable *Dest, Operand *Src0) {
    743     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    744     Context.insert<typename Traits::Insts::Maxss>(Dest, Src0);
    745   }
    746   void _minss(Variable *Dest, Operand *Src0) {
    747     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    748     Context.insert<typename Traits::Insts::Minss>(Dest, Src0);
    749   }
    750   void _maxps(Variable *Dest, Operand *Src0) {
    751     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    752     Context.insert<typename Traits::Insts::Maxps>(Dest, Src0);
    753   }
    754   void _minps(Variable *Dest, Operand *Src0) {
    755     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    756     Context.insert<typename Traits::Insts::Minps>(Dest, Src0);
    757   }
    758   void _mul(Variable *Dest, Variable *Src0, Operand *Src1) {
    759     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    760     Context.insert<typename Traits::Insts::Mul>(Dest, Src0, Src1);
    761   }
    762   void _mulps(Variable *Dest, Operand *Src0) {
    763     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    764     Context.insert<typename Traits::Insts::Mulps>(Dest, Src0);
    765   }
    766   void _mulss(Variable *Dest, Operand *Src0) {
    767     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    768     Context.insert<typename Traits::Insts::Mulss>(Dest, Src0);
    769   }
    770   void _neg(Variable *SrcDest) {
    771     AutoMemorySandboxer<> _(this, &SrcDest);
    772     Context.insert<typename Traits::Insts::Neg>(SrcDest);
    773   }
    774   void _nop(SizeT Variant) {
    775     Context.insert<typename Traits::Insts::Nop>(Variant);
    776   }
    777   void _or(Variable *Dest, Operand *Src0) {
    778     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    779     Context.insert<typename Traits::Insts::Or>(Dest, Src0);
    780   }
    781   void _orps(Variable *Dest, Operand *Src0) {
    782     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    783     Context.insert<typename Traits::Insts::Orps>(Dest, Src0);
    784   }
    785   void _or_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
    786     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
    787     Context.insert<typename Traits::Insts::OrRMW>(DestSrc0, Src1);
    788   }
    789   void _padd(Variable *Dest, Operand *Src0) {
    790     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    791     Context.insert<typename Traits::Insts::Padd>(Dest, Src0);
    792   }
    793   void _padds(Variable *Dest, Operand *Src0) {
    794     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    795     Context.insert<typename Traits::Insts::Padds>(Dest, Src0);
    796   }
    797   void _paddus(Variable *Dest, Operand *Src0) {
    798     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    799     Context.insert<typename Traits::Insts::Paddus>(Dest, Src0);
    800   }
    801   void _pand(Variable *Dest, Operand *Src0) {
    802     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    803     Context.insert<typename Traits::Insts::Pand>(Dest, Src0);
    804   }
    805   void _pandn(Variable *Dest, Operand *Src0) {
    806     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    807     Context.insert<typename Traits::Insts::Pandn>(Dest, Src0);
    808   }
    809   void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) {
    810     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    811     Context.insert<typename Traits::Insts::Pblendvb>(Dest, Src0, Src1);
    812   }
    813   void _pcmpeq(Variable *Dest, Operand *Src0,
    814                Type ArithmeticTypeOverride = IceType_void) {
    815     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    816     Context.insert<typename Traits::Insts::Pcmpeq>(Dest, Src0,
    817                                                    ArithmeticTypeOverride);
    818   }
    819   void _pcmpgt(Variable *Dest, Operand *Src0) {
    820     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    821     Context.insert<typename Traits::Insts::Pcmpgt>(Dest, Src0);
    822   }
    823   void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) {
    824     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    825     Context.insert<typename Traits::Insts::Pextr>(Dest, Src0, Src1);
    826   }
    827   void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) {
    828     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    829     Context.insert<typename Traits::Insts::Pinsr>(Dest, Src0, Src1);
    830   }
    831   void _pmull(Variable *Dest, Operand *Src0) {
    832     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    833     Context.insert<typename Traits::Insts::Pmull>(Dest, Src0);
    834   }
    835   void _pmulhw(Variable *Dest, Operand *Src0) {
    836     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    837     Context.insert<typename Traits::Insts::Pmulhw>(Dest, Src0);
    838   }
    839   void _pmulhuw(Variable *Dest, Operand *Src0) {
    840     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    841     Context.insert<typename Traits::Insts::Pmulhuw>(Dest, Src0);
    842   }
    843   void _pmaddwd(Variable *Dest, Operand *Src0) {
    844     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    845     Context.insert<typename Traits::Insts::Pmaddwd>(Dest, Src0);
    846   }
    847   void _pmuludq(Variable *Dest, Operand *Src0) {
    848     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    849     Context.insert<typename Traits::Insts::Pmuludq>(Dest, Src0);
    850   }
    851   void _pop(Variable *Dest) {
    852     Context.insert<typename Traits::Insts::Pop>(Dest);
    853   }
    854   void _por(Variable *Dest, Operand *Src0) {
    855     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    856     Context.insert<typename Traits::Insts::Por>(Dest, Src0);
    857   }
    858   void _punpckl(Variable *Dest, Operand *Src0) {
    859     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    860     Context.insert<typename Traits::Insts::Punpckl>(Dest, Src0);
    861   }
    862   void _punpckh(Variable *Dest, Operand *Src0) {
    863     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    864     Context.insert<typename Traits::Insts::Punpckh>(Dest, Src0);
    865   }
    866   void _packss(Variable *Dest, Operand *Src0) {
    867     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    868     Context.insert<typename Traits::Insts::Packss>(Dest, Src0);
    869   }
    870   void _packus(Variable *Dest, Operand *Src0) {
    871     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    872     Context.insert<typename Traits::Insts::Packus>(Dest, Src0);
    873   }
    874   void _pshufb(Variable *Dest, Operand *Src0) {
    875     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    876     Context.insert<typename Traits::Insts::Pshufb>(Dest, Src0);
    877   }
    878   void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) {
    879     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    880     Context.insert<typename Traits::Insts::Pshufd>(Dest, Src0, Src1);
    881   }
    882   void _psll(Variable *Dest, Operand *Src0) {
    883     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    884     Context.insert<typename Traits::Insts::Psll>(Dest, Src0);
    885   }
    886   void _psra(Variable *Dest, Operand *Src0) {
    887     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    888     Context.insert<typename Traits::Insts::Psra>(Dest, Src0);
    889   }
    890   void _psrl(Variable *Dest, Operand *Src0) {
    891     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    892     Context.insert<typename Traits::Insts::Psrl>(Dest, Src0);
    893   }
    894   void _psub(Variable *Dest, Operand *Src0) {
    895     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    896     Context.insert<typename Traits::Insts::Psub>(Dest, Src0);
    897   }
    898   void _psubs(Variable *Dest, Operand *Src0) {
    899     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    900     Context.insert<typename Traits::Insts::Psubs>(Dest, Src0);
    901   }
    902   void _psubus(Variable *Dest, Operand *Src0) {
    903     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    904     Context.insert<typename Traits::Insts::Psubus>(Dest, Src0);
    905   }
    906   void _push(Operand *Src0) {
    907     Context.insert<typename Traits::Insts::Push>(Src0);
    908   }
    909   void _pxor(Variable *Dest, Operand *Src0) {
    910     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    911     Context.insert<typename Traits::Insts::Pxor>(Dest, Src0);
    912   }
    913   void _ret(Variable *Src0 = nullptr) {
    914     Context.insert<typename Traits::Insts::Ret>(Src0);
    915   }
    916   void _rol(Variable *Dest, Operand *Src0) {
    917     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    918     Context.insert<typename Traits::Insts::Rol>(Dest, Src0);
    919   }
    920   void _round(Variable *Dest, Operand *Src, Constant *Imm) {
    921     AutoMemorySandboxer<> _(this, &Dest, &Src);
    922     Context.insert<typename Traits::Insts::Round>(Dest, Src, Imm);
    923   }
    924   X86OperandMem *_sandbox_mem_reference(X86OperandMem *Mem) {
    925     return dispatchToConcrete(&Traits::ConcreteTarget::_sandbox_mem_reference,
    926                               std::move(Mem));
    927   }
    928   void _sar(Variable *Dest, Operand *Src0) {
    929     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    930     Context.insert<typename Traits::Insts::Sar>(Dest, Src0);
    931   }
    932   void _sbb(Variable *Dest, Operand *Src0) {
    933     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    934     Context.insert<typename Traits::Insts::Sbb>(Dest, Src0);
    935   }
    936   void _sbb_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
    937     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
    938     Context.insert<typename Traits::Insts::SbbRMW>(DestSrc0, Src1);
    939   }
    940   void _setcc(Variable *Dest, BrCond Condition) {
    941     Context.insert<typename Traits::Insts::Setcc>(Dest, Condition);
    942   }
    943   void _shl(Variable *Dest, Operand *Src0) {
    944     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    945     Context.insert<typename Traits::Insts::Shl>(Dest, Src0);
    946   }
    947   void _shld(Variable *Dest, Variable *Src0, Operand *Src1) {
    948     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    949     Context.insert<typename Traits::Insts::Shld>(Dest, Src0, Src1);
    950   }
    951   void _shr(Variable *Dest, Operand *Src0) {
    952     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    953     Context.insert<typename Traits::Insts::Shr>(Dest, Src0);
    954   }
    955   void _shrd(Variable *Dest, Variable *Src0, Operand *Src1) {
    956     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    957     Context.insert<typename Traits::Insts::Shrd>(Dest, Src0, Src1);
    958   }
    959   void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) {
    960     AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
    961     Context.insert<typename Traits::Insts::Shufps>(Dest, Src0, Src1);
    962   }
    963   void _movmsk(Variable *Dest, Operand *Src0) {
    964     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    965     Context.insert<typename Traits::Insts::Movmsk>(Dest, Src0);
    966   }
    967   void _sqrt(Variable *Dest, Operand *Src0) {
    968     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    969     Context.insert<typename Traits::Insts::Sqrt>(Dest, Src0);
    970   }
    971   void _store(Operand *Value, X86Operand *Mem) {
    972     AutoMemorySandboxer<> _(this, &Value, &Mem);
    973     Context.insert<typename Traits::Insts::Store>(Value, Mem);
    974   }
    975   void _storep(Variable *Value, X86OperandMem *Mem) {
    976     AutoMemorySandboxer<> _(this, &Value, &Mem);
    977     Context.insert<typename Traits::Insts::StoreP>(Value, Mem);
    978   }
    979   void _storeq(Operand *Value, X86OperandMem *Mem) {
    980     AutoMemorySandboxer<> _(this, &Value, &Mem);
    981     Context.insert<typename Traits::Insts::StoreQ>(Value, Mem);
    982   }
    983   void _stored(Operand *Value, X86OperandMem *Mem) {
    984     AutoMemorySandboxer<> _(this, &Value, &Mem);
    985     Context.insert<typename Traits::Insts::StoreD>(Value, Mem);
    986   }
    987   void _sub(Variable *Dest, Operand *Src0) {
    988     AutoMemorySandboxer<> _(this, &Dest, &Src0);
    989     Context.insert<typename Traits::Insts::Sub>(Dest, Src0);
    990   }
    991   void _sub_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
    992     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
    993     Context.insert<typename Traits::Insts::SubRMW>(DestSrc0, Src1);
    994   }
    995   void _sub_sp(Operand *Adjustment) {
    996     dispatchToConcrete(&Traits::ConcreteTarget::_sub_sp, std::move(Adjustment));
    997   }
    998   void _subps(Variable *Dest, Operand *Src0) {
    999     AutoMemorySandboxer<> _(this, &Dest, &Src0);
   1000     Context.insert<typename Traits::Insts::Subps>(Dest, Src0);
   1001   }
   1002   void _subss(Variable *Dest, Operand *Src0) {
   1003     AutoMemorySandboxer<> _(this, &Dest, &Src0);
   1004     Context.insert<typename Traits::Insts::Subss>(Dest, Src0);
   1005   }
   1006   void _test(Operand *Src0, Operand *Src1) {
   1007     AutoMemorySandboxer<> _(this, &Src0, &Src1);
   1008     Context.insert<typename Traits::Insts::Test>(Src0, Src1);
   1009   }
   1010   void _ucomiss(Operand *Src0, Operand *Src1) {
   1011     AutoMemorySandboxer<> _(this, &Src0, &Src1);
   1012     Context.insert<typename Traits::Insts::Ucomiss>(Src0, Src1);
   1013   }
   1014   void _ud2() { Context.insert<typename Traits::Insts::UD2>(); }
   1015   void _unlink_bp() { dispatchToConcrete(&Traits::ConcreteTarget::_unlink_bp); }
   1016   void _xadd(Operand *Dest, Variable *Src, bool Locked) {
   1017     AutoMemorySandboxer<> _(this, &Dest, &Src);
   1018     Context.insert<typename Traits::Insts::Xadd>(Dest, Src, Locked);
   1019     // The xadd exchanges Dest and Src (modifying Src). Model that update with
   1020     // a FakeDef followed by a FakeUse.
   1021     Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
   1022     _set_dest_redefined();
   1023     Context.insert<InstFakeUse>(Src);
   1024   }
   1025   void _xchg(Operand *Dest, Variable *Src) {
   1026     AutoMemorySandboxer<> _(this, &Dest, &Src);
   1027     Context.insert<typename Traits::Insts::Xchg>(Dest, Src);
   1028     // The xchg modifies Dest and Src -- model that update with a
   1029     // FakeDef/FakeUse.
   1030     Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest));
   1031     _set_dest_redefined();
   1032     Context.insert<InstFakeUse>(Src);
   1033   }
   1034   void _xor(Variable *Dest, Operand *Src0) {
   1035     AutoMemorySandboxer<> _(this, &Dest, &Src0);
   1036     Context.insert<typename Traits::Insts::Xor>(Dest, Src0);
   1037   }
   1038   void _xorps(Variable *Dest, Operand *Src0) {
   1039     AutoMemorySandboxer<> _(this, &Dest, &Src0);
   1040     Context.insert<typename Traits::Insts::Xorps>(Dest, Src0);
   1041   }
   1042   void _xor_rmw(X86OperandMem *DestSrc0, Operand *Src1) {
   1043     AutoMemorySandboxer<> _(this, &DestSrc0, &Src1);
   1044     Context.insert<typename Traits::Insts::XorRMW>(DestSrc0, Src1);
   1045   }
   1046 
   1047   void _iaca_start() {
   1048     if (!BuildDefs::minimal())
   1049       Context.insert<typename Traits::Insts::IacaStart>();
   1050   }
   1051   void _iaca_end() {
   1052     if (!BuildDefs::minimal())
   1053       Context.insert<typename Traits::Insts::IacaEnd>();
   1054   }
   1055 
   1056   /// This class helps wrap IACA markers around the code generated by the
   1057   /// current scope. It means you don't need to put an end before each return.
   1058   class ScopedIacaMark {
   1059     ScopedIacaMark(const ScopedIacaMark &) = delete;
   1060     ScopedIacaMark &operator=(const ScopedIacaMark &) = delete;
   1061 
   1062   public:
   1063     ScopedIacaMark(TargetX86Base *Lowering) : Lowering(Lowering) {
   1064       Lowering->_iaca_start();
   1065     }
   1066     ~ScopedIacaMark() { end(); }
   1067     void end() {
   1068       if (!Lowering)
   1069         return;
   1070       Lowering->_iaca_end();
   1071       Lowering = nullptr;
   1072     }
   1073 
   1074   private:
   1075     TargetX86Base *Lowering;
   1076   };
   1077 
   1078   bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
   1079   void findRMW();
   1080 
   1081   InstructionSetEnum InstructionSet = Traits::InstructionSet::Begin;
   1082   bool IsEbpBasedFrame = false;
   1083   size_t RequiredStackAlignment = sizeof(Traits::WordType);
   1084   size_t SpillAreaSizeBytes = 0;
   1085   size_t FixedAllocaSizeBytes = 0;
   1086   size_t FixedAllocaAlignBytes = 0;
   1087   bool PrologEmitsFixedAllocas = false;
   1088   uint32_t MaxOutArgsSizeBytes = 0;
   1089   static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSet;
   1090   static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSetUnfiltered;
   1091   static std::array<SmallBitVector, Traits::RegisterSet::Reg_NUM>
   1092       RegisterAliases;
   1093   SmallBitVector RegsUsed;
   1094   std::array<VarList, IceType_NUM> PhysicalRegisters;
   1095   // RebasePtr is a Variable that holds the Rebasing pointer (if any) for the
   1096   // current sandboxing type.
   1097   Variable *RebasePtr = nullptr;
   1098 
   1099   /// Randomize a given immediate operand
   1100   Operand *randomizeOrPoolImmediate(Constant *Immediate,
   1101                                     RegNumT RegNum = RegNumT());
   1102   X86OperandMem *randomizeOrPoolImmediate(X86OperandMem *MemOperand,
   1103                                           RegNumT RegNum = RegNumT());
   1104   bool RandomizationPoolingPaused = false;
   1105 
   1106 private:
   1107   /// dispatchToConcrete is the template voodoo that allows TargetX86Base to
   1108   /// invoke methods in Machine (which inherits from TargetX86Base) without
   1109   /// having to rely on virtual method calls. There are two overloads, one for
   1110   /// non-void types, and one for void types. We need this becase, for non-void
   1111   /// types, we need to return the method result, where as for void, we don't.
   1112   /// While it is true that the code compiles without the void "version", there
   1113   /// used to be a time when compilers would reject such code.
   1114   ///
   1115   /// This machinery is far from perfect. Note that, in particular, the
   1116   /// arguments provided to dispatchToConcrete() need to match the arguments for
   1117   /// Method **exactly** (i.e., no argument promotion is performed.)
   1118   template <typename Ret, typename... Args>
   1119   typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
   1120   dispatchToConcrete(Ret (ConcreteTarget::*Method)(Args...), Args &&... args) {
   1121     return (static_cast<ConcreteTarget *>(this)->*Method)(
   1122         std::forward<Args>(args)...);
   1123   }
   1124 
   1125   template <typename... Args>
   1126   void dispatchToConcrete(void (ConcreteTarget::*Method)(Args...),
   1127                           Args &&... args) {
   1128     (static_cast<ConcreteTarget *>(this)->*Method)(std::forward<Args>(args)...);
   1129   }
   1130 
   1131   void lowerShift64(InstArithmetic::OpKind Op, Operand *Src0Lo, Operand *Src0Hi,
   1132                     Operand *Src1Lo, Variable *DestLo, Variable *DestHi);
   1133 
   1134   /// Emit the code for a combined operation and consumer instruction, or set
   1135   /// the destination variable of the operation if Consumer == nullptr.
   1136   void lowerIcmpAndConsumer(const InstIcmp *Icmp, const Inst *Consumer);
   1137   void lowerFcmpAndConsumer(const InstFcmp *Fcmp, const Inst *Consumer);
   1138   void lowerArithAndConsumer(const InstArithmetic *Arith, const Inst *Consumer);
   1139 
   1140   /// Emit a setcc instruction if Consumer == nullptr; otherwise emit a
   1141   /// specialized version of Consumer.
   1142   void setccOrConsumer(BrCond Condition, Variable *Dest, const Inst *Consumer);
   1143 
   1144   /// Emit a mov [1|0] instruction if Consumer == nullptr; otherwise emit a
   1145   /// specialized version of Consumer.
   1146   void movOrConsumer(bool IcmpResult, Variable *Dest, const Inst *Consumer);
   1147 
   1148   /// Emit the code for instructions with a vector type.
   1149   void lowerIcmpVector(const InstIcmp *Icmp);
   1150   void lowerFcmpVector(const InstFcmp *Icmp);
   1151   void lowerSelectVector(const InstSelect *Instr);
   1152 
   1153   /// Helpers for select lowering.
   1154   void lowerSelectMove(Variable *Dest, BrCond Cond, Operand *SrcT,
   1155                        Operand *SrcF);
   1156   void lowerSelectIntMove(Variable *Dest, BrCond Cond, Operand *SrcT,
   1157                           Operand *SrcF);
   1158   /// Generic helper to move an arbitrary type from Src to Dest.
   1159   void lowerMove(Variable *Dest, Operand *Src, bool IsRedefinition);
   1160 
   1161   /// Optimizations for idiom recognition.
   1162   bool lowerOptimizeFcmpSelect(const InstFcmp *Fcmp, const InstSelect *Select);
   1163 
   1164   /// Complains loudly if invoked because the cpu can handle 64-bit types
   1165   /// natively.
   1166   template <typename T = Traits>
   1167   typename std::enable_if<T::Is64Bit, void>::type lowerIcmp64(const InstIcmp *,
   1168                                                               const Inst *) {
   1169     llvm::report_fatal_error(
   1170         "Hey, yo! This is x86-64. Watcha doin'? (lowerIcmp64)");
   1171   }
   1172   /// x86lowerIcmp64 handles 64-bit icmp lowering.
   1173   template <typename T = Traits>
   1174   typename std::enable_if<!T::Is64Bit, void>::type
   1175   lowerIcmp64(const InstIcmp *Icmp, const Inst *Consumer);
   1176 
   1177   BoolFolding<Traits> FoldingInfo;
   1178 
   1179   /// Helpers for lowering ShuffleVector
   1180   /// @{
   1181   Variable *lowerShuffleVector_AllFromSameSrc(Operand *Src, SizeT Index0,
   1182                                               SizeT Index1, SizeT Index2,
   1183                                               SizeT Index3);
   1184   static constexpr SizeT IGNORE_INDEX = 0x80000000u;
   1185   Variable *lowerShuffleVector_TwoFromSameSrc(Operand *Src0, SizeT Index0,
   1186                                               SizeT Index1, Operand *Src1,
   1187                                               SizeT Index2, SizeT Index3);
   1188   static constexpr SizeT UNIFIED_INDEX_0 = 0;
   1189   static constexpr SizeT UNIFIED_INDEX_1 = 2;
   1190   Variable *lowerShuffleVector_UnifyFromDifferentSrcs(Operand *Src0,
   1191                                                       SizeT Index0,
   1192                                                       Operand *Src1,
   1193                                                       SizeT Index1);
   1194   static constexpr SizeT CLEAR_ALL_BITS = 0x80;
   1195   SizeT PshufbMaskCount = 0;
   1196   GlobalString lowerShuffleVector_NewMaskName();
   1197   ConstantRelocatable *lowerShuffleVector_CreatePshufbMask(
   1198       int8_t Idx0, int8_t Idx1, int8_t Idx2, int8_t Idx3, int8_t Idx4,
   1199       int8_t Idx5, int8_t Idx6, int8_t Idx7, int8_t Idx8, int8_t Idx9,
   1200       int8_t Idx10, int8_t Idx11, int8_t Idx12, int8_t Idx13, int8_t Idx14,
   1201       int8_t Idx15);
   1202   void lowerShuffleVector_UsingPshufb(Variable *Dest, Operand *Src0,
   1203                                       Operand *Src1, int8_t Idx0, int8_t Idx1,
   1204                                       int8_t Idx2, int8_t Idx3, int8_t Idx4,
   1205                                       int8_t Idx5, int8_t Idx6, int8_t Idx7,
   1206                                       int8_t Idx8, int8_t Idx9, int8_t Idx10,
   1207                                       int8_t Idx11, int8_t Idx12, int8_t Idx13,
   1208                                       int8_t Idx14, int8_t Idx15);
   1209   /// @}
   1210 
   1211   static FixupKind PcRelFixup;
   1212   static FixupKind AbsFixup;
   1213 };
   1214 
   1215 template <typename TraitsType>
   1216 class TargetDataX86 final : public TargetDataLowering {
   1217   using Traits = TraitsType;
   1218   TargetDataX86() = delete;
   1219   TargetDataX86(const TargetDataX86 &) = delete;
   1220   TargetDataX86 &operator=(const TargetDataX86 &) = delete;
   1221 
   1222 public:
   1223   ~TargetDataX86() override = default;
   1224 
   1225   static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
   1226     return makeUnique<TargetDataX86>(Ctx);
   1227   }
   1228 
   1229   void lowerGlobals(const VariableDeclarationList &Vars,
   1230                     const std::string &SectionSuffix) override;
   1231   void lowerConstants() override;
   1232   void lowerJumpTables() override;
   1233 
   1234 private:
   1235   ENABLE_MAKE_UNIQUE;
   1236 
   1237   explicit TargetDataX86(GlobalContext *Ctx) : TargetDataLowering(Ctx){};
   1238   template <typename T> static void emitConstantPool(GlobalContext *Ctx);
   1239 };
   1240 
   1241 class TargetHeaderX86 : public TargetHeaderLowering {
   1242   TargetHeaderX86() = delete;
   1243   TargetHeaderX86(const TargetHeaderX86 &) = delete;
   1244   TargetHeaderX86 &operator=(const TargetHeaderX86 &) = delete;
   1245 
   1246 public:
   1247   ~TargetHeaderX86() = default;
   1248 
   1249   static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
   1250     return makeUnique<TargetHeaderX86>(Ctx);
   1251   }
   1252 
   1253 private:
   1254   ENABLE_MAKE_UNIQUE;
   1255 
   1256   explicit TargetHeaderX86(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {}
   1257 };
   1258 
   1259 } // end of namespace X86NAMESPACE
   1260 } // end of namespace Ice
   1261 
   1262 #include "IceTargetLoweringX86BaseImpl.h"
   1263 
   1264 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H
   1265