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 //===----------------------------------------------------------------------===//
200 // AMDGPUTargetELFStreamer
201 //===----------------------------------------------------------------------===//
202 
203 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(
204     MCStreamer &S, const MCSubtargetInfo &STI)
205     : AMDGPUTargetStreamer(S), Streamer(S) {
206   MCAssembler &MCA = getStreamer().getAssembler();
207   unsigned EFlags = MCA.getELFHeaderEFlags();
208 
209   EFlags &= ~ELF::EF_AMDGPU_MACH;
210   EFlags |= getMACH(STI.getCPU());
211 
212   EFlags &= ~ELF::EF_AMDGPU_XNACK;
213   if (AMDGPU::hasXNACK(STI))
214     EFlags |= ELF::EF_AMDGPU_XNACK;
215 
216   MCA.setELFHeaderEFlags(EFlags);
217 }
218 
219 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() {
220   return static_cast<MCELFStreamer &>(Streamer);
221 }
222 
223 void AMDGPUTargetELFStreamer::EmitAMDGPUNote(
224     const MCExpr *DescSZ, unsigned NoteType,
225     function_ref<void(MCELFStreamer &)> EmitDesc) {
226   auto &S = getStreamer();
227   auto &Context = S.getContext();
228 
229   auto NameSZ = sizeof(ElfNote::NoteName);
230 
231   S.PushSection();
232   S.SwitchSection(Context.getELFSection(
233     ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC));
234   S.EmitIntValue(NameSZ, 4);                                  // namesz
235   S.EmitValue(DescSZ, 4);                                     // descz
236   S.EmitIntValue(NoteType, 4);                                // type
237   S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ));          // name
238   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
239   EmitDesc(S);                                                // desc
240   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
241   S.PopSection();
242 }
243 
244 void
245 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
246                                                            uint32_t Minor) {
247 
248   EmitAMDGPUNote(
249     MCConstantExpr::create(8, getContext()),
250     ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION,
251     [&](MCELFStreamer &OS){
252       OS.EmitIntValue(Major, 4);
253       OS.EmitIntValue(Minor, 4);
254     }
255   );
256 }
257 
258 void
259 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
260                                                        uint32_t Minor,
261                                                        uint32_t Stepping,
262                                                        StringRef VendorName,
263                                                        StringRef ArchName) {
264   uint16_t VendorNameSize = VendorName.size() + 1;
265   uint16_t ArchNameSize = ArchName.size() + 1;
266 
267   unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) +
268     sizeof(Major) + sizeof(Minor) + sizeof(Stepping) +
269     VendorNameSize + ArchNameSize;
270 
271   EmitAMDGPUNote(
272     MCConstantExpr::create(DescSZ, getContext()),
273     ElfNote::NT_AMDGPU_HSA_ISA,
274     [&](MCELFStreamer &OS) {
275       OS.EmitIntValue(VendorNameSize, 2);
276       OS.EmitIntValue(ArchNameSize, 2);
277       OS.EmitIntValue(Major, 4);
278       OS.EmitIntValue(Minor, 4);
279       OS.EmitIntValue(Stepping, 4);
280       OS.EmitBytes(VendorName);
281       OS.EmitIntValue(0, 1); // NULL terminate VendorName
282       OS.EmitBytes(ArchName);
283       OS.EmitIntValue(0, 1); // NULL terminte ArchName
284     }
285   );
286 }
287 
288 void
289 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
290 
291   MCStreamer &OS = getStreamer();
292   OS.PushSection();
293   OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header)));
294   OS.PopSection();
295 }
296 
297 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
298                                                    unsigned Type) {
299   MCSymbolELF *Symbol = cast<MCSymbolELF>(
300       getStreamer().getContext().getOrCreateSymbol(SymbolName));
301   Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL);
302 }
303 
304 bool AMDGPUTargetELFStreamer::EmitISAVersion(StringRef IsaVersionString) {
305   // Create two labels to mark the beginning and end of the desc field
306   // and a MCExpr to calculate the size of the desc field.
307   auto &Context = getContext();
308   auto *DescBegin = Context.createTempSymbol();
309   auto *DescEnd = Context.createTempSymbol();
310   auto *DescSZ = MCBinaryExpr::createSub(
311     MCSymbolRefExpr::create(DescEnd, Context),
312     MCSymbolRefExpr::create(DescBegin, Context), Context);
313 
314   EmitAMDGPUNote(
315     DescSZ,
316     ELF::NT_AMD_AMDGPU_ISA,
317     [&](MCELFStreamer &OS) {
318       OS.EmitLabel(DescBegin);
319       OS.EmitBytes(IsaVersionString);
320       OS.EmitLabel(DescEnd);
321     }
322   );
323   return true;
324 }
325 
326 bool AMDGPUTargetELFStreamer::EmitHSAMetadata(
327     const AMDGPU::HSAMD::Metadata &HSAMetadata) {
328   std::string HSAMetadataString;
329   if (HSAMD::toString(HSAMetadata, HSAMetadataString))
330     return false;
331 
332   // Create two labels to mark the beginning and end of the desc field
333   // and a MCExpr to calculate the size of the desc field.
334   auto &Context = getContext();
335   auto *DescBegin = Context.createTempSymbol();
336   auto *DescEnd = Context.createTempSymbol();
337   auto *DescSZ = MCBinaryExpr::createSub(
338     MCSymbolRefExpr::create(DescEnd, Context),
339     MCSymbolRefExpr::create(DescBegin, Context), Context);
340 
341   EmitAMDGPUNote(
342     DescSZ,
343     ELF::NT_AMD_AMDGPU_HSA_METADATA,
344     [&](MCELFStreamer &OS) {
345       OS.EmitLabel(DescBegin);
346       OS.EmitBytes(HSAMetadataString);
347       OS.EmitLabel(DescEnd);
348     }
349   );
350   return true;
351 }
352 
353 bool AMDGPUTargetELFStreamer::EmitPALMetadata(
354     const PALMD::Metadata &PALMetadata) {
355   EmitAMDGPUNote(
356     MCConstantExpr::create(PALMetadata.size() * sizeof(uint32_t), getContext()),
357     ELF::NT_AMD_AMDGPU_PAL_METADATA,
358     [&](MCELFStreamer &OS){
359       for (auto I : PALMetadata)
360         OS.EmitIntValue(I, sizeof(uint32_t));
361     }
362   );
363   return true;
364 }
365