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