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 //===----------------------------------------------------------------------===// 200 // AMDGPUTargetELFStreamer 201 //===----------------------------------------------------------------------===// 202 203 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer( 204 MCStreamer &S, const MCSubtargetInfo &STI) 205 : AMDGPUTargetStreamer(S), Streamer(S) { 206 MCAssembler &MCA = getStreamer().getAssembler(); 207 unsigned EFlags = MCA.getELFHeaderEFlags(); 208 209 EFlags &= ~ELF::EF_AMDGPU_MACH; 210 EFlags |= getMACH(STI.getCPU()); 211 212 EFlags &= ~ELF::EF_AMDGPU_XNACK; 213 if (AMDGPU::hasXNACK(STI)) 214 EFlags |= ELF::EF_AMDGPU_XNACK; 215 216 MCA.setELFHeaderEFlags(EFlags); 217 } 218 219 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() { 220 return static_cast<MCELFStreamer &>(Streamer); 221 } 222 223 void AMDGPUTargetELFStreamer::EmitAMDGPUNote( 224 const MCExpr *DescSZ, unsigned NoteType, 225 function_ref<void(MCELFStreamer &)> EmitDesc) { 226 auto &S = getStreamer(); 227 auto &Context = S.getContext(); 228 229 auto NameSZ = sizeof(ElfNote::NoteName); 230 231 S.PushSection(); 232 S.SwitchSection(Context.getELFSection( 233 ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC)); 234 S.EmitIntValue(NameSZ, 4); // namesz 235 S.EmitValue(DescSZ, 4); // descz 236 S.EmitIntValue(NoteType, 4); // type 237 S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ)); // name 238 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 239 EmitDesc(S); // desc 240 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 241 S.PopSection(); 242 } 243 244 void 245 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major, 246 uint32_t Minor) { 247 248 EmitAMDGPUNote( 249 MCConstantExpr::create(8, getContext()), 250 ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION, 251 [&](MCELFStreamer &OS){ 252 OS.EmitIntValue(Major, 4); 253 OS.EmitIntValue(Minor, 4); 254 } 255 ); 256 } 257 258 void 259 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major, 260 uint32_t Minor, 261 uint32_t Stepping, 262 StringRef VendorName, 263 StringRef ArchName) { 264 uint16_t VendorNameSize = VendorName.size() + 1; 265 uint16_t ArchNameSize = ArchName.size() + 1; 266 267 unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) + 268 sizeof(Major) + sizeof(Minor) + sizeof(Stepping) + 269 VendorNameSize + ArchNameSize; 270 271 EmitAMDGPUNote( 272 MCConstantExpr::create(DescSZ, getContext()), 273 ElfNote::NT_AMDGPU_HSA_ISA, 274 [&](MCELFStreamer &OS) { 275 OS.EmitIntValue(VendorNameSize, 2); 276 OS.EmitIntValue(ArchNameSize, 2); 277 OS.EmitIntValue(Major, 4); 278 OS.EmitIntValue(Minor, 4); 279 OS.EmitIntValue(Stepping, 4); 280 OS.EmitBytes(VendorName); 281 OS.EmitIntValue(0, 1); // NULL terminate VendorName 282 OS.EmitBytes(ArchName); 283 OS.EmitIntValue(0, 1); // NULL terminte ArchName 284 } 285 ); 286 } 287 288 void 289 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { 290 291 MCStreamer &OS = getStreamer(); 292 OS.PushSection(); 293 OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header))); 294 OS.PopSection(); 295 } 296 297 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName, 298 unsigned Type) { 299 MCSymbolELF *Symbol = cast<MCSymbolELF>( 300 getStreamer().getContext().getOrCreateSymbol(SymbolName)); 301 Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL); 302 } 303 304 bool AMDGPUTargetELFStreamer::EmitISAVersion(StringRef IsaVersionString) { 305 // Create two labels to mark the beginning and end of the desc field 306 // and a MCExpr to calculate the size of the desc field. 307 auto &Context = getContext(); 308 auto *DescBegin = Context.createTempSymbol(); 309 auto *DescEnd = Context.createTempSymbol(); 310 auto *DescSZ = MCBinaryExpr::createSub( 311 MCSymbolRefExpr::create(DescEnd, Context), 312 MCSymbolRefExpr::create(DescBegin, Context), Context); 313 314 EmitAMDGPUNote( 315 DescSZ, 316 ELF::NT_AMD_AMDGPU_ISA, 317 [&](MCELFStreamer &OS) { 318 OS.EmitLabel(DescBegin); 319 OS.EmitBytes(IsaVersionString); 320 OS.EmitLabel(DescEnd); 321 } 322 ); 323 return true; 324 } 325 326 bool AMDGPUTargetELFStreamer::EmitHSAMetadata( 327 const AMDGPU::HSAMD::Metadata &HSAMetadata) { 328 std::string HSAMetadataString; 329 if (HSAMD::toString(HSAMetadata, HSAMetadataString)) 330 return false; 331 332 // Create two labels to mark the beginning and end of the desc field 333 // and a MCExpr to calculate the size of the desc field. 334 auto &Context = getContext(); 335 auto *DescBegin = Context.createTempSymbol(); 336 auto *DescEnd = Context.createTempSymbol(); 337 auto *DescSZ = MCBinaryExpr::createSub( 338 MCSymbolRefExpr::create(DescEnd, Context), 339 MCSymbolRefExpr::create(DescBegin, Context), Context); 340 341 EmitAMDGPUNote( 342 DescSZ, 343 ELF::NT_AMD_AMDGPU_HSA_METADATA, 344 [&](MCELFStreamer &OS) { 345 OS.EmitLabel(DescBegin); 346 OS.EmitBytes(HSAMetadataString); 347 OS.EmitLabel(DescEnd); 348 } 349 ); 350 return true; 351 } 352 353 bool AMDGPUTargetELFStreamer::EmitPALMetadata( 354 const PALMD::Metadata &PALMetadata) { 355 EmitAMDGPUNote( 356 MCConstantExpr::create(PALMetadata.size() * sizeof(uint32_t), getContext()), 357 ELF::NT_AMD_AMDGPU_PAL_METADATA, 358 [&](MCELFStreamer &OS){ 359 for (auto I : PALMetadata) 360 OS.EmitIntValue(I, sizeof(uint32_t)); 361 } 362 ); 363 return true; 364 } 365