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   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() = 0;
49 
50   virtual void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
51                                                  uint32_t Minor) = 0;
52 
53   virtual void EmitDirectiveHSACodeObjectISAV2(uint32_t Major, uint32_t Minor,
54                                                uint32_t Stepping,
55                                                StringRef VendorName,
56                                                StringRef ArchName) = 0;
57 
58   virtual void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) = 0;
59 
60   virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) = 0;
61 
62   virtual void emitAMDGPULDS(MCSymbol *Symbol, unsigned Size,
63                              Align Alignment) = 0;
64 
65   /// \returns True on success, false on failure.
66   virtual bool EmitISAVersion() = 0;
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) = 0;
82 
83   /// \returns True on success, false on failure.
84   virtual bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) = 0;
85 
86   /// \returns True on success, false on failure.
87   virtual bool EmitCodeEnd(const MCSubtargetInfo &STI) = 0;
88 
89   virtual void EmitAmdhsaKernelDescriptor(
90       const MCSubtargetInfo &STI, StringRef KernelName,
91       const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR,
92       uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) = 0;
93 
94   static StringRef getArchNameFromElfMach(unsigned ElfMach);
95   static unsigned getElfMach(StringRef GPU);
96 
97   const Optional<AMDGPU::IsaInfo::AMDGPUTargetID> &getTargetID() const {
98     return TargetID;
99   }
100   Optional<AMDGPU::IsaInfo::AMDGPUTargetID> &getTargetID() {
101     return TargetID;
102   }
103   void initializeTargetID(const MCSubtargetInfo &STI) {
104     assert(TargetID == None && "TargetID can only be initialized once");
105     TargetID.emplace(STI);
106   }
107   void initializeTargetID(const MCSubtargetInfo &STI, StringRef FeatureString) {
108     initializeTargetID(STI);
109 
110     assert(getTargetID() != None && "TargetID is None");
111     getTargetID()->setTargetIDFromFeaturesString(FeatureString);
112   }
113 };
114 
115 class AMDGPUTargetAsmStreamer final : public AMDGPUTargetStreamer {
116   formatted_raw_ostream &OS;
117 public:
118   AMDGPUTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
119 
120   void finish() override;
121 
122   void EmitDirectiveAMDGCNTarget() override;
123 
124   void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
125                                          uint32_t Minor) override;
126 
127   void EmitDirectiveHSACodeObjectISAV2(uint32_t Major, uint32_t Minor,
128                                        uint32_t Stepping, StringRef VendorName,
129                                        StringRef ArchName) override;
130 
131   void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override;
132 
133   void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
134 
135   void emitAMDGPULDS(MCSymbol *Sym, unsigned Size, Align Alignment) override;
136 
137   /// \returns True on success, false on failure.
138   bool EmitISAVersion() override;
139 
140   /// \returns True on success, false on failure.
141   bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) override;
142 
143   /// \returns True on success, false on failure.
144   bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override;
145 
146   /// \returns True on success, false on failure.
147   bool EmitCodeEnd(const MCSubtargetInfo &STI) override;
148 
149   void EmitAmdhsaKernelDescriptor(
150       const MCSubtargetInfo &STI, StringRef KernelName,
151       const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR,
152       uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override;
153 };
154 
155 class AMDGPUTargetELFStreamer final : public AMDGPUTargetStreamer {
156   const MCSubtargetInfo &STI;
157   MCStreamer &Streamer;
158 
159   void EmitNote(StringRef Name, const MCExpr *DescSize, unsigned NoteType,
160                 function_ref<void(MCELFStreamer &)> EmitDesc);
161 
162   unsigned getEFlags();
163 
164   unsigned getEFlagsR600();
165   unsigned getEFlagsAMDGCN();
166 
167   unsigned getEFlagsUnknownOS();
168   unsigned getEFlagsAMDHSA();
169   unsigned getEFlagsAMDPAL();
170   unsigned getEFlagsMesa3D();
171 
172   unsigned getEFlagsV3();
173   unsigned getEFlagsV4();
174 
175 public:
176   AMDGPUTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
177 
178   MCELFStreamer &getStreamer();
179 
180   void finish() override;
181 
182   void EmitDirectiveAMDGCNTarget() override;
183 
184   void EmitDirectiveHSACodeObjectVersion(uint32_t Major,
185                                          uint32_t Minor) override;
186 
187   void EmitDirectiveHSACodeObjectISAV2(uint32_t Major, uint32_t Minor,
188                                        uint32_t Stepping, StringRef VendorName,
189                                        StringRef ArchName) override;
190 
191   void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override;
192 
193   void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override;
194 
195   void emitAMDGPULDS(MCSymbol *Sym, unsigned Size, Align Alignment) override;
196 
197   /// \returns True on success, false on failure.
198   bool EmitISAVersion() override;
199 
200   /// \returns True on success, false on failure.
201   bool EmitHSAMetadata(msgpack::Document &HSAMetadata, bool Strict) override;
202 
203   /// \returns True on success, false on failure.
204   bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override;
205 
206   /// \returns True on success, false on failure.
207   bool EmitCodeEnd(const MCSubtargetInfo &STI) override;
208 
209   void EmitAmdhsaKernelDescriptor(
210       const MCSubtargetInfo &STI, StringRef KernelName,
211       const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR,
212       uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override;
213 };
214 
215 }
216 #endif
217