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(Module &M) {
97   OS << "\t.amdgpu_runtime_metadata\n";
98   OS << getRuntimeMDYAMLString(M);
99   OS << "\n\t.end_amdgpu_runtime_metadata\n";
100 }
101 
102 void AMDGPUTargetAsmStreamer::EmitRuntimeMetadata(StringRef Metadata) {
103   OS << "\t.amdgpu_runtime_metadata";
104   OS << Metadata;
105   OS << "\t.end_amdgpu_runtime_metadata\n";
106 }
107 
108 //===----------------------------------------------------------------------===//
109 // AMDGPUTargetELFStreamer
110 //===----------------------------------------------------------------------===//
111 
112 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(MCStreamer &S)
113     : AMDGPUTargetStreamer(S), Streamer(S) {}
114 
115 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() {
116   return static_cast<MCELFStreamer &>(Streamer);
117 }
118 
119 void
120 AMDGPUTargetELFStreamer::EmitAMDGPUNote(const MCExpr* DescSZ,
121                                         PT_NOTE::NoteType Type,
122                               std::function<void(MCELFStreamer &)> EmitDesc) {
123   auto &S = getStreamer();
124   auto &Context = S.getContext();
125 
126   auto NameSZ = sizeof(PT_NOTE::NoteName);
127 
128   S.PushSection();
129   S.SwitchSection(Context.getELFSection(
130     PT_NOTE::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC));
131   S.EmitIntValue(NameSZ, 4);                                  // namesz
132   S.EmitValue(DescSZ, 4);                                     // descz
133   S.EmitIntValue(Type, 4); // type
134   S.EmitBytes(StringRef(PT_NOTE::NoteName, NameSZ));          // name
135   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
136   EmitDesc(S);                                                // desc
137   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
138   S.PopSection();
139 }
140 
141 void
142 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
143                                                            uint32_t Minor) {
144 
145   EmitAMDGPUNote(
146     MCConstantExpr::create(8, getContext()),
147     PT_NOTE::NT_AMDGPU_HSA_CODE_OBJECT_VERSION,
148     [&](MCELFStreamer &OS){
149       OS.EmitIntValue(Major, 4);
150       OS.EmitIntValue(Minor, 4);
151     }
152   );
153 }
154 
155 void
156 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
157                                                        uint32_t Minor,
158                                                        uint32_t Stepping,
159                                                        StringRef VendorName,
160                                                        StringRef ArchName) {
161   uint16_t VendorNameSize = VendorName.size() + 1;
162   uint16_t ArchNameSize = ArchName.size() + 1;
163 
164   unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) +
165     sizeof(Major) + sizeof(Minor) + sizeof(Stepping) +
166     VendorNameSize + ArchNameSize;
167 
168   EmitAMDGPUNote(
169     MCConstantExpr::create(DescSZ, getContext()),
170     PT_NOTE::NT_AMDGPU_HSA_ISA,
171     [&](MCELFStreamer &OS) {
172       OS.EmitIntValue(VendorNameSize, 2);
173       OS.EmitIntValue(ArchNameSize, 2);
174       OS.EmitIntValue(Major, 4);
175       OS.EmitIntValue(Minor, 4);
176       OS.EmitIntValue(Stepping, 4);
177       OS.EmitBytes(VendorName);
178       OS.EmitIntValue(0, 1); // NULL terminate VendorName
179       OS.EmitBytes(ArchName);
180       OS.EmitIntValue(0, 1); // NULL terminte ArchName
181     }
182   );
183 }
184 
185 void
186 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
187 
188   MCStreamer &OS = getStreamer();
189   OS.PushSection();
190   OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header)));
191   OS.PopSection();
192 }
193 
194 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
195                                                    unsigned Type) {
196   MCSymbolELF *Symbol = cast<MCSymbolELF>(
197       getStreamer().getContext().getOrCreateSymbol(SymbolName));
198   Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL);
199 }
200 
201 void AMDGPUTargetELFStreamer::EmitAMDGPUHsaModuleScopeGlobal(
202     StringRef GlobalName) {
203 
204   MCSymbolELF *Symbol = cast<MCSymbolELF>(
205       getStreamer().getContext().getOrCreateSymbol(GlobalName));
206   Symbol->setType(ELF::STT_OBJECT);
207   Symbol->setBinding(ELF::STB_LOCAL);
208 }
209 
210 void AMDGPUTargetELFStreamer::EmitAMDGPUHsaProgramScopeGlobal(
211     StringRef GlobalName) {
212 
213   MCSymbolELF *Symbol = cast<MCSymbolELF>(
214       getStreamer().getContext().getOrCreateSymbol(GlobalName));
215   Symbol->setType(ELF::STT_OBJECT);
216   Symbol->setBinding(ELF::STB_GLOBAL);
217 }
218 
219 void AMDGPUTargetELFStreamer::EmitRuntimeMetadata(StringRef Metadata) {
220   // Create two labels to mark the beginning and end of the desc field
221   // and a MCExpr to calculate the size of the desc field.
222   auto &Context = getContext();
223   auto *DescBegin = Context.createTempSymbol();
224   auto *DescEnd = Context.createTempSymbol();
225   auto *DescSZ = MCBinaryExpr::createSub(
226     MCSymbolRefExpr::create(DescEnd, Context),
227     MCSymbolRefExpr::create(DescBegin, Context), Context);
228 
229   EmitAMDGPUNote(
230     DescSZ,
231     PT_NOTE::NT_AMDGPU_HSA_RUNTIME_METADATA,
232     [&](MCELFStreamer &OS) {
233       OS.EmitLabel(DescBegin);
234       OS.EmitBytes(Metadata);
235       OS.EmitLabel(DescEnd);
236     }
237   );
238 }
239 
240 void AMDGPUTargetELFStreamer::EmitRuntimeMetadata(Module &M) {
241   EmitRuntimeMetadata(getRuntimeMDYAMLString(M));
242 }
243