1 //===-- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 //===----------------------------------------------------------------------===// 11 // 12 /// \file 13 /// 14 /// This file contains definition for AMDGPU ISA disassembler 15 // 16 //===----------------------------------------------------------------------===// 17 18 // ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)? 19 20 #include "AMDGPUDisassembler.h" 21 #include "AMDGPU.h" 22 #include "AMDGPURegisterInfo.h" 23 #include "SIDefines.h" 24 #include "Utils/AMDGPUBaseInfo.h" 25 26 #include "llvm/MC/MCContext.h" 27 #include "llvm/MC/MCFixedLenDisassembler.h" 28 #include "llvm/MC/MCInst.h" 29 #include "llvm/MC/MCInstrDesc.h" 30 #include "llvm/MC/MCSubtargetInfo.h" 31 #include "llvm/Support/ELF.h" 32 #include "llvm/Support/Endian.h" 33 #include "llvm/Support/Debug.h" 34 #include "llvm/Support/TargetRegistry.h" 35 36 37 using namespace llvm; 38 39 #define DEBUG_TYPE "amdgpu-disassembler" 40 41 typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; 42 43 44 inline static MCDisassembler::DecodeStatus 45 addOperand(MCInst &Inst, const MCOperand& Opnd) { 46 Inst.addOperand(Opnd); 47 return Opnd.isValid() ? 48 MCDisassembler::Success : 49 MCDisassembler::SoftFail; 50 } 51 52 static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm, 53 uint64_t Addr, const void *Decoder) { 54 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 55 56 APInt SignedOffset(18, Imm * 4, true); 57 int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue(); 58 59 if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2)) 60 return MCDisassembler::Success; 61 return addOperand(Inst, MCOperand::createImm(Imm)); 62 } 63 64 #define DECODE_OPERAND2(RegClass, DecName) \ 65 static DecodeStatus Decode##RegClass##RegisterClass(MCInst &Inst, \ 66 unsigned Imm, \ 67 uint64_t /*Addr*/, \ 68 const void *Decoder) { \ 69 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); \ 70 return addOperand(Inst, DAsm->decodeOperand_##DecName(Imm)); \ 71 } 72 73 #define DECODE_OPERAND(RegClass) DECODE_OPERAND2(RegClass, RegClass) 74 75 DECODE_OPERAND(VGPR_32) 76 DECODE_OPERAND(VS_32) 77 DECODE_OPERAND(VS_64) 78 79 DECODE_OPERAND(VReg_64) 80 DECODE_OPERAND(VReg_96) 81 DECODE_OPERAND(VReg_128) 82 83 DECODE_OPERAND(SReg_32) 84 DECODE_OPERAND(SReg_32_XM0_XEXEC) 85 DECODE_OPERAND(SReg_64) 86 DECODE_OPERAND(SReg_64_XEXEC) 87 DECODE_OPERAND(SReg_128) 88 DECODE_OPERAND(SReg_256) 89 DECODE_OPERAND(SReg_512) 90 91 92 static DecodeStatus decodeOperand_VSrc16(MCInst &Inst, 93 unsigned Imm, 94 uint64_t Addr, 95 const void *Decoder) { 96 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 97 return addOperand(Inst, DAsm->decodeOperand_VSrc16(Imm)); 98 } 99 100 static DecodeStatus decodeOperand_VSrcV216(MCInst &Inst, 101 unsigned Imm, 102 uint64_t Addr, 103 const void *Decoder) { 104 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 105 return addOperand(Inst, DAsm->decodeOperand_VSrcV216(Imm)); 106 } 107 108 #define GET_SUBTARGETINFO_ENUM 109 #include "AMDGPUGenSubtargetInfo.inc" 110 #undef GET_SUBTARGETINFO_ENUM 111 112 #include "AMDGPUGenDisassemblerTables.inc" 113 114 //===----------------------------------------------------------------------===// 115 // 116 //===----------------------------------------------------------------------===// 117 118 template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) { 119 assert(Bytes.size() >= sizeof(T)); 120 const auto Res = support::endian::read<T, support::endianness::little>(Bytes.data()); 121 Bytes = Bytes.slice(sizeof(T)); 122 return Res; 123 } 124 125 DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table, 126 MCInst &MI, 127 uint64_t Inst, 128 uint64_t Address) const { 129 assert(MI.getOpcode() == 0); 130 assert(MI.getNumOperands() == 0); 131 MCInst TmpInst; 132 const auto SavedBytes = Bytes; 133 if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) { 134 MI = TmpInst; 135 return MCDisassembler::Success; 136 } 137 Bytes = SavedBytes; 138 return MCDisassembler::Fail; 139 } 140 141 DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 142 ArrayRef<uint8_t> Bytes_, 143 uint64_t Address, 144 raw_ostream &WS, 145 raw_ostream &CS) const { 146 CommentStream = &CS; 147 148 // ToDo: AMDGPUDisassembler supports only VI ISA. 149 if (!STI.getFeatureBits()[AMDGPU::FeatureGCN3Encoding]) 150 report_fatal_error("Disassembly not yet supported for subtarget"); 151 152 const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size()); 153 Bytes = Bytes_.slice(0, MaxInstBytesNum); 154 155 DecodeStatus Res = MCDisassembler::Fail; 156 do { 157 // ToDo: better to switch encoding length using some bit predicate 158 // but it is unknown yet, so try all we can 159 160 // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2 161 // encodings 162 if (Bytes.size() >= 8) { 163 const uint64_t QW = eatBytes<uint64_t>(Bytes); 164 Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address); 165 if (Res) break; 166 167 Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address); 168 if (Res) break; 169 } 170 171 // Reinitialize Bytes as DPP64 could have eaten too much 172 Bytes = Bytes_.slice(0, MaxInstBytesNum); 173 174 // Try decode 32-bit instruction 175 if (Bytes.size() < 4) break; 176 const uint32_t DW = eatBytes<uint32_t>(Bytes); 177 Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address); 178 if (Res) break; 179 180 Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address); 181 if (Res) break; 182 183 if (Bytes.size() < 4) break; 184 const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW; 185 Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address); 186 if (Res) break; 187 188 Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address); 189 } while (false); 190 191 Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0; 192 return Res; 193 } 194 195 const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const { 196 return getContext().getRegisterInfo()-> 197 getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]); 198 } 199 200 inline 201 MCOperand AMDGPUDisassembler::errOperand(unsigned V, 202 const Twine& ErrMsg) const { 203 *CommentStream << "Error: " + ErrMsg; 204 205 // ToDo: add support for error operands to MCInst.h 206 // return MCOperand::createError(V); 207 return MCOperand(); 208 } 209 210 inline 211 MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const { 212 return MCOperand::createReg(RegId); 213 } 214 215 inline 216 MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID, 217 unsigned Val) const { 218 const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID]; 219 if (Val >= RegCl.getNumRegs()) 220 return errOperand(Val, Twine(getRegClassName(RegClassID)) + 221 ": unknown register " + Twine(Val)); 222 return createRegOperand(RegCl.getRegister(Val)); 223 } 224 225 inline 226 MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID, 227 unsigned Val) const { 228 // ToDo: SI/CI have 104 SGPRs, VI - 102 229 // Valery: here we accepting as much as we can, let assembler sort it out 230 int shift = 0; 231 switch (SRegClassID) { 232 case AMDGPU::SGPR_32RegClassID: 233 case AMDGPU::TTMP_32RegClassID: 234 break; 235 case AMDGPU::SGPR_64RegClassID: 236 case AMDGPU::TTMP_64RegClassID: 237 shift = 1; 238 break; 239 case AMDGPU::SGPR_128RegClassID: 240 case AMDGPU::TTMP_128RegClassID: 241 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in 242 // this bundle? 243 case AMDGPU::SReg_256RegClassID: 244 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in 245 // this bundle? 246 case AMDGPU::SReg_512RegClassID: 247 shift = 2; 248 break; 249 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in 250 // this bundle? 251 default: 252 llvm_unreachable("unhandled register class"); 253 } 254 255 if (Val % (1 << shift)) { 256 *CommentStream << "Warning: " << getRegClassName(SRegClassID) 257 << ": scalar reg isn't aligned " << Val; 258 } 259 260 return createRegOperand(SRegClassID, Val >> shift); 261 } 262 263 MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const { 264 return decodeSrcOp(OPW32, Val); 265 } 266 267 MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const { 268 return decodeSrcOp(OPW64, Val); 269 } 270 271 MCOperand AMDGPUDisassembler::decodeOperand_VSrc16(unsigned Val) const { 272 return decodeSrcOp(OPW16, Val); 273 } 274 275 MCOperand AMDGPUDisassembler::decodeOperand_VSrcV216(unsigned Val) const { 276 return decodeSrcOp(OPWV216, Val); 277 } 278 279 MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const { 280 // Some instructions have operand restrictions beyond what the encoding 281 // allows. Some ordinarily VSrc_32 operands are VGPR_32, so clear the extra 282 // high bit. 283 Val &= 255; 284 285 return createRegOperand(AMDGPU::VGPR_32RegClassID, Val); 286 } 287 288 MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const { 289 return createRegOperand(AMDGPU::VReg_64RegClassID, Val); 290 } 291 292 MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const { 293 return createRegOperand(AMDGPU::VReg_96RegClassID, Val); 294 } 295 296 MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const { 297 return createRegOperand(AMDGPU::VReg_128RegClassID, Val); 298 } 299 300 MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const { 301 // table-gen generated disassembler doesn't care about operand types 302 // leaving only registry class so SSrc_32 operand turns into SReg_32 303 // and therefore we accept immediates and literals here as well 304 return decodeSrcOp(OPW32, Val); 305 } 306 307 MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0_XEXEC( 308 unsigned Val) const { 309 // SReg_32_XM0 is SReg_32 without M0 or EXEC_LO/EXEC_HI 310 return decodeOperand_SReg_32(Val); 311 } 312 313 MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const { 314 return decodeSrcOp(OPW64, Val); 315 } 316 317 MCOperand AMDGPUDisassembler::decodeOperand_SReg_64_XEXEC(unsigned Val) const { 318 return decodeSrcOp(OPW64, Val); 319 } 320 321 MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const { 322 return decodeSrcOp(OPW128, Val); 323 } 324 325 MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const { 326 return createSRegOperand(AMDGPU::SReg_256RegClassID, Val); 327 } 328 329 MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const { 330 return createSRegOperand(AMDGPU::SReg_512RegClassID, Val); 331 } 332 333 334 MCOperand AMDGPUDisassembler::decodeLiteralConstant() const { 335 // For now all literal constants are supposed to be unsigned integer 336 // ToDo: deal with signed/unsigned 64-bit integer constants 337 // ToDo: deal with float/double constants 338 if (Bytes.size() < 4) 339 return errOperand(0, "cannot read literal, inst bytes left " + 340 Twine(Bytes.size())); 341 return MCOperand::createImm(eatBytes<uint32_t>(Bytes)); 342 } 343 344 MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) { 345 using namespace AMDGPU::EncValues; 346 assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX); 347 return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ? 348 (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) : 349 (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm))); 350 // Cast prevents negative overflow. 351 } 352 353 static int64_t getInlineImmVal32(unsigned Imm) { 354 switch (Imm) { 355 case 240: 356 return FloatToBits(0.5f); 357 case 241: 358 return FloatToBits(-0.5f); 359 case 242: 360 return FloatToBits(1.0f); 361 case 243: 362 return FloatToBits(-1.0f); 363 case 244: 364 return FloatToBits(2.0f); 365 case 245: 366 return FloatToBits(-2.0f); 367 case 246: 368 return FloatToBits(4.0f); 369 case 247: 370 return FloatToBits(-4.0f); 371 case 248: // 1 / (2 * PI) 372 return 0x3e22f983; 373 default: 374 llvm_unreachable("invalid fp inline imm"); 375 } 376 } 377 378 static int64_t getInlineImmVal64(unsigned Imm) { 379 switch (Imm) { 380 case 240: 381 return DoubleToBits(0.5); 382 case 241: 383 return DoubleToBits(-0.5); 384 case 242: 385 return DoubleToBits(1.0); 386 case 243: 387 return DoubleToBits(-1.0); 388 case 244: 389 return DoubleToBits(2.0); 390 case 245: 391 return DoubleToBits(-2.0); 392 case 246: 393 return DoubleToBits(4.0); 394 case 247: 395 return DoubleToBits(-4.0); 396 case 248: // 1 / (2 * PI) 397 return 0x3fc45f306dc9c882; 398 default: 399 llvm_unreachable("invalid fp inline imm"); 400 } 401 } 402 403 static int64_t getInlineImmVal16(unsigned Imm) { 404 switch (Imm) { 405 case 240: 406 return 0x3800; 407 case 241: 408 return 0xB800; 409 case 242: 410 return 0x3C00; 411 case 243: 412 return 0xBC00; 413 case 244: 414 return 0x4000; 415 case 245: 416 return 0xC000; 417 case 246: 418 return 0x4400; 419 case 247: 420 return 0xC400; 421 case 248: // 1 / (2 * PI) 422 return 0x3118; 423 default: 424 llvm_unreachable("invalid fp inline imm"); 425 } 426 } 427 428 MCOperand AMDGPUDisassembler::decodeFPImmed(OpWidthTy Width, unsigned Imm) { 429 assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN 430 && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX); 431 432 // ToDo: case 248: 1/(2*PI) - is allowed only on VI 433 switch (Width) { 434 case OPW32: 435 return MCOperand::createImm(getInlineImmVal32(Imm)); 436 case OPW64: 437 return MCOperand::createImm(getInlineImmVal64(Imm)); 438 case OPW16: 439 case OPWV216: 440 return MCOperand::createImm(getInlineImmVal16(Imm)); 441 default: 442 llvm_unreachable("implement me"); 443 } 444 } 445 446 unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const { 447 using namespace AMDGPU; 448 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 449 switch (Width) { 450 default: // fall 451 case OPW32: 452 case OPW16: 453 case OPWV216: 454 return VGPR_32RegClassID; 455 case OPW64: return VReg_64RegClassID; 456 case OPW128: return VReg_128RegClassID; 457 } 458 } 459 460 unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const { 461 using namespace AMDGPU; 462 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 463 switch (Width) { 464 default: // fall 465 case OPW32: 466 case OPW16: 467 case OPWV216: 468 return SGPR_32RegClassID; 469 case OPW64: return SGPR_64RegClassID; 470 case OPW128: return SGPR_128RegClassID; 471 } 472 } 473 474 unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const { 475 using namespace AMDGPU; 476 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 477 switch (Width) { 478 default: // fall 479 case OPW32: 480 case OPW16: 481 case OPWV216: 482 return TTMP_32RegClassID; 483 case OPW64: return TTMP_64RegClassID; 484 case OPW128: return TTMP_128RegClassID; 485 } 486 } 487 488 MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const { 489 using namespace AMDGPU::EncValues; 490 assert(Val < 512); // enum9 491 492 if (VGPR_MIN <= Val && Val <= VGPR_MAX) { 493 return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN); 494 } 495 if (Val <= SGPR_MAX) { 496 assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning. 497 return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN); 498 } 499 if (TTMP_MIN <= Val && Val <= TTMP_MAX) { 500 return createSRegOperand(getTtmpClassId(Width), Val - TTMP_MIN); 501 } 502 503 assert(Width == OPW16 || Width == OPW32 || Width == OPW64); 504 505 if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX) 506 return decodeIntImmed(Val); 507 508 if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX) 509 return decodeFPImmed(Width, Val); 510 511 if (Val == LITERAL_CONST) 512 return decodeLiteralConstant(); 513 514 switch (Width) { 515 case OPW32: 516 case OPW16: 517 case OPWV216: 518 return decodeSpecialReg32(Val); 519 case OPW64: 520 return decodeSpecialReg64(Val); 521 default: 522 llvm_unreachable("unexpected immediate type"); 523 } 524 } 525 526 MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const { 527 using namespace AMDGPU; 528 switch (Val) { 529 case 102: return createRegOperand(getMCReg(FLAT_SCR_LO, STI)); 530 case 103: return createRegOperand(getMCReg(FLAT_SCR_HI, STI)); 531 // ToDo: no support for xnack_mask_lo/_hi register 532 case 104: 533 case 105: break; 534 case 106: return createRegOperand(VCC_LO); 535 case 107: return createRegOperand(VCC_HI); 536 case 108: return createRegOperand(TBA_LO); 537 case 109: return createRegOperand(TBA_HI); 538 case 110: return createRegOperand(TMA_LO); 539 case 111: return createRegOperand(TMA_HI); 540 case 124: return createRegOperand(M0); 541 case 126: return createRegOperand(EXEC_LO); 542 case 127: return createRegOperand(EXEC_HI); 543 case 235: return createRegOperand(SRC_SHARED_BASE); 544 case 236: return createRegOperand(SRC_SHARED_LIMIT); 545 case 237: return createRegOperand(SRC_PRIVATE_BASE); 546 case 238: return createRegOperand(SRC_PRIVATE_LIMIT); 547 // TODO: SRC_POPS_EXITING_WAVE_ID 548 // ToDo: no support for vccz register 549 case 251: break; 550 // ToDo: no support for execz register 551 case 252: break; 552 case 253: return createRegOperand(SCC); 553 default: break; 554 } 555 return errOperand(Val, "unknown operand encoding " + Twine(Val)); 556 } 557 558 MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const { 559 using namespace AMDGPU; 560 switch (Val) { 561 case 102: return createRegOperand(getMCReg(FLAT_SCR, STI)); 562 case 106: return createRegOperand(VCC); 563 case 108: return createRegOperand(TBA); 564 case 110: return createRegOperand(TMA); 565 case 126: return createRegOperand(EXEC); 566 default: break; 567 } 568 return errOperand(Val, "unknown operand encoding " + Twine(Val)); 569 } 570 571 //===----------------------------------------------------------------------===// 572 // AMDGPUSymbolizer 573 //===----------------------------------------------------------------------===// 574 575 // Try to find symbol name for specified label 576 bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst, 577 raw_ostream &/*cStream*/, int64_t Value, 578 uint64_t /*Address*/, bool IsBranch, 579 uint64_t /*Offset*/, uint64_t /*InstSize*/) { 580 typedef std::tuple<uint64_t, StringRef, uint8_t> SymbolInfoTy; 581 typedef std::vector<SymbolInfoTy> SectionSymbolsTy; 582 583 if (!IsBranch) { 584 return false; 585 } 586 587 auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo); 588 auto Result = std::find_if(Symbols->begin(), Symbols->end(), 589 [Value](const SymbolInfoTy& Val) { 590 return std::get<0>(Val) == static_cast<uint64_t>(Value) 591 && std::get<2>(Val) == ELF::STT_NOTYPE; 592 }); 593 if (Result != Symbols->end()) { 594 auto *Sym = Ctx.getOrCreateSymbol(std::get<1>(*Result)); 595 const auto *Add = MCSymbolRefExpr::create(Sym, Ctx); 596 Inst.addOperand(MCOperand::createExpr(Add)); 597 return true; 598 } 599 return false; 600 } 601 602 void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, 603 int64_t Value, 604 uint64_t Address) { 605 llvm_unreachable("unimplemented"); 606 } 607 608 //===----------------------------------------------------------------------===// 609 // Initialization 610 //===----------------------------------------------------------------------===// 611 612 static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/, 613 LLVMOpInfoCallback /*GetOpInfo*/, 614 LLVMSymbolLookupCallback /*SymbolLookUp*/, 615 void *DisInfo, 616 MCContext *Ctx, 617 std::unique_ptr<MCRelocationInfo> &&RelInfo) { 618 return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo); 619 } 620 621 static MCDisassembler *createAMDGPUDisassembler(const Target &T, 622 const MCSubtargetInfo &STI, 623 MCContext &Ctx) { 624 return new AMDGPUDisassembler(STI, Ctx); 625 } 626 627 extern "C" void LLVMInitializeAMDGPUDisassembler() { 628 TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(), 629 createAMDGPUDisassembler); 630 TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(), 631 createAMDGPUSymbolizer); 632 } 633