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