1 //===-- AMDGPUTargetStreamer.cpp - Mips Target Streamer Methods -----------===// 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 // This file provides AMDGPU specific target streamer methods. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AMDGPUTargetStreamer.h" 15 #include "AMDGPU.h" 16 #include "SIDefines.h" 17 #include "Utils/AMDGPUBaseInfo.h" 18 #include "Utils/AMDKernelCodeTUtils.h" 19 #include "llvm/ADT/Twine.h" 20 #include "llvm/BinaryFormat/ELF.h" 21 #include "llvm/IR/Constants.h" 22 #include "llvm/IR/Function.h" 23 #include "llvm/IR/Metadata.h" 24 #include "llvm/IR/Module.h" 25 #include "llvm/MC/MCContext.h" 26 #include "llvm/MC/MCELFStreamer.h" 27 #include "llvm/MC/MCObjectFileInfo.h" 28 #include "llvm/MC/MCSectionELF.h" 29 #include "llvm/Support/FormattedStream.h" 30 31 namespace llvm { 32 #include "AMDGPUPTNote.h" 33 } 34 35 using namespace llvm; 36 using namespace llvm::AMDGPU; 37 38 //===----------------------------------------------------------------------===// 39 // AMDGPUTargetStreamer 40 //===----------------------------------------------------------------------===// 41 42 static const struct { 43 const char *Name; 44 unsigned Mach; 45 } MachTable[] = { 46 // Radeon HD 2000/3000 Series (R600). 47 { "r600", ELF::EF_AMDGPU_MACH_R600_R600 }, 48 { "r630", ELF::EF_AMDGPU_MACH_R600_R630 }, 49 { "rs880", ELF::EF_AMDGPU_MACH_R600_RS880 }, 50 { "rv670", ELF::EF_AMDGPU_MACH_R600_RV670 }, 51 // Radeon HD 4000 Series (R700). 52 { "rv710", ELF::EF_AMDGPU_MACH_R600_RV710 }, 53 { "rv730", ELF::EF_AMDGPU_MACH_R600_RV730 }, 54 { "rv770", ELF::EF_AMDGPU_MACH_R600_RV770 }, 55 // Radeon HD 5000 Series (Evergreen). 56 { "cedar", ELF::EF_AMDGPU_MACH_R600_CEDAR }, 57 { "cypress", ELF::EF_AMDGPU_MACH_R600_CYPRESS }, 58 { "juniper", ELF::EF_AMDGPU_MACH_R600_JUNIPER }, 59 { "redwood", ELF::EF_AMDGPU_MACH_R600_REDWOOD }, 60 { "sumo", ELF::EF_AMDGPU_MACH_R600_SUMO }, 61 // Radeon HD 6000 Series (Northern Islands). 62 { "barts", ELF::EF_AMDGPU_MACH_R600_BARTS }, 63 { "caicos", ELF::EF_AMDGPU_MACH_R600_CAICOS }, 64 { "cayman", ELF::EF_AMDGPU_MACH_R600_CAYMAN }, 65 { "turks", ELF::EF_AMDGPU_MACH_R600_TURKS }, 66 // AMDGCN GFX6. 67 { "gfx600", ELF::EF_AMDGPU_MACH_AMDGCN_GFX600 }, 68 { "tahiti", ELF::EF_AMDGPU_MACH_AMDGCN_GFX600 }, 69 { "gfx601", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601 }, 70 { "hainan", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601 }, 71 { "oland", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601 }, 72 { "pitcairn", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601 }, 73 { "verde", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601 }, 74 // AMDGCN GFX7. 75 { "gfx700", ELF::EF_AMDGPU_MACH_AMDGCN_GFX700 }, 76 { "kaveri", ELF::EF_AMDGPU_MACH_AMDGCN_GFX700 }, 77 { "gfx701", ELF::EF_AMDGPU_MACH_AMDGCN_GFX701 }, 78 { "hawaii", ELF::EF_AMDGPU_MACH_AMDGCN_GFX701 }, 79 { "gfx702", ELF::EF_AMDGPU_MACH_AMDGCN_GFX702 }, 80 { "gfx703", ELF::EF_AMDGPU_MACH_AMDGCN_GFX703 }, 81 { "kabini", ELF::EF_AMDGPU_MACH_AMDGCN_GFX703 }, 82 { "mullins", ELF::EF_AMDGPU_MACH_AMDGCN_GFX703 }, 83 { "gfx704", ELF::EF_AMDGPU_MACH_AMDGCN_GFX704 }, 84 { "bonaire", ELF::EF_AMDGPU_MACH_AMDGCN_GFX704 }, 85 // AMDGCN GFX8. 86 { "gfx801", ELF::EF_AMDGPU_MACH_AMDGCN_GFX801 }, 87 { "carrizo", ELF::EF_AMDGPU_MACH_AMDGCN_GFX801 }, 88 { "gfx802", ELF::EF_AMDGPU_MACH_AMDGCN_GFX802 }, 89 { "iceland", ELF::EF_AMDGPU_MACH_AMDGCN_GFX802 }, 90 { "tonga", ELF::EF_AMDGPU_MACH_AMDGCN_GFX802 }, 91 { "gfx803", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803 }, 92 { "fiji", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803 }, 93 { "polaris10", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803 }, 94 { "polaris11", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803 }, 95 { "gfx810", ELF::EF_AMDGPU_MACH_AMDGCN_GFX810 }, 96 { "stoney", ELF::EF_AMDGPU_MACH_AMDGCN_GFX810 }, 97 // AMDGCN GFX9. 98 { "gfx900", ELF::EF_AMDGPU_MACH_AMDGCN_GFX900 }, 99 { "gfx902", ELF::EF_AMDGPU_MACH_AMDGCN_GFX902 }, 100 { "gfx904", ELF::EF_AMDGPU_MACH_AMDGCN_GFX904 }, 101 { "gfx906", ELF::EF_AMDGPU_MACH_AMDGCN_GFX906 }, 102 // Not specified processor. 103 { nullptr, ELF::EF_AMDGPU_MACH_NONE } 104 }; 105 106 unsigned AMDGPUTargetStreamer::getMACH(StringRef GPU) const { 107 auto Entry = MachTable; 108 for (; Entry->Name && GPU != Entry->Name; ++Entry) 109 ; 110 return Entry->Mach; 111 } 112 113 const char *AMDGPUTargetStreamer::getMachName(unsigned Mach) { 114 auto Entry = MachTable; 115 for (; Entry->Name && Mach != Entry->Mach; ++Entry) 116 ; 117 return Entry->Name; 118 } 119 120 bool AMDGPUTargetStreamer::EmitHSAMetadata(StringRef HSAMetadataString) { 121 HSAMD::Metadata HSAMetadata; 122 if (HSAMD::fromString(HSAMetadataString, HSAMetadata)) 123 return false; 124 125 return EmitHSAMetadata(HSAMetadata); 126 } 127 128 //===----------------------------------------------------------------------===// 129 // AMDGPUTargetAsmStreamer 130 //===----------------------------------------------------------------------===// 131 132 AMDGPUTargetAsmStreamer::AMDGPUTargetAsmStreamer(MCStreamer &S, 133 formatted_raw_ostream &OS) 134 : AMDGPUTargetStreamer(S), OS(OS) { } 135 136 void 137 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major, 138 uint32_t Minor) { 139 OS << "\t.hsa_code_object_version " << 140 Twine(Major) << "," << Twine(Minor) << '\n'; 141 } 142 143 void 144 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major, 145 uint32_t Minor, 146 uint32_t Stepping, 147 StringRef VendorName, 148 StringRef ArchName) { 149 OS << "\t.hsa_code_object_isa " << 150 Twine(Major) << "," << Twine(Minor) << "," << Twine(Stepping) << 151 ",\"" << VendorName << "\",\"" << ArchName << "\"\n"; 152 153 } 154 155 void 156 AMDGPUTargetAsmStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { 157 OS << "\t.amd_kernel_code_t\n"; 158 dumpAmdKernelCode(&Header, OS, "\t\t"); 159 OS << "\t.end_amd_kernel_code_t\n"; 160 } 161 162 void AMDGPUTargetAsmStreamer::EmitAMDGPUSymbolType(StringRef SymbolName, 163 unsigned Type) { 164 switch (Type) { 165 default: llvm_unreachable("Invalid AMDGPU symbol type"); 166 case ELF::STT_AMDGPU_HSA_KERNEL: 167 OS << "\t.amdgpu_hsa_kernel " << SymbolName << '\n' ; 168 break; 169 } 170 } 171 172 bool AMDGPUTargetAsmStreamer::EmitISAVersion(StringRef IsaVersionString) { 173 OS << "\t.amd_amdgpu_isa \"" << IsaVersionString << "\"\n"; 174 return true; 175 } 176 177 bool AMDGPUTargetAsmStreamer::EmitHSAMetadata( 178 const AMDGPU::HSAMD::Metadata &HSAMetadata) { 179 std::string HSAMetadataString; 180 if (HSAMD::toString(HSAMetadata, HSAMetadataString)) 181 return false; 182 183 OS << '\t' << HSAMD::AssemblerDirectiveBegin << '\n'; 184 OS << HSAMetadataString << '\n'; 185 OS << '\t' << HSAMD::AssemblerDirectiveEnd << '\n'; 186 return true; 187 } 188 189 bool AMDGPUTargetAsmStreamer::EmitPALMetadata( 190 const PALMD::Metadata &PALMetadata) { 191 std::string PALMetadataString; 192 if (PALMD::toString(PALMetadata, PALMetadataString)) 193 return false; 194 195 OS << '\t' << PALMD::AssemblerDirective << PALMetadataString << '\n'; 196 return true; 197 } 198 199 void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor( 200 StringRef KernelName, 201 const amdhsa::kernel_descriptor_t &KernelDescriptor) { 202 // FIXME: not supported yet. 203 } 204 205 //===----------------------------------------------------------------------===// 206 // AMDGPUTargetELFStreamer 207 //===----------------------------------------------------------------------===// 208 209 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer( 210 MCStreamer &S, const MCSubtargetInfo &STI) 211 : AMDGPUTargetStreamer(S), Streamer(S) { 212 MCAssembler &MCA = getStreamer().getAssembler(); 213 unsigned EFlags = MCA.getELFHeaderEFlags(); 214 215 EFlags &= ~ELF::EF_AMDGPU_MACH; 216 EFlags |= getMACH(STI.getCPU()); 217 218 EFlags &= ~ELF::EF_AMDGPU_XNACK; 219 if (AMDGPU::hasXNACK(STI)) 220 EFlags |= ELF::EF_AMDGPU_XNACK; 221 222 MCA.setELFHeaderEFlags(EFlags); 223 } 224 225 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() { 226 return static_cast<MCELFStreamer &>(Streamer); 227 } 228 229 void AMDGPUTargetELFStreamer::EmitAMDGPUNote( 230 const MCExpr *DescSZ, unsigned NoteType, 231 function_ref<void(MCELFStreamer &)> EmitDesc) { 232 auto &S = getStreamer(); 233 auto &Context = S.getContext(); 234 235 auto NameSZ = sizeof(ElfNote::NoteName); 236 237 S.PushSection(); 238 S.SwitchSection(Context.getELFSection( 239 ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC)); 240 S.EmitIntValue(NameSZ, 4); // namesz 241 S.EmitValue(DescSZ, 4); // descz 242 S.EmitIntValue(NoteType, 4); // type 243 S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ)); // name 244 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 245 EmitDesc(S); // desc 246 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 247 S.PopSection(); 248 } 249 250 void 251 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major, 252 uint32_t Minor) { 253 254 EmitAMDGPUNote( 255 MCConstantExpr::create(8, getContext()), 256 ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION, 257 [&](MCELFStreamer &OS){ 258 OS.EmitIntValue(Major, 4); 259 OS.EmitIntValue(Minor, 4); 260 } 261 ); 262 } 263 264 void 265 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major, 266 uint32_t Minor, 267 uint32_t Stepping, 268 StringRef VendorName, 269 StringRef ArchName) { 270 uint16_t VendorNameSize = VendorName.size() + 1; 271 uint16_t ArchNameSize = ArchName.size() + 1; 272 273 unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) + 274 sizeof(Major) + sizeof(Minor) + sizeof(Stepping) + 275 VendorNameSize + ArchNameSize; 276 277 EmitAMDGPUNote( 278 MCConstantExpr::create(DescSZ, getContext()), 279 ElfNote::NT_AMDGPU_HSA_ISA, 280 [&](MCELFStreamer &OS) { 281 OS.EmitIntValue(VendorNameSize, 2); 282 OS.EmitIntValue(ArchNameSize, 2); 283 OS.EmitIntValue(Major, 4); 284 OS.EmitIntValue(Minor, 4); 285 OS.EmitIntValue(Stepping, 4); 286 OS.EmitBytes(VendorName); 287 OS.EmitIntValue(0, 1); // NULL terminate VendorName 288 OS.EmitBytes(ArchName); 289 OS.EmitIntValue(0, 1); // NULL terminte ArchName 290 } 291 ); 292 } 293 294 void 295 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { 296 297 MCStreamer &OS = getStreamer(); 298 OS.PushSection(); 299 OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header))); 300 OS.PopSection(); 301 } 302 303 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName, 304 unsigned Type) { 305 MCSymbolELF *Symbol = cast<MCSymbolELF>( 306 getStreamer().getContext().getOrCreateSymbol(SymbolName)); 307 Symbol->setType(Type); 308 } 309 310 bool AMDGPUTargetELFStreamer::EmitISAVersion(StringRef IsaVersionString) { 311 // Create two labels to mark the beginning and end of the desc field 312 // and a MCExpr to calculate the size of the desc field. 313 auto &Context = getContext(); 314 auto *DescBegin = Context.createTempSymbol(); 315 auto *DescEnd = Context.createTempSymbol(); 316 auto *DescSZ = MCBinaryExpr::createSub( 317 MCSymbolRefExpr::create(DescEnd, Context), 318 MCSymbolRefExpr::create(DescBegin, Context), Context); 319 320 EmitAMDGPUNote( 321 DescSZ, 322 ELF::NT_AMD_AMDGPU_ISA, 323 [&](MCELFStreamer &OS) { 324 OS.EmitLabel(DescBegin); 325 OS.EmitBytes(IsaVersionString); 326 OS.EmitLabel(DescEnd); 327 } 328 ); 329 return true; 330 } 331 332 bool AMDGPUTargetELFStreamer::EmitHSAMetadata( 333 const AMDGPU::HSAMD::Metadata &HSAMetadata) { 334 std::string HSAMetadataString; 335 if (HSAMD::toString(HSAMetadata, HSAMetadataString)) 336 return false; 337 338 // Create two labels to mark the beginning and end of the desc field 339 // and a MCExpr to calculate the size of the desc field. 340 auto &Context = getContext(); 341 auto *DescBegin = Context.createTempSymbol(); 342 auto *DescEnd = Context.createTempSymbol(); 343 auto *DescSZ = MCBinaryExpr::createSub( 344 MCSymbolRefExpr::create(DescEnd, Context), 345 MCSymbolRefExpr::create(DescBegin, Context), Context); 346 347 EmitAMDGPUNote( 348 DescSZ, 349 ELF::NT_AMD_AMDGPU_HSA_METADATA, 350 [&](MCELFStreamer &OS) { 351 OS.EmitLabel(DescBegin); 352 OS.EmitBytes(HSAMetadataString); 353 OS.EmitLabel(DescEnd); 354 } 355 ); 356 return true; 357 } 358 359 bool AMDGPUTargetELFStreamer::EmitPALMetadata( 360 const PALMD::Metadata &PALMetadata) { 361 EmitAMDGPUNote( 362 MCConstantExpr::create(PALMetadata.size() * sizeof(uint32_t), getContext()), 363 ELF::NT_AMD_AMDGPU_PAL_METADATA, 364 [&](MCELFStreamer &OS){ 365 for (auto I : PALMetadata) 366 OS.EmitIntValue(I, sizeof(uint32_t)); 367 } 368 ); 369 return true; 370 } 371 372 void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor( 373 StringRef KernelName, 374 const amdhsa::kernel_descriptor_t &KernelDescriptor) { 375 auto &Streamer = getStreamer(); 376 auto &Context = Streamer.getContext(); 377 378 MCSymbolELF *KernelDescriptorSymbol = cast<MCSymbolELF>( 379 Context.getOrCreateSymbol(Twine(KernelName) + Twine(".kd"))); 380 KernelDescriptorSymbol->setBinding(ELF::STB_GLOBAL); 381 KernelDescriptorSymbol->setType(ELF::STT_OBJECT); 382 KernelDescriptorSymbol->setSize( 383 MCConstantExpr::create(sizeof(KernelDescriptor), Context)); 384 385 MCSymbolELF *KernelCodeSymbol = cast<MCSymbolELF>( 386 Context.getOrCreateSymbol(Twine(KernelName))); 387 KernelCodeSymbol->setBinding(ELF::STB_LOCAL); 388 389 Streamer.EmitLabel(KernelDescriptorSymbol); 390 Streamer.EmitBytes(StringRef( 391 (const char*)&(KernelDescriptor), 392 offsetof(amdhsa::kernel_descriptor_t, kernel_code_entry_byte_offset))); 393 // FIXME: Remove the use of VK_AMDGPU_REL64 in the expression below. The 394 // expression being created is: 395 // (start of kernel code) - (start of kernel descriptor) 396 // It implies R_AMDGPU_REL64, but ends up being R_AMDGPU_ABS64. 397 Streamer.EmitValue(MCBinaryExpr::createSub( 398 MCSymbolRefExpr::create( 399 KernelCodeSymbol, MCSymbolRefExpr::VK_AMDGPU_REL64, Context), 400 MCSymbolRefExpr::create( 401 KernelDescriptorSymbol, MCSymbolRefExpr::VK_None, Context), 402 Context), 403 sizeof(KernelDescriptor.kernel_code_entry_byte_offset)); 404 Streamer.EmitBytes(StringRef( 405 (const char*)&(KernelDescriptor) + 406 offsetof(amdhsa::kernel_descriptor_t, kernel_code_entry_byte_offset) + 407 sizeof(KernelDescriptor.kernel_code_entry_byte_offset), 408 sizeof(KernelDescriptor) - 409 offsetof(amdhsa::kernel_descriptor_t, kernel_code_entry_byte_offset) - 410 sizeof(KernelDescriptor.kernel_code_entry_byte_offset))); 411 } 412