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