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 void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor(
200     StringRef KernelName,
201     const amdhsa::kernel_descriptor_t &KernelDescriptor) {
202   // FIXME: not supported yet.
203 }
204 
205 //===----------------------------------------------------------------------===//
206 // AMDGPUTargetELFStreamer
207 //===----------------------------------------------------------------------===//
208 
209 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(
210     MCStreamer &S, const MCSubtargetInfo &STI)
211     : AMDGPUTargetStreamer(S), Streamer(S) {
212   MCAssembler &MCA = getStreamer().getAssembler();
213   unsigned EFlags = MCA.getELFHeaderEFlags();
214 
215   EFlags &= ~ELF::EF_AMDGPU_MACH;
216   EFlags |= getMACH(STI.getCPU());
217 
218   EFlags &= ~ELF::EF_AMDGPU_XNACK;
219   if (AMDGPU::hasXNACK(STI))
220     EFlags |= ELF::EF_AMDGPU_XNACK;
221 
222   MCA.setELFHeaderEFlags(EFlags);
223 }
224 
225 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() {
226   return static_cast<MCELFStreamer &>(Streamer);
227 }
228 
229 void AMDGPUTargetELFStreamer::EmitAMDGPUNote(
230     const MCExpr *DescSZ, unsigned NoteType,
231     function_ref<void(MCELFStreamer &)> EmitDesc) {
232   auto &S = getStreamer();
233   auto &Context = S.getContext();
234 
235   auto NameSZ = sizeof(ElfNote::NoteName);
236 
237   S.PushSection();
238   S.SwitchSection(Context.getELFSection(
239     ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC));
240   S.EmitIntValue(NameSZ, 4);                                  // namesz
241   S.EmitValue(DescSZ, 4);                                     // descz
242   S.EmitIntValue(NoteType, 4);                                // type
243   S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ));          // name
244   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
245   EmitDesc(S);                                                // desc
246   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
247   S.PopSection();
248 }
249 
250 void
251 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
252                                                            uint32_t Minor) {
253 
254   EmitAMDGPUNote(
255     MCConstantExpr::create(8, getContext()),
256     ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION,
257     [&](MCELFStreamer &OS){
258       OS.EmitIntValue(Major, 4);
259       OS.EmitIntValue(Minor, 4);
260     }
261   );
262 }
263 
264 void
265 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
266                                                        uint32_t Minor,
267                                                        uint32_t Stepping,
268                                                        StringRef VendorName,
269                                                        StringRef ArchName) {
270   uint16_t VendorNameSize = VendorName.size() + 1;
271   uint16_t ArchNameSize = ArchName.size() + 1;
272 
273   unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) +
274     sizeof(Major) + sizeof(Minor) + sizeof(Stepping) +
275     VendorNameSize + ArchNameSize;
276 
277   EmitAMDGPUNote(
278     MCConstantExpr::create(DescSZ, getContext()),
279     ElfNote::NT_AMDGPU_HSA_ISA,
280     [&](MCELFStreamer &OS) {
281       OS.EmitIntValue(VendorNameSize, 2);
282       OS.EmitIntValue(ArchNameSize, 2);
283       OS.EmitIntValue(Major, 4);
284       OS.EmitIntValue(Minor, 4);
285       OS.EmitIntValue(Stepping, 4);
286       OS.EmitBytes(VendorName);
287       OS.EmitIntValue(0, 1); // NULL terminate VendorName
288       OS.EmitBytes(ArchName);
289       OS.EmitIntValue(0, 1); // NULL terminte ArchName
290     }
291   );
292 }
293 
294 void
295 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
296 
297   MCStreamer &OS = getStreamer();
298   OS.PushSection();
299   OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header)));
300   OS.PopSection();
301 }
302 
303 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
304                                                    unsigned Type) {
305   MCSymbolELF *Symbol = cast<MCSymbolELF>(
306       getStreamer().getContext().getOrCreateSymbol(SymbolName));
307   Symbol->setType(Type);
308 }
309 
310 bool AMDGPUTargetELFStreamer::EmitISAVersion(StringRef IsaVersionString) {
311   // Create two labels to mark the beginning and end of the desc field
312   // and a MCExpr to calculate the size of the desc field.
313   auto &Context = getContext();
314   auto *DescBegin = Context.createTempSymbol();
315   auto *DescEnd = Context.createTempSymbol();
316   auto *DescSZ = MCBinaryExpr::createSub(
317     MCSymbolRefExpr::create(DescEnd, Context),
318     MCSymbolRefExpr::create(DescBegin, Context), Context);
319 
320   EmitAMDGPUNote(
321     DescSZ,
322     ELF::NT_AMD_AMDGPU_ISA,
323     [&](MCELFStreamer &OS) {
324       OS.EmitLabel(DescBegin);
325       OS.EmitBytes(IsaVersionString);
326       OS.EmitLabel(DescEnd);
327     }
328   );
329   return true;
330 }
331 
332 bool AMDGPUTargetELFStreamer::EmitHSAMetadata(
333     const AMDGPU::HSAMD::Metadata &HSAMetadata) {
334   std::string HSAMetadataString;
335   if (HSAMD::toString(HSAMetadata, HSAMetadataString))
336     return false;
337 
338   // Create two labels to mark the beginning and end of the desc field
339   // and a MCExpr to calculate the size of the desc field.
340   auto &Context = getContext();
341   auto *DescBegin = Context.createTempSymbol();
342   auto *DescEnd = Context.createTempSymbol();
343   auto *DescSZ = MCBinaryExpr::createSub(
344     MCSymbolRefExpr::create(DescEnd, Context),
345     MCSymbolRefExpr::create(DescBegin, Context), Context);
346 
347   EmitAMDGPUNote(
348     DescSZ,
349     ELF::NT_AMD_AMDGPU_HSA_METADATA,
350     [&](MCELFStreamer &OS) {
351       OS.EmitLabel(DescBegin);
352       OS.EmitBytes(HSAMetadataString);
353       OS.EmitLabel(DescEnd);
354     }
355   );
356   return true;
357 }
358 
359 bool AMDGPUTargetELFStreamer::EmitPALMetadata(
360     const PALMD::Metadata &PALMetadata) {
361   EmitAMDGPUNote(
362     MCConstantExpr::create(PALMetadata.size() * sizeof(uint32_t), getContext()),
363     ELF::NT_AMD_AMDGPU_PAL_METADATA,
364     [&](MCELFStreamer &OS){
365       for (auto I : PALMetadata)
366         OS.EmitIntValue(I, sizeof(uint32_t));
367     }
368   );
369   return true;
370 }
371 
372 void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor(
373     StringRef KernelName,
374     const amdhsa::kernel_descriptor_t &KernelDescriptor) {
375   auto &Streamer = getStreamer();
376   auto &Context = Streamer.getContext();
377 
378   MCSymbolELF *KernelDescriptorSymbol = cast<MCSymbolELF>(
379       Context.getOrCreateSymbol(Twine(KernelName) + Twine(".kd")));
380   KernelDescriptorSymbol->setBinding(ELF::STB_GLOBAL);
381   KernelDescriptorSymbol->setType(ELF::STT_OBJECT);
382   KernelDescriptorSymbol->setSize(
383       MCConstantExpr::create(sizeof(KernelDescriptor), Context));
384 
385   MCSymbolELF *KernelCodeSymbol = cast<MCSymbolELF>(
386       Context.getOrCreateSymbol(Twine(KernelName)));
387   KernelCodeSymbol->setBinding(ELF::STB_LOCAL);
388 
389   Streamer.EmitLabel(KernelDescriptorSymbol);
390   Streamer.EmitBytes(StringRef(
391       (const char*)&(KernelDescriptor),
392       offsetof(amdhsa::kernel_descriptor_t, kernel_code_entry_byte_offset)));
393   // FIXME: Remove the use of VK_AMDGPU_REL64 in the expression below. The
394   // expression being created is:
395   //   (start of kernel code) - (start of kernel descriptor)
396   // It implies R_AMDGPU_REL64, but ends up being R_AMDGPU_ABS64.
397   Streamer.EmitValue(MCBinaryExpr::createSub(
398       MCSymbolRefExpr::create(
399           KernelCodeSymbol, MCSymbolRefExpr::VK_AMDGPU_REL64, Context),
400       MCSymbolRefExpr::create(
401           KernelDescriptorSymbol, MCSymbolRefExpr::VK_None, Context),
402       Context),
403       sizeof(KernelDescriptor.kernel_code_entry_byte_offset));
404   Streamer.EmitBytes(StringRef(
405       (const char*)&(KernelDescriptor) +
406           offsetof(amdhsa::kernel_descriptor_t, kernel_code_entry_byte_offset) +
407           sizeof(KernelDescriptor.kernel_code_entry_byte_offset),
408       sizeof(KernelDescriptor) -
409           offsetof(amdhsa::kernel_descriptor_t, kernel_code_entry_byte_offset) -
410           sizeof(KernelDescriptor.kernel_code_entry_byte_offset)));
411 }
412