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