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