xref: /llvm-project/offload/plugins-nextgen/common/include/GlobalHandler.h (revision fde2d23ee2a204050a210f2f7b290643a272f737)
1 //===- GlobalHandler.h - Target independent global & enviroment handling --===//
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 // Target independent global handler and environment manager.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_GLOBALHANDLER_H
14 #define LLVM_OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_GLOBALHANDLER_H
15 
16 #include <type_traits>
17 
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/Object/ELFObjectFile.h"
20 #include "llvm/ProfileData/InstrProf.h"
21 
22 #include "Shared/Debug.h"
23 #include "Shared/Utils.h"
24 
25 #include "omptarget.h"
26 
27 namespace llvm {
28 namespace omp {
29 namespace target {
30 namespace plugin {
31 
32 class DeviceImageTy;
33 struct GenericDeviceTy;
34 
35 using namespace llvm::object;
36 
37 /// Common abstraction for globals that live on the host and device.
38 /// It simply encapsulates the symbol name, symbol size, and symbol address
39 /// (which might be host or device depending on the context).
40 class GlobalTy {
41   // NOTE: Maybe we can have a pointer to the offload entry name instead of
42   // holding a private copy of the name as a std::string.
43   std::string Name;
44   uint32_t Size;
45   void *Ptr;
46 
47 public:
48   GlobalTy(const std::string &Name, uint32_t Size, void *Ptr = nullptr)
49       : Name(Name), Size(Size), Ptr(Ptr) {}
50 
51   const std::string &getName() const { return Name; }
52   uint32_t getSize() const { return Size; }
53   void *getPtr() const { return Ptr; }
54 
55   void setSize(int32_t S) { Size = S; }
56   void setPtr(void *P) { Ptr = P; }
57 };
58 
59 using IntPtrT = void *;
60 struct __llvm_profile_data {
61 #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer)                     \
62   std::remove_const<Type>::type Name;
63 #include "llvm/ProfileData/InstrProfData.inc"
64 };
65 
66 /// PGO profiling data extracted from a GPU device
67 struct GPUProfGlobals {
68   SmallVector<uint8_t> NamesData;
69   SmallVector<SmallVector<int64_t>> Counts;
70   SmallVector<__llvm_profile_data> Data;
71   Triple TargetTriple;
72 
73   void dump() const;
74 };
75 
76 /// Subclass of GlobalTy that holds the memory for a global of \p Ty.
77 template <typename Ty> class StaticGlobalTy : public GlobalTy {
78   Ty Data;
79 
80 public:
81   template <typename... Args>
82   StaticGlobalTy(const std::string &Name, Args &&...args)
83       : GlobalTy(Name, sizeof(Ty), &Data),
84         Data(Ty{std::forward<Args>(args)...}) {}
85 
86   template <typename... Args>
87   StaticGlobalTy(const char *Name, Args &&...args)
88       : GlobalTy(Name, sizeof(Ty), &Data),
89         Data(Ty{std::forward<Args>(args)...}) {}
90 
91   template <typename... Args>
92   StaticGlobalTy(const char *Name, const char *Suffix, Args &&...args)
93       : GlobalTy(std::string(Name) + Suffix, sizeof(Ty), &Data),
94         Data(Ty{std::forward<Args>(args)...}) {}
95 
96   Ty &getValue() { return Data; }
97   const Ty &getValue() const { return Data; }
98   void setValue(const Ty &V) { Data = V; }
99 };
100 
101 /// Helper class to do the heavy lifting when it comes to moving globals between
102 /// host and device. Through the GenericDeviceTy we access memcpy DtoH and HtoD,
103 /// which means the only things specialized by the subclass is the retrival of
104 /// global metadata (size, addr) from the device.
105 /// \see getGlobalMetadataFromDevice
106 class GenericGlobalHandlerTy {
107   /// Actually move memory between host and device. See readGlobalFromDevice and
108   /// writeGlobalToDevice for the interface description.
109   Error moveGlobalBetweenDeviceAndHost(GenericDeviceTy &Device,
110                                        DeviceImageTy &Image,
111                                        const GlobalTy &HostGlobal,
112                                        bool Device2Host);
113 
114   /// Actually move memory between host and device. See readGlobalFromDevice and
115   /// writeGlobalToDevice for the interface description.
116   Error moveGlobalBetweenDeviceAndHost(GenericDeviceTy &Device,
117                                        const GlobalTy &HostGlobal,
118                                        const GlobalTy &DeviceGlobal,
119                                        bool Device2Host);
120 
121 public:
122   virtual ~GenericGlobalHandlerTy() {}
123 
124   /// Helper function for getting an ELF from a device image.
125   Expected<std::unique_ptr<ObjectFile>> getELFObjectFile(DeviceImageTy &Image);
126 
127   /// Returns whether the symbol named \p SymName is present in the given \p
128   /// Image.
129   bool isSymbolInImage(GenericDeviceTy &Device, DeviceImageTy &Image,
130                        StringRef SymName);
131 
132   /// Get the address and size of a global in the image. Address and size are
133   /// return in \p ImageGlobal, the global name is passed in \p ImageGlobal.
134   Error getGlobalMetadataFromImage(GenericDeviceTy &Device,
135                                    DeviceImageTy &Image, GlobalTy &ImageGlobal);
136 
137   /// Read the memory associated with a global from the image and store it on
138   /// the host. The name, size, and destination are defined by \p HostGlobal.
139   Error readGlobalFromImage(GenericDeviceTy &Device, DeviceImageTy &Image,
140                             const GlobalTy &HostGlobal);
141 
142   /// Get the address and size of a global from the device. Address is return in
143   /// \p DeviceGlobal, the global name and expected size are passed in
144   /// \p DeviceGlobal.
145   virtual Error getGlobalMetadataFromDevice(GenericDeviceTy &Device,
146                                             DeviceImageTy &Image,
147                                             GlobalTy &DeviceGlobal) = 0;
148 
149   /// Copy the memory associated with a global from the device to its
150   /// counterpart on the host. The name, size, and destination are defined by
151   /// \p HostGlobal. The origin is defined by \p DeviceGlobal.
152   Error readGlobalFromDevice(GenericDeviceTy &Device,
153                              const GlobalTy &HostGlobal,
154                              const GlobalTy &DeviceGlobal) {
155     return moveGlobalBetweenDeviceAndHost(Device, HostGlobal, DeviceGlobal,
156                                           /*D2H=*/true);
157   }
158 
159   /// Copy the memory associated with a global from the device to its
160   /// counterpart on the host. The name, size, and destination are defined by
161   /// \p HostGlobal. The origin is automatically resolved.
162   Error readGlobalFromDevice(GenericDeviceTy &Device, DeviceImageTy &Image,
163                              const GlobalTy &HostGlobal) {
164     return moveGlobalBetweenDeviceAndHost(Device, Image, HostGlobal,
165                                           /*D2H=*/true);
166   }
167 
168   /// Copy the memory associated with a global from the host to its counterpart
169   /// on the device. The name, size, and origin are defined by \p HostGlobal.
170   /// The destination is defined by \p DeviceGlobal.
171   Error writeGlobalToDevice(GenericDeviceTy &Device, const GlobalTy &HostGlobal,
172                             const GlobalTy &DeviceGlobal) {
173     return moveGlobalBetweenDeviceAndHost(Device, HostGlobal, DeviceGlobal,
174                                           /*D2H=*/false);
175   }
176 
177   /// Copy the memory associated with a global from the host to its counterpart
178   /// on the device. The name, size, and origin are defined by \p HostGlobal.
179   /// The destination is automatically resolved.
180   Error writeGlobalToDevice(GenericDeviceTy &Device, DeviceImageTy &Image,
181                             const GlobalTy &HostGlobal) {
182     return moveGlobalBetweenDeviceAndHost(Device, Image, HostGlobal,
183                                           /*D2H=*/false);
184   }
185 
186   /// Checks whether a given image contains profiling globals.
187   bool hasProfilingGlobals(GenericDeviceTy &Device, DeviceImageTy &Image);
188 
189   /// Reads profiling data from a GPU image to supplied profdata struct.
190   /// Iterates through the image symbol table and stores global values
191   /// with profiling prefixes.
192   Expected<GPUProfGlobals> readProfilingGlobals(GenericDeviceTy &Device,
193                                                 DeviceImageTy &Image);
194 };
195 
196 } // namespace plugin
197 } // namespace target
198 } // namespace omp
199 } // namespace llvm
200 
201 #endif // LLVM_OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_GLOBALHANDLER_H
202