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 =
53464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens      ::Ice::Assembler::Asm_X8664;
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;
718aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static constexpr RegisterSet::AllRegisters StackPtr = RegX8664::Reg_rsp;
728aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static constexpr RegisterSet::AllRegisters 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;
7727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32S;
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
304467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  static const char *getRegName(RegNumT 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    };
3138aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3145bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return RegNames[RegNum];
3155bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3165bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
3178aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static GPRRegister getEncodedGPR(RegNumT RegNum) {
3184a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
3195bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
32056958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
32156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3225bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
323453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        REGX8664_TABLE
324453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
325453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    };
3268aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3275bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
3285bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return GPRRegs[RegNum];
3295bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
330453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
3318aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static ByteRegister getEncodedByteReg(RegNumT RegNum) {
3324a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
3335bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
33456958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
33556958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3365bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
3375bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3385bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3395bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3408aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3415bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
3425bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return ByteRegs[RegNum];
343453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
344453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
3458aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static XmmRegister getEncodedXmm(RegNumT RegNum) {
3464a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
3475bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
34856958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
34956958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
3515bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3525bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3548aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3555bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
3565bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return XmmRegs[RegNum];
3575bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3585bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
3598aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static uint32_t getEncoding(RegNumT RegNum) {
3604a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
3615bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
36256958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
36356958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3645bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  encode,
3655bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3665bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3675bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3688aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3695bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return Encoding[RegNum];
3705bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3715bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
3728aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static inline RegNumT getBaseReg(RegNumT RegNum) {
3738aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
3745bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
37556958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
37656958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
3778aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  RegisterSet::base,
3785bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth        REGX8664_TABLE
3795bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#undef X
3805bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    };
3818aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    RegNum.assertIsValid();
3825bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    return BaseRegs[RegNum];
3835bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }
3845bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
385008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portoprivate:
3868aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getFirstGprForType(Type Ty) {
387008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    switch (Ty) {
388008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    default:
389008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      llvm_unreachable("Invalid type for GPR.");
390008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i1:
391008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i8:
392008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_al;
393008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i16:
394008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_ax;
395008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i32:
396008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_eax;
397008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    case IceType_i64:
398008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegisterSet::Reg_rax;
399008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
400008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  }
401008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
402008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Portopublic:
4038aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
4045fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler    assert(RegNum.hasValue());
405008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
406008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    if (!isScalarIntegerType(Ty)) {
407008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegNum;
408008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
409008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
410008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 ||
411008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto           Ty == IceType_i32 || Ty == IceType_i64);
412008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
413008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    if (RegNum == RegisterSet::Reg_ah) {
414008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      assert(Ty == IceType_i8);
415008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      return RegNum;
416008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
417008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
418008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(RegNum != RegisterSet::Reg_bh);
419008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(RegNum != RegisterSet::Reg_ch);
420008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(RegNum != RegisterSet::Reg_dh);
421008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
4228aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    const RegNumT FirstGprForType = getFirstGprForType(Ty);
423008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto
424008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    switch (RegNum) {
425008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    default:
426008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      llvm::report_fatal_error("Unknown register.");
427008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
42856958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
42956958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
430008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  case RegisterSet::val: {                                                     \
43156958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (!isGPR)                                                                \
43256958cb33d3c1d045f2844408d825442d523f59fJohn Porto      return RegisterSet::val;                                                 \
433008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert((is64) || (is32) || (is16) || (is8) ||                              \
434ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth           getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp);              \
4358aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize =               \
436ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth        ((is64) || RegisterSet::val == RegisterSet::Reg_rsp)                   \
437008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto            ? RegisterSet::Reg_rax                                             \
438ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth            : (((is32) || RegisterSet::val == RegisterSet::Reg_esp)            \
439008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto                   ? RegisterSet::Reg_eax                                      \
440ee1aae820b08055583e6c9be7a3118d1e975a45dJim Stichnoth                   : (((is16) || RegisterSet::val == RegisterSet::Reg_sp)      \
441008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto                          ? RegisterSet::Reg_ax                                \
442008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto                          : RegisterSet::Reg_al));                             \
4438aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    const auto NewRegNum =                                                     \
4448aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
445008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
446008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto           "Error involving " #val);                                           \
447008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    return NewRegNum;                                                          \
448008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  }
449008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto      REGX8664_TABLE
450008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto#undef X
451008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto    }
452008f4ce5417c97891ea02b54b691b39aa2e2a0afJohn Porto  }
4535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth
4544a308cedda6bfe381dc9506f3508c4547a06275fJohn Portoprivate:
4554a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// SizeOf is used to obtain the size of an initializer list as a constexpr
4564a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// expression. This is only needed until our C++ library is updated to
4574a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  /// C++ 14 -- which defines constexpr members to std::initializer_list.
4584a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  class SizeOf {
4594a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    SizeOf(const SizeOf &) = delete;
4604a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    SizeOf &operator=(const SizeOf &) = delete;
4614a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4624a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  public:
4634a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    constexpr SizeOf() : Size(0) {}
4644a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    template <typename... T>
4654a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    explicit constexpr SizeOf(T...)
46656958cb33d3c1d045f2844408d825442d523f59fJohn Porto        : Size(length<T...>::value) {}
4674a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    constexpr SizeT size() const { return Size; }
4684a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4694a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  private:
47056958cb33d3c1d045f2844408d825442d523f59fJohn Porto    template <typename T, typename... U> struct length {
47156958cb33d3c1d045f2844408d825442d523f59fJohn Porto      static constexpr std::size_t value = 1 + length<U...>::value;
4724a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
4734a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
47456958cb33d3c1d045f2844408d825442d523f59fJohn Porto    template <typename T> struct length<T> {
4754a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      static constexpr std::size_t value = 1;
4764a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
4774a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4784a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    const std::size_t Size;
4794a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  };
4804a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
4814a308cedda6bfe381dc9506f3508c4547a06275fJohn Portopublic:
482bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  static void initRegisterSet(
48356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      const ::Ice::ClFlags &Flags,
484e82b560e649f8a68bcb252b9b002708e74d962d3John Porto      std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
485e82b560e649f8a68bcb252b9b002708e74d962d3John Porto      std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
486e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM);
487e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
488e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
489e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
490e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
491e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
492e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
493e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
494e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
495e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
496e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
497e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
498bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
4994a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    static constexpr struct {
5004a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      uint16_t Val;
50156958cb33d3c1d045f2844408d825442d523f59fJohn Porto      unsigned IsReservedWhenSandboxing : 1;
502caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is64 : 1;
503caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is32 : 1;
504caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is16 : 1;
505caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is8 : 1;
506caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsXmm : 1;
507caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is64To8 : 1;
508caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is32To8 : 1;
509caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned Is16To8 : 1;
510caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsTrunc8Rcvr : 1;
511caeaa27b18e94cbad635dbe21da87e816a35c7daJim Stichnoth      unsigned IsAhRcvr : 1;
5124a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#define NUM_ALIASES_BITS 2
5134a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      SizeT NumAliases : (NUM_ALIASES_BITS + 1);
5144a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      uint16_t Aliases[1 << NUM_ALIASES_BITS];
5154a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto#undef NUM_ALIASES_BITS
5164a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    } X8664RegTable[RegisterSet::Reg_NUM] = {
5175bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
51856958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
51956958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
5204a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  {                                                                            \
52156958cb33d3c1d045f2844408d825442d523f59fJohn Porto    RegisterSet::val, sboxres, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
52229d15fd619f1d46f8e0c3d22932b9931c4b81367Jim Stichnoth        is16To8, isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases,     \
5235bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth  }                                                                            \
5244a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto  ,
5254a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto        REGX8664_TABLE
526453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
5274a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    };
5284a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto
52956958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const bool NeedSandboxing = Flags.getUseSandboxing();
5304a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) {
5314a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      const auto &Entry = X8664RegTable[ii];
53256958cb33d3c1d045f2844408d825442d523f59fJohn Porto      // Even though the register is disabled for register allocation, it might
53356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      // still be used by the Target Lowering (e.g., base pointer), so the
53456958cb33d3c1d045f2844408d825442d523f59fJohn Porto      // register alias table still needs to be defined.
53556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
53656958cb33d3c1d045f2844408d825442d523f59fJohn Porto      for (int J = 0; J < Entry.NumAliases; ++J) {
53756958cb33d3c1d045f2844408d825442d523f59fJohn Porto        SizeT Alias = Entry.Aliases[J];
53856958cb33d3c1d045f2844408d825442d523f59fJohn Porto        assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
53956958cb33d3c1d045f2844408d825442d523f59fJohn Porto        (*RegisterAliases)[Entry.Val].set(Alias);
54056958cb33d3c1d045f2844408d825442d523f59fJohn Porto      }
54156958cb33d3c1d045f2844408d825442d523f59fJohn Porto
54256958cb33d3c1d045f2844408d825442d523f59fJohn Porto      (*RegisterAliases)[Entry.Val].set(Entry.Val);
54356958cb33d3c1d045f2844408d825442d523f59fJohn Porto      const bool DisabledRegister =
54456958cb33d3c1d045f2844408d825442d523f59fJohn Porto          NeedSandboxing && Entry.IsReservedWhenSandboxing;
54556958cb33d3c1d045f2844408d825442d523f59fJohn Porto      if (DisabledRegister) {
54656958cb33d3c1d045f2844408d825442d523f59fJohn Porto        continue;
54756958cb33d3c1d045f2844408d825442d523f59fJohn Porto      }
5484a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI64)[Entry.Val] = Entry.Is64;
5494a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
5504a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
5514a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
5524a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (FloatRegisters)[Entry.Val] = Entry.IsXmm;
5534a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (VectorRegisters)[Entry.Val] = Entry.IsXmm;
5544a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
5554a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
5564a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
5574a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
5584a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto      (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
5594a308cedda6bfe381dc9506f3508c4547a06275fJohn Porto    }
560bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
561c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
562c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
563c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
564c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
565c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
566c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64;
567c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
568c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
569c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
570c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
571c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
572c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
573c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
574c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
575c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
576c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
577c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
578c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
579c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
580c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
581453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
582453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
583e82b560e649f8a68bcb252b9b002708e74d962d3John Porto  static SmallBitVector getRegisterSet(const ::Ice::ClFlags &Flags,
584e82b560e649f8a68bcb252b9b002708e74d962d3John Porto                                       TargetLowering::RegSetMask Include,
585e82b560e649f8a68bcb252b9b002708e74d962d3John Porto                                       TargetLowering::RegSetMask Exclude) {
586e82b560e649f8a68bcb252b9b002708e74d962d3John Porto    SmallBitVector Registers(RegisterSet::Reg_NUM);
587453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
58856958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const bool NeedSandboxing = Flags.getUseSandboxing();
5895bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
59056958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
59156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
59256958cb33d3c1d045f2844408d825442d523f59fJohn Porto  if (!NeedSandboxing || !(sboxres)) {                                         \
59356958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))       \
59456958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
59556958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))     \
59656958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
59756958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))    \
59856958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
59956958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))    \
60056958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = true;                                      \
60156958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))       \
60256958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
60356958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))     \
60456958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
60556958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))    \
60656958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
60756958cb33d3c1d045f2844408d825442d523f59fJohn Porto    if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))    \
60856958cb33d3c1d045f2844408d825442d523f59fJohn Porto      Registers[RegisterSet::val] = false;                                     \
60956958cb33d3c1d045f2844408d825442d523f59fJohn Porto  }
610453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
611453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    REGX8664_TABLE
612453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
613453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
614453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
615453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    return Registers;
616453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
617453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
618d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf  static void makeRandomRegisterPermutation(
619d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf      Cfg *Func, llvm::SmallVectorImpl<RegNumT> &Permutation,
620d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf      const SmallBitVector &ExcludeRegisters, uint64_t Salt) {
621453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // TODO(stichnot): Declaring Permutation this way loses type/size
62257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // information. Fix this in conjunction with the caller-side TODO.
623453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(Permutation.size() >= RegisterSet::Reg_NUM);
624453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // Expected upper bound on the number of registers in a single equivalence
62557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // class.  For x86-64, this would comprise the 16 XMM registers. This is
626453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // for performance, not correctness.
627453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static const unsigned MaxEquivalenceClassSize = 8;
6288aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
6298072bae156fa62e51e02925997992c4908a2682fAndrew Scull    using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
630453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    EquivalenceClassMap EquivalenceClasses;
631453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SizeT NumShuffled = 0, NumPreserved = 0;
632453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
633453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// Build up the equivalence classes of registers by looking at the register
634453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// properties as well as whether the registers should be explicitly excluded
635453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto// from shuffling.
6365bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
63756958cb33d3c1d045f2844408d825442d523f59fJohn Porto          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
63856958cb33d3c1d045f2844408d825442d523f59fJohn Porto          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
639453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  if (ExcludeRegisters[RegisterSet::val]) {                                    \
640453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /* val stays the same in the resulting permutation. */                     \
641453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Permutation[RegisterSet::val] = RegisterSet::val;                          \
642453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    ++NumPreserved;                                                            \
643453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } else {                                                                     \
6445bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    uint32_t AttrKey = 0;                                                      \
6455bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    uint32_t Index = 0;                                                        \
6465bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    /* Combine relevant attributes into an equivalence class key. */           \
6475bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (scratch << (AttrKey++));                                         \
6485bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (preserved << (AttrKey++));                                       \
6495bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is8 << (AttrKey++));                                             \
6505bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is16 << (AttrKey++));                                            \
6515bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is32 << (AttrKey++));                                            \
6525bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (is64 << (AttrKey++));                                            \
6535bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth    Index |= (isXmm << (AttrKey++));                                           \
654c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is16To8 << (AttrKey++));                                         \
655c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is32To8 << (AttrKey++));                                         \
656c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (is64To8 << (AttrKey++));                                         \
657c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth    Index |= (isTrunc8Rcvr << (AttrKey++));                                    \
658453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /* val is assigned to an equivalence class based on its properties. */     \
659453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    EquivalenceClasses[Index].push_back(RegisterSet::val);                     \
660453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
661453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    REGX8664_TABLE
662453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto#undef X
663453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
664aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    // Create a random number generator for regalloc randomization.
665d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf    RandomNumberGenerator RNG(getFlags().getRandomSeed(),
666aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                              RPE_RegAllocRandomization, Salt);
667aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    RandomNumberGeneratorWrapper RNGW(RNG);
668453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
669453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    // Shuffle the resulting equivalence classes.
670453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    for (auto I : EquivalenceClasses) {
671453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      const RegisterList &List = I.second;
672453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      RegisterList Shuffled(List);
673aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu      RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
674453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
675453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        Permutation[List[SI]] = Shuffled[SI];
676453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        ++NumShuffled;
677453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      }
678453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
679453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
680453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM);
681453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
682453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    if (Func->isVerbose(IceV_Random)) {
683453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      OstreamLocker L(Func->getContext());
684453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Ostream &Str = Func->getContext()->getStrDump();
685453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Str << "Register equivalence classes:\n";
686453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      for (auto I : EquivalenceClasses) {
687453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        Str << "{";
688453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        const RegisterList &List = I.second;
689453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        bool First = true;
6908aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth        for (RegNumT Register : List) {
691453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto          if (!First)
692453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto            Str << " ";
693453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto          First = false;
6945bff61c44841990680781892036adb17b3cff0c4Jim Stichnoth          Str << getRegName(Register);
695453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        }
696453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        Str << "}\n";
697453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      }
698453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
699453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
700453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
7018aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getRaxOrDie() { return RegisterSet::Reg_rax; }
7023c275ce1e832ba9ccfb730c4235db786cf080465John Porto
7038aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getRdxOrDie() { return RegisterSet::Reg_rdx; }
7043c275ce1e832ba9ccfb730c4235db786cf080465John Porto
7054e679e51f645b99940f43c80fec7f146d59eb00fNicolas Capens#if defined(SUBZERO_USE_MICROSOFT_ABI)
706464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // Microsoft x86-64 calling convention:
707464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  //
708464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // * The first four arguments of vector/fp type, regardless of their
709464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // position relative to the other arguments in the argument list, are placed
710464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // in registers %xmm0 - %xmm3.
711464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  //
712464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // * The first four arguments of integer types, regardless of their position
713464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // relative to the other arguments in the argument list, are placed in
714464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // registers %rcx, %rdx, %r8, and %r9.
715464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens
716464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  /// The maximum number of arguments to pass in XMM registers
717464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
718464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  /// The maximum number of arguments to pass in GPR registers
719464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  static constexpr uint32_t X86_MAX_GPR_ARGS = 4;
720464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
721464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    if (ArgNum >= X86_MAX_GPR_ARGS) {
722464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens      return RegNumT();
723464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    }
724464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    static const RegisterSet::AllRegisters GprForArgNum[] = {
725464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens        RegisterSet::Reg_rcx, RegisterSet::Reg_rdx, RegisterSet::Reg_r8,
726464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens        RegisterSet::Reg_r9,
727464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    };
728464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS,
729464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens                  "Mismatch between MAX_GPR_ARGS and GprForArgNum.");
730464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    assert(Ty == IceType_i64 || Ty == IceType_i32);
731464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    return getGprForType(Ty, GprForArgNum[ArgNum]);
732464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  }
7334b1bdae3955769f62e563e826065d10ddfe040eaNicolas Capens#else
734464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  // System V x86-64 calling convention:
7350c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
7360c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // * The first eight arguments of vector/fp type, regardless of their
7370c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // position relative to the other arguments in the argument list, are placed
7380c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // in registers %xmm0 - %xmm7.
7390c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
7400c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // * The first six arguments of integer types, regardless of their position
7410c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // relative to the other arguments in the argument list, are placed in
7420c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9.
7430c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  //
7440c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // This intends to match the section "Function Calling Sequence" of the
7450c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  // document "System V Application Binary Interface."
7460c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr
747453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The maximum number of arguments to pass in XMM registers
7480c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_MAX_XMM_ARGS = 8;
749e0d9afa80ee55711d25fae87e50d11685d1ad6d7John Porto  /// The maximum number of arguments to pass in GPR registers
7500c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_MAX_GPR_ARGS = 6;
7510c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  /// Get the register for a given argument slot in the GPRs.
7528aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth  static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
7530c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    if (ArgNum >= X86_MAX_GPR_ARGS) {
7545fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler      return RegNumT();
7550c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    }
7560c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    static const RegisterSet::AllRegisters GprForArgNum[] = {
7570c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr        RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
7580c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr        RegisterSet::Reg_rcx, RegisterSet::Reg_r8,  RegisterSet::Reg_r9,
7590c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    };
7600c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS,
7610c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr                  "Mismatch between MAX_GPR_ARGS and GprForArgNum.");
7620c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr    assert(Ty == IceType_i64 || Ty == IceType_i32);
7638aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    return getGprForType(Ty, GprForArgNum[ArgNum]);
7640c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  }
76573ae4fdc32345ad1dc44cc5268204174555b2b55Nicolas Capens#endif
766464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens
767464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  /// Whether scalar floating point arguments are passed in XMM registers
768464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true;
769464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  /// Get the register for a given argument slot in the XMM registers.
770464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
771464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    // TODO(sehr): Change to use the CCArg technique used in ARM32.
772464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
773464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens                  "Inconsistency between XMM register numbers and ordinals");
774464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    if (ArgNum >= X86_MAX_XMM_ARGS) {
775464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens      return RegNumT();
776464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    }
777464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens    return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
778464df5b9f7f3518a263c3f7f7050cc07dc6ce458Nicolas Capens  }
7790c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr
780453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The number of bits in a byte
7810c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_CHAR_BIT = 8;
782453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it
783453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// is used as an argument to std::max(), and the default std::less<T> has an
784453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// operator(T const&, T const&) which requires this member to have an
785453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// address.
786453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const uint32_t X86_STACK_ALIGNMENT_BYTES;
787453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Size of the return address on the stack
7880c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8;
789453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The number of different NOP instructions
7900c68bef895ea8987922922ede6f1918763eaa00bDavid Sehr  static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
791453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
792cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// \name Limits for unrolling memory intrinsics.
793cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @{
794cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
795cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
79635e160025c5a7005f97c5ad55120999cf83a4ce1Jim Stichnoth  static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
797cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @}
798cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull
79957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Value is in bytes. Return Value adjusted to the next highest multiple of
80057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// the stack alignment.
801453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static uint32_t applyStackAlignment(uint32_t Value) {
802453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
803453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
804453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
805453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Return the type which the elements of the vector have in the X86
806453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// representation of the vector.
807453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static Type getInVectorElementType(Type Ty) {
808453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    assert(isVectorType(Ty));
8092d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth    assert(Ty < TableTypeX8664AttributesSize);
810453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    return TableTypeX8664Attributes[Ty].InVectorElementType;
811453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
812453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
813453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // Note: The following data structures are defined in
814453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // IceTargetLoweringX8664.cpp.
815453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
816453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The following table summarizes the logic for lowering the fcmp
817453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// instruction. There is one table entry for each of the 16 conditions.
818453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  ///
819453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The first four columns describe the case when the operands are floating
82057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// point scalar values. A comment in lowerFcmp() describes the lowering
82157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// template. In the most general case, there is a compare followed by two
822453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// conditional branches, because some fcmp conditions don't map to a single
82357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// x86 conditional branch. However, in many cases it is possible to swap the
82457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// operands in the comparison and have a single conditional branch. Since
825453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// it's quite tedious to validate the table by hand, good execution tests are
826453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// helpful.
827453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  ///
828453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The last two columns describe the case when the operands are vectors of
82957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// floating point values. For most fcmp conditions, there is a clear mapping
83057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// to a single x86 cmpps instruction variant. Some fcmp conditions require
831453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// special code to handle and these are marked in the table with a
832453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// Cmpps_Invalid predicate.
833453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// {@
834453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableFcmpType {
835453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    uint32_t Default;
836453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool SwapScalarOperands;
837453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::BrCond C1, C2;
838453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool SwapVectorOperands;
839453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::CmppsCond Predicate;
840453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TableFcmp[];
841453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableFcmpSize;
842453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// @}
843453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
844453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The following table summarizes the logic for lowering the icmp instruction
84557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// for i32 and narrower types. Each icmp condition has a clear mapping to an
846453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// x86 conditional branch instruction.
847453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// {@
848453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
849453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableIcmp32Size;
850453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// @}
851453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
852453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// The following table summarizes the logic for lowering the icmp instruction
85357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
85457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// conditional branches are needed. For the other conditions, three separate
855453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// conditional branches are needed.
856453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// {@
857453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableIcmp64Type {
858453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::BrCond C1, C2, C3;
859453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TableIcmp64[];
860453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableIcmp64Size;
861453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// @}
862453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
863453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
8642d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth    assert(Cond < TableIcmp32Size);
8652d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth    return TableIcmp32[Cond].Mapping;
866453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  }
867453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
868453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TableTypeX8664AttributesType {
869453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Type InVectorElementType;
870453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TableTypeX8664Attributes[];
871453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const size_t TableTypeX8664AttributesSize;
872453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
873453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //----------------------------------------------------------------------------
874453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //      __  __   __  ______  ______
875453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //    /\ \/\ "-.\ \/\  ___\/\__  _\
876453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //    \ \ \ \ \-.  \ \___  \/_/\ \/
877453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //     \ \_\ \_\\"\_\/\_____\ \ \_\
878453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //      \/_/\/_/ \/_/\/_____/  \/_/
879453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //
880453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  //----------------------------------------------------------------------------
8814a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Traits = TargetX8664Traits;
8824a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Insts = ::Ice::X8664::Insts<Traits>;
883453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
8844a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using TargetLowering = ::Ice::X8664::TargetX86Base<Traits>;
8854a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using ConcreteTarget = ::Ice::X8664::TargetX8664;
8864a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto  using Assembler = ::Ice::X8664::AssemblerX86Base<Traits>;
887453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
88857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem
88957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// and VariableSplit.
890453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  class X86Operand : public ::Ice::Operand {
891453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand() = delete;
892453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand(const X86Operand &) = delete;
893453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand &operator=(const X86Operand &) = delete;
894453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
895453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  public:
896453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    enum OperandKindX8664 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
897453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    using ::Ice::Operand::dump;
898453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
899453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void dump(const Cfg *, Ostream &Str) const override;
900453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
901453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  protected:
902453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86Operand(OperandKindX8664 Kind, Type Ty)
903453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
904453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
905453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
906453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// X86OperandMem represents the m64 addressing mode, with optional base and
907453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// index registers, a constant offset, and a fixed shift value for the index
908453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// register.
909453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  class X86OperandMem : public X86Operand {
910453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem() = delete;
911453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem(const X86OperandMem &) = delete;
912453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem &operator=(const X86OperandMem &) = delete;
913453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
914453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  public:
915453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM };
916453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static X86OperandMem *
917453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
918453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto           Variable *Index = nullptr, uint16_t Shift = 0,
9198ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth           SegmentRegisters SegmentRegister = DefaultSegment,
92056958cb33d3c1d045f2844408d825442d523f59fJohn Porto           bool IsRebased = false) {
921453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      assert(SegmentRegister == DefaultSegment);
922453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      (void)SegmentRegister;
923453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return new (Func->allocate<X86OperandMem>())
92456958cb33d3c1d045f2844408d825442d523f59fJohn Porto          X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsRebased);
92556958cb33d3c1d045f2844408d825442d523f59fJohn Porto    }
92656958cb33d3c1d045f2844408d825442d523f59fJohn Porto    static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
92756958cb33d3c1d045f2844408d825442d523f59fJohn Porto                                 Constant *Offset, bool IsRebased) {
92856958cb33d3c1d045f2844408d825442d523f59fJohn Porto      constexpr Variable *NoIndex = nullptr;
92956958cb33d3c1d045f2844408d825442d523f59fJohn Porto      constexpr uint16_t NoShift = 0;
93056958cb33d3c1d045f2844408d825442d523f59fJohn Porto      return new (Func->allocate<X86OperandMem>())
93156958cb33d3c1d045f2844408d825442d523f59fJohn Porto          X86OperandMem(Func, Ty, Base, Offset, NoIndex, NoShift, IsRebased);
932453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
933453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *getBase() const { return Base; }
934453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Constant *getOffset() const { return Offset; }
935453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *getIndex() const { return Index; }
936453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    uint16_t getShift() const { return Shift; }
937453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    SegmentRegisters getSegmentRegister() const { return DefaultSegment; }
938453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void emitSegmentOverride(Assembler *) const {}
93956958cb33d3c1d045f2844408d825442d523f59fJohn Porto    bool getIsRebased() const { return IsRebased; }
94056958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target,
94156958cb33d3c1d045f2844408d825442d523f59fJohn Porto                         bool IsLeaAddr = false) const;
942453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
943453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void emit(const Cfg *Func) const override;
944453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    using X86Operand::dump;
945453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void dump(const Cfg *Func, Ostream &Str) const override;
946453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
947453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static bool classof(const Operand *Operand) {
948453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return Operand->getKind() == static_cast<OperandKind>(kMem);
949453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
950453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
951453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void setRandomized(bool R) { Randomized = R; }
952453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
953453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool getRandomized() const { return Randomized; }
954453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
955453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  private:
956453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
95756958cb33d3c1d045f2844408d825442d523f59fJohn Porto                  Variable *Index, uint16_t Shift, bool IsRebased);
958453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
95956958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Variable *const Base;
96056958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Constant *const Offset;
96156958cb33d3c1d045f2844408d825442d523f59fJohn Porto    Variable *const Index;
96256958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const uint16_t Shift;
96356958cb33d3c1d045f2844408d825442d523f59fJohn Porto    const bool IsRebased;
964453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /// A flag to show if this memory operand is a randomized one. Randomized
965453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /// memory operands are generated in
966453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    /// TargetX86Base::randomizeOrPoolImmediate()
967453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    bool Randomized = false;
968453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
969453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
970453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// VariableSplit is a way to treat an f64 memory location as a pair of i32
97157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// locations (Low and High). This is needed for some cases of the Bitcast
97257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// instruction. Since it's not possible for integer registers to access the
973453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
974453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  /// the stack and then accesses through the VariableSplit.
975453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
976453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // targets can natively handle these.
977453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  class VariableSplit : public X86Operand {
978453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit() = delete;
979453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit(const VariableSplit &) = delete;
980453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit &operator=(const VariableSplit &) = delete;
981453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
982453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  public:
983453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    enum Portion { Low, High };
984453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
985453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return new (Func->allocate<VariableSplit>())
986453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto          VariableSplit(Func, Var, Part);
987453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
988453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    int32_t getOffset() const { return Part == High ? 4 : 0; }
989453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
990453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Address toAsmAddress(const Cfg *Func) const;
991453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void emit(const Cfg *Func) const override;
992453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    using X86Operand::dump;
993453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    void dump(const Cfg *Func, Ostream &Str) const override;
994453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
995453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    static bool classof(const Operand *Operand) {
996453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      return Operand->getKind() == static_cast<OperandKind>(kSplit);
997453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
998453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
999453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  private:
1000453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    VariableSplit(Cfg *Func, Variable *Var, Portion Part)
1001453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto        : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
1002453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      assert(Var->getType() == IceType_f64);
1003453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Vars = Func->allocateArrayOf<Variable *>(1);
1004453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      Vars[0] = Var;
1005453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto      NumVars = 1;
1006453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    }
1007453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1008453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Variable *Var;
1009453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Portion Part;
1010453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  };
1011453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1012453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  // Note: The following data structures are defined in IceInstX8664.cpp.
1013453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1014453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct InstBrAttributesType {
1015453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    Cond::BrCond Opposite;
1016453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *DisplayString;
1017453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *EmitString;
1018453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } InstBrAttributes[];
1019453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1020453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct InstCmppsAttributesType {
1021453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto    const char *EmitString;
1022453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } InstCmppsAttributes[];
1023453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto
1024453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  static const struct TypeAttributesType {
10257638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *CvtString;      // i (integer), s (single FP), d (double FP)
10267638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *SdSsString;     // ss, sd, or <blank>
10277638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *PdPsString;     // ps, pd, or <blank>
10287638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *SpSdString;     // ss, sd, ps, pd, or <blank>
10297638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *IntegralString; // b, w, d, or <blank>
10307638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *UnpackString;   // bw, wd, dq, or <blank>
10317638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *PackString;     // wb, dw, or <blank>
10327638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *WidthString;    // b, w, l, q, or <blank>
10337638e275845ae4e6e2087198dde9b969d5a7f0d2Nicolas Capens    const char *FldString;      // s, l, or <blank>
1034453660ff4f0702f5cd95acdaf9e88196341b9cc6John Porto  } TypeAttributes[];
10352fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto};
10362fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
10374a56686b5b56db6803f90ad53514bf2fa190d9f7John Portousing Traits = ::Ice::X8664::TargetX8664Traits;
10382fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace X8664
10392fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
10402fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto} // end of namespace Ice
10412fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
10422fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
1043