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 //===----------------------------------------------------------------------===// 116 // AMDGPUTargetELFStreamer 117 //===----------------------------------------------------------------------===// 118 119 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(MCStreamer &S) 120 : AMDGPUTargetStreamer(S), Streamer(S) {} 121 122 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() { 123 return static_cast<MCELFStreamer &>(Streamer); 124 } 125 126 void AMDGPUTargetELFStreamer::EmitAMDGPUNote( 127 const MCExpr *DescSZ, ElfNote::NoteType Type, 128 function_ref<void(MCELFStreamer &)> EmitDesc) { 129 auto &S = getStreamer(); 130 auto &Context = S.getContext(); 131 132 auto NameSZ = sizeof(ElfNote::NoteName); 133 134 S.PushSection(); 135 S.SwitchSection(Context.getELFSection( 136 ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC)); 137 S.EmitIntValue(NameSZ, 4); // namesz 138 S.EmitValue(DescSZ, 4); // descz 139 S.EmitIntValue(Type, 4); // type 140 S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ)); // name 141 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 142 EmitDesc(S); // desc 143 S.EmitValueToAlignment(4, 0, 1, 0); // padding 0 144 S.PopSection(); 145 } 146 147 void 148 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major, 149 uint32_t Minor) { 150 151 EmitAMDGPUNote( 152 MCConstantExpr::create(8, getContext()), 153 ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION, 154 [&](MCELFStreamer &OS){ 155 OS.EmitIntValue(Major, 4); 156 OS.EmitIntValue(Minor, 4); 157 } 158 ); 159 } 160 161 void 162 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major, 163 uint32_t Minor, 164 uint32_t Stepping, 165 StringRef VendorName, 166 StringRef ArchName) { 167 uint16_t VendorNameSize = VendorName.size() + 1; 168 uint16_t ArchNameSize = ArchName.size() + 1; 169 170 unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) + 171 sizeof(Major) + sizeof(Minor) + sizeof(Stepping) + 172 VendorNameSize + ArchNameSize; 173 174 EmitAMDGPUNote( 175 MCConstantExpr::create(DescSZ, getContext()), 176 ElfNote::NT_AMDGPU_HSA_ISA, 177 [&](MCELFStreamer &OS) { 178 OS.EmitIntValue(VendorNameSize, 2); 179 OS.EmitIntValue(ArchNameSize, 2); 180 OS.EmitIntValue(Major, 4); 181 OS.EmitIntValue(Minor, 4); 182 OS.EmitIntValue(Stepping, 4); 183 OS.EmitBytes(VendorName); 184 OS.EmitIntValue(0, 1); // NULL terminate VendorName 185 OS.EmitBytes(ArchName); 186 OS.EmitIntValue(0, 1); // NULL terminte ArchName 187 } 188 ); 189 } 190 191 void 192 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { 193 194 MCStreamer &OS = getStreamer(); 195 OS.PushSection(); 196 OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header))); 197 OS.PopSection(); 198 } 199 200 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName, 201 unsigned Type) { 202 MCSymbolELF *Symbol = cast<MCSymbolELF>( 203 getStreamer().getContext().getOrCreateSymbol(SymbolName)); 204 Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL); 205 } 206 207 bool AMDGPUTargetELFStreamer::EmitCodeObjectMetadata(StringRef YamlString) { 208 auto VerifiedYamlString = CodeObjectMetadataStreamer.toYamlString(YamlString); 209 if (!VerifiedYamlString) 210 return false; 211 212 // Create two labels to mark the beginning and end of the desc field 213 // and a MCExpr to calculate the size of the desc field. 214 auto &Context = getContext(); 215 auto *DescBegin = Context.createTempSymbol(); 216 auto *DescEnd = Context.createTempSymbol(); 217 auto *DescSZ = MCBinaryExpr::createSub( 218 MCSymbolRefExpr::create(DescEnd, Context), 219 MCSymbolRefExpr::create(DescBegin, Context), Context); 220 221 EmitAMDGPUNote( 222 DescSZ, 223 ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_METADATA, 224 [&](MCELFStreamer &OS) { 225 OS.EmitLabel(DescBegin); 226 OS.EmitBytes(VerifiedYamlString.get()); 227 OS.EmitLabel(DescEnd); 228 } 229 ); 230 231 return true; 232 } 233