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/MC/MCStreamer.h"
15 
16 struct amd_kernel_code_t;
17 
18 namespace llvm {
19 
20 class MCELFStreamer;
21 class MCSymbol;
22 class formatted_raw_ostream;
23 
24 namespace AMDGPU {
25 namespace HSAMD {
26 struct Metadata;
27 }
28 } // namespace AMDGPU
29 
30 namespace amdhsa {
31 struct kernel_descriptor_t;
32 }
33 
34 class AMDGPUTargetStreamer : public MCTargetStreamer {
35   AMDGPUPALMetadata PALMetadata;
36 
37 protected:
38   // TODO: Move HSAMetadataStream to AMDGPUTargetStreamer.
39   std::optional<AMDGPU::IsaInfo::AMDGPUTargetID> TargetID;
40 
41   MCContext &getContext() const { return Streamer.getContext(); }
42 
43 public:
44   AMDGPUTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
45 
46   AMDGPUPALMetadata *getPALMetadata() { return &PALMetadata; }
47 
48   virtual void EmitDirectiveAMDGCNTarget(){};
49 
50   virtual void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
51                                                  uint32_t Minor){};
52 
53   virtual void EmitDirectiveHSACodeObjectISAV2(uint32_t Major, uint32_t Minor,
54                                                uint32_t Stepping,
55                                                StringRef VendorName,
56                                                StringRef ArchName){};
57 
58   virtual void EmitAMDKernelCodeT(const amd_kernel_code_t &Header){};
59 
60   virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type){};
61 
62   virtual void emitAMDGPULDS(MCSymbol *Symbol, unsigned Size, Align Alignment) {
63   }
64 
65   /// \returns True on success, false on failure.
66   virtual bool EmitISAVersion() { return true; }
67 
68   /// \returns True on success, false on failure.
69   virtual bool EmitHSAMetadataV2(StringRef HSAMetadataString);
70 
71   /// \returns True on success, false on failure.
72   virtual bool EmitHSAMetadataV3(StringRef HSAMetadataString);
73 
74   /// Emit HSA Metadata
75   ///
76   /// When \p Strict is true, known metadata elements must already be
77   /// well-typed. When \p Strict is false, known types are inferred and
78   /// the \p HSAMetadata structure is updated with the correct types.
79   ///
80   /// \returns True on success, false on failure.
81   virtual bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) {
82     return true;
83   }
84 
85   /// \returns True on success, false on failure.
86   virtual bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) {
87     return true;
88   }
89 
90   /// \returns True on success, false on failure.
91   virtual bool EmitCodeEnd(const MCSubtargetInfo &STI) { return true; }
92 
93   virtual void EmitAmdhsaKernelDescriptor(
94       const MCSubtargetInfo &STI, StringRef KernelName,
95       const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR,
96       uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr){};
97 
98   static StringRef getArchNameFromElfMach(unsigned ElfMach);
99   static unsigned getElfMach(StringRef GPU);
100 
101   const std::optional<AMDGPU::IsaInfo::AMDGPUTargetID> &getTargetID() const {
102     return TargetID;
103   }
104   std::optional<AMDGPU::IsaInfo::AMDGPUTargetID> &getTargetID() {
105     return TargetID;
106   }
107   void initializeTargetID(const MCSubtargetInfo &STI) {
108     assert(TargetID == std::nullopt && "TargetID can only be initialized once");
109     TargetID.emplace(STI);
110   }
111   void initializeTargetID(const MCSubtargetInfo &STI, StringRef FeatureString) {
112     initializeTargetID(STI);
113 
114     assert(getTargetID() != std::nullopt && "TargetID is None");
115     getTargetID()->setTargetIDFromFeaturesString(FeatureString);
116   }
117 };
118 
119 class AMDGPUTargetAsmStreamer final : public AMDGPUTargetStreamer {
120   formatted_raw_ostream &OS;
121 public:
122   AMDGPUTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
123 
124   void finish() override;
125 
126   void EmitDirectiveAMDGCNTarget() override;
127 
128   void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
129                                          uint32_t Minor) override;
130 
131   void EmitDirectiveHSACodeObjectISAV2(uint32_t Major, uint32_t Minor,
132                                        uint32_t Stepping, StringRef VendorName,
133                                        StringRef ArchName) override;
134 
135   void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override;
136 
137   void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
138 
139   void emitAMDGPULDS(MCSymbol *Sym, unsigned Size, Align Alignment) override;
140 
141   /// \returns True on success, false on failure.
142   bool EmitISAVersion() override;
143 
144   /// \returns True on success, false on failure.
145   bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) override;
146 
147   /// \returns True on success, false on failure.
148   bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override;
149 
150   /// \returns True on success, false on failure.
151   bool EmitCodeEnd(const MCSubtargetInfo &STI) override;
152 
153   void EmitAmdhsaKernelDescriptor(
154       const MCSubtargetInfo &STI, StringRef KernelName,
155       const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR,
156       uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override;
157 };
158 
159 class AMDGPUTargetELFStreamer final : public AMDGPUTargetStreamer {
160   const MCSubtargetInfo &STI;
161   MCStreamer &Streamer;
162 
163   void EmitNote(StringRef Name, const MCExpr *DescSize, unsigned NoteType,
164                 function_ref<void(MCELFStreamer &)> EmitDesc);
165 
166   unsigned getEFlags();
167 
168   unsigned getEFlagsR600();
169   unsigned getEFlagsAMDGCN();
170 
171   unsigned getEFlagsUnknownOS();
172   unsigned getEFlagsAMDHSA();
173   unsigned getEFlagsAMDPAL();
174   unsigned getEFlagsMesa3D();
175 
176   unsigned getEFlagsV3();
177   unsigned getEFlagsV4();
178 
179 public:
180   AMDGPUTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
181 
182   MCELFStreamer &getStreamer();
183 
184   void finish() override;
185 
186   void EmitDirectiveAMDGCNTarget() override;
187 
188   void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
189                                          uint32_t Minor) override;
190 
191   void EmitDirectiveHSACodeObjectISAV2(uint32_t Major, uint32_t Minor,
192                                        uint32_t Stepping, StringRef VendorName,
193                                        StringRef ArchName) override;
194 
195   void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override;
196 
197   void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
198 
199   void emitAMDGPULDS(MCSymbol *Sym, unsigned Size, Align Alignment) override;
200 
201   /// \returns True on success, false on failure.
202   bool EmitISAVersion() override;
203 
204   /// \returns True on success, false on failure.
205   bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) override;
206 
207   /// \returns True on success, false on failure.
208   bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override;
209 
210   /// \returns True on success, false on failure.
211   bool EmitCodeEnd(const MCSubtargetInfo &STI) override;
212 
213   void EmitAmdhsaKernelDescriptor(
214       const MCSubtargetInfo &STI, StringRef KernelName,
215       const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR,
216       uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override;
217 };
218 
219 }
220 #endif
221