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