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 "AMDGPU.h"
15 #include "AMDGPUTargetStreamer.h"
16 #include "SIDefines.h"
17 #include "Utils/AMDGPUBaseInfo.h"
18 #include "Utils/AMDKernelCodeTUtils.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/IR/Constants.h"
21 #include "llvm/IR/Function.h"
22 #include "llvm/IR/Metadata.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCELFStreamer.h"
26 #include "llvm/MC/MCObjectFileInfo.h"
27 #include "llvm/MC/MCSectionELF.h"
28 #include "llvm/Support/ELF.h"
29 #include "llvm/Support/FormattedStream.h"
30 #include "AMDGPURuntimeMD.h"
31 
32 namespace llvm {
33 #include "AMDGPUPTNote.h"
34 }
35 
36 using namespace llvm;
37 using namespace llvm::AMDGPU;
38 
39 AMDGPUTargetStreamer::AMDGPUTargetStreamer(MCStreamer &S)
40     : MCTargetStreamer(S) {}
41 
42 //===----------------------------------------------------------------------===//
43 // AMDGPUTargetAsmStreamer
44 //===----------------------------------------------------------------------===//
45 
46 AMDGPUTargetAsmStreamer::AMDGPUTargetAsmStreamer(MCStreamer &S,
47                                                  formatted_raw_ostream &OS)
48     : AMDGPUTargetStreamer(S), OS(OS) { }
49 
50 void
51 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
52                                                            uint32_t Minor) {
53   OS << "\t.hsa_code_object_version " <<
54         Twine(Major) << "," << Twine(Minor) << '\n';
55 }
56 
57 void
58 AMDGPUTargetAsmStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
59                                                        uint32_t Minor,
60                                                        uint32_t Stepping,
61                                                        StringRef VendorName,
62                                                        StringRef ArchName) {
63   OS << "\t.hsa_code_object_isa " <<
64         Twine(Major) << "," << Twine(Minor) << "," << Twine(Stepping) <<
65         ",\"" << VendorName << "\",\"" << ArchName << "\"\n";
66 
67 }
68 
69 void
70 AMDGPUTargetAsmStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
71   OS << "\t.amd_kernel_code_t\n";
72   dumpAmdKernelCode(&Header, OS, "\t\t");
73   OS << "\t.end_amd_kernel_code_t\n";
74 }
75 
76 void AMDGPUTargetAsmStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
77                                                    unsigned Type) {
78   switch (Type) {
79     default: llvm_unreachable("Invalid AMDGPU symbol type");
80     case ELF::STT_AMDGPU_HSA_KERNEL:
81       OS << "\t.amdgpu_hsa_kernel " << SymbolName << '\n' ;
82       break;
83   }
84 }
85 
86 void AMDGPUTargetAsmStreamer::EmitAMDGPUHsaModuleScopeGlobal(
87     StringRef GlobalName) {
88   OS << "\t.amdgpu_hsa_module_global " << GlobalName << '\n';
89 }
90 
91 void AMDGPUTargetAsmStreamer::EmitAMDGPUHsaProgramScopeGlobal(
92     StringRef GlobalName) {
93   OS << "\t.amdgpu_hsa_program_global " << GlobalName << '\n';
94 }
95 
96 void AMDGPUTargetAsmStreamer::EmitRuntimeMetadata(const FeatureBitset &Features,
97                                                   const Module &M) {
98   OS << "\t.amdgpu_runtime_metadata\n";
99   OS << getRuntimeMDYAMLString(Features, M);
100   OS << "\n\t.end_amdgpu_runtime_metadata\n";
101 }
102 
103 bool AMDGPUTargetAsmStreamer::EmitRuntimeMetadata(const FeatureBitset &Features,
104                                                   StringRef Metadata) {
105   auto VerifiedMetadata = getRuntimeMDYAMLString(Features, Metadata);
106   if (!VerifiedMetadata)
107     return true;
108 
109   OS << "\t.amdgpu_runtime_metadata";
110   OS << VerifiedMetadata.get();
111   OS << "\t.end_amdgpu_runtime_metadata\n";
112 
113   return false;
114 }
115 
116 //===----------------------------------------------------------------------===//
117 // AMDGPUTargetELFStreamer
118 //===----------------------------------------------------------------------===//
119 
120 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(MCStreamer &S)
121     : AMDGPUTargetStreamer(S), Streamer(S) {}
122 
123 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() {
124   return static_cast<MCELFStreamer &>(Streamer);
125 }
126 
127 void AMDGPUTargetELFStreamer::EmitAMDGPUNote(
128     const MCExpr *DescSZ, PT_NOTE::NoteType Type,
129     function_ref<void(MCELFStreamer &)> EmitDesc) {
130   auto &S = getStreamer();
131   auto &Context = S.getContext();
132 
133   auto NameSZ = sizeof(PT_NOTE::NoteName);
134 
135   S.PushSection();
136   S.SwitchSection(Context.getELFSection(
137     PT_NOTE::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC));
138   S.EmitIntValue(NameSZ, 4);                                  // namesz
139   S.EmitValue(DescSZ, 4);                                     // descz
140   S.EmitIntValue(Type, 4); // type
141   S.EmitBytes(StringRef(PT_NOTE::NoteName, NameSZ));          // name
142   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
143   EmitDesc(S);                                                // desc
144   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
145   S.PopSection();
146 }
147 
148 void
149 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
150                                                            uint32_t Minor) {
151 
152   EmitAMDGPUNote(
153     MCConstantExpr::create(8, getContext()),
154     PT_NOTE::NT_AMDGPU_HSA_CODE_OBJECT_VERSION,
155     [&](MCELFStreamer &OS){
156       OS.EmitIntValue(Major, 4);
157       OS.EmitIntValue(Minor, 4);
158     }
159   );
160 }
161 
162 void
163 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
164                                                        uint32_t Minor,
165                                                        uint32_t Stepping,
166                                                        StringRef VendorName,
167                                                        StringRef ArchName) {
168   uint16_t VendorNameSize = VendorName.size() + 1;
169   uint16_t ArchNameSize = ArchName.size() + 1;
170 
171   unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) +
172     sizeof(Major) + sizeof(Minor) + sizeof(Stepping) +
173     VendorNameSize + ArchNameSize;
174 
175   EmitAMDGPUNote(
176     MCConstantExpr::create(DescSZ, getContext()),
177     PT_NOTE::NT_AMDGPU_HSA_ISA,
178     [&](MCELFStreamer &OS) {
179       OS.EmitIntValue(VendorNameSize, 2);
180       OS.EmitIntValue(ArchNameSize, 2);
181       OS.EmitIntValue(Major, 4);
182       OS.EmitIntValue(Minor, 4);
183       OS.EmitIntValue(Stepping, 4);
184       OS.EmitBytes(VendorName);
185       OS.EmitIntValue(0, 1); // NULL terminate VendorName
186       OS.EmitBytes(ArchName);
187       OS.EmitIntValue(0, 1); // NULL terminte ArchName
188     }
189   );
190 }
191 
192 void
193 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
194 
195   MCStreamer &OS = getStreamer();
196   OS.PushSection();
197   OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header)));
198   OS.PopSection();
199 }
200 
201 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
202                                                    unsigned Type) {
203   MCSymbolELF *Symbol = cast<MCSymbolELF>(
204       getStreamer().getContext().getOrCreateSymbol(SymbolName));
205   Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL);
206 }
207 
208 void AMDGPUTargetELFStreamer::EmitAMDGPUHsaModuleScopeGlobal(
209     StringRef GlobalName) {
210 
211   MCSymbolELF *Symbol = cast<MCSymbolELF>(
212       getStreamer().getContext().getOrCreateSymbol(GlobalName));
213   Symbol->setType(ELF::STT_OBJECT);
214   Symbol->setBinding(ELF::STB_LOCAL);
215 }
216 
217 void AMDGPUTargetELFStreamer::EmitAMDGPUHsaProgramScopeGlobal(
218     StringRef GlobalName) {
219 
220   MCSymbolELF *Symbol = cast<MCSymbolELF>(
221       getStreamer().getContext().getOrCreateSymbol(GlobalName));
222   Symbol->setType(ELF::STT_OBJECT);
223   Symbol->setBinding(ELF::STB_GLOBAL);
224 }
225 
226 bool AMDGPUTargetELFStreamer::EmitRuntimeMetadata(const FeatureBitset &Features,
227                                                   StringRef Metadata) {
228   auto VerifiedMetadata = getRuntimeMDYAMLString(Features, Metadata);
229   if (!VerifiedMetadata)
230     return true;
231 
232   // Create two labels to mark the beginning and end of the desc field
233   // and a MCExpr to calculate the size of the desc field.
234   auto &Context = getContext();
235   auto *DescBegin = Context.createTempSymbol();
236   auto *DescEnd = Context.createTempSymbol();
237   auto *DescSZ = MCBinaryExpr::createSub(
238     MCSymbolRefExpr::create(DescEnd, Context),
239     MCSymbolRefExpr::create(DescBegin, Context), Context);
240 
241   EmitAMDGPUNote(
242     DescSZ,
243     PT_NOTE::NT_AMDGPU_HSA_RUNTIME_METADATA,
244     [&](MCELFStreamer &OS) {
245       OS.EmitLabel(DescBegin);
246       OS.EmitBytes(VerifiedMetadata.get());
247       OS.EmitLabel(DescEnd);
248     }
249   );
250 
251   return false;
252 }
253 
254 void AMDGPUTargetELFStreamer::EmitRuntimeMetadata(const FeatureBitset &Features,
255                                                   const Module &M) {
256   EmitRuntimeMetadata(Features, getRuntimeMDYAMLString(Features, M));
257 }
258