187 lines
7.7 KiB
C++
187 lines
7.7 KiB
C++
//===- GlobalHandler.h - Target independent global & enviroment handling --===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Target independent global handler and environment manager.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_GLOBALHANDLER_H
|
|
#define LLVM_OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_GLOBALHANDLER_H
|
|
|
|
#include <string>
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/Object/ELFObjectFile.h"
|
|
|
|
#include "Debug.h"
|
|
#include "Utilities.h"
|
|
#include "omptarget.h"
|
|
|
|
namespace llvm {
|
|
namespace omp {
|
|
namespace target {
|
|
namespace plugin {
|
|
|
|
class DeviceImageTy;
|
|
struct GenericDeviceTy;
|
|
|
|
using namespace llvm::object;
|
|
|
|
/// Common abstraction for globals that live on the host and device.
|
|
/// It simply encapsulates the symbol name, symbol size, and symbol address
|
|
/// (which might be host or device depending on the context).
|
|
class GlobalTy {
|
|
// NOTE: Maybe we can have a pointer to the offload entry name instead of
|
|
// holding a private copy of the name as a std::string.
|
|
std::string Name;
|
|
uint32_t Size;
|
|
void *Ptr;
|
|
|
|
public:
|
|
GlobalTy(const std::string &Name, uint32_t Size, void *Ptr = nullptr)
|
|
: Name(Name), Size(Size), Ptr(Ptr) {}
|
|
|
|
GlobalTy(const __tgt_offload_entry &Entry)
|
|
: Name(Entry.name), Size(Entry.size), Ptr(Entry.addr) {}
|
|
|
|
const std::string &getName() const { return Name; }
|
|
uint32_t getSize() const { return Size; }
|
|
void *getPtr() const { return Ptr; }
|
|
|
|
void setSize(int32_t S) { Size = S; }
|
|
void setPtr(void *P) { Ptr = P; }
|
|
};
|
|
|
|
/// Subclass of GlobalTy that holds the memory for a global of \p Ty.
|
|
template <typename Ty> class StaticGlobalTy : public GlobalTy {
|
|
Ty Data;
|
|
|
|
public:
|
|
template <typename... Args>
|
|
StaticGlobalTy(const std::string &Name, Args &&...args)
|
|
: GlobalTy(Name, sizeof(Ty), &Data),
|
|
Data(Ty{std::forward<Args>(args)...}) {}
|
|
|
|
template <typename... Args>
|
|
StaticGlobalTy(const char *Name, Args &&...args)
|
|
: GlobalTy(Name, sizeof(Ty), &Data),
|
|
Data(Ty{std::forward<Args>(args)...}) {}
|
|
|
|
template <typename... Args>
|
|
StaticGlobalTy(const char *Name, const char *Suffix, Args &&...args)
|
|
: GlobalTy(std::string(Name) + Suffix, sizeof(Ty), &Data),
|
|
Data(Ty{std::forward<Args>(args)...}) {}
|
|
|
|
Ty &getValue() { return Data; }
|
|
const Ty &getValue() const { return Data; }
|
|
void setValue(const Ty &V) { Data = V; }
|
|
};
|
|
|
|
/// Helper class to do the heavy lifting when it comes to moving globals between
|
|
/// host and device. Through the GenericDeviceTy we access memcpy DtoH and HtoD,
|
|
/// which means the only things specialized by the subclass is the retrival of
|
|
/// global metadata (size, addr) from the device.
|
|
/// \see getGlobalMetadataFromDevice
|
|
class GenericGlobalHandlerTy {
|
|
/// Map to store the ELF object files that have been loaded.
|
|
llvm::DenseMap<int32_t, ELF64LEObjectFile> ELFObjectFiles;
|
|
|
|
/// Get the cached ELF64LEObjectFile previosuly created for a specific
|
|
/// device image or create it if did not exist.
|
|
const ELF64LEObjectFile *
|
|
getOrCreateELFObjectFile(const GenericDeviceTy &Device, DeviceImageTy &Image);
|
|
|
|
/// Extract the global's information from the ELF image, section, and symbol.
|
|
virtual Error getGlobalMetadataFromELF(const DeviceImageTy &Image,
|
|
const ELF64LE::Sym &Symbol,
|
|
const ELF64LE::Shdr &Section,
|
|
GlobalTy &ImageGlobal);
|
|
|
|
/// Actually move memory between host and device. See readGlobalFromDevice and
|
|
/// writeGlobalToDevice for the interface description.
|
|
Error moveGlobalBetweenDeviceAndHost(GenericDeviceTy &Device,
|
|
DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal,
|
|
bool Device2Host);
|
|
|
|
/// Actually move memory between host and device. See readGlobalFromDevice and
|
|
/// writeGlobalToDevice for the interface description.
|
|
Error moveGlobalBetweenDeviceAndHost(GenericDeviceTy &Device,
|
|
DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal,
|
|
const GlobalTy &DeviceGlobal,
|
|
bool Device2Host);
|
|
|
|
public:
|
|
virtual ~GenericGlobalHandlerTy() {}
|
|
|
|
/// Get the address and size of a global in the image. Address and size are
|
|
/// return in \p ImageGlobal, the global name is passed in \p ImageGlobal.
|
|
Error getGlobalMetadataFromImage(GenericDeviceTy &Device,
|
|
DeviceImageTy &Image, GlobalTy &ImageGlobal);
|
|
|
|
/// Read the memory associated with a global from the image and store it on
|
|
/// the host. The name, size, and destination are defined by \p HostGlobal.
|
|
Error readGlobalFromImage(GenericDeviceTy &Device, DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal);
|
|
|
|
/// Get the address and size of a global from the device. Address is return in
|
|
/// \p DeviceGlobal, the global name and expected size are passed in
|
|
/// \p DeviceGlobal.
|
|
virtual Error getGlobalMetadataFromDevice(GenericDeviceTy &Device,
|
|
DeviceImageTy &Image,
|
|
GlobalTy &DeviceGlobal) = 0;
|
|
|
|
/// Copy the memory associated with a global from the device to its
|
|
/// counterpart on the host. The name, size, and destination are defined by
|
|
/// \p HostGlobal. The origin is defined by \p DeviceGlobal.
|
|
Error readGlobalFromDevice(GenericDeviceTy &Device, DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal,
|
|
const GlobalTy &DeviceGlobal) {
|
|
return moveGlobalBetweenDeviceAndHost(Device, Image, HostGlobal,
|
|
DeviceGlobal,
|
|
/* D2H */ true);
|
|
}
|
|
|
|
/// Copy the memory associated with a global from the device to its
|
|
/// counterpart on the host. The name, size, and destination are defined by
|
|
/// \p HostGlobal. The origin is automatically resolved.
|
|
Error readGlobalFromDevice(GenericDeviceTy &Device, DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal) {
|
|
return moveGlobalBetweenDeviceAndHost(Device, Image, HostGlobal,
|
|
/* D2H */ true);
|
|
}
|
|
|
|
/// Copy the memory associated with a global from the host to its counterpart
|
|
/// on the device. The name, size, and origin are defined by \p HostGlobal.
|
|
/// The destination is defined by \p DeviceGlobal.
|
|
Error writeGlobalToDevice(GenericDeviceTy &Device, DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal,
|
|
const GlobalTy &DeviceGlobal) {
|
|
return moveGlobalBetweenDeviceAndHost(Device, Image, HostGlobal,
|
|
DeviceGlobal,
|
|
/* D2H */ false);
|
|
}
|
|
|
|
/// Copy the memory associated with a global from the host to its counterpart
|
|
/// on the device. The name, size, and origin are defined by \p HostGlobal.
|
|
/// The destination is automatically resolved.
|
|
Error writeGlobalToDevice(GenericDeviceTy &Device, DeviceImageTy &Image,
|
|
const GlobalTy &HostGlobal) {
|
|
return moveGlobalBetweenDeviceAndHost(Device, Image, HostGlobal,
|
|
/* D2H */ false);
|
|
}
|
|
};
|
|
|
|
} // namespace plugin
|
|
} // namespace target
|
|
} // namespace omp
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_GLOBALHANDLER_H
|