1//===-- AMDGPUTargetStreamer.h - AMDGPU Target Streamer --------*- C++ -*--===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUTARGETSTREAMER_H
10#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUTARGETSTREAMER_H
11
12#include "Utils/AMDGPUBaseInfo.h"
13#include "Utils/AMDGPUPALMetadata.h"
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/MC/MCStreamer.h"
16#include <string>
17#include <utility>
18
19namespace llvm {
20
21class MCELFStreamer;
22class MCSymbol;
23class formatted_raw_ostream;
24
25namespace AMDGPU {
26
27struct AMDGPUMCKernelCodeT;
28struct MCKernelDescriptor;
29namespace HSAMD {
30struct Metadata;
31}
32
33struct FuncInfo {
34 uint32_t NumSGPR = 0;
35 uint32_t NumArchVGPR = 0;
36 uint32_t NumAccVGPR = 0;
37 uint32_t PrivateSegmentSize = 0;
38 bool UsesVCC = false;
39 bool UsesFlatScratch = false;
40 bool HasDynStack = false;
41
42 MCSymbol *Sym = nullptr;
43};
44
45struct InfoSectionData {
46 SmallVector<FuncInfo, 8> Funcs;
47 SmallVector<std::pair<MCSymbol *, MCSymbol *>, 4> Uses;
48 SmallVector<std::pair<MCSymbol *, MCSymbol *>, 8> Calls;
49 SmallVector<std::pair<MCSymbol *, std::string>, 4> IndirectCalls;
50 SmallVector<std::pair<MCSymbol *, std::string>, 4> TypeIds;
51};
52
53} // namespace AMDGPU
54
55class AMDGPUTargetStreamer : public MCTargetStreamer {
56 AMDGPUPALMetadata PALMetadata;
57
58protected:
59 // TODO: Move HSAMetadataStream to AMDGPUTargetStreamer.
60 std::optional<AMDGPU::TargetID> TargetID;
61 unsigned CodeObjectVersion;
62
63 MCContext &getContext() const { return Streamer.getContext(); }
64
65public:
66 AMDGPUTargetStreamer(MCStreamer &S)
67 : MCTargetStreamer(S),
68 // Assume the default COV for now, EmitDirectiveAMDHSACodeObjectVersion
69 // will update this if it is encountered.
70 CodeObjectVersion(AMDGPU::getDefaultAMDHSACodeObjectVersion()) {}
71
72 AMDGPUPALMetadata *getPALMetadata() { return &PALMetadata; }
73
74 virtual void EmitDirectiveAMDGCNTarget(){};
75
76 virtual void EmitDirectiveAMDHSACodeObjectVersion(unsigned COV) {
77 CodeObjectVersion = COV;
78 }
79
80 virtual void EmitAMDKernelCodeT(AMDGPU::AMDGPUMCKernelCodeT &Header) {};
81
82 virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type){};
83
84 virtual void emitAMDGPULDS(MCSymbol *Symbol, unsigned Size, Align Alignment) {
85 }
86
87 virtual void EmitMCResourceInfo(
88 const MCSymbol *NumVGPR, const MCSymbol *NumAGPR,
89 const MCSymbol *NumExplicitSGPR, const MCSymbol *NumNamedBarrier,
90 const MCSymbol *PrivateSegmentSize, const MCSymbol *UsesVCC,
91 const MCSymbol *UsesFlatScratch, const MCSymbol *HasDynamicallySizedStack,
92 const MCSymbol *HasRecursion, const MCSymbol *HasIndirectCall) {};
93
94 virtual void EmitMCResourceMaximums(const MCSymbol *MaxVGPR,
95 const MCSymbol *MaxAGPR,
96 const MCSymbol *MaxSGPR,
97 const MCSymbol *MaxNamedBarrier) {};
98
99 /// \returns True on success, false on failure.
100 virtual bool EmitISAVersion() { return true; }
101
102 /// \returns True on success, false on failure.
103 virtual bool EmitHSAMetadataV3(StringRef HSAMetadataString);
104
105 /// Emit HSA Metadata
106 ///
107 /// When \p Strict is true, known metadata elements must already be
108 /// well-typed. When \p Strict is false, known types are inferred and
109 /// the \p HSAMetadata structure is updated with the correct types.
110 ///
111 /// \returns True on success, false on failure.
112 virtual bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) {
113 return true;
114 }
115
116 /// \returns True on success, false on failure.
117 virtual bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) {
118 return true;
119 }
120
121 /// \returns True on success, false on failure.
122 virtual bool EmitCodeEnd(const MCSubtargetInfo &STI) { return true; }
123
124 virtual void
125 EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName,
126 const AMDGPU::MCKernelDescriptor &KernelDescriptor,
127 const MCExpr *NextVGPR, const MCExpr *NextSGPR,
128 const MCExpr *ReserveVCC,
129 const MCExpr *ReserveFlatScr) {}
130
131 virtual void emitAMDGPUInfo(const AMDGPU::InfoSectionData &Data) {}
132
133 static StringRef getArchNameFromElfMach(unsigned ElfMach);
134 static unsigned getElfMach(StringRef GPU);
135
136 const std::optional<AMDGPU::TargetID> &getTargetID() const {
137 return TargetID;
138 }
139 std::optional<AMDGPU::TargetID> &getTargetID() { return TargetID; }
140 void initializeTargetID(const MCSubtargetInfo &STI, StringRef FeatureString) {
141 assert(TargetID == std::nullopt && "TargetID can only be initialized once");
142 TargetID = AMDGPU::createAMDGPUTargetID(STI, FeatureString);
143 }
144};
145
146class AMDGPUTargetAsmStreamer final : public AMDGPUTargetStreamer {
147 formatted_raw_ostream &OS;
148public:
149 AMDGPUTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
150
151 void finish() override;
152
153 void EmitDirectiveAMDGCNTarget() override;
154
155 void EmitDirectiveAMDHSACodeObjectVersion(unsigned COV) override;
156
157 void EmitAMDKernelCodeT(AMDGPU::AMDGPUMCKernelCodeT &Header) override;
158
159 void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
160
161 void emitAMDGPULDS(MCSymbol *Sym, unsigned Size, Align Alignment) override;
162
163 void EmitMCResourceInfo(
164 const MCSymbol *NumVGPR, const MCSymbol *NumAGPR,
165 const MCSymbol *NumExplicitSGPR, const MCSymbol *NumNamedBarrier,
166 const MCSymbol *PrivateSegmentSize, const MCSymbol *UsesVCC,
167 const MCSymbol *UsesFlatScratch, const MCSymbol *HasDynamicallySizedStack,
168 const MCSymbol *HasRecursion, const MCSymbol *HasIndirectCall) override;
169
170 void EmitMCResourceMaximums(const MCSymbol *MaxVGPR, const MCSymbol *MaxAGPR,
171 const MCSymbol *MaxSGPR,
172 const MCSymbol *MaxNamedBarrier) override;
173
174 /// \returns True on success, false on failure.
175 bool EmitISAVersion() override;
176
177 /// \returns True on success, false on failure.
178 bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) override;
179
180 /// \returns True on success, false on failure.
181 bool EmitCodeEnd(const MCSubtargetInfo &STI) override;
182
183 void
184 EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName,
185 const AMDGPU::MCKernelDescriptor &KernelDescriptor,
186 const MCExpr *NextVGPR, const MCExpr *NextSGPR,
187 const MCExpr *ReserveVCC,
188 const MCExpr *ReserveFlatScr) override;
189
190 void emitAMDGPUInfo(const AMDGPU::InfoSectionData &Data) override;
191};
192
193class AMDGPUTargetELFStreamer final : public AMDGPUTargetStreamer {
194 const MCSubtargetInfo &STI;
195 MCStreamer &Streamer;
196
197 void EmitNote(StringRef Name, const MCExpr *DescSize, unsigned NoteType,
198 function_ref<void(MCELFStreamer &)> EmitDesc);
199
200 unsigned getEFlags();
201
202 unsigned getEFlagsR600();
203 unsigned getEFlagsAMDGCN();
204
205 unsigned getEFlagsUnknownOS();
206 unsigned getEFlagsAMDHSA();
207 unsigned getEFlagsAMDPAL();
208 unsigned getEFlagsMesa3D();
209
210 unsigned getEFlagsV3();
211 unsigned getEFlagsV4();
212 unsigned getEFlagsV6();
213
214public:
215 AMDGPUTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
216
217 MCELFStreamer &getStreamer();
218
219 void finish() override;
220
221 void EmitDirectiveAMDGCNTarget() override;
222
223 void EmitAMDKernelCodeT(AMDGPU::AMDGPUMCKernelCodeT &Header) override;
224
225 void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
226
227 void emitAMDGPULDS(MCSymbol *Sym, unsigned Size, Align Alignment) override;
228
229 /// \returns True on success, false on failure.
230 bool EmitISAVersion() override;
231
232 /// \returns True on success, false on failure.
233 bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) override;
234
235 /// \returns True on success, false on failure.
236 bool EmitCodeEnd(const MCSubtargetInfo &STI) override;
237
238 void
239 EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName,
240 const AMDGPU::MCKernelDescriptor &KernelDescriptor,
241 const MCExpr *NextVGPR, const MCExpr *NextSGPR,
242 const MCExpr *ReserveVCC,
243 const MCExpr *ReserveFlatScr) override;
244
245 void emitAMDGPUInfo(const AMDGPU::InfoSectionData &Data) override;
246};
247}
248#endif
249