IceTargetLoweringX8664Traits.h revision d1bd1d330c8eb8116811ad4dc01fe636b80b86cb
12fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=//
22fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//
32fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//                        The Subzero Code Generator
42fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//
52fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// This file is distributed under the University of Illinois Open Source
62fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto// License. See LICENSE.TXT for details.
72fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//
82fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//===----------------------------------------------------------------------===//
92fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto///
102fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the X8664 Target Lowering Traits.
122fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto///
132fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto//===----------------------------------------------------------------------===//
142fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
152fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
162fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#define SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
172fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
182fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceAssembler.h"
192fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceConditionCodesX8664.h"
202fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceDefs.h"
212fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceInst.h"
222fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceInstX8664.def"
232fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceOperand.h"
242fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceRegistersX8664.h"
252fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#include "IceTargetLowering.h"
26453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#include "IceTargetLoweringX8664.def"
27c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth#include "IceTargetLoweringX86RegClass.h"
282fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
29bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto#include <array>
304a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#include <initializer_list>
31bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
322fea26cae5a6b140c67e18aec3dcf645a16694d5John Portonamespace Ice {
332fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
342fea26cae5a6b140c67e18aec3dcf645a16694d5John Portonamespace X8664 {
354a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing namespace ::Ice::X86;
362fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
374a56686b5b56db6803f90ad53514bf2fa190d9f7John Portotemplate <class TraitsType> class AssemblerX86Base;
384a56686b5b56db6803f90ad53514bf2fa190d9f7John Portotemplate <class TraitsType> struct Insts;
394a56686b5b56db6803f90ad53514bf2fa190d9f7John Portotemplate <class TraitsType> class TargetX86Base;
402fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
414a56686b5b56db6803f90ad53514bf2fa190d9f7John Portoclass TargetX8664;
422fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
434a56686b5b56db6803f90ad53514bf2fa190d9f7John Portostruct TargetX8664Traits {
442fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //----------------------------------------------------------------------------
452fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //     ______  ______  __    __
462fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //    /\  __ \/\  ___\/\ "-./  \
472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //    \ \  __ \ \___  \ \ \-./\ \
482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //     \ \_\ \_\/\_____\ \_\ \ \_\
492fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //      \/_/\/_/\/_____/\/_/  \/_/
502fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //
512fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //----------------------------------------------------------------------------
524a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  static constexpr ::Ice::Assembler::AssemblerKind AsmKind =
534a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto      ::Ice::Assembler::Asm_X8632;
544a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto
552fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool Is64Bit = true;
562fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool HasPopa = false;
572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool HasPusha = false;
582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool UsesX87 = false;
592fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr ::Ice::RegX8664::GPRRegister Last8BitGPR =
602fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      ::Ice::RegX8664::GPRRegister::Encoded_Reg_r15d;
612fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
622fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
632fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
642fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  using GPRRegister = ::Ice::RegX8664::GPRRegister;
652fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  using ByteRegister = ::Ice::RegX8664::ByteRegister;
665bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  using XmmRegister = ::Ice::RegX8664::XmmRegister;
672fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
682fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  using Cond = ::Ice::CondX8664;
692fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
702fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  using RegisterSet = ::Ice::RegX8664;
710c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr SizeT StackPtr = RegX8664::Reg_rsp;
720c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr SizeT FramePtr = RegX8664::Reg_rbp;
730c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr GPRRegister Encoded_Reg_Accumulator =
740c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr      RegX8664::Encoded_Reg_eax;
750c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx;
768ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32;
778ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32;
788ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_Gotoff = llvm::ELF::R_X86_64_GOTOFF64;
798ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  static constexpr FixupKind FK_GotPC = llvm::ELF::R_X86_64_GOTPC32;
802fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
812fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  class Operand {
822fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  public:
832fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    enum RexBits {
842fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      RexNone = 0x00,
852fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      RexBase = 0x40,
862fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      RexW = RexBase | (1 << 3),
872fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      RexR = RexBase | (1 << 2),
882fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      RexX = RexBase | (1 << 1),
892fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      RexB = RexBase | (1 << 0),
902fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    };
912fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
92d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto  protected:
93d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    // Needed by subclass Address.
94d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Operand() = default;
952fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
96d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto  public:
97d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Operand(const Operand &) = default;
98d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Operand(Operand &&) = default;
99d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Operand &operator=(const Operand &) = default;
100d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Operand &operator=(Operand &&) = default;
1012fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1022fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
1032fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1042fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    uint8_t rexX() const { return (rex_ & RexX) != RexX ? RexNone : RexX; }
1052fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    uint8_t rexB() const { return (rex_ & RexB) != RexB ? RexNone : RexB; }
1062fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1072fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    GPRRegister rm() const {
1082fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
1092fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto                                      (encoding_at(0) & 7));
1102fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1112fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1122fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    ScaleFactor scale() const {
1132fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
1142fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1152fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1162fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    GPRRegister index() const {
1172fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      return static_cast<GPRRegister>((rexX() != 0 ? 0x08 : 0) |
1182fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto                                      ((encoding_at(1) >> 3) & 7));
1192fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1202fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1212fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    GPRRegister base() const {
1222fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
1232fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto                                      (encoding_at(1) & 7));
1242fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1252fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1262fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    int8_t disp8() const {
1272fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      assert(length_ >= 2);
1282fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      return static_cast<int8_t>(encoding_[length_ - 1]);
1292fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1302fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1312fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    AssemblerFixup *fixup() const { return fixup_; }
1322fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1332fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  protected:
1342fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    void SetModRM(int mod, GPRRegister rm) {
1352fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      assert((mod & ~3) == 0);
1362fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      encoding_[0] = (mod << 6) | (rm & 0x07);
1372fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      rex_ = (rm & 0x08) ? RexB : RexNone;
1382fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      length_ = 1;
1392fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1402fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1412fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
1422fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      assert(length_ == 1);
1432fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      assert((scale & ~3) == 0);
1442fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      encoding_[1] = (scale << 6) | ((index & 0x07) << 3) | (base & 0x07);
1452fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      rex_ =
1462fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto          ((base & 0x08) ? RexB : RexNone) | ((index & 0x08) ? RexX : RexNone);
1472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      length_ = 2;
1482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1492fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1502fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    void SetDisp8(int8_t disp) {
1512fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      assert(length_ == 1 || length_ == 2);
1522fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      encoding_[length_++] = static_cast<uint8_t>(disp);
1532fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1542fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1552fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    void SetDisp32(int32_t disp) {
1562fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      assert(length_ == 1 || length_ == 2);
1572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      intptr_t disp_size = sizeof(disp);
1582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      memmove(&encoding_[length_], &disp, disp_size);
1592fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      length_ += disp_size;
1602fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1612fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1622fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
1632fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1642fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  private:
165d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    AssemblerFixup *fixup_ = nullptr;
1662fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    uint8_t rex_ = 0;
1672fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    uint8_t encoding_[6];
168d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    uint8_t length_ = 0;
1692fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1702fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
1712fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1722fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    /// Get the operand encoding byte at the given index.
1732fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    uint8_t encoding_at(intptr_t index) const {
1742fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      assert(index >= 0 && index < length_);
1752fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      return encoding_[index];
1762fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1772fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1782fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    /// Returns whether or not this operand is really the given register in
1792fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    /// disguise. Used from the assembler to generate better encodings.
1802fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    bool IsRegister(GPRRegister reg) const {
1812fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      return ((encoding_[0] & 0xF8) ==
1822fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto              0xC0) // Addressing mode is register only.
1832fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto             &&
1842fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto             (rm() == reg); // Register codes match.
1852fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
1862fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1874a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto    friend class AssemblerX86Base<TargetX8664Traits>;
1882fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  };
1892fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1902fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  class Address : public Operand {
191d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Address() = default;
1922fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
1932fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  public:
194d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Address(const Address &) = default;
195d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Address(Address &&) = default;
196d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Address &operator=(const Address &) = default;
197d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    Address &operator=(Address &&) = default;
1982fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
199aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
200aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup == nullptr && Disp == 0 &&
201d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto          (Base & 7) != RegX8664::Encoded_Reg_rbp) {
202aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetModRM(0, Base);
203d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto        if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
204d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto          SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
205aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
206aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetModRM(1, Base);
207d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto        if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
208d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto          SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
209aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp8(Disp);
2102fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      } else {
211aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetModRM(2, Base);
212d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto        if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
213d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto          SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
214aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp32(Disp);
215aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        if (Fixup)
216aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr          SetFixup(Fixup);
2172fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      }
2182fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
2192fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
220aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
221aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr            AssemblerFixup *Fixup) {
222d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
223d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      SetModRM(0, RegX8664::Encoded_Reg_rsp);
224d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      SetSIB(Scale, Index, RegX8664::Encoded_Reg_rbp);
225aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      SetDisp32(Disp);
226aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup)
227aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetFixup(Fixup);
2282fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
2292fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
230aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
231aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr            int32_t Disp, AssemblerFixup *Fixup) {
232d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
233aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup == nullptr && Disp == 0 &&
234d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto          (Base & 7) != RegX8664::Encoded_Reg_rbp) {
235d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto        SetModRM(0, RegX8664::Encoded_Reg_rsp);
236aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetSIB(Scale, Index, Base);
237aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
238d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto        SetModRM(1, RegX8664::Encoded_Reg_rsp);
239aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetSIB(Scale, Index, Base);
240aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp8(Disp);
2412fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      } else {
242d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto        SetModRM(2, RegX8664::Encoded_Reg_rsp);
243aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetSIB(Scale, Index, Base);
244aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        SetDisp32(Disp);
245aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr        if (Fixup)
246aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr          SetFixup(Fixup);
2472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      }
2482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
2492fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
250aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr    /// Generate a RIP-relative address expression on x86-64.
251d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    static Address RipRelative(RelocOffsetT Offset, AssemblerFixup *Fixup) {
252d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      assert(Fixup != nullptr);
253d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      assert(Fixup->kind() == FK_PcRel);
254d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      Address NewAddress;
255d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rbp);
2563c275ce1e832ba9ccfb730c4235db786cf080465John Porto
2572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      // Use the Offset in the displacement for now. If we decide to process
2582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      // fixups later, we'll need to patch up the emitted displacement.
259d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      NewAddress.SetDisp32(Offset);
260aa0b1a176f6c3306be3e95374d72e735bab2bbabDavid Sehr      if (Fixup)
261d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto        NewAddress.SetFixup(Fixup);
262d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto
263d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      return NewAddress;
264d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    }
265d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto
266d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    /// Generate an absolute address.
267d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto    static Address Absolute(RelocOffsetT Addr) {
268d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      Address NewAddress;
269d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rsp);
270d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      static constexpr ScaleFactor NoScale = TIMES_1;
271d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      NewAddress.SetSIB(NoScale, RegX8664::Encoded_Reg_rsp,
272d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto                        RegX8664::Encoded_Reg_rbp);
273d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      NewAddress.SetDisp32(Addr);
274d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      return NewAddress;
2752fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
2762fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
2772fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
2782fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      // TODO(jpp): ???
2798ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth      AssemblerFixup *Fixup = Asm->createFixup(FK_Abs, Imm);
2801d235425dab1f3dd059973fc53f1b1d5879469e3John Porto      const RelocOffsetT Offset = 4;
281d1bd1d330c8eb8116811ad4dc01fe636b80b86cbJohn Porto      return Address::RipRelative(Offset, Fixup);
2822fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto    }
2832fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  };
2842fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
2852fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //----------------------------------------------------------------------------
2862fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //     __      ______  __     __  ______  ______  __  __   __  ______
2872fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
2882fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
2892fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //     \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
2902fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //      \/_____/\/_____/\/_/   \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
2912fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //
2922fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  //----------------------------------------------------------------------------
293453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  enum InstructionSet {
294453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Begin,
295453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // SSE2 is the PNaCl baseline instruction set.
296453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SSE2 = Begin,
297453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SSE4_1,
298453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    End
299453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
300453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
301453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const char *TargetName;
3021d235425dab1f3dd059973fc53f1b1d5879469e3John Porto  static constexpr Type WordType = IceType_i64;
303453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
3045bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  static IceString getRegName(int32_t RegNum) {
3054a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const char *const RegNames[RegisterSet::Reg_NUM] = {
3065bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
30756958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
30856958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3095bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  name,
3105bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3115bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3125bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3135bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum >= 0);
314453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(RegNum < RegisterSet::Reg_NUM);
3155bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return RegNames[RegNum];
3165bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3175bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
3185bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  static GPRRegister getEncodedGPR(int32_t RegNum) {
3194a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
3205bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
32156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
32256958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3235bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
324453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        REGX8664_TABLE
325453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
326453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    };
3275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum >= 0);
3285bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum < RegisterSet::Reg_NUM);
3295bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
3305bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return GPRRegs[RegNum];
3315bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
332453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
3335bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  static ByteRegister getEncodedByteReg(int32_t RegNum) {
3344a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
3355bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
33656958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
33756958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3385bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
3395bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3405bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3415bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3425bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum >= 0);
3435bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum < RegisterSet::Reg_NUM);
3445bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
3455bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return ByteRegs[RegNum];
346453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
347453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
3485bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  static XmmRegister getEncodedXmm(int32_t RegNum) {
3494a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
3505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
35156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
35256958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
3545bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3555bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3565bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3575bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum >= 0);
3585bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum < RegisterSet::Reg_NUM);
3595bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
3605bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return XmmRegs[RegNum];
3615bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3625bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
3635bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  static uint32_t getEncoding(int32_t RegNum) {
3644a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
3655bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
36656958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
36756958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3685bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  encode,
3695bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3705bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3715bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3725bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum >= 0);
3735bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum < RegisterSet::Reg_NUM);
3745bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return Encoding[RegNum];
3755bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3765bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
3775bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  static inline int32_t getBaseReg(int32_t RegNum) {
3784a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const int32_t BaseRegs[RegisterSet::Reg_NUM] = {
3795bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
38056958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
38156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
38256958cb33d3c1d045f2844408d825442d523f59fJohn Porto  encode,
3835bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3845bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3855bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3865bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum >= 0);
3875bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(RegNum < RegisterSet::Reg_NUM);
3885bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return BaseRegs[RegNum];
3895bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3905bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
391008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portoprivate:
392008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  static int32_t getFirstGprForType(Type Ty) {
393008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    switch (Ty) {
394008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    default:
395008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      llvm_unreachable("Invalid type for GPR.");
396008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i1:
397008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i8:
398008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_al;
399008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i16:
400008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_ax;
401008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i32:
402008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_eax;
403008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i64:
404008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_rax;
405008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
406008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  }
407008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
408008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portopublic:
409008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  static int32_t getGprForType(Type Ty, int32_t RegNum) {
410008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(RegNum != Variable::NoRegister);
411008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
412008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    if (!isScalarIntegerType(Ty)) {
413008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegNum;
414008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
415008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
416008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 ||
417008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto           Ty == IceType_i32 || Ty == IceType_i64);
418008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
419008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    if (RegNum == RegisterSet::Reg_ah) {
420008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      assert(Ty == IceType_i8);
421008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegNum;
422008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
423008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
424008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(RegNum != RegisterSet::Reg_bh);
425008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(RegNum != RegisterSet::Reg_ch);
426008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(RegNum != RegisterSet::Reg_dh);
427008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
428008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    const int32_t FirstGprForType = getFirstGprForType(Ty);
429008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
430008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    switch (RegNum) {
431008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    default:
432008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      llvm::report_fatal_error("Unknown register.");
433008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
43456958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
43556958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
436008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  case RegisterSet::val: {                                                     \
43756958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (!isGPR)                                                                \
43856958cb33d3c1d045f2844408d825442d523f59fJohn Porto      return RegisterSet::val;                                                 \
439008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert((is64) || (is32) || (is16) || (is8) ||                              \
44056958cb33d3c1d045f2844408d825442d523f59fJohn Porto           getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp ||             \
44156958cb33d3c1d045f2844408d825442d523f59fJohn Porto           getBaseReg(RegisterSet::val) == RegisterSet::Reg_rbp);              \
442008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    constexpr int32_t FirstGprWithRegNumSize =                                 \
44356958cb33d3c1d045f2844408d825442d523f59fJohn Porto        ((is64) || RegisterSet::val == RegisterSet::Reg_rsp ||                 \
44456958cb33d3c1d045f2844408d825442d523f59fJohn Porto         RegisterSet::val == RegisterSet::Reg_rbp)                             \
445008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto            ? RegisterSet::Reg_rax                                             \
44656958cb33d3c1d045f2844408d825442d523f59fJohn Porto            : (((is32) || RegisterSet::val == RegisterSet::Reg_esp ||          \
44756958cb33d3c1d045f2844408d825442d523f59fJohn Porto                RegisterSet::val == RegisterSet::Reg_ebp)                      \
448008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto                   ? RegisterSet::Reg_eax                                      \
44956958cb33d3c1d045f2844408d825442d523f59fJohn Porto                   : (((is16) || RegisterSet::val == RegisterSet::Reg_sp ||    \
45056958cb33d3c1d045f2844408d825442d523f59fJohn Porto                       RegisterSet::val == RegisterSet::Reg_bp)                \
451008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto                          ? RegisterSet::Reg_ax                                \
452008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto                          : RegisterSet::Reg_al));                             \
453008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    const int32_t NewRegNum =                                                  \
454008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto        RegNum - FirstGprWithRegNumSize + FirstGprForType;                     \
455008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
456008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto           "Error involving " #val);                                           \
457008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    return NewRegNum;                                                          \
458008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  }
459008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      REGX8664_TABLE
460008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#undef X
461008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
462008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  }
4635bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
4644a308cedda6bfe381dc9506f3508c4547a06275fJohn Portoprivate:
4654a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// SizeOf is used to obtain the size of an initializer list as a constexpr
4664a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// expression. This is only needed until our C++ library is updated to
4674a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// C++ 14 -- which defines constexpr members to std::initializer_list.
4684a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  class SizeOf {
4694a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    SizeOf(const SizeOf &) = delete;
4704a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    SizeOf &operator=(const SizeOf &) = delete;
4714a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4724a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  public:
4734a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    constexpr SizeOf() : Size(0) {}
4744a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    template <typename... T>
4754a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    explicit constexpr SizeOf(T...)
47656958cb33d3c1d045f2844408d825442d523f59fJohn Porto        : Size(length<T...>::value) {}
4774a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    constexpr SizeT size() const { return Size; }
4784a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4794a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  private:
48056958cb33d3c1d045f2844408d825442d523f59fJohn Porto    template <typename T, typename... U> struct length {
48156958cb33d3c1d045f2844408d825442d523f59fJohn Porto      static constexpr std::size_t value = 1 + length<U...>::value;
4824a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
4834a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
48456958cb33d3c1d045f2844408d825442d523f59fJohn Porto    template <typename T> struct length<T> {
4854a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      static constexpr std::size_t value = 1;
4864a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
4874a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4884a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    const std::size_t Size;
4894a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  };
4904a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4914a308cedda6bfe381dc9506f3508c4547a06275fJohn Portopublic:
492bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  static void initRegisterSet(
49356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      const ::Ice::ClFlags &Flags,
494c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth      std::array<llvm::SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
49529d15fd619f1d46f8e0c3d22932b9931c4b81367Jim Stichnoth      std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
4965bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    llvm::SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM);
4975bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    llvm::SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
4985bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    llvm::SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
499bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
500bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
501bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
502c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    llvm::SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
503c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    llvm::SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
504c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    llvm::SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
505c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    llvm::SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
506c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    llvm::SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
507bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
508bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
5094a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static constexpr struct {
5104a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      uint16_t Val;
51156958cb33d3c1d045f2844408d825442d523f59fJohn Porto      unsigned IsReservedWhenSandboxing : 1;
512caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is64 : 1;
513caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is32 : 1;
514caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is16 : 1;
515caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is8 : 1;
516caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsXmm : 1;
517caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is64To8 : 1;
518caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is32To8 : 1;
519caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is16To8 : 1;
520caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsTrunc8Rcvr : 1;
521caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsAhRcvr : 1;
5224a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#define NUM_ALIASES_BITS 2
5234a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      SizeT NumAliases : (NUM_ALIASES_BITS + 1);
5244a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      uint16_t Aliases[1 << NUM_ALIASES_BITS];
5254a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#undef NUM_ALIASES_BITS
5264a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    } X8664RegTable[RegisterSet::Reg_NUM] = {
5275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
52856958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
52956958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
5304a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  {                                                                            \
53156958cb33d3c1d045f2844408d825442d523f59fJohn Porto    RegisterSet::val, sboxres, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
53229d15fd619f1d46f8e0c3d22932b9931c4b81367Jim Stichnoth        is16To8, isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases,     \
5335bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }                                                                            \
5344a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  ,
5354a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto        REGX8664_TABLE
536453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
5374a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
5384a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
53956958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const bool NeedSandboxing = Flags.getUseSandboxing();
5404a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) {
5414a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      const auto &Entry = X8664RegTable[ii];
54256958cb33d3c1d045f2844408d825442d523f59fJohn Porto      // Even though the register is disabled for register allocation, it might
54356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      // still be used by the Target Lowering (e.g., base pointer), so the
54456958cb33d3c1d045f2844408d825442d523f59fJohn Porto      // register alias table still needs to be defined.
54556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
54656958cb33d3c1d045f2844408d825442d523f59fJohn Porto      for (int J = 0; J < Entry.NumAliases; ++J) {
54756958cb33d3c1d045f2844408d825442d523f59fJohn Porto        SizeT Alias = Entry.Aliases[J];
54856958cb33d3c1d045f2844408d825442d523f59fJohn Porto        assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
54956958cb33d3c1d045f2844408d825442d523f59fJohn Porto        (*RegisterAliases)[Entry.Val].set(Alias);
55056958cb33d3c1d045f2844408d825442d523f59fJohn Porto      }
55156958cb33d3c1d045f2844408d825442d523f59fJohn Porto
55256958cb33d3c1d045f2844408d825442d523f59fJohn Porto      (*RegisterAliases)[Entry.Val].set(Entry.Val);
55356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      const bool DisabledRegister =
55456958cb33d3c1d045f2844408d825442d523f59fJohn Porto          NeedSandboxing && Entry.IsReservedWhenSandboxing;
55556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      if (DisabledRegister) {
55656958cb33d3c1d045f2844408d825442d523f59fJohn Porto        continue;
55756958cb33d3c1d045f2844408d825442d523f59fJohn Porto      }
5584a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI64)[Entry.Val] = Entry.Is64;
5594a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
5604a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
5614a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
5624a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (FloatRegisters)[Entry.Val] = Entry.IsXmm;
5634a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (VectorRegisters)[Entry.Val] = Entry.IsXmm;
5644a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
5654a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
5664a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
5674a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
5684a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
5694a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    }
570bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
571c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
572c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
573c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
574c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
575c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
576c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64;
577c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
578c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
579c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
580c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
581c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
582c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
583c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
584c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
585c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
586c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
587c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
588c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
589c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
590c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
591453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
592453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
593453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static llvm::SmallBitVector
59456958cb33d3c1d045f2844408d825442d523f59fJohn Porto  getRegisterSet(const ::Ice::ClFlags &Flags,
59556958cb33d3c1d045f2844408d825442d523f59fJohn Porto                 TargetLowering::RegSetMask Include,
596453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto                 TargetLowering::RegSetMask Exclude) {
597453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    llvm::SmallBitVector Registers(RegisterSet::Reg_NUM);
598453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
59956958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const bool NeedSandboxing = Flags.getUseSandboxing();
6005bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
60156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
60256958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
60356958cb33d3c1d045f2844408d825442d523f59fJohn Porto  if (!NeedSandboxing || !(sboxres)) {                                         \
60456958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))       \
60556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
60656958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))     \
60756958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
60856958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))    \
60956958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
61056958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))    \
61156958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
61256958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))       \
61356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
61456958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))     \
61556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
61656958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))    \
61756958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
61856958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))    \
61956958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
62056958cb33d3c1d045f2844408d825442d523f59fJohn Porto  }
621453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
622453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    REGX8664_TABLE
623453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
624453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
625453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
626453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    return Registers;
627453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
628453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
629453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static void
630453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
631453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto                                llvm::SmallVectorImpl<int32_t> &Permutation,
632aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                                const llvm::SmallBitVector &ExcludeRegisters,
633aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                                uint64_t Salt) {
634453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // TODO(stichnot): Declaring Permutation this way loses type/size
63557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // information. Fix this in conjunction with the caller-side TODO.
636453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(Permutation.size() >= RegisterSet::Reg_NUM);
637453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // Expected upper bound on the number of registers in a single equivalence
63857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // class.  For x86-64, this would comprise the 16 XMM registers. This is
639453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // for performance, not correctness.
640453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static const unsigned MaxEquivalenceClassSize = 8;
6418072bae156fa62e51e02925997992c4908a2682fAndrew Scull    using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>;
6428072bae156fa62e51e02925997992c4908a2682fAndrew Scull    using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
643453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    EquivalenceClassMap EquivalenceClasses;
644453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SizeT NumShuffled = 0, NumPreserved = 0;
645453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
646453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// Build up the equivalence classes of registers by looking at the register
647453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// properties as well as whether the registers should be explicitly excluded
648453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// from shuffling.
6495bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
65056958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
65156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
652453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  if (ExcludeRegisters[RegisterSet::val]) {                                    \
653453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /* val stays the same in the resulting permutation. */                     \
654453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Permutation[RegisterSet::val] = RegisterSet::val;                          \
655453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    ++NumPreserved;                                                            \
656453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } else {                                                                     \
6575bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    uint32_t AttrKey = 0;                                                      \
6585bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    uint32_t Index = 0;                                                        \
6595bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    /* Combine relevant attributes into an equivalence class key. */           \
6605bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (scratch << (AttrKey++));                                         \
6615bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (preserved << (AttrKey++));                                       \
6625bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is8 << (AttrKey++));                                             \
6635bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is16 << (AttrKey++));                                            \
6645bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is32 << (AttrKey++));                                            \
6655bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is64 << (AttrKey++));                                            \
6665bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (isXmm << (AttrKey++));                                           \
667c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is16To8 << (AttrKey++));                                         \
668c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is32To8 << (AttrKey++));                                         \
669c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is64To8 << (AttrKey++));                                         \
670c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (isTrunc8Rcvr << (AttrKey++));                                    \
671453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /* val is assigned to an equivalence class based on its properties. */     \
672453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    EquivalenceClasses[Index].push_back(RegisterSet::val);                     \
673453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
674453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    REGX8664_TABLE
675453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
676453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
677aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    // Create a random number generator for regalloc randomization.
678aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
679aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                              RPE_RegAllocRandomization, Salt);
680aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    RandomNumberGeneratorWrapper RNGW(RNG);
681453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
682453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // Shuffle the resulting equivalence classes.
683453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    for (auto I : EquivalenceClasses) {
684453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      const RegisterList &List = I.second;
685453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      RegisterList Shuffled(List);
686aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu      RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
687453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
688453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        Permutation[List[SI]] = Shuffled[SI];
689453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        ++NumShuffled;
690453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      }
691453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
692453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
693453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM);
694453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
695453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    if (Func->isVerbose(IceV_Random)) {
696453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      OstreamLocker L(Func->getContext());
697453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Ostream &Str = Func->getContext()->getStrDump();
698453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Str << "Register equivalence classes:\n";
699453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      for (auto I : EquivalenceClasses) {
700453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        Str << "{";
701453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        const RegisterList &List = I.second;
702453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        bool First = true;
703453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        for (int32_t Register : List) {
704453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto          if (!First)
705453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto            Str << " ";
706453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto          First = false;
7075bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          Str << getRegName(Register);
708453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        }
709453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        Str << "}\n";
710453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      }
711453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
712453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
713453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
7143c275ce1e832ba9ccfb730c4235db786cf080465John Porto  static int32_t getRaxOrDie() { return RegisterSet::Reg_rax; }
7153c275ce1e832ba9ccfb730c4235db786cf080465John Porto
7163c275ce1e832ba9ccfb730c4235db786cf080465John Porto  static int32_t getRdxOrDie() { return RegisterSet::Reg_rdx; }
7173c275ce1e832ba9ccfb730c4235db786cf080465John Porto
7180c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // x86-64 calling convention:
7190c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
7200c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // * The first eight arguments of vector/fp type, regardless of their
7210c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // position relative to the other arguments in the argument list, are placed
7220c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // in registers %xmm0 - %xmm7.
7230c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
7240c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // * The first six arguments of integer types, regardless of their position
7250c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // relative to the other arguments in the argument list, are placed in
7260c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9.
7270c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
7280c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // This intends to match the section "Function Calling Sequence" of the
7290c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // document "System V Application Binary Interface."
7300c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr
731453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The maximum number of arguments to pass in XMM registers
7320c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_MAX_XMM_ARGS = 8;
733e0d9afa80ee55711d25fae87e50d11685d1ad6d7John Porto  /// The maximum number of arguments to pass in GPR registers
7340c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_MAX_GPR_ARGS = 6;
7350c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  /// Whether scalar floating point arguments are passed in XMM registers
7360c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true;
7370c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  /// Get the register for a given argument slot in the XMM registers.
7380c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) {
7390c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    // TODO(sehr): Change to use the CCArg technique used in ARM32.
7400c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
7410c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr                  "Inconsistency between XMM register numbers and ordinals");
7420c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    if (ArgNum >= X86_MAX_XMM_ARGS) {
7430c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr      return Variable::NoRegister;
7440c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    }
7450c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum);
7460c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  }
7470c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  /// Get the register for a given argument slot in the GPRs.
7480c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
7490c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    if (ArgNum >= X86_MAX_GPR_ARGS) {
7500c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr      return Variable::NoRegister;
7510c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    }
7520c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    static const RegisterSet::AllRegisters GprForArgNum[] = {
7530c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr        RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
7540c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr        RegisterSet::Reg_rcx, RegisterSet::Reg_r8,  RegisterSet::Reg_r9,
7550c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    };
7560c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS,
7570c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr                  "Mismatch between MAX_GPR_ARGS and GprForArgNum.");
7580c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    assert(Ty == IceType_i64 || Ty == IceType_i32);
7590c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    return static_cast<int32_t>(getGprForType(Ty, GprForArgNum[ArgNum]));
7600c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  }
7610c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr
762453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The number of bits in a byte
7630c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_CHAR_BIT = 8;
764453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it
765453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// is used as an argument to std::max(), and the default std::less<T> has an
766453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// operator(T const&, T const&) which requires this member to have an
767453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// address.
768453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const uint32_t X86_STACK_ALIGNMENT_BYTES;
769453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Size of the return address on the stack
7700c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8;
771453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The number of different NOP instructions
7720c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
773453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
774cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// \name Limits for unrolling memory intrinsics.
775cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @{
776cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
777cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
778cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMSET_UNROLL_LIMIT = 16;
779cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @}
780cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull
78157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Value is in bytes. Return Value adjusted to the next highest multiple of
78257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// the stack alignment.
783453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static uint32_t applyStackAlignment(uint32_t Value) {
784453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
785453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
786453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
787453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Return the type which the elements of the vector have in the X86
788453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// representation of the vector.
789453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static Type getInVectorElementType(Type Ty) {
790453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(isVectorType(Ty));
791453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    size_t Index = static_cast<size_t>(Ty);
792453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    (void)Index;
793453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(Index < TableTypeX8664AttributesSize);
794453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    return TableTypeX8664Attributes[Ty].InVectorElementType;
795453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
796453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
797453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // Note: The following data structures are defined in
798453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // IceTargetLoweringX8664.cpp.
799453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
800453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The following table summarizes the logic for lowering the fcmp
801453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// instruction. There is one table entry for each of the 16 conditions.
802453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  ///
803453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The first four columns describe the case when the operands are floating
80457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// point scalar values. A comment in lowerFcmp() describes the lowering
80557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// template. In the most general case, there is a compare followed by two
806453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// conditional branches, because some fcmp conditions don't map to a single
80757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// x86 conditional branch. However, in many cases it is possible to swap the
80857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands in the comparison and have a single conditional branch. Since
809453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// it's quite tedious to validate the table by hand, good execution tests are
810453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// helpful.
811453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  ///
812453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The last two columns describe the case when the operands are vectors of
81357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// floating point values. For most fcmp conditions, there is a clear mapping
81457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to a single x86 cmpps instruction variant. Some fcmp conditions require
815453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// special code to handle and these are marked in the table with a
816453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Cmpps_Invalid predicate.
817453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// {@
818453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableFcmpType {
819453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    uint32_t Default;
820453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool SwapScalarOperands;
821453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::BrCond C1, C2;
822453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool SwapVectorOperands;
823453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::CmppsCond Predicate;
824453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TableFcmp[];
825453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableFcmpSize;
826453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// @}
827453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
828453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The following table summarizes the logic for lowering the icmp instruction
82957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// for i32 and narrower types. Each icmp condition has a clear mapping to an
830453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// x86 conditional branch instruction.
831453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// {@
832453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
833453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableIcmp32Size;
834453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// @}
835453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
836453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The following table summarizes the logic for lowering the icmp instruction
83757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
83857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// conditional branches are needed. For the other conditions, three separate
839453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// conditional branches are needed.
840453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// {@
841453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableIcmp64Type {
842453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::BrCond C1, C2, C3;
843453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TableIcmp64[];
844453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableIcmp64Size;
845453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// @}
846453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
847453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
848453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    size_t Index = static_cast<size_t>(Cond);
849453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(Index < TableIcmp32Size);
850453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    return TableIcmp32[Index].Mapping;
851453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
852453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
853453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableTypeX8664AttributesType {
854453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Type InVectorElementType;
855453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TableTypeX8664Attributes[];
856453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableTypeX8664AttributesSize;
857453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
858453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //----------------------------------------------------------------------------
859453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //      __  __   __  ______  ______
860453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //    /\ \/\ "-.\ \/\  ___\/\__  _\
861453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //    \ \ \ \ \-.  \ \___  \/_/\ \/
862453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //     \ \_\ \_\\"\_\/\_____\ \ \_\
863453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //      \/_/\/_/ \/_/\/_____/  \/_/
864453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //
865453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //----------------------------------------------------------------------------
8664a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Traits = TargetX8664Traits;
8674a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Insts = ::Ice::X8664::Insts<Traits>;
868453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
8694a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using TargetLowering = ::Ice::X8664::TargetX86Base<Traits>;
8704a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using ConcreteTarget = ::Ice::X8664::TargetX8664;
8714a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Assembler = ::Ice::X8664::AssemblerX86Base<Traits>;
872453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
87357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem
87457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and VariableSplit.
875453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  class X86Operand : public ::Ice::Operand {
876453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand() = delete;
877453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand(const X86Operand &) = delete;
878453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand &operator=(const X86Operand &) = delete;
879453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
880453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  public:
881453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    enum OperandKindX8664 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
882453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    using ::Ice::Operand::dump;
883453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
884453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void dump(const Cfg *, Ostream &Str) const override;
885453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
886453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  protected:
887453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand(OperandKindX8664 Kind, Type Ty)
888453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
889453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
890453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
891453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// X86OperandMem represents the m64 addressing mode, with optional base and
892453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// index registers, a constant offset, and a fixed shift value for the index
893453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// register.
894453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  class X86OperandMem : public X86Operand {
895453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem() = delete;
896453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem(const X86OperandMem &) = delete;
897453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem &operator=(const X86OperandMem &) = delete;
898453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
899453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  public:
900453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM };
901453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static X86OperandMem *
902453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
903453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto           Variable *Index = nullptr, uint16_t Shift = 0,
9048ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth           SegmentRegisters SegmentRegister = DefaultSegment,
90556958cb33d3c1d045f2844408d825442d523f59fJohn Porto           bool IsRebased = false) {
906453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      assert(SegmentRegister == DefaultSegment);
907453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      (void)SegmentRegister;
908453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return new (Func->allocate<X86OperandMem>())
90956958cb33d3c1d045f2844408d825442d523f59fJohn Porto          X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsRebased);
91056958cb33d3c1d045f2844408d825442d523f59fJohn Porto    }
91156958cb33d3c1d045f2844408d825442d523f59fJohn Porto    static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
91256958cb33d3c1d045f2844408d825442d523f59fJohn Porto                                 Constant *Offset, bool IsRebased) {
91356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      constexpr Variable *NoIndex = nullptr;
91456958cb33d3c1d045f2844408d825442d523f59fJohn Porto      constexpr uint16_t NoShift = 0;
91556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      return new (Func->allocate<X86OperandMem>())
91656958cb33d3c1d045f2844408d825442d523f59fJohn Porto          X86OperandMem(Func, Ty, Base, Offset, NoIndex, NoShift, IsRebased);
917453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
918453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *getBase() const { return Base; }
919453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Constant *getOffset() const { return Offset; }
920453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *getIndex() const { return Index; }
921453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    uint16_t getShift() const { return Shift; }
922453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SegmentRegisters getSegmentRegister() const { return DefaultSegment; }
923453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void emitSegmentOverride(Assembler *) const {}
92456958cb33d3c1d045f2844408d825442d523f59fJohn Porto    bool getIsRebased() const { return IsRebased; }
92556958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target,
92656958cb33d3c1d045f2844408d825442d523f59fJohn Porto                         bool IsLeaAddr = false) const;
927453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
928453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void emit(const Cfg *Func) const override;
929453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    using X86Operand::dump;
930453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void dump(const Cfg *Func, Ostream &Str) const override;
931453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
932453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static bool classof(const Operand *Operand) {
933453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return Operand->getKind() == static_cast<OperandKind>(kMem);
934453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
935453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
936453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void setRandomized(bool R) { Randomized = R; }
937453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
938453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool getRandomized() const { return Randomized; }
939453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
940453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  private:
941453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
94256958cb33d3c1d045f2844408d825442d523f59fJohn Porto                  Variable *Index, uint16_t Shift, bool IsRebased);
943453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
94456958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Variable *const Base;
94556958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Constant *const Offset;
94656958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Variable *const Index;
94756958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const uint16_t Shift;
94856958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const bool IsRebased;
949453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /// A flag to show if this memory operand is a randomized one. Randomized
950453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /// memory operands are generated in
951453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /// TargetX86Base::randomizeOrPoolImmediate()
952453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool Randomized = false;
953453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
954453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
955453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// VariableSplit is a way to treat an f64 memory location as a pair of i32
95657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// locations (Low and High). This is needed for some cases of the Bitcast
95757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. Since it's not possible for integer registers to access the
958453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
959453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// the stack and then accesses through the VariableSplit.
960453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
961453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // targets can natively handle these.
962453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  class VariableSplit : public X86Operand {
963453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit() = delete;
964453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit(const VariableSplit &) = delete;
965453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit &operator=(const VariableSplit &) = delete;
966453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
967453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  public:
968453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    enum Portion { Low, High };
969453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
970453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return new (Func->allocate<VariableSplit>())
971453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto          VariableSplit(Func, Var, Part);
972453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
973453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    int32_t getOffset() const { return Part == High ? 4 : 0; }
974453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
975453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Address toAsmAddress(const Cfg *Func) const;
976453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void emit(const Cfg *Func) const override;
977453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    using X86Operand::dump;
978453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void dump(const Cfg *Func, Ostream &Str) const override;
979453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
980453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static bool classof(const Operand *Operand) {
981453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return Operand->getKind() == static_cast<OperandKind>(kSplit);
982453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
983453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
984453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  private:
985453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit(Cfg *Func, Variable *Var, Portion Part)
986453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
987453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      assert(Var->getType() == IceType_f64);
988453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Vars = Func->allocateArrayOf<Variable *>(1);
989453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Vars[0] = Var;
990453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      NumVars = 1;
991453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
992453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
993453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *Var;
994453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Portion Part;
995453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
996453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
99757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// SpillVariable decorates a Variable by linking it to another Variable. When
99857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// stack frame offsets are computed, the SpillVariable is given a distinct
99957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// stack slot only if its linked Variable has a register. If the linked
100057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Variable has a stack slot, then the Variable and SpillVariable share that
100157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// slot.
1002453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  class SpillVariable : public Variable {
1003453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SpillVariable() = delete;
1004453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SpillVariable(const SpillVariable &) = delete;
1005453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SpillVariable &operator=(const SpillVariable &) = delete;
1006453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1007453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  public:
1008453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
1009453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index);
1010453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
1011453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const static OperandKind SpillVariableKind =
1012453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        static_cast<OperandKind>(kVariable_Target);
1013453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static bool classof(const Operand *Operand) {
1014453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return Operand->getKind() == SpillVariableKind;
1015453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
1016453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void setLinkedTo(Variable *Var) { LinkedTo = Var; }
1017453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *getLinkedTo() const { return LinkedTo; }
1018453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // Inherit dump() and emit() from Variable.
1019453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1020453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  private:
1021453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SpillVariable(Type Ty, SizeT Index)
1022453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {}
1023453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *LinkedTo;
1024453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
1025453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1026453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // Note: The following data structures are defined in IceInstX8664.cpp.
1027453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1028453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct InstBrAttributesType {
1029453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::BrCond Opposite;
1030453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *DisplayString;
1031453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *EmitString;
1032453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } InstBrAttributes[];
1033453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1034453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct InstCmppsAttributesType {
1035453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *EmitString;
1036453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } InstCmppsAttributes[];
1037453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1038453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TypeAttributesType {
1039453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *CvtString;   // i (integer), s (single FP), d (double FP)
1040453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *SdSsString;  // ss, sd, or <blank>
1041e398428c3ef8ed2339c0f334dd30a7d3f0ed4b6eDavid Sehr    const char *PdPsString;  // ps, pd, or <blank>
1042e398428c3ef8ed2339c0f334dd30a7d3f0ed4b6eDavid Sehr    const char *SpSdString;  // ss, sd, ps, pd, or <blank>
1043453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *PackString;  // b, w, d, or <blank>
1044453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *WidthString; // b, w, l, q, or <blank>
1045453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *FldString;   // s, l, or <blank>
1046453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TypeAttributes[];
10472fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto};
10482fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
10494a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing Traits = ::Ice::X8664::TargetX8664Traits;
10502fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace X8664
10512fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
10522fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace Ice
10532fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
10542fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
1055