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 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 bool AMDGPUTargetAsmStreamer::EmitCodeObjectMetadata(StringRef YamlString) {
104   auto VerifiedYamlString = CodeObjectMetadataStreamer.toYamlString(YamlString);
105   if (!VerifiedYamlString)
106     return false;
107 
108   OS << '\t' << AMDGPU::CodeObject::MetadataAssemblerDirectiveBegin << '\n';
109   OS << VerifiedYamlString.get();
110   OS << '\t' << AMDGPU::CodeObject::MetadataAssemblerDirectiveEnd << '\n';
111 
112   return true;
113 }
114 
115 bool AMDGPUTargetAsmStreamer::EmitPalMetadata(ArrayRef<uint32_t> Data) {
116   OS << "\t.amdgpu_pal_metadata";
117   for (auto I = Data.begin(), E = Data.end(); I != E; ++I)
118     OS << (I == Data.begin() ? " 0x" : ",0x") << Twine::utohexstr(*I);
119   OS << "\n";
120   return true;
121 }
122 
123 //===----------------------------------------------------------------------===//
124 // AMDGPUTargetELFStreamer
125 //===----------------------------------------------------------------------===//
126 
127 AMDGPUTargetELFStreamer::AMDGPUTargetELFStreamer(MCStreamer &S)
128     : AMDGPUTargetStreamer(S), Streamer(S) {}
129 
130 MCELFStreamer &AMDGPUTargetELFStreamer::getStreamer() {
131   return static_cast<MCELFStreamer &>(Streamer);
132 }
133 
134 void AMDGPUTargetELFStreamer::EmitAMDGPUNote(
135     const MCExpr *DescSZ, ElfNote::NoteType Type,
136     function_ref<void(MCELFStreamer &)> EmitDesc) {
137   auto &S = getStreamer();
138   auto &Context = S.getContext();
139 
140   auto NameSZ = sizeof(ElfNote::NoteName);
141 
142   S.PushSection();
143   S.SwitchSection(Context.getELFSection(
144     ElfNote::SectionName, ELF::SHT_NOTE, ELF::SHF_ALLOC));
145   S.EmitIntValue(NameSZ, 4);                                  // namesz
146   S.EmitValue(DescSZ, 4);                                     // descz
147   S.EmitIntValue(Type, 4);                                    // type
148   S.EmitBytes(StringRef(ElfNote::NoteName, NameSZ));          // name
149   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
150   EmitDesc(S);                                                // desc
151   S.EmitValueToAlignment(4, 0, 1, 0);                         // padding 0
152   S.PopSection();
153 }
154 
155 void
156 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectVersion(uint32_t Major,
157                                                            uint32_t Minor) {
158 
159   EmitAMDGPUNote(
160     MCConstantExpr::create(8, getContext()),
161     ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_VERSION,
162     [&](MCELFStreamer &OS){
163       OS.EmitIntValue(Major, 4);
164       OS.EmitIntValue(Minor, 4);
165     }
166   );
167 }
168 
169 void
170 AMDGPUTargetELFStreamer::EmitDirectiveHSACodeObjectISA(uint32_t Major,
171                                                        uint32_t Minor,
172                                                        uint32_t Stepping,
173                                                        StringRef VendorName,
174                                                        StringRef ArchName) {
175   uint16_t VendorNameSize = VendorName.size() + 1;
176   uint16_t ArchNameSize = ArchName.size() + 1;
177 
178   unsigned DescSZ = sizeof(VendorNameSize) + sizeof(ArchNameSize) +
179     sizeof(Major) + sizeof(Minor) + sizeof(Stepping) +
180     VendorNameSize + ArchNameSize;
181 
182   EmitAMDGPUNote(
183     MCConstantExpr::create(DescSZ, getContext()),
184     ElfNote::NT_AMDGPU_HSA_ISA,
185     [&](MCELFStreamer &OS) {
186       OS.EmitIntValue(VendorNameSize, 2);
187       OS.EmitIntValue(ArchNameSize, 2);
188       OS.EmitIntValue(Major, 4);
189       OS.EmitIntValue(Minor, 4);
190       OS.EmitIntValue(Stepping, 4);
191       OS.EmitBytes(VendorName);
192       OS.EmitIntValue(0, 1); // NULL terminate VendorName
193       OS.EmitBytes(ArchName);
194       OS.EmitIntValue(0, 1); // NULL terminte ArchName
195     }
196   );
197 }
198 
199 void
200 AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) {
201 
202   MCStreamer &OS = getStreamer();
203   OS.PushSection();
204   OS.EmitBytes(StringRef((const char*)&Header, sizeof(Header)));
205   OS.PopSection();
206 }
207 
208 void AMDGPUTargetELFStreamer::EmitAMDGPUSymbolType(StringRef SymbolName,
209                                                    unsigned Type) {
210   MCSymbolELF *Symbol = cast<MCSymbolELF>(
211       getStreamer().getContext().getOrCreateSymbol(SymbolName));
212   Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL);
213 }
214 
215 bool AMDGPUTargetELFStreamer::EmitCodeObjectMetadata(StringRef YamlString) {
216   auto VerifiedYamlString = CodeObjectMetadataStreamer.toYamlString(YamlString);
217   if (!VerifiedYamlString)
218     return false;
219 
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     ElfNote::NT_AMDGPU_HSA_CODE_OBJECT_METADATA,
232     [&](MCELFStreamer &OS) {
233       OS.EmitLabel(DescBegin);
234       OS.EmitBytes(VerifiedYamlString.get());
235       OS.EmitLabel(DescEnd);
236     }
237   );
238 
239   return true;
240 }
241 
242 bool AMDGPUTargetELFStreamer::EmitPalMetadata(ArrayRef<uint32_t> Data) {
243   EmitAMDGPUNote(
244     MCConstantExpr::create(Data.size() * sizeof(uint32_t), getContext()),
245     ElfNote::NT_AMDGPU_PAL_METADATA,
246     [&](MCELFStreamer &OS){
247       for (auto I : Data)
248         OS.EmitIntValue(I, sizeof(uint32_t));
249     }
250   );
251   return true;
252 }
253 
254