• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
OperandTargetX8632Traits83     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 
modTargetX8632Traits95     uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
96 
rmTargetX8632Traits97     GPRRegister rm() const {
98       return static_cast<GPRRegister>(encoding_at(0) & 7);
99     }
100 
scaleTargetX8632Traits101     ScaleFactor scale() const {
102       return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
103     }
104 
indexTargetX8632Traits105     GPRRegister index() const {
106       return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
107     }
108 
baseTargetX8632Traits109     GPRRegister base() const {
110       return static_cast<GPRRegister>(encoding_at(1) & 7);
111     }
112 
disp8TargetX8632Traits113     int8_t disp8() const {
114       assert(length_ >= 2);
115       return static_cast<int8_t>(encoding_[length_ - 1]);
116     }
117 
disp32TargetX8632Traits118     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 
fixupTargetX8632Traits126     AssemblerFixup *fixup() const { return fixup_; }
127 
128   protected:
OperandTargetX8632Traits129     Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address.
130 
SetModRMTargetX8632Traits131     void SetModRM(int mod, GPRRegister rm) {
132       assert((mod & ~3) == 0);
133       encoding_[0] = (mod << 6) | rm;
134       length_ = 1;
135     }
136 
SetSIBTargetX8632Traits137     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 
SetDisp8TargetX8632Traits144     void SetDisp8(int8_t disp) {
145       assert(length_ == 1 || length_ == 2);
146       encoding_[length_++] = static_cast<uint8_t>(disp);
147     }
148 
SetDisp32TargetX8632Traits149     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 
SetFixupTargetX8632Traits156     void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
157 
158   private:
159     AssemblerFixup *fixup_;
160     uint8_t encoding_[6];
161     uint8_t length_;
162 
OperandTargetX8632Traits163     explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
164 
165     /// Get the operand encoding byte at the given index.
encoding_atTargetX8632Traits166     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.
IsRegisterTargetX8632Traits173     bool IsRegister(GPRRegister reg) const {
174       return ((encoding_[0] & 0xF8) ==
175               0xC0) // Addressing mode is register only.
176              && ((encoding_[0] & 0x07) == reg); // Register codes match.
177     }
178 
179     friend class AssemblerX86Base<TargetX8632Traits>;
180   };
181 
182   class Address : public Operand {
183     Address() = delete;
184 
185   public:
AddressTargetX8632Traits186     Address(const Address &other) : Operand(other) {}
187 
188     Address &operator=(const Address &other) {
189       Operand::operator=(other);
190       return *this;
191     }
192 
AddressTargetX8632Traits193     Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
194       if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
195         SetModRM(0, Base);
196         if (Base == RegX8632::Encoded_Reg_esp)
197           SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
198       } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
199         SetModRM(1, Base);
200         if (Base == RegX8632::Encoded_Reg_esp)
201           SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
202         SetDisp8(Disp);
203       } else {
204         SetModRM(2, Base);
205         if (Base == RegX8632::Encoded_Reg_esp)
206           SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
207         SetDisp32(Disp);
208         if (Fixup)
209           SetFixup(Fixup);
210       }
211     }
212 
AddressTargetX8632Traits213     Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
214             AssemblerFixup *Fixup) {
215       assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
216       SetModRM(0, RegX8632::Encoded_Reg_esp);
217       SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp);
218       SetDisp32(Disp);
219       if (Fixup)
220         SetFixup(Fixup);
221     }
222 
AddressTargetX8632Traits223     Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
224             int32_t Disp, AssemblerFixup *Fixup) {
225       assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
226       if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
227         SetModRM(0, RegX8632::Encoded_Reg_esp);
228         SetSIB(Scale, Index, Base);
229       } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
230         SetModRM(1, RegX8632::Encoded_Reg_esp);
231         SetSIB(Scale, Index, Base);
232         SetDisp8(Disp);
233       } else {
234         SetModRM(2, RegX8632::Encoded_Reg_esp);
235         SetSIB(Scale, Index, Base);
236         SetDisp32(Disp);
237         if (Fixup)
238           SetFixup(Fixup);
239       }
240     }
241 
242     /// Generate an absolute address expression on x86-32.
AddressTargetX8632Traits243     Address(RelocOffsetT Offset, AssemblerFixup *Fixup) {
244       SetModRM(0, RegX8632::Encoded_Reg_ebp);
245       // Use the Offset in the displacement for now. If we decide to process
246       // fixups later, we'll need to patch up the emitted displacement.
247       SetDisp32(Offset);
248       if (Fixup)
249         SetFixup(Fixup);
250     }
251 
ofConstPoolTargetX8632Traits252     static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
253       AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
254       const RelocOffsetT Offset = 0;
255       return Address(Offset, Fixup);
256     }
257   };
258 
259   //----------------------------------------------------------------------------
260   //     __      ______  __     __  ______  ______  __  __   __  ______
261   //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
262   //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
263   //     \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
264   //      \/_____/\/_____/\/_/   \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
265   //
266   //----------------------------------------------------------------------------
267   enum InstructionSet {
268     Begin,
269     // SSE2 is the PNaCl baseline instruction set.
270     SSE2 = Begin,
271     SSE4_1,
272     End
273   };
274 
275   static const char *TargetName;
276   static constexpr Type WordType = IceType_i32;
277 
getRegNameTargetX8632Traits278   static const char *getRegName(RegNumT RegNum) {
279     static const char *const RegNames[RegisterSet::Reg_NUM] = {
280 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
281           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
282           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
283   name,
284         REGX8632_TABLE
285 #undef X
286     };
287     RegNum.assertIsValid();
288     return RegNames[RegNum];
289   }
290 
getEncodedGPRTargetX8632Traits291   static GPRRegister getEncodedGPR(RegNumT RegNum) {
292     static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
293 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
294           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
295           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
296   GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
297         REGX8632_TABLE
298 #undef X
299     };
300     RegNum.assertIsValid();
301     assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
302     return GPRRegs[RegNum];
303   }
304 
getEncodedByteRegTargetX8632Traits305   static ByteRegister getEncodedByteReg(RegNumT RegNum) {
306     static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
307 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
308           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
309           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
310   ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
311         REGX8632_TABLE
312 #undef X
313     };
314     RegNum.assertIsValid();
315     assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
316     return ByteRegs[RegNum];
317   }
318 
isXmmTargetX8632Traits319   static bool isXmm(RegNumT RegNum) {
320     static const bool IsXmm[RegisterSet::Reg_NUM] = {
321 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
322           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
323           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
324   isXmm,
325         REGX8632_TABLE
326 #undef X
327     };
328     return IsXmm[RegNum];
329   }
330 
getEncodedXmmTargetX8632Traits331   static XmmRegister getEncodedXmm(RegNumT RegNum) {
332     static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
333 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
334           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
335           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
336   XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
337         REGX8632_TABLE
338 #undef X
339     };
340     RegNum.assertIsValid();
341     assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
342     return XmmRegs[RegNum];
343   }
344 
getEncodingTargetX8632Traits345   static uint32_t getEncoding(RegNumT RegNum) {
346     static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
347 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
348           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
349           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
350   encode,
351         REGX8632_TABLE
352 #undef X
353     };
354     RegNum.assertIsValid();
355     return Encoding[RegNum];
356   }
357 
getBaseRegTargetX8632Traits358   static RegNumT getBaseReg(RegNumT RegNum) {
359     static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
360 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
361           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
362           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
363   RegisterSet::base,
364         REGX8632_TABLE
365 #undef X
366     };
367     RegNum.assertIsValid();
368     return BaseRegs[RegNum];
369   }
370 
371 private:
getFirstGprForTypeTargetX8632Traits372   static RegisterSet::AllRegisters getFirstGprForType(Type Ty) {
373     switch (Ty) {
374     default:
375       llvm_unreachable("Invalid type for GPR.");
376     case IceType_i1:
377     case IceType_i8:
378       return RegisterSet::Reg_al;
379     case IceType_i16:
380       return RegisterSet::Reg_ax;
381     case IceType_i32:
382       return RegisterSet::Reg_eax;
383     }
384   }
385 
386 public:
387   // Return a register in RegNum's alias set that is suitable for Ty.
getGprForTypeTargetX8632Traits388   static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
389     assert(RegNum.hasValue());
390 
391     if (!isScalarIntegerType(Ty)) {
392       return RegNum;
393     }
394 
395     // [abcd]h registers are not convertible to their ?l, ?x, and e?x versions.
396     switch (RegNum) {
397     default:
398       break;
399     case RegisterSet::Reg_ah:
400     case RegisterSet::Reg_bh:
401     case RegisterSet::Reg_ch:
402     case RegisterSet::Reg_dh:
403       assert(isByteSizedType(Ty));
404       return RegNum;
405     }
406 
407     const RegisterSet::AllRegisters FirstGprForType = getFirstGprForType(Ty);
408 
409     switch (RegNum) {
410     default:
411       llvm::report_fatal_error("Unknown register.");
412 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
413           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
414           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
415   case RegisterSet::val: {                                                     \
416     if (!isGPR)                                                                \
417       return RegisterSet::val;                                                 \
418     assert((is32) || (is16) || (is8) ||                                        \
419            getBaseReg(RegisterSet::val) == RegisterSet::Reg_esp);              \
420     constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize =               \
421         (((is32) || RegisterSet::val == RegisterSet::Reg_esp)                  \
422              ? RegisterSet::Reg_eax                                            \
423              : (((is16) || RegisterSet::val == RegisterSet::Reg_sp)            \
424                     ? RegisterSet::Reg_ax                                      \
425                     : RegisterSet::Reg_al));                                   \
426     const RegNumT NewRegNum =                                                  \
427         RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
428     assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
429            "Error involving " #val);                                           \
430     return NewRegNum;                                                          \
431   }
432       REGX8632_TABLE
433 #undef X
434     }
435   }
436 
437 private:
438   /// SizeOf is used to obtain the size of an initializer list as a constexpr
439   /// expression. This is only needed until our C++ library is updated to
440   /// C++ 14 -- which defines constexpr members to std::initializer_list.
441   class SizeOf {
442     SizeOf(const SizeOf &) = delete;
443     SizeOf &operator=(const SizeOf &) = delete;
444 
445   public:
SizeOfTargetX8632Traits446     constexpr SizeOf() : Size(0) {}
447     template <typename... T>
SizeOfTargetX8632Traits448     explicit constexpr SizeOf(T...) : Size(__length<T...>::value) {}
sizeTargetX8632Traits449     constexpr SizeT size() const { return Size; }
450 
451   private:
452     template <typename T, typename... U> struct __length {
453       static constexpr std::size_t value = 1 + __length<U...>::value;
454     };
455 
456     template <typename T> struct __length<T> {
457       static constexpr std::size_t value = 1;
458     };
459 
460     const std::size_t Size;
461   };
462 
463 public:
464   static void initRegisterSet(
465       const ::Ice::ClFlags & /*Flags*/,
466       std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
467       std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
468     SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
469     SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
470     SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
471     SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
472     SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
473     SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
474     SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
475     SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
476     SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
477     SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
478     SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
479 
480     static constexpr struct {
481       uint16_t Val;
482       unsigned Is64 : 1;
483       unsigned Is32 : 1;
484       unsigned Is16 : 1;
485       unsigned Is8 : 1;
486       unsigned IsXmm : 1;
487       unsigned Is64To8 : 1;
488       unsigned Is32To8 : 1;
489       unsigned Is16To8 : 1;
490       unsigned IsTrunc8Rcvr : 1;
491       unsigned IsAhRcvr : 1;
492 #define NUM_ALIASES_BITS 2
493       SizeT NumAliases : (NUM_ALIASES_BITS + 1);
494       uint16_t Aliases[1 << NUM_ALIASES_BITS];
495 #undef NUM_ALIASES_BITS
496     } X8632RegTable[RegisterSet::Reg_NUM] = {
497 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
498           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
499           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
500   {                                                                            \
501       RegisterSet::val,                                                        \
502       is64,                                                                    \
503       is32,                                                                    \
504       is16,                                                                    \
505       is8,                                                                     \
506       isXmm,                                                                   \
507       is64To8,                                                                 \
508       is32To8,                                                                 \
509       is16To8,                                                                 \
510       isTrunc8Rcvr,                                                            \
511       isAhRcvr,                                                                \
512       (SizeOf aliases).size(),                                                 \
513       aliases,                                                                 \
514   },
515         REGX8632_TABLE
516 #undef X
517     };
518 
519     for (SizeT ii = 0; ii < llvm::array_lengthof(X8632RegTable); ++ii) {
520       const auto &Entry = X8632RegTable[ii];
521       (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
522       (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
523       (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
524       (FloatRegisters)[Entry.Val] = Entry.IsXmm;
525       (VectorRegisters)[Entry.Val] = Entry.IsXmm;
526       (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
527       (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
528       (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
529       (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
530       (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
531       (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
532       for (SizeT J = 0; J < Entry.NumAliases; J++) {
533         SizeT Alias = Entry.Aliases[J];
534         assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
535         (*RegisterAliases)[Entry.Val].set(Alias);
536       }
537       (*RegisterAliases)[Entry.Val].set(Entry.Val);
538     }
539 
540     (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
541     (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
542     (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
543     (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
544     (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
545     (*TypeToRegisterSet)[RC_i64] = InvalidRegisters;
546     (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
547     (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
548     (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
549     (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
550     (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
551     (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
552     (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
553     (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
554     (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
555     (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
556     (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
557     (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
558     (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
559     (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
560   }
561 
562   static SmallBitVector getRegisterSet(const ::Ice::ClFlags & /*Flags*/,
563                                        TargetLowering::RegSetMask Include,
564                                        TargetLowering::RegSetMask Exclude) {
565     SmallBitVector Registers(RegisterSet::Reg_NUM);
566 
567 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
568           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
569           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
570   if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
571     Registers[RegisterSet::val] = true;                                        \
572   if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
573     Registers[RegisterSet::val] = true;                                        \
574   if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
575     Registers[RegisterSet::val] = true;                                        \
576   if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
577     Registers[RegisterSet::val] = true;                                        \
578   if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
579     Registers[RegisterSet::val] = false;                                       \
580   if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
581     Registers[RegisterSet::val] = false;                                       \
582   if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
583     Registers[RegisterSet::val] = false;                                       \
584   if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
585     Registers[RegisterSet::val] = false;
586 
587     REGX8632_TABLE
588 
589 #undef X
590 
591     return Registers;
592   }
593 
594   static RegNumT getRaxOrDie() {
595     llvm::report_fatal_error("no rax in non-64-bit mode.");
596   }
597 
598   static RegNumT getRdxOrDie() {
599     llvm::report_fatal_error("no rdx in non-64-bit mode.");
600   }
601 
602   // x86-32 calling convention:
603   //
604   // * The first four arguments of vector type, regardless of their position
605   // relative to the other arguments in the argument list, are placed in
606   // registers xmm0 - xmm3.
607   //
608   // This intends to match the section "IA-32 Function Calling Convention" of
609   // the document "OS X ABI Function Call Guide" by Apple.
610 
611   /// The maximum number of arguments to pass in XMM registers
612   static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
613   /// The maximum number of arguments to pass in GPR registers
614   static constexpr uint32_t X86_MAX_GPR_ARGS = 0;
615   /// Whether scalar floating point arguments are passed in XMM registers
616   static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = false;
617   /// Get the register for a given argument slot in the XMM registers.
618   static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
619     // TODO(sehr): Change to use the CCArg technique used in ARM32.
620     static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
621                   "Inconsistency between XMM register numbers and ordinals");
622     if (ArgNum >= X86_MAX_XMM_ARGS) {
623       return RegNumT();
624     }
625     return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
626   }
627   /// Get the register for a given argument slot in the GPRs.
628   static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
629     assert(Ty == IceType_i64 || Ty == IceType_i32);
630     (void)Ty;
631     (void)ArgNum;
632     return RegNumT();
633   }
634   // Given the absolute argument position and argument position by type, return
635   // the register index to assign it to.
636   static SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
637     (void)argPos;
638     return argPosByType;
639   };
640 
641   /// The number of bits in a byte
642   static constexpr uint32_t X86_CHAR_BIT = 8;
643   /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
644   /// is used as an argument to std::max(), and the default std::less<T> has an
645   /// operator(T const&, T const&) which requires this member to have an
646   /// address.
647   static const uint32_t X86_STACK_ALIGNMENT_BYTES;
648   /// Size of the return address on the stack
649   static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 4;
650   /// The number of different NOP instructions
651   static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
652 
653   /// \name Limits for unrolling memory intrinsics.
654   /// @{
655   static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
656   static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
657   static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
658   /// @}
659 
660   /// Value is in bytes. Return Value adjusted to the next highest multiple of
661   /// the stack alignment.
662   static uint32_t applyStackAlignment(uint32_t Value) {
663     return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
664   }
665 
666   /// Return the type which the elements of the vector have in the X86
667   /// representation of the vector.
668   static Type getInVectorElementType(Type Ty) {
669     assert(isVectorType(Ty));
670     assert(static_cast<size_t>(Ty) < TableTypeX8632AttributesSize);
671     return TableTypeX8632Attributes[Ty].InVectorElementType;
672   }
673 
674   // Note: The following data structures are defined in
675   // IceTargetLoweringX8632.cpp.
676 
677   /// The following table summarizes the logic for lowering the fcmp
678   /// instruction. There is one table entry for each of the 16 conditions.
679   ///
680   /// The first four columns describe the case when the operands are floating
681   /// point scalar values. A comment in lowerFcmp() describes the lowering
682   /// template. In the most general case, there is a compare followed by two
683   /// conditional branches, because some fcmp conditions don't map to a single
684   /// x86 conditional branch. However, in many cases it is possible to swap the
685   /// operands in the comparison and have a single conditional branch. Since
686   /// it's quite tedious to validate the table by hand, good execution tests are
687   /// helpful.
688   ///
689   /// The last two columns describe the case when the operands are vectors of
690   /// floating point values. For most fcmp conditions, there is a clear mapping
691   /// to a single x86 cmpps instruction variant. Some fcmp conditions require
692   /// special code to handle and these are marked in the table with a
693   /// Cmpps_Invalid predicate.
694   /// {@
695   static const struct TableFcmpType {
696     uint32_t Default;
697     bool SwapScalarOperands;
698     Cond::BrCond C1, C2;
699     bool SwapVectorOperands;
700     Cond::CmppsCond Predicate;
701   } TableFcmp[];
702   static const size_t TableFcmpSize;
703   /// @}
704 
705   /// The following table summarizes the logic for lowering the icmp instruction
706   /// for i32 and narrower types. Each icmp condition has a clear mapping to an
707   /// x86 conditional branch instruction.
708   /// {@
709   static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
710   static const size_t TableIcmp32Size;
711   /// @}
712 
713   /// The following table summarizes the logic for lowering the icmp instruction
714   /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
715   /// conditional branches are needed. For the other conditions, three separate
716   /// conditional branches are needed.
717   /// {@
718   static const struct TableIcmp64Type {
719     Cond::BrCond C1, C2, C3;
720   } TableIcmp64[];
721   static const size_t TableIcmp64Size;
722   /// @}
723 
724   static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
725     assert(static_cast<size_t>(Cond) < TableIcmp32Size);
726     return TableIcmp32[Cond].Mapping;
727   }
728 
729   static const struct TableTypeX8632AttributesType {
730     Type InVectorElementType;
731   } TableTypeX8632Attributes[];
732   static const size_t TableTypeX8632AttributesSize;
733 
734   //----------------------------------------------------------------------------
735   //      __  __   __  ______  ______
736   //    /\ \/\ "-.\ \/\  ___\/\__  _\
737   //    \ \ \ \ \-.  \ \___  \/_/\ \/
738   //     \ \_\ \_\\"\_\/\_____\ \ \_\
739   //      \/_/\/_/ \/_/\/_____/  \/_/
740   //
741   //----------------------------------------------------------------------------
742   using Traits = TargetX8632Traits;
743   using Insts = ::Ice::X8632::Insts<Traits>;
744 
745   using TargetLowering = ::Ice::X8632::TargetX86Base<Traits>;
746   using ConcreteTarget = ::Ice::X8632::TargetX8632;
747   using Assembler = ::Ice::X8632::AssemblerX86Base<Traits>;
748 
749   /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem
750   /// and VariableSplit.
751   class X86Operand : public ::Ice::Operand {
752     X86Operand() = delete;
753     X86Operand(const X86Operand &) = delete;
754     X86Operand &operator=(const X86Operand &) = delete;
755 
756   public:
757     enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
758     using ::Ice::Operand::dump;
759 
760     void dump(const Cfg *, Ostream &Str) const override;
761 
762   protected:
763     X86Operand(OperandKindX8632 Kind, Type Ty)
764         : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
765   };
766 
767   /// X86OperandMem represents the m32 addressing mode, with optional base and
768   /// index registers, a constant offset, and a fixed shift value for the index
769   /// register.
770   class X86OperandMem : public X86Operand {
771     X86OperandMem() = delete;
772     X86OperandMem(const X86OperandMem &) = delete;
773     X86OperandMem &operator=(const X86OperandMem &) = delete;
774 
775   public:
776     enum SegmentRegisters {
777       DefaultSegment = -1,
778 #define X(val, name, prefix) val,
779       SEG_REGX8632_TABLE
780 #undef X
781           SegReg_NUM
782     };
783     static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
784                                  Constant *Offset, Variable *Index = nullptr,
785                                  uint16_t Shift = 0,
786                                  SegmentRegisters SegmentReg = DefaultSegment,
787                                  bool IsRebased = false) {
788       return new (Func->allocate<X86OperandMem>()) X86OperandMem(
789           Func, Ty, Base, Offset, Index, Shift, SegmentReg, IsRebased);
790     }
791     static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
792                                  Constant *Offset, bool IsRebased) {
793       constexpr Variable *NoIndex = nullptr;
794       constexpr uint16_t NoShift = 0;
795       return new (Func->allocate<X86OperandMem>()) X86OperandMem(
796           Func, Ty, Base, Offset, NoIndex, NoShift, DefaultSegment, IsRebased);
797     }
798     Variable *getBase() const { return Base; }
799     Constant *getOffset() const { return Offset; }
800     Variable *getIndex() const { return Index; }
801     uint16_t getShift() const { return Shift; }
802     SegmentRegisters getSegmentRegister() const { return SegmentReg; }
803     void emitSegmentOverride(Assembler *Asm) const;
804     bool getIsRebased() const { return IsRebased; }
805     Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target,
806                          bool LeaAddr = false) const;
807 
808     void emit(const Cfg *Func) const override;
809     using X86Operand::dump;
810     void dump(const Cfg *Func, Ostream &Str) const override;
811 
812     static bool classof(const Operand *Operand) {
813       return Operand->getKind() == static_cast<OperandKind>(kMem);
814     }
815 
816   private:
817     X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
818                   Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg,
819                   bool IsRebased);
820 
821     Variable *const Base;
822     Constant *const Offset;
823     Variable *const Index;
824     const uint16_t Shift;
825     const SegmentRegisters SegmentReg : 16;
826     const bool IsRebased;
827   };
828 
829   /// VariableSplit is a way to treat an f64 memory location as a pair of i32
830   /// locations (Low and High). This is needed for some cases of the Bitcast
831   /// instruction. Since it's not possible for integer registers to access the
832   /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
833   /// the stack and then accesses through the VariableSplit.
834   // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
835   // targets can natively handle these.
836   class VariableSplit : public X86Operand {
837     VariableSplit() = delete;
838     VariableSplit(const VariableSplit &) = delete;
839     VariableSplit &operator=(const VariableSplit &) = delete;
840 
841   public:
842     enum Portion { Low, High };
843     static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
844       return new (Func->allocate<VariableSplit>())
845           VariableSplit(Func, Var, Part);
846     }
847     int32_t getOffset() const { return Part == High ? 4 : 0; }
848 
849     Address toAsmAddress(const Cfg *Func) const;
850     void emit(const Cfg *Func) const override;
851     using X86Operand::dump;
852     void dump(const Cfg *Func, Ostream &Str) const override;
853 
854     static bool classof(const Operand *Operand) {
855       return Operand->getKind() == static_cast<OperandKind>(kSplit);
856     }
857 
858   private:
859     VariableSplit(Cfg *Func, Variable *Var, Portion Part)
860         : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
861       assert(Var->getType() == IceType_f64);
862       Vars = Func->allocateArrayOf<Variable *>(1);
863       Vars[0] = Var;
864       NumVars = 1;
865     }
866 
867     Variable *Var;
868     Portion Part;
869   };
870 
871   // Note: The following data structures are defined in IceInstX8632.cpp.
872 
873   static const struct InstBrAttributesType {
874     Cond::BrCond Opposite;
875     const char *DisplayString;
876     const char *EmitString;
877   } InstBrAttributes[];
878 
879   static const struct InstCmppsAttributesType {
880     const char *EmitString;
881   } InstCmppsAttributes[];
882 
883   static const struct TypeAttributesType {
884     const char *CvtString;      // i (integer), s (single FP), d (double FP)
885     const char *SdSsString;     // ss, sd, or <blank>
886     const char *PdPsString;     // ps, pd, or <blank>
887     const char *SpSdString;     // ss, sd, ps, pd, or <blank>
888     const char *IntegralString; // b, w, d, or <blank>
889     const char *UnpackString;   // bw, wd, dq, or <blank>
890     const char *PackString;     // wb, dw, or <blank>
891     const char *WidthString;    // b, w, l, q, or <blank>
892     const char *FldString;      // s, l, or <blank>
893   } TypeAttributes[];
894 
895   static const char *InstSegmentRegNames[];
896 
897   static uint8_t InstSegmentPrefixes[];
898 };
899 
900 using Traits = ::Ice::X8632::TargetX8632Traits;
901 } // end of namespace X8632
902 
903 } // end of namespace Ice
904 
905 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
906