Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Declares the X8632 Target Lowering Traits.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
     16 #define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
     17 
     18 #include "IceAssembler.h"
     19 #include "IceConditionCodesX8632.h"
     20 #include "IceDefs.h"
     21 #include "IceInst.h"
     22 #include "IceInstX8632.def"
     23 #include "IceOperand.h"
     24 #include "IceRegistersX8632.h"
     25 #include "IceTargetLowering.h"
     26 #include "IceTargetLoweringX8632.def"
     27 #include "IceTargetLoweringX86RegClass.h"
     28 
     29 #include <array>
     30 
     31 namespace Ice {
     32 
     33 namespace X8632 {
     34 using namespace ::Ice::X86;
     35 
     36 template <class Machine> struct Insts;
     37 template <class Machine> class TargetX86Base;
     38 template <class Machine> class AssemblerX86Base;
     39 
     40 class TargetX8632;
     41 
     42 struct TargetX8632Traits {
     43   //----------------------------------------------------------------------------
     44   //     ______  ______  __    __
     45   //    /\  __ \/\  ___\/\ "-./  \
     46   //    \ \  __ \ \___  \ \ \-./\ \
     47   //     \ \_\ \_\/\_____\ \_\ \ \_\
     48   //      \/_/\/_/\/_____/\/_/  \/_/
     49   //
     50   //----------------------------------------------------------------------------
     51   static constexpr ::Ice::Assembler::AssemblerKind AsmKind =
     52       ::Ice::Assembler::Asm_X8632;
     53 
     54   static constexpr bool Is64Bit = false;
     55   static constexpr bool HasPopa = true;
     56   static constexpr bool HasPusha = true;
     57   static constexpr bool UsesX87 = true;
     58   static constexpr ::Ice::RegX8632::GPRRegister Last8BitGPR =
     59       ::Ice::RegX8632::GPRRegister::Encoded_Reg_ebx;
     60 
     61   enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
     62 
     63   using GPRRegister = ::Ice::RegX8632::GPRRegister;
     64   using ByteRegister = ::Ice::RegX8632::ByteRegister;
     65   using XmmRegister = ::Ice::RegX8632::XmmRegister;
     66   using X87STRegister = ::Ice::RegX8632::X87STRegister;
     67 
     68   using Cond = ::Ice::CondX86;
     69 
     70   using RegisterSet = ::Ice::RegX8632;
     71   static constexpr RegisterSet::AllRegisters StackPtr = RegX8632::Reg_esp;
     72   static constexpr RegisterSet::AllRegisters FramePtr = RegX8632::Reg_ebp;
     73   static constexpr GPRRegister Encoded_Reg_Accumulator =
     74       RegX8632::Encoded_Reg_eax;
     75   static constexpr GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
     76   static constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32;
     77   static constexpr FixupKind FK_Abs = llvm::ELF::R_386_32;
     78   static constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF;
     79   static constexpr FixupKind FK_GotPC = llvm::ELF::R_386_GOTPC;
     80 
     81   class Operand {
     82   public:
     83     Operand(const Operand &other)
     84         : fixup_(other.fixup_), length_(other.length_) {
     85       memmove(&encoding_[0], &other.encoding_[0], other.length_);
     86     }
     87 
     88     Operand &operator=(const Operand &other) {
     89       length_ = other.length_;
     90       fixup_ = other.fixup_;
     91       memmove(&encoding_[0], &other.encoding_[0], other.length_);
     92       return *this;
     93     }
     94 
     95     uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
     96 
     97     GPRRegister rm() const {
     98       return static_cast<GPRRegister>(encoding_at(0) & 7);
     99     }
    100 
    101     ScaleFactor scale() const {
    102       return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
    103     }
    104 
    105     GPRRegister index() const {
    106       return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
    107     }
    108 
    109     GPRRegister base() const {
    110       return static_cast<GPRRegister>(encoding_at(1) & 7);
    111     }
    112 
    113     int8_t disp8() const {
    114       assert(length_ >= 2);
    115       return static_cast<int8_t>(encoding_[length_ - 1]);
    116     }
    117 
    118     int32_t disp32() const {
    119       assert(length_ >= 5);
    120       // TODO(stichnot): This method is not currently used.  Delete it along
    121       // with other unused methods, or use a safe version of bitCopy().
    122       llvm::report_fatal_error("Unexpected call to disp32()");
    123       // return Utils::bitCopy<int32_t>(encoding_[length_ - 4]);
    124     }
    125 
    126     AssemblerFixup *fixup() const { return fixup_; }
    127 
    128   protected:
    129     Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address.
    130 
    131     void SetModRM(int mod, GPRRegister rm) {
    132       assert((mod & ~3) == 0);
    133       encoding_[0] = (mod << 6) | rm;
    134       length_ = 1;
    135     }
    136 
    137     void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
    138       assert(length_ == 1);
    139       assert((scale & ~3) == 0);
    140       encoding_[1] = (scale << 6) | (index << 3) | base;
    141       length_ = 2;
    142     }
    143 
    144     void SetDisp8(int8_t disp) {
    145       assert(length_ == 1 || length_ == 2);
    146       encoding_[length_++] = static_cast<uint8_t>(disp);
    147     }
    148 
    149     void SetDisp32(int32_t disp) {
    150       assert(length_ == 1 || length_ == 2);
    151       intptr_t disp_size = sizeof(disp);
    152       memmove(&encoding_[length_], &disp, disp_size);
    153       length_ += disp_size;
    154     }
    155 
    156     void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
    157 
    158   private:
    159     AssemblerFixup *fixup_;
    160     uint8_t encoding_[6];
    161     uint8_t length_;
    162 
    163     explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
    164 
    165     /// Get the operand encoding byte at the given index.
    166     uint8_t encoding_at(intptr_t index) const {
    167       assert(index >= 0 && index < length_);
    168       return encoding_[index];
    169     }
    170 
    171     /// Returns whether or not this operand is really the given register in
    172     /// disguise. Used from the assembler to generate better encodings.
    173     bool IsRegister(GPRRegister reg) const {
    174       return ((encoding_[0] & 0xF8) ==
    175               0xC0) // Addressing mode is register only.
    176              &&
    177              ((encoding_[0] & 0x07) == reg); // Register codes match.
    178     }
    179 
    180     friend class AssemblerX86Base<TargetX8632Traits>;
    181   };
    182 
    183   class Address : public Operand {
    184     Address() = delete;
    185 
    186   public:
    187     Address(const Address &other) : Operand(other) {}
    188 
    189     Address &operator=(const Address &other) {
    190       Operand::operator=(other);
    191       return *this;
    192     }
    193 
    194     Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
    195       if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
    196         SetModRM(0, Base);
    197         if (Base == RegX8632::Encoded_Reg_esp)
    198           SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
    199       } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
    200         SetModRM(1, Base);
    201         if (Base == RegX8632::Encoded_Reg_esp)
    202           SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
    203         SetDisp8(Disp);
    204       } else {
    205         SetModRM(2, Base);
    206         if (Base == RegX8632::Encoded_Reg_esp)
    207           SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
    208         SetDisp32(Disp);
    209         if (Fixup)
    210           SetFixup(Fixup);
    211       }
    212     }
    213 
    214     Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
    215             AssemblerFixup *Fixup) {
    216       assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
    217       SetModRM(0, RegX8632::Encoded_Reg_esp);
    218       SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp);
    219       SetDisp32(Disp);
    220       if (Fixup)
    221         SetFixup(Fixup);
    222     }
    223 
    224     Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
    225             int32_t Disp, AssemblerFixup *Fixup) {
    226       assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
    227       if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
    228         SetModRM(0, RegX8632::Encoded_Reg_esp);
    229         SetSIB(Scale, Index, Base);
    230       } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
    231         SetModRM(1, RegX8632::Encoded_Reg_esp);
    232         SetSIB(Scale, Index, Base);
    233         SetDisp8(Disp);
    234       } else {
    235         SetModRM(2, RegX8632::Encoded_Reg_esp);
    236         SetSIB(Scale, Index, Base);
    237         SetDisp32(Disp);
    238         if (Fixup)
    239           SetFixup(Fixup);
    240       }
    241     }
    242 
    243     /// Generate an absolute address expression on x86-32.
    244     Address(RelocOffsetT Offset, AssemblerFixup *Fixup) {
    245       SetModRM(0, RegX8632::Encoded_Reg_ebp);
    246       // Use the Offset in the displacement for now. If we decide to process
    247       // fixups later, we'll need to patch up the emitted displacement.
    248       SetDisp32(Offset);
    249       if (Fixup)
    250         SetFixup(Fixup);
    251     }
    252 
    253     static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
    254       AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
    255       const RelocOffsetT Offset = 0;
    256       return Address(Offset, Fixup);
    257     }
    258   };
    259 
    260   //----------------------------------------------------------------------------
    261   //     __      ______  __     __  ______  ______  __  __   __  ______
    262   //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
    263   //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
    264   //     \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
    265   //      \/_____/\/_____/\/_/   \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
    266   //
    267   //----------------------------------------------------------------------------
    268   enum InstructionSet {
    269     Begin,
    270     // SSE2 is the PNaCl baseline instruction set.
    271     SSE2 = Begin,
    272     SSE4_1,
    273     End
    274   };
    275 
    276   static const char *TargetName;
    277   static constexpr Type WordType = IceType_i32;
    278 
    279   static const char *getRegName(RegNumT RegNum) {
    280     static const char *const RegNames[RegisterSet::Reg_NUM] = {
    281 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    282           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    283           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    284   name,
    285         REGX8632_TABLE
    286 #undef X
    287     };
    288     RegNum.assertIsValid();
    289     return RegNames[RegNum];
    290   }
    291 
    292   static GPRRegister getEncodedGPR(RegNumT RegNum) {
    293     static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
    294 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    295           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    296           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    297   GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
    298         REGX8632_TABLE
    299 #undef X
    300     };
    301     RegNum.assertIsValid();
    302     assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
    303     return GPRRegs[RegNum];
    304   }
    305 
    306   static ByteRegister getEncodedByteReg(RegNumT RegNum) {
    307     static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
    308 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    309           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    310           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    311   ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
    312         REGX8632_TABLE
    313 #undef X
    314     };
    315     RegNum.assertIsValid();
    316     assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
    317     return ByteRegs[RegNum];
    318   }
    319 
    320   static XmmRegister getEncodedXmm(RegNumT RegNum) {
    321     static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
    322 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    323           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    324           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    325   XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
    326         REGX8632_TABLE
    327 #undef X
    328     };
    329     RegNum.assertIsValid();
    330     assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
    331     return XmmRegs[RegNum];
    332   }
    333 
    334   static uint32_t getEncoding(RegNumT RegNum) {
    335     static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
    336 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    337           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    338           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    339   encode,
    340         REGX8632_TABLE
    341 #undef X
    342     };
    343     RegNum.assertIsValid();
    344     return Encoding[RegNum];
    345   }
    346 
    347   static RegNumT getBaseReg(RegNumT RegNum) {
    348     static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
    349 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    350           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    351           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    352   RegisterSet::base,
    353         REGX8632_TABLE
    354 #undef X
    355     };
    356     RegNum.assertIsValid();
    357     return BaseRegs[RegNum];
    358   }
    359 
    360 private:
    361   static RegisterSet::AllRegisters getFirstGprForType(Type Ty) {
    362     switch (Ty) {
    363     default:
    364       llvm_unreachable("Invalid type for GPR.");
    365     case IceType_i1:
    366     case IceType_i8:
    367       return RegisterSet::Reg_al;
    368     case IceType_i16:
    369       return RegisterSet::Reg_ax;
    370     case IceType_i32:
    371       return RegisterSet::Reg_eax;
    372     }
    373   }
    374 
    375 public:
    376   // Return a register in RegNum's alias set that is suitable for Ty.
    377   static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
    378     assert(RegNum.hasValue());
    379 
    380     if (!isScalarIntegerType(Ty)) {
    381       return RegNum;
    382     }
    383 
    384     // [abcd]h registers are not convertible to their ?l, ?x, and e?x versions.
    385     switch (RegNum) {
    386     default:
    387       break;
    388     case RegisterSet::Reg_ah:
    389     case RegisterSet::Reg_bh:
    390     case RegisterSet::Reg_ch:
    391     case RegisterSet::Reg_dh:
    392       assert(isByteSizedType(Ty));
    393       return RegNum;
    394     }
    395 
    396     const RegisterSet::AllRegisters FirstGprForType = getFirstGprForType(Ty);
    397 
    398     switch (RegNum) {
    399     default:
    400       llvm::report_fatal_error("Unknown register.");
    401 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    402           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    403           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    404   case RegisterSet::val: {                                                     \
    405     if (!isGPR)                                                                \
    406       return RegisterSet::val;                                                 \
    407     assert((is32) || (is16) || (is8) ||                                        \
    408            getBaseReg(RegisterSet::val) == RegisterSet::Reg_esp);              \
    409     constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize =               \
    410         (((is32) || RegisterSet::val == RegisterSet::Reg_esp)                  \
    411              ? RegisterSet::Reg_eax                                            \
    412              : (((is16) || RegisterSet::val == RegisterSet::Reg_sp)            \
    413                     ? RegisterSet::Reg_ax                                      \
    414                     : RegisterSet::Reg_al));                                   \
    415     const RegNumT NewRegNum =                                                  \
    416         RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
    417     assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
    418            "Error involving " #val);                                           \
    419     return NewRegNum;                                                          \
    420   }
    421       REGX8632_TABLE
    422 #undef X
    423     }
    424   }
    425 
    426 private:
    427   /// SizeOf is used to obtain the size of an initializer list as a constexpr
    428   /// expression. This is only needed until our C++ library is updated to
    429   /// C++ 14 -- which defines constexpr members to std::initializer_list.
    430   class SizeOf {
    431     SizeOf(const SizeOf &) = delete;
    432     SizeOf &operator=(const SizeOf &) = delete;
    433 
    434   public:
    435     constexpr SizeOf() : Size(0) {}
    436     template <typename... T>
    437     explicit constexpr SizeOf(T...)
    438         : Size(__length<T...>::value) {}
    439     constexpr SizeT size() const { return Size; }
    440 
    441   private:
    442     template <typename T, typename... U> struct __length {
    443       static constexpr std::size_t value = 1 + __length<U...>::value;
    444     };
    445 
    446     template <typename T> struct __length<T> {
    447       static constexpr std::size_t value = 1;
    448     };
    449 
    450     const std::size_t Size;
    451   };
    452 
    453 public:
    454   static void initRegisterSet(
    455       const ::Ice::ClFlags & /*Flags*/,
    456       std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
    457       std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
    458     SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
    459     SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
    460     SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
    461     SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
    462     SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
    463     SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
    464     SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
    465     SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
    466     SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
    467     SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
    468     SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
    469 
    470     static constexpr struct {
    471       uint16_t Val;
    472       unsigned Is64 : 1;
    473       unsigned Is32 : 1;
    474       unsigned Is16 : 1;
    475       unsigned Is8 : 1;
    476       unsigned IsXmm : 1;
    477       unsigned Is64To8 : 1;
    478       unsigned Is32To8 : 1;
    479       unsigned Is16To8 : 1;
    480       unsigned IsTrunc8Rcvr : 1;
    481       unsigned IsAhRcvr : 1;
    482 #define NUM_ALIASES_BITS 2
    483       SizeT NumAliases : (NUM_ALIASES_BITS + 1);
    484       uint16_t Aliases[1 << NUM_ALIASES_BITS];
    485 #undef NUM_ALIASES_BITS
    486     } X8632RegTable[RegisterSet::Reg_NUM] = {
    487 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    488           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    489           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    490   {                                                                            \
    491     RegisterSet::val, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
    492         isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases,              \
    493   }                                                                            \
    494   ,
    495         REGX8632_TABLE
    496 #undef X
    497     };
    498 
    499     for (SizeT ii = 0; ii < llvm::array_lengthof(X8632RegTable); ++ii) {
    500       const auto &Entry = X8632RegTable[ii];
    501       (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
    502       (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
    503       (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
    504       (FloatRegisters)[Entry.Val] = Entry.IsXmm;
    505       (VectorRegisters)[Entry.Val] = Entry.IsXmm;
    506       (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
    507       (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
    508       (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
    509       (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
    510       (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
    511       (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
    512       for (int J = 0; J < Entry.NumAliases; J++) {
    513         SizeT Alias = Entry.Aliases[J];
    514         assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
    515         (*RegisterAliases)[Entry.Val].set(Alias);
    516       }
    517       (*RegisterAliases)[Entry.Val].set(Entry.Val);
    518     }
    519 
    520     (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
    521     (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
    522     (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
    523     (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
    524     (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
    525     (*TypeToRegisterSet)[RC_i64] = InvalidRegisters;
    526     (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
    527     (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
    528     (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
    529     (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
    530     (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
    531     (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
    532     (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
    533     (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
    534     (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
    535     (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
    536     (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
    537     (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
    538     (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
    539     (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
    540   }
    541 
    542   static SmallBitVector getRegisterSet(const ::Ice::ClFlags & /*Flags*/,
    543                                        TargetLowering::RegSetMask Include,
    544                                        TargetLowering::RegSetMask Exclude) {
    545     SmallBitVector Registers(RegisterSet::Reg_NUM);
    546 
    547 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    548           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    549           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    550   if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
    551     Registers[RegisterSet::val] = true;                                        \
    552   if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
    553     Registers[RegisterSet::val] = true;                                        \
    554   if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
    555     Registers[RegisterSet::val] = true;                                        \
    556   if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
    557     Registers[RegisterSet::val] = true;                                        \
    558   if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
    559     Registers[RegisterSet::val] = false;                                       \
    560   if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
    561     Registers[RegisterSet::val] = false;                                       \
    562   if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
    563     Registers[RegisterSet::val] = false;                                       \
    564   if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
    565     Registers[RegisterSet::val] = false;
    566 
    567     REGX8632_TABLE
    568 
    569 #undef X
    570 
    571     return Registers;
    572   }
    573 
    574   static void makeRandomRegisterPermutation(
    575       Cfg *Func, llvm::SmallVectorImpl<RegNumT> &Permutation,
    576       const SmallBitVector &ExcludeRegisters, uint64_t Salt) {
    577     // TODO(stichnot): Declaring Permutation this way loses type/size
    578     // information. Fix this in conjunction with the caller-side TODO.
    579     assert(Permutation.size() >= RegisterSet::Reg_NUM);
    580     // Expected upper bound on the number of registers in a single equivalence
    581     // class. For x86-32, this would comprise the 8 XMM registers. This is for
    582     // performance, not correctness.
    583     static const unsigned MaxEquivalenceClassSize = 8;
    584     using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
    585     using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
    586     EquivalenceClassMap EquivalenceClasses;
    587     SizeT NumShuffled = 0, NumPreserved = 0;
    588 
    589 // Build up the equivalence classes of registers by looking at the register
    590 // properties as well as whether the registers should be explicitly excluded
    591 // from shuffling.
    592 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
    593           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
    594           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
    595   if (ExcludeRegisters[RegisterSet::val]) {                                    \
    596     /* val stays the same in the resulting permutation. */                     \
    597     Permutation[RegisterSet::val] = RegisterSet::val;                          \
    598     ++NumPreserved;                                                            \
    599   } else {                                                                     \
    600     uint32_t AttrKey = 0;                                                      \
    601     uint32_t Index = 0;                                                        \
    602     /* Combine relevant attributes into an equivalence class key. */           \
    603     Index |= (scratch << (AttrKey++));                                         \
    604     Index |= (preserved << (AttrKey++));                                       \
    605     Index |= (is8 << (AttrKey++));                                             \
    606     Index |= (is16 << (AttrKey++));                                            \
    607     Index |= (is32 << (AttrKey++));                                            \
    608     Index |= (is64 << (AttrKey++));                                            \
    609     Index |= (isXmm << (AttrKey++));                                           \
    610     Index |= (is16To8 << (AttrKey++));                                         \
    611     Index |= (is32To8 << (AttrKey++));                                         \
    612     Index |= (is64To8 << (AttrKey++));                                         \
    613     Index |= (isTrunc8Rcvr << (AttrKey++));                                    \
    614     /* val is assigned to an equivalence class based on its properties. */     \
    615     EquivalenceClasses[Index].push_back(RegisterSet::val);                     \
    616   }
    617     REGX8632_TABLE
    618 #undef X
    619 
    620     // Create a random number generator for regalloc randomization.
    621     RandomNumberGenerator RNG(getFlags().getRandomSeed(),
    622                               RPE_RegAllocRandomization, Salt);
    623     RandomNumberGeneratorWrapper RNGW(RNG);
    624 
    625     // Shuffle the resulting equivalence classes.
    626     for (auto I : EquivalenceClasses) {
    627       const RegisterList &List = I.second;
    628       RegisterList Shuffled(List);
    629       RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
    630       for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
    631         Permutation[List[SI]] = Shuffled[SI];
    632         ++NumShuffled;
    633       }
    634     }
    635 
    636     assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM);
    637 
    638     if (Func->isVerbose(IceV_Random)) {
    639       OstreamLocker L(Func->getContext());
    640       Ostream &Str = Func->getContext()->getStrDump();
    641       Str << "Register equivalence classes:\n";
    642       for (auto I : EquivalenceClasses) {
    643         Str << "{";
    644         const RegisterList &List = I.second;
    645         bool First = true;
    646         for (RegNumT Register : List) {
    647           if (!First)
    648             Str << " ";
    649           First = false;
    650           Str << getRegName(Register);
    651         }
    652         Str << "}\n";
    653       }
    654     }
    655   }
    656 
    657   static RegNumT getRaxOrDie() {
    658     llvm::report_fatal_error("no rax in non-64-bit mode.");
    659   }
    660 
    661   static RegNumT getRdxOrDie() {
    662     llvm::report_fatal_error("no rdx in non-64-bit mode.");
    663   }
    664 
    665   // x86-32 calling convention:
    666   //
    667   // * The first four arguments of vector type, regardless of their position
    668   // relative to the other arguments in the argument list, are placed in
    669   // registers xmm0 - xmm3.
    670   //
    671   // This intends to match the section "IA-32 Function Calling Convention" of
    672   // the document "OS X ABI Function Call Guide" by Apple.
    673 
    674   /// The maximum number of arguments to pass in XMM registers
    675   static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
    676   /// The maximum number of arguments to pass in GPR registers
    677   static constexpr uint32_t X86_MAX_GPR_ARGS = 0;
    678   /// Whether scalar floating point arguments are passed in XMM registers
    679   static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = false;
    680   /// Get the register for a given argument slot in the XMM registers.
    681   static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
    682     // TODO(sehr): Change to use the CCArg technique used in ARM32.
    683     static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
    684                   "Inconsistency between XMM register numbers and ordinals");
    685     if (ArgNum >= X86_MAX_XMM_ARGS) {
    686       return RegNumT();
    687     }
    688     return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
    689   }
    690   /// Get the register for a given argument slot in the GPRs.
    691   static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
    692     assert(Ty == IceType_i64 || Ty == IceType_i32);
    693     (void)Ty;
    694     (void)ArgNum;
    695     return RegNumT();
    696   }
    697 
    698   /// The number of bits in a byte
    699   static constexpr uint32_t X86_CHAR_BIT = 8;
    700   /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
    701   /// is used as an argument to std::max(), and the default std::less<T> has an
    702   /// operator(T const&, T const&) which requires this member to have an
    703   /// address.
    704   static const uint32_t X86_STACK_ALIGNMENT_BYTES;
    705   /// Size of the return address on the stack
    706   static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 4;
    707   /// The number of different NOP instructions
    708   static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
    709 
    710   /// \name Limits for unrolling memory intrinsics.
    711   /// @{
    712   static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
    713   static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
    714   static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
    715   /// @}
    716 
    717   /// Value is in bytes. Return Value adjusted to the next highest multiple of
    718   /// the stack alignment.
    719   static uint32_t applyStackAlignment(uint32_t Value) {
    720     return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
    721   }
    722 
    723   /// Return the type which the elements of the vector have in the X86
    724   /// representation of the vector.
    725   static Type getInVectorElementType(Type Ty) {
    726     assert(isVectorType(Ty));
    727     assert(Ty < TableTypeX8632AttributesSize);
    728     return TableTypeX8632Attributes[Ty].InVectorElementType;
    729   }
    730 
    731   // Note: The following data structures are defined in
    732   // IceTargetLoweringX8632.cpp.
    733 
    734   /// The following table summarizes the logic for lowering the fcmp
    735   /// instruction. There is one table entry for each of the 16 conditions.
    736   ///
    737   /// The first four columns describe the case when the operands are floating
    738   /// point scalar values. A comment in lowerFcmp() describes the lowering
    739   /// template. In the most general case, there is a compare followed by two
    740   /// conditional branches, because some fcmp conditions don't map to a single
    741   /// x86 conditional branch. However, in many cases it is possible to swap the
    742   /// operands in the comparison and have a single conditional branch. Since
    743   /// it's quite tedious to validate the table by hand, good execution tests are
    744   /// helpful.
    745   ///
    746   /// The last two columns describe the case when the operands are vectors of
    747   /// floating point values. For most fcmp conditions, there is a clear mapping
    748   /// to a single x86 cmpps instruction variant. Some fcmp conditions require
    749   /// special code to handle and these are marked in the table with a
    750   /// Cmpps_Invalid predicate.
    751   /// {@
    752   static const struct TableFcmpType {
    753     uint32_t Default;
    754     bool SwapScalarOperands;
    755     Cond::BrCond C1, C2;
    756     bool SwapVectorOperands;
    757     Cond::CmppsCond Predicate;
    758   } TableFcmp[];
    759   static const size_t TableFcmpSize;
    760   /// @}
    761 
    762   /// The following table summarizes the logic for lowering the icmp instruction
    763   /// for i32 and narrower types. Each icmp condition has a clear mapping to an
    764   /// x86 conditional branch instruction.
    765   /// {@
    766   static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
    767   static const size_t TableIcmp32Size;
    768   /// @}
    769 
    770   /// The following table summarizes the logic for lowering the icmp instruction
    771   /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
    772   /// conditional branches are needed. For the other conditions, three separate
    773   /// conditional branches are needed.
    774   /// {@
    775   static const struct TableIcmp64Type {
    776     Cond::BrCond C1, C2, C3;
    777   } TableIcmp64[];
    778   static const size_t TableIcmp64Size;
    779   /// @}
    780 
    781   static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
    782     assert(Cond < TableIcmp32Size);
    783     return TableIcmp32[Cond].Mapping;
    784   }
    785 
    786   static const struct TableTypeX8632AttributesType {
    787     Type InVectorElementType;
    788   } TableTypeX8632Attributes[];
    789   static const size_t TableTypeX8632AttributesSize;
    790 
    791   //----------------------------------------------------------------------------
    792   //      __  __   __  ______  ______
    793   //    /\ \/\ "-.\ \/\  ___\/\__  _\
    794   //    \ \ \ \ \-.  \ \___  \/_/\ \/
    795   //     \ \_\ \_\\"\_\/\_____\ \ \_\
    796   //      \/_/\/_/ \/_/\/_____/  \/_/
    797   //
    798   //----------------------------------------------------------------------------
    799   using Traits = TargetX8632Traits;
    800   using Insts = ::Ice::X8632::Insts<Traits>;
    801 
    802   using TargetLowering = ::Ice::X8632::TargetX86Base<Traits>;
    803   using ConcreteTarget = ::Ice::X8632::TargetX8632;
    804   using Assembler = ::Ice::X8632::AssemblerX86Base<Traits>;
    805 
    806   /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem
    807   /// and VariableSplit.
    808   class X86Operand : public ::Ice::Operand {
    809     X86Operand() = delete;
    810     X86Operand(const X86Operand &) = delete;
    811     X86Operand &operator=(const X86Operand &) = delete;
    812 
    813   public:
    814     enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
    815     using ::Ice::Operand::dump;
    816 
    817     void dump(const Cfg *, Ostream &Str) const override;
    818 
    819   protected:
    820     X86Operand(OperandKindX8632 Kind, Type Ty)
    821         : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
    822   };
    823 
    824   /// X86OperandMem represents the m32 addressing mode, with optional base and
    825   /// index registers, a constant offset, and a fixed shift value for the index
    826   /// register.
    827   class X86OperandMem : public X86Operand {
    828     X86OperandMem() = delete;
    829     X86OperandMem(const X86OperandMem &) = delete;
    830     X86OperandMem &operator=(const X86OperandMem &) = delete;
    831 
    832   public:
    833     enum SegmentRegisters {
    834       DefaultSegment = -1,
    835 #define X(val, name, prefix) val,
    836       SEG_REGX8632_TABLE
    837 #undef X
    838           SegReg_NUM
    839     };
    840     static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
    841                                  Constant *Offset, Variable *Index = nullptr,
    842                                  uint16_t Shift = 0,
    843                                  SegmentRegisters SegmentReg = DefaultSegment,
    844                                  bool IsRebased = false) {
    845       return new (Func->allocate<X86OperandMem>()) X86OperandMem(
    846           Func, Ty, Base, Offset, Index, Shift, SegmentReg, IsRebased);
    847     }
    848     static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
    849                                  Constant *Offset, bool IsRebased) {
    850       constexpr Variable *NoIndex = nullptr;
    851       constexpr uint16_t NoShift = 0;
    852       return new (Func->allocate<X86OperandMem>()) X86OperandMem(
    853           Func, Ty, Base, Offset, NoIndex, NoShift, DefaultSegment, IsRebased);
    854     }
    855     Variable *getBase() const { return Base; }
    856     Constant *getOffset() const { return Offset; }
    857     Variable *getIndex() const { return Index; }
    858     uint16_t getShift() const { return Shift; }
    859     SegmentRegisters getSegmentRegister() const { return SegmentReg; }
    860     void emitSegmentOverride(Assembler *Asm) const;
    861     bool getIsRebased() const { return IsRebased; }
    862     Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target,
    863                          bool LeaAddr = false) const;
    864 
    865     void emit(const Cfg *Func) const override;
    866     using X86Operand::dump;
    867     void dump(const Cfg *Func, Ostream &Str) const override;
    868 
    869     static bool classof(const Operand *Operand) {
    870       return Operand->getKind() == static_cast<OperandKind>(kMem);
    871     }
    872 
    873     void setRandomized(bool R) { Randomized = R; }
    874 
    875     bool getRandomized() const { return Randomized; }
    876 
    877   private:
    878     X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
    879                   Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg,
    880                   bool IsRebased);
    881 
    882     Variable *const Base;
    883     Constant *const Offset;
    884     Variable *const Index;
    885     const uint16_t Shift;
    886     const SegmentRegisters SegmentReg : 16;
    887     const bool IsRebased;
    888     /// A flag to show if this memory operand is a randomized one. Randomized
    889     /// memory operands are generated in
    890     /// TargetX86Base::randomizeOrPoolImmediate()
    891     bool Randomized = false;
    892   };
    893 
    894   /// VariableSplit is a way to treat an f64 memory location as a pair of i32
    895   /// locations (Low and High). This is needed for some cases of the Bitcast
    896   /// instruction. Since it's not possible for integer registers to access the
    897   /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
    898   /// the stack and then accesses through the VariableSplit.
    899   // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
    900   // targets can natively handle these.
    901   class VariableSplit : public X86Operand {
    902     VariableSplit() = delete;
    903     VariableSplit(const VariableSplit &) = delete;
    904     VariableSplit &operator=(const VariableSplit &) = delete;
    905 
    906   public:
    907     enum Portion { Low, High };
    908     static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
    909       return new (Func->allocate<VariableSplit>())
    910           VariableSplit(Func, Var, Part);
    911     }
    912     int32_t getOffset() const { return Part == High ? 4 : 0; }
    913 
    914     Address toAsmAddress(const Cfg *Func) const;
    915     void emit(const Cfg *Func) const override;
    916     using X86Operand::dump;
    917     void dump(const Cfg *Func, Ostream &Str) const override;
    918 
    919     static bool classof(const Operand *Operand) {
    920       return Operand->getKind() == static_cast<OperandKind>(kSplit);
    921     }
    922 
    923   private:
    924     VariableSplit(Cfg *Func, Variable *Var, Portion Part)
    925         : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
    926       assert(Var->getType() == IceType_f64);
    927       Vars = Func->allocateArrayOf<Variable *>(1);
    928       Vars[0] = Var;
    929       NumVars = 1;
    930     }
    931 
    932     Variable *Var;
    933     Portion Part;
    934   };
    935 
    936   // Note: The following data structures are defined in IceInstX8632.cpp.
    937 
    938   static const struct InstBrAttributesType {
    939     Cond::BrCond Opposite;
    940     const char *DisplayString;
    941     const char *EmitString;
    942   } InstBrAttributes[];
    943 
    944   static const struct InstCmppsAttributesType {
    945     const char *EmitString;
    946   } InstCmppsAttributes[];
    947 
    948   static const struct TypeAttributesType {
    949     const char *CvtString;      // i (integer), s (single FP), d (double FP)
    950     const char *SdSsString;     // ss, sd, or <blank>
    951     const char *PdPsString;     // ps, pd, or <blank>
    952     const char *SpSdString;     // ss, sd, ps, pd, or <blank>
    953     const char *IntegralString; // b, w, d, or <blank>
    954     const char *UnpackString;   // bw, wd, dq, or <blank>
    955     const char *PackString;     // wb, dw, or <blank>
    956     const char *WidthString;    // b, w, l, q, or <blank>
    957     const char *FldString;      // s, l, or <blank>
    958   } TypeAttributes[];
    959 
    960   static const char *InstSegmentRegNames[];
    961 
    962   static uint8_t InstSegmentPrefixes[];
    963 };
    964 
    965 using Traits = ::Ice::X8632::TargetX8632Traits;
    966 } // end of namespace X8632
    967 
    968 } // end of namespace Ice
    969 
    970 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
    971