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