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 unsigned AMDGPUTargetStreamer::getMACH(StringRef GPU) const {
43   return llvm::StringSwitch<unsigned>(GPU)
44       // Radeon HD 2000/3000 Series (R600).
45       .Case("r600", ELF::EF_AMDGPU_MACH_R600_R600)
46       .Case("r630", ELF::EF_AMDGPU_MACH_R600_R630)
47       .Case("rs880", ELF::EF_AMDGPU_MACH_R600_RS880)
48       .Case("rv670", ELF::EF_AMDGPU_MACH_R600_RV670)
49       // Radeon HD 4000 Series (R700).
50       .Case("rv710", ELF::EF_AMDGPU_MACH_R600_RV710)
51       .Case("rv730", ELF::EF_AMDGPU_MACH_R600_RV730)
52       .Case("rv770", ELF::EF_AMDGPU_MACH_R600_RV770)
53       // Radeon HD 5000 Series (Evergreen).
54       .Case("cedar", ELF::EF_AMDGPU_MACH_R600_CEDAR)
55       .Case("cypress", ELF::EF_AMDGPU_MACH_R600_CYPRESS)
56       .Case("juniper", ELF::EF_AMDGPU_MACH_R600_JUNIPER)
57       .Case("redwood", ELF::EF_AMDGPU_MACH_R600_REDWOOD)
58       .Case("sumo", ELF::EF_AMDGPU_MACH_R600_SUMO)
59       // Radeon HD 6000 Series (Northern Islands).
60       .Case("barts", ELF::EF_AMDGPU_MACH_R600_BARTS)
61       .Case("caicos", ELF::EF_AMDGPU_MACH_R600_CAICOS)
62       .Case("cayman", ELF::EF_AMDGPU_MACH_R600_CAYMAN)
63       .Case("turks", ELF::EF_AMDGPU_MACH_R600_TURKS)
64       // AMDGCN GFX6.
65       .Case("gfx600", ELF::EF_AMDGPU_MACH_AMDGCN_GFX600)
66       .Case("tahiti", ELF::EF_AMDGPU_MACH_AMDGCN_GFX600)
67       .Case("gfx601", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601)
68       .Case("hainan", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601)
69       .Case("oland", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601)
70       .Case("pitcairn", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601)
71       .Case("verde", ELF::EF_AMDGPU_MACH_AMDGCN_GFX601)
72       // AMDGCN GFX7.
73       .Case("gfx700", ELF::EF_AMDGPU_MACH_AMDGCN_GFX700)
74       .Case("kaveri", ELF::EF_AMDGPU_MACH_AMDGCN_GFX700)
75       .Case("gfx701", ELF::EF_AMDGPU_MACH_AMDGCN_GFX701)
76       .Case("hawaii", ELF::EF_AMDGPU_MACH_AMDGCN_GFX701)
77       .Case("gfx702", ELF::EF_AMDGPU_MACH_AMDGCN_GFX702)
78       .Case("gfx703", ELF::EF_AMDGPU_MACH_AMDGCN_GFX703)
79       .Case("kabini", ELF::EF_AMDGPU_MACH_AMDGCN_GFX703)
80       .Case("mullins", ELF::EF_AMDGPU_MACH_AMDGCN_GFX703)
81       .Case("gfx704", ELF::EF_AMDGPU_MACH_AMDGCN_GFX704)
82       .Case("bonaire", ELF::EF_AMDGPU_MACH_AMDGCN_GFX704)
83       // AMDGCN GFX8.
84       .Case("gfx801", ELF::EF_AMDGPU_MACH_AMDGCN_GFX801)
85       .Case("carrizo", ELF::EF_AMDGPU_MACH_AMDGCN_GFX801)
86       .Case("gfx802", ELF::EF_AMDGPU_MACH_AMDGCN_GFX802)
87       .Case("iceland", ELF::EF_AMDGPU_MACH_AMDGCN_GFX802)
88       .Case("tonga", ELF::EF_AMDGPU_MACH_AMDGCN_GFX802)
89       .Case("gfx803", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803)
90       .Case("fiji", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803)
91       .Case("polaris10", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803)
92       .Case("polaris11", ELF::EF_AMDGPU_MACH_AMDGCN_GFX803)
93       .Case("gfx810", ELF::EF_AMDGPU_MACH_AMDGCN_GFX810)
94       .Case("stoney", ELF::EF_AMDGPU_MACH_AMDGCN_GFX810)
95       // AMDGCN GFX9.
96       .Case("gfx900", ELF::EF_AMDGPU_MACH_AMDGCN_GFX900)
97       .Case("gfx902", ELF::EF_AMDGPU_MACH_AMDGCN_GFX902)
98       // Not specified processor.
99       .Default(ELF::EF_AMDGPU_MACH_NONE);
100 }
101 
102 bool AMDGPUTargetStreamer::EmitHSAMetadata(StringRef HSAMetadataString) {
103   HSAMD::Metadata HSAMetadata;
104   if (HSAMD::fromString(HSAMetadataString, HSAMetadata))
105     return false;
106 
107   return EmitHSAMetadata(HSAMetadata);
108 }
109 
110 //===----------------------------------------------------------------------===//
111 // AMDGPUTargetAsmStreamer
112 //===----------------------------------------------------------------------===//
113 
114 AMDGPUTargetAsmStreamer::AMDGPUTargetAsmStreamer(MCStreamer &S,
115                                                  formatted_raw_ostream &OS)
116     : AMDGPUTargetStreamer(S), OS(OS) { }
117 
118 void
119 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
120                                                            uint32_t Minor) {
121   OS << "\t.hsa_code_object_version " <<
122         Twine(Major) << "," << Twine(Minor) << '\n';
123 }
124 
125 void
126 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
127                                                        uint32_t Minor,
128                                                        uint32_t Stepping,
129                                                        StringRef VendorName,
130                                                        StringRef ArchName) {
131   OS << "\t.hsa_code_object_isa " <<
132         Twine(Major) << "," << Twine(Minor) << "," << Twine(Stepping) <<
133         ",\"" << VendorName << "\",\"" << ArchName << "\"\n";
134 
135 }
136 
137 void
138 AMDGPUTargetAsmStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
139   OS << "\t.amd_kernel_code_t\n";
140   dumpAmdKernelCode(&Header, OS, "\t\t");
141   OS << "\t.end_amd_kernel_code_t\n";
142 }
143 
144 void AMDGPUTargetAsmStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
145                                                    unsigned Type) {
146   switch (Type) {
147     default: llvm_unreachable("Invalid AMDGPU symbol type");
148     case ELF::STT_AMDGPU_HSA_KERNEL:
149       OS << "\t.amdgpu_hsa_kernel " << SymbolName << '\n' ;
150       break;
151   }
152 }
153 
154 bool AMDGPUTargetAsmStreamer::EmitISAVersion(StringRef IsaVersionString) {
155   OS << "\t.amd_amdgpu_isa \"" << IsaVersionString << "\"\n";
156   return true;
157 }
158 
159 bool AMDGPUTargetAsmStreamer::EmitHSAMetadata(
160     const AMDGPU::HSAMD::Metadata &HSAMetadata) {
161   std::string HSAMetadataString;
162   if (HSAMD::toString(HSAMetadata, HSAMetadataString))
163     return false;
164 
165   OS << '\t' << HSAMD::AssemblerDirectiveBegin << '\n';
166   OS << HSAMetadataString << '\n';
167   OS << '\t' << HSAMD::AssemblerDirectiveEnd << '\n';
168   return true;
169 }
170 
171 bool AMDGPUTargetAsmStreamer::EmitPALMetadata(
172     const PALMD::Metadata &PALMetadata) {
173   std::string PALMetadataString;
174   if (PALMD::toString(PALMetadata, PALMetadataString))
175     return false;
176 
177   OS << '\t' << PALMD::AssemblerDirective << PALMetadataString << '\n';
178   return true;
179 }
180 
181 //===----------------------------------------------------------------------===//
182 // AMDGPUTargetELFStreamer
183 //===----------------------------------------------------------------------===//
184 
185 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(
186     MCStreamer &S, const MCSubtargetInfo &STI)
187     : AMDGPUTargetStreamer(S), Streamer(S) {
188   MCAssembler &MCA = getStreamer().getAssembler();
189   unsigned EFlags = MCA.getELFHeaderEFlags();
190 
191   EFlags &= ~ELF::EF_AMDGPU_MACH;
192   EFlags |= getMACH(STI.getCPU());
193 
194   EFlags &= ~ELF::EF_AMDGPU_XNACK;
195   if (AMDGPU::hasXNACK(STI))
196     EFlags |= ELF::EF_AMDGPU_XNACK;
197 
198   MCA.setELFHeaderEFlags(EFlags);
199 }
200 
201 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() {
202   return static_cast<MCELFStreamer &>(Streamer);
203 }
204 
205 void AMDGPUTargetELFStreamer::EmitAMDGPUNote(
206     const MCExpr *DescSZ, unsigned NoteType,
207     function_ref<void(MCELFStreamer &)> EmitDesc) {
208   auto &S = getStreamer();
209   auto &Context = S.getContext();
210 
211   auto NameSZ = sizeof(ElfNote::NoteName);
212 
213   S.PushSection();
214   S.SwitchSection(Context.getELFSection(
215     ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC));
216   S.EmitIntValue(NameSZ, 4);                                  // namesz
217   S.EmitValue(DescSZ, 4);                                     // descz
218   S.EmitIntValue(NoteType, 4);                                // type
219   S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ));          // name
220   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
221   EmitDesc(S);                                                // desc
222   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
223   S.PopSection();
224 }
225 
226 void
227 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
228                                                            uint32_t Minor) {
229 
230   EmitAMDGPUNote(
231     MCConstantExpr::create(8, getContext()),
232     ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION,
233     [&](MCELFStreamer &OS){
234       OS.EmitIntValue(Major, 4);
235       OS.EmitIntValue(Minor, 4);
236     }
237   );
238 }
239 
240 void
241 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
242                                                        uint32_t Minor,
243                                                        uint32_t Stepping,
244                                                        StringRef VendorName,
245                                                        StringRef ArchName) {
246   uint16_t VendorNameSize = VendorName.size() + 1;
247   uint16_t ArchNameSize = ArchName.size() + 1;
248 
249   unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) +
250     sizeof(Major) + sizeof(Minor) + sizeof(Stepping) +
251     VendorNameSize + ArchNameSize;
252 
253   EmitAMDGPUNote(
254     MCConstantExpr::create(DescSZ, getContext()),
255     ElfNote::NT_AMDGPU_HSA_ISA,
256     [&](MCELFStreamer &OS) {
257       OS.EmitIntValue(VendorNameSize, 2);
258       OS.EmitIntValue(ArchNameSize, 2);
259       OS.EmitIntValue(Major, 4);
260       OS.EmitIntValue(Minor, 4);
261       OS.EmitIntValue(Stepping, 4);
262       OS.EmitBytes(VendorName);
263       OS.EmitIntValue(0, 1); // NULL terminate VendorName
264       OS.EmitBytes(ArchName);
265       OS.EmitIntValue(0, 1); // NULL terminte ArchName
266     }
267   );
268 }
269 
270 void
271 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
272 
273   MCStreamer &OS = getStreamer();
274   OS.PushSection();
275   OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header)));
276   OS.PopSection();
277 }
278 
279 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
280                                                    unsigned Type) {
281   MCSymbolELF *Symbol = cast<MCSymbolELF>(
282       getStreamer().getContext().getOrCreateSymbol(SymbolName));
283   Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL);
284 }
285 
286 bool AMDGPUTargetELFStreamer::EmitISAVersion(StringRef IsaVersionString) {
287   // Create two labels to mark the beginning and end of the desc field
288   // and a MCExpr to calculate the size of the desc field.
289   auto &Context = getContext();
290   auto *DescBegin = Context.createTempSymbol();
291   auto *DescEnd = Context.createTempSymbol();
292   auto *DescSZ = MCBinaryExpr::createSub(
293     MCSymbolRefExpr::create(DescEnd, Context),
294     MCSymbolRefExpr::create(DescBegin, Context), Context);
295 
296   EmitAMDGPUNote(
297     DescSZ,
298     ELF::NT_AMD_AMDGPU_ISA,
299     [&](MCELFStreamer &OS) {
300       OS.EmitLabel(DescBegin);
301       OS.EmitBytes(IsaVersionString);
302       OS.EmitLabel(DescEnd);
303     }
304   );
305   return true;
306 }
307 
308 bool AMDGPUTargetELFStreamer::EmitHSAMetadata(
309     const AMDGPU::HSAMD::Metadata &HSAMetadata) {
310   std::string HSAMetadataString;
311   if (HSAMD::toString(HSAMetadata, HSAMetadataString))
312     return false;
313 
314   // Create two labels to mark the beginning and end of the desc field
315   // and a MCExpr to calculate the size of the desc field.
316   auto &Context = getContext();
317   auto *DescBegin = Context.createTempSymbol();
318   auto *DescEnd = Context.createTempSymbol();
319   auto *DescSZ = MCBinaryExpr::createSub(
320     MCSymbolRefExpr::create(DescEnd, Context),
321     MCSymbolRefExpr::create(DescBegin, Context), Context);
322 
323   EmitAMDGPUNote(
324     DescSZ,
325     ELF::NT_AMD_AMDGPU_HSA_METADATA,
326     [&](MCELFStreamer &OS) {
327       OS.EmitLabel(DescBegin);
328       OS.EmitBytes(HSAMetadataString);
329       OS.EmitLabel(DescEnd);
330     }
331   );
332   return true;
333 }
334 
335 bool AMDGPUTargetELFStreamer::EmitPALMetadata(
336     const PALMD::Metadata &PALMetadata) {
337   EmitAMDGPUNote(
338     MCConstantExpr::create(PALMetadata.size() * sizeof(uint32_t), getContext()),
339     ELF::NT_AMD_AMDGPU_PAL_METADATA,
340     [&](MCELFStreamer &OS){
341       for (auto I : PALMetadata)
342         OS.EmitIntValue(I, sizeof(uint32_t));
343     }
344   );
345   return true;
346 }
347