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