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