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 AMDGPUTargetStreamer::AMDGPUTargetStreamer(MCStreamer &S) 43 : MCTargetStreamer(S) {} 44 45 bool AMDGPUTargetStreamer::EmitHSAMetadata(StringRef HSAMetadataString) { 46 HSAMD::Metadata HSAMetadata; 47 if (HSAMD::fromString(HSAMetadataString, HSAMetadata)) 48 return false; 49 50 return EmitHSAMetadata(HSAMetadata); 51 } 52 53 //===----------------------------------------------------------------------===// 54 // AMDGPUTargetAsmStreamer 55 //===----------------------------------------------------------------------===// 56 57 AMDGPUTargetAsmStreamer::AMDGPUTargetAsmStreamer(MCStreamer &S, 58 formatted_raw_ostream &OS) 59 : AMDGPUTargetStreamer(S), OS(OS) { } 60 61 void 62 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major, 63 uint32_t Minor) { 64 OS << "\t.hsa_code_object_version " << 65 Twine(Major) << "," << Twine(Minor) << '\n'; 66 } 67 68 void 69 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major, 70 uint32_t Minor, 71 uint32_t Stepping, 72 StringRef VendorName, 73 StringRef ArchName) { 74 OS << "\t.hsa_code_object_isa " << 75 Twine(Major) << "," << Twine(Minor) << "," << Twine(Stepping) << 76 ",\"" << VendorName << "\",\"" << ArchName << "\"\n"; 77 78 } 79 80 void 81 AMDGPUTargetAsmStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { 82 OS << "\t.amd_kernel_code_t\n"; 83 dumpAmdKernelCode(&Header, OS, "\t\t"); 84 OS << "\t.end_amd_kernel_code_t\n"; 85 } 86 87 void AMDGPUTargetAsmStreamer::EmitAMDGPUSymbolType(StringRef SymbolName, 88 unsigned Type) { 89 switch (Type) { 90 default: llvm_unreachable("Invalid AMDGPU symbol type"); 91 case ELF::STT_AMDGPU_HSA_KERNEL: 92 OS << "\t.amdgpu_hsa_kernel " << SymbolName << '\n' ; 93 break; 94 } 95 } 96 97 bool AMDGPUTargetAsmStreamer::EmitHSAMetadata( 98 const AMDGPU::HSAMD::Metadata &HSAMetadata) { 99 std::string HSAMetadataString; 100 if (HSAMD::toString(HSAMetadata, HSAMetadataString)) 101 return false; 102 103 OS << '\t' << HSAMD::AssemblerDirectiveBegin << '\n'; 104 OS << HSAMetadataString << '\n'; 105 OS << '\t' << HSAMD::AssemblerDirectiveEnd << '\n'; 106 return true; 107 } 108 109 bool AMDGPUTargetAsmStreamer::EmitPALMetadata( 110 const PALMD::Metadata &PALMetadata) { 111 std::string PALMetadataString; 112 if (PALMD::toString(PALMetadata, PALMetadataString)) 113 return false; 114 115 OS << '\t' << PALMD::AssemblerDirective << PALMetadataString << '\n'; 116 return true; 117 } 118 119 //===----------------------------------------------------------------------===// 120 // AMDGPUTargetELFStreamer 121 //===----------------------------------------------------------------------===// 122 123 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(MCStreamer &S) 124 : AMDGPUTargetStreamer(S), Streamer(S) {} 125 126 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() { 127 return static_cast<MCELFStreamer &>(Streamer); 128 } 129 130 void AMDGPUTargetELFStreamer::EmitAMDGPUNote( 131 const MCExpr *DescSZ, unsigned NoteType, 132 function_ref<void(MCELFStreamer &)> EmitDesc) { 133 auto &S = getStreamer(); 134 auto &Context = S.getContext(); 135 136 auto NameSZ = sizeof(ElfNote::NoteName); 137 138 S.PushSection(); 139 S.SwitchSection(Context.getELFSection( 140 ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC)); 141 S.EmitIntValue(NameSZ, 4); // namesz 142 S.EmitValue(DescSZ, 4); // descz 143 S.EmitIntValue(NoteType, 4); // type 144 S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ)); // name 145 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 146 EmitDesc(S); // desc 147 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 148 S.PopSection(); 149 } 150 151 void 152 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major, 153 uint32_t Minor) { 154 155 EmitAMDGPUNote( 156 MCConstantExpr::create(8, getContext()), 157 ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION, 158 [&](MCELFStreamer &OS){ 159 OS.EmitIntValue(Major, 4); 160 OS.EmitIntValue(Minor, 4); 161 } 162 ); 163 } 164 165 void 166 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major, 167 uint32_t Minor, 168 uint32_t Stepping, 169 StringRef VendorName, 170 StringRef ArchName) { 171 uint16_t VendorNameSize = VendorName.size() + 1; 172 uint16_t ArchNameSize = ArchName.size() + 1; 173 174 unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) + 175 sizeof(Major) + sizeof(Minor) + sizeof(Stepping) + 176 VendorNameSize + ArchNameSize; 177 178 EmitAMDGPUNote( 179 MCConstantExpr::create(DescSZ, getContext()), 180 ElfNote::NT_AMDGPU_HSA_ISA, 181 [&](MCELFStreamer &OS) { 182 OS.EmitIntValue(VendorNameSize, 2); 183 OS.EmitIntValue(ArchNameSize, 2); 184 OS.EmitIntValue(Major, 4); 185 OS.EmitIntValue(Minor, 4); 186 OS.EmitIntValue(Stepping, 4); 187 OS.EmitBytes(VendorName); 188 OS.EmitIntValue(0, 1); // NULL terminate VendorName 189 OS.EmitBytes(ArchName); 190 OS.EmitIntValue(0, 1); // NULL terminte ArchName 191 } 192 ); 193 } 194 195 void 196 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { 197 198 MCStreamer &OS = getStreamer(); 199 OS.PushSection(); 200 OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header))); 201 OS.PopSection(); 202 } 203 204 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName, 205 unsigned Type) { 206 MCSymbolELF *Symbol = cast<MCSymbolELF>( 207 getStreamer().getContext().getOrCreateSymbol(SymbolName)); 208 Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL); 209 } 210 211 bool AMDGPUTargetELFStreamer::EmitHSAMetadata( 212 const AMDGPU::HSAMD::Metadata &HSAMetadata) { 213 std::string HSAMetadataString; 214 if (HSAMD::toString(HSAMetadata, HSAMetadataString)) 215 return false; 216 217 // Create two labels to mark the beginning and end of the desc field 218 // and a MCExpr to calculate the size of the desc field. 219 auto &Context = getContext(); 220 auto *DescBegin = Context.createTempSymbol(); 221 auto *DescEnd = Context.createTempSymbol(); 222 auto *DescSZ = MCBinaryExpr::createSub( 223 MCSymbolRefExpr::create(DescEnd, Context), 224 MCSymbolRefExpr::create(DescBegin, Context), Context); 225 226 EmitAMDGPUNote( 227 DescSZ, 228 ELF::NT_AMD_AMDGPU_HSA_METADATA, 229 [&](MCELFStreamer &OS) { 230 OS.EmitLabel(DescBegin); 231 OS.EmitBytes(HSAMetadataString); 232 OS.EmitLabel(DescEnd); 233 } 234 ); 235 return true; 236 } 237 238 bool AMDGPUTargetELFStreamer::EmitPALMetadata( 239 const PALMD::Metadata &PALMetadata) { 240 EmitAMDGPUNote( 241 MCConstantExpr::create(PALMetadata.size() * sizeof(uint32_t), getContext()), 242 ELF::NT_AMD_AMDGPU_PAL_METADATA, 243 [&](MCELFStreamer &OS){ 244 for (auto I : PALMetadata) 245 OS.EmitIntValue(I, sizeof(uint32_t)); 246 } 247 ); 248 return true; 249 } 250