[llvm][frontend][offloading] Move clang-linker-wrapper/OffloadWrapper.* to llvm/Frontend/Offloading (#78057)
This patch moves `clang/tools/clang-linker-wrapper/OffloadWrapper.*` to `llvm/Frontend/Offloading` allowing them to be re-utilized by other projects. Additionally, it makes minor modifications to the API to make it more flexible. Concretely: - The `wrap*` methods now have additional arguments `EntryArray`, `Suffix` and `EmitSurfacesAndTextures` to specify some additional options. - The `EntryArray` is now constructed by the caller. This change is needed to enable JIT compilation, as ORC doesn't fully support `__start_` and `__stop_` symbols. Thus, to JIT the code, the `EntryArray` has to be constructed explicitly in the IR. - The `Suffix` field is used when emitting the descriptor, registration methods, etc, to make them more readable. It is empty by default. - The `EmitSurfacesAndTextures` field controls whether to emit surface and texture registration code, as those functions were removed from `CUDART` in CUDA 12. It is true by default. - The function `getOffloadingEntryInitializer` was added to help create the `EntryArray`, as it returns the constant initializer and not a global variable.
This commit is contained in:
@@ -45,10 +45,6 @@
|
||||
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
|
||||
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-COFF
|
||||
|
||||
// CUDA: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".nv_fatbin"
|
||||
// CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 8
|
||||
// CUDA-NEXT: @.cuda.binary_handle = internal global ptr null
|
||||
|
||||
// CUDA-ELF: @__start_cuda_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
|
||||
// CUDA-ELF-NEXT: @__stop_cuda_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
|
||||
// CUDA-ELF-NEXT: @__dummy.cuda_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "cuda_offloading_entries"
|
||||
@@ -56,6 +52,10 @@
|
||||
// CUDA-COFF: @__start_cuda_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "cuda_offloading_entries$OA"
|
||||
// CUDA-COFF-NEXT: @__stop_cuda_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "cuda_offloading_entries$OZ"
|
||||
|
||||
// CUDA: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".nv_fatbin"
|
||||
// CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 8
|
||||
// CUDA-NEXT: @.cuda.binary_handle = internal global ptr null
|
||||
|
||||
// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.cuda.fatbin_reg, ptr null }]
|
||||
|
||||
// CUDA: define internal void @.cuda.fatbin_reg() section ".text.startup" {
|
||||
@@ -145,10 +145,6 @@
|
||||
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
|
||||
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-COFF
|
||||
|
||||
// HIP: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".hip_fatbin"
|
||||
// HIP-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1212764230, i32 1, ptr @.fatbin_image, ptr null }, section ".hipFatBinSegment", align 8
|
||||
// HIP-NEXT: @.hip.binary_handle = internal global ptr null
|
||||
|
||||
// HIP-ELF: @__start_hip_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
|
||||
// HIP-ELF-NEXT: @__stop_hip_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
|
||||
// HIP-ELF-NEXT: @__dummy.hip_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "hip_offloading_entries"
|
||||
@@ -156,6 +152,10 @@
|
||||
// HIP-COFF: @__start_hip_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "hip_offloading_entries$OA"
|
||||
// HIP-COFF-NEXT: @__stop_hip_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "hip_offloading_entries$OZ"
|
||||
|
||||
// HIP: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".hip_fatbin"
|
||||
// HIP-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1212764230, i32 1, ptr @.fatbin_image, ptr null }, section ".hipFatBinSegment", align 8
|
||||
// HIP-NEXT: @.hip.binary_handle = internal global ptr null
|
||||
|
||||
// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.hip.fatbin_reg, ptr null }]
|
||||
|
||||
// HIP: define internal void @.hip.fatbin_reg() section ".text.startup" {
|
||||
|
||||
@@ -28,7 +28,6 @@ endif()
|
||||
|
||||
add_clang_tool(clang-linker-wrapper
|
||||
ClangLinkerWrapper.cpp
|
||||
OffloadWrapper.cpp
|
||||
|
||||
DEPENDS
|
||||
${tablegen_deps}
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#include "OffloadWrapper.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Bitcode/BitcodeWriter.h"
|
||||
#include "llvm/CodeGen/CommandFlags.h"
|
||||
#include "llvm/Frontend/Offloading/OffloadWrapper.h"
|
||||
#include "llvm/Frontend/Offloading/Utility.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DiagnosticPrinter.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
@@ -906,15 +907,21 @@ wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers,
|
||||
|
||||
switch (Kind) {
|
||||
case OFK_OpenMP:
|
||||
if (Error Err = wrapOpenMPBinaries(M, BuffersToWrap))
|
||||
if (Error Err = offloading::wrapOpenMPBinaries(
|
||||
M, BuffersToWrap,
|
||||
offloading::getOffloadEntryArray(M, "omp_offloading_entries")))
|
||||
return std::move(Err);
|
||||
break;
|
||||
case OFK_Cuda:
|
||||
if (Error Err = wrapCudaBinary(M, BuffersToWrap.front()))
|
||||
if (Error Err = offloading::wrapCudaBinary(
|
||||
M, BuffersToWrap.front(),
|
||||
offloading::getOffloadEntryArray(M, "cuda_offloading_entries")))
|
||||
return std::move(Err);
|
||||
break;
|
||||
case OFK_HIP:
|
||||
if (Error Err = wrapHIPBinary(M, BuffersToWrap.front()))
|
||||
if (Error Err = offloading::wrapHIPBinary(
|
||||
M, BuffersToWrap.front(),
|
||||
offloading::getOffloadEntryArray(M, "hip_offloading_entries")))
|
||||
return std::move(Err);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
//===- OffloadWrapper.h --r-------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_CLANG_LINKER_WRAPPER_OFFLOAD_WRAPPER_H
|
||||
#define LLVM_CLANG_TOOLS_CLANG_LINKER_WRAPPER_OFFLOAD_WRAPPER_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
/// Wraps the input device images into the module \p M as global symbols and
|
||||
/// registers the images with the OpenMP Offloading runtime libomptarget.
|
||||
llvm::Error wrapOpenMPBinaries(llvm::Module &M,
|
||||
llvm::ArrayRef<llvm::ArrayRef<char>> Images);
|
||||
|
||||
/// Wraps the input fatbinary image into the module \p M as global symbols and
|
||||
/// registers the images with the CUDA runtime.
|
||||
llvm::Error wrapCudaBinary(llvm::Module &M, llvm::ArrayRef<char> Images);
|
||||
|
||||
/// Wraps the input bundled image into the module \p M as global symbols and
|
||||
/// registers the images with the HIP runtime.
|
||||
llvm::Error wrapHIPBinary(llvm::Module &M, llvm::ArrayRef<char> Images);
|
||||
|
||||
#endif
|
||||
52
llvm/include/llvm/Frontend/Offloading/OffloadWrapper.h
Normal file
52
llvm/include/llvm/Frontend/Offloading/OffloadWrapper.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//===- OffloadWrapper.h --r-------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_FRONTEND_OFFLOADING_OFFLOADWRAPPER_H
|
||||
#define LLVM_FRONTEND_OFFLOADING_OFFLOADWRAPPER_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace offloading {
|
||||
using EntryArrayTy = std::pair<GlobalVariable *, GlobalVariable *>;
|
||||
/// Wraps the input device images into the module \p M as global symbols and
|
||||
/// registers the images with the OpenMP Offloading runtime libomptarget.
|
||||
/// \param EntryArray Optional pair pointing to the `__start` and `__stop`
|
||||
/// symbols holding the `__tgt_offload_entry` array.
|
||||
/// \param Suffix An optional suffix appended to the emitted symbols.
|
||||
llvm::Error wrapOpenMPBinaries(llvm::Module &M,
|
||||
llvm::ArrayRef<llvm::ArrayRef<char>> Images,
|
||||
EntryArrayTy EntryArray,
|
||||
llvm::StringRef Suffix = "");
|
||||
|
||||
/// Wraps the input fatbinary image into the module \p M as global symbols and
|
||||
/// registers the images with the CUDA runtime.
|
||||
/// \param EntryArray Optional pair pointing to the `__start` and `__stop`
|
||||
/// symbols holding the `__tgt_offload_entry` array.
|
||||
/// \param Suffix An optional suffix appended to the emitted symbols.
|
||||
/// \param EmitSurfacesAndTextures Whether to emit surface and textures
|
||||
/// registration code. It defaults to false.
|
||||
llvm::Error wrapCudaBinary(llvm::Module &M, llvm::ArrayRef<char> Images,
|
||||
EntryArrayTy EntryArray, llvm::StringRef Suffix = "",
|
||||
bool EmitSurfacesAndTextures = true);
|
||||
|
||||
/// Wraps the input bundled image into the module \p M as global symbols and
|
||||
/// registers the images with the HIP runtime.
|
||||
/// \param EntryArray Optional pair pointing to the `__start` and `__stop`
|
||||
/// symbols holding the `__tgt_offload_entry` array.
|
||||
/// \param Suffix An optional suffix appended to the emitted symbols.
|
||||
/// \param EmitSurfacesAndTextures Whether to emit surface and textures
|
||||
/// registration code. It defaults to false.
|
||||
llvm::Error wrapHIPBinary(llvm::Module &M, llvm::ArrayRef<char> Images,
|
||||
EntryArrayTy EntryArray, llvm::StringRef Suffix = "",
|
||||
bool EmitSurfacesAndTextures = true);
|
||||
} // namespace offloading
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_FRONTEND_OFFLOADING_OFFLOADWRAPPER_H
|
||||
@@ -61,6 +61,12 @@ StructType *getEntryTy(Module &M);
|
||||
void emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,
|
||||
uint64_t Size, int32_t Flags, int32_t Data,
|
||||
StringRef SectionName);
|
||||
/// Create a constant struct initializer used to register this global at
|
||||
/// runtime.
|
||||
/// \return the constant struct and the global variable holding the symbol name.
|
||||
std::pair<Constant *, GlobalVariable *>
|
||||
getOffloadingEntryInitializer(Module &M, Constant *Addr, StringRef Name,
|
||||
uint64_t Size, int32_t Flags, int32_t Data);
|
||||
|
||||
/// Creates a pair of globals used to iterate the array of offloading entries by
|
||||
/// accessing the section variables provided by the linker.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
add_llvm_component_library(LLVMFrontendOffloading
|
||||
Utility.cpp
|
||||
OffloadWrapper.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
|
||||
@@ -9,6 +10,7 @@ add_llvm_component_library(LLVMFrontendOffloading
|
||||
|
||||
LINK_COMPONENTS
|
||||
Core
|
||||
BinaryFormat
|
||||
Support
|
||||
TransformUtils
|
||||
TargetParser
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OffloadWrapper.h"
|
||||
#include "llvm/Frontend/Offloading/OffloadWrapper.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Frontend/Offloading/Utility.h"
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::offloading;
|
||||
|
||||
namespace {
|
||||
/// Magic number that begins the section containing the CUDA fatbinary.
|
||||
@@ -110,10 +111,10 @@ PointerType *getBinDescPtrTy(Module &M) {
|
||||
/// };
|
||||
///
|
||||
/// Global variable that represents BinDesc is returned.
|
||||
GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs) {
|
||||
GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs,
|
||||
EntryArrayTy EntryArray, StringRef Suffix) {
|
||||
LLVMContext &C = M.getContext();
|
||||
auto [EntriesB, EntriesE] =
|
||||
offloading::getOffloadEntryArray(M, "omp_offloading_entries");
|
||||
auto [EntriesB, EntriesE] = EntryArray;
|
||||
|
||||
auto *Zero = ConstantInt::get(getSizeTTy(M), 0u);
|
||||
Constant *ZeroZero[] = {Zero, Zero};
|
||||
@@ -126,7 +127,7 @@ GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs) {
|
||||
auto *Data = ConstantDataArray::get(C, Buf);
|
||||
auto *Image = new GlobalVariable(M, Data->getType(), /*isConstant=*/true,
|
||||
GlobalVariable::InternalLinkage, Data,
|
||||
".omp_offloading.device_image");
|
||||
".omp_offloading.device_image" + Suffix);
|
||||
Image->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
|
||||
Image->setSection(".llvm.offloading");
|
||||
Image->setAlignment(Align(object::OffloadBinary::getAlignment()));
|
||||
@@ -166,7 +167,7 @@ GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs) {
|
||||
auto *Images =
|
||||
new GlobalVariable(M, ImagesData->getType(), /*isConstant*/ true,
|
||||
GlobalValue::InternalLinkage, ImagesData,
|
||||
".omp_offloading.device_images");
|
||||
".omp_offloading.device_images" + Suffix);
|
||||
Images->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
|
||||
|
||||
auto *ImagesB =
|
||||
@@ -180,14 +181,15 @@ GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs) {
|
||||
|
||||
return new GlobalVariable(M, DescInit->getType(), /*isConstant*/ true,
|
||||
GlobalValue::InternalLinkage, DescInit,
|
||||
".omp_offloading.descriptor");
|
||||
".omp_offloading.descriptor" + Suffix);
|
||||
}
|
||||
|
||||
void createRegisterFunction(Module &M, GlobalVariable *BinDesc) {
|
||||
void createRegisterFunction(Module &M, GlobalVariable *BinDesc,
|
||||
StringRef Suffix) {
|
||||
LLVMContext &C = M.getContext();
|
||||
auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
|
||||
auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage,
|
||||
".omp_offloading.descriptor_reg", &M);
|
||||
".omp_offloading.descriptor_reg" + Suffix, &M);
|
||||
Func->setSection(".text.startup");
|
||||
|
||||
// Get __tgt_register_lib function declaration.
|
||||
@@ -210,11 +212,13 @@ void createRegisterFunction(Module &M, GlobalVariable *BinDesc) {
|
||||
appendToGlobalCtors(M, Func, /*Priority*/ 1);
|
||||
}
|
||||
|
||||
void createUnregisterFunction(Module &M, GlobalVariable *BinDesc) {
|
||||
void createUnregisterFunction(Module &M, GlobalVariable *BinDesc,
|
||||
StringRef Suffix) {
|
||||
LLVMContext &C = M.getContext();
|
||||
auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
|
||||
auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage,
|
||||
".omp_offloading.descriptor_unreg", &M);
|
||||
auto *Func =
|
||||
Function::Create(FuncTy, GlobalValue::InternalLinkage,
|
||||
".omp_offloading.descriptor_unreg" + Suffix, &M);
|
||||
Func->setSection(".text.startup");
|
||||
|
||||
// Get __tgt_unregister_lib function declaration.
|
||||
@@ -251,7 +255,8 @@ StructType *getFatbinWrapperTy(Module &M) {
|
||||
|
||||
/// Embed the image \p Image into the module \p M so it can be found by the
|
||||
/// runtime.
|
||||
GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP) {
|
||||
GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP,
|
||||
StringRef Suffix) {
|
||||
LLVMContext &C = M.getContext();
|
||||
llvm::Type *Int8PtrTy = PointerType::getUnqual(C);
|
||||
llvm::Triple Triple = llvm::Triple(M.getTargetTriple());
|
||||
@@ -263,7 +268,7 @@ GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP) {
|
||||
auto *Data = ConstantDataArray::get(C, Image);
|
||||
auto *Fatbin = new GlobalVariable(M, Data->getType(), /*isConstant*/ true,
|
||||
GlobalVariable::InternalLinkage, Data,
|
||||
".fatbin_image");
|
||||
".fatbin_image" + Suffix);
|
||||
Fatbin->setSection(FatbinConstantSection);
|
||||
|
||||
// Create the fatbinary wrapper
|
||||
@@ -282,7 +287,7 @@ GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP) {
|
||||
auto *FatbinDesc =
|
||||
new GlobalVariable(M, getFatbinWrapperTy(M),
|
||||
/*isConstant*/ true, GlobalValue::InternalLinkage,
|
||||
FatbinInitializer, ".fatbin_wrapper");
|
||||
FatbinInitializer, ".fatbin_wrapper" + Suffix);
|
||||
FatbinDesc->setSection(FatbinWrapperSection);
|
||||
FatbinDesc->setAlignment(Align(8));
|
||||
|
||||
@@ -312,10 +317,12 @@ GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP) {
|
||||
/// 0, entry->size, 0, 0);
|
||||
/// }
|
||||
/// }
|
||||
Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
|
||||
Function *createRegisterGlobalsFunction(Module &M, bool IsHIP,
|
||||
EntryArrayTy EntryArray,
|
||||
StringRef Suffix,
|
||||
bool EmitSurfacesAndTextures) {
|
||||
LLVMContext &C = M.getContext();
|
||||
auto [EntriesB, EntriesE] = offloading::getOffloadEntryArray(
|
||||
M, IsHIP ? "hip_offloading_entries" : "cuda_offloading_entries");
|
||||
auto [EntriesB, EntriesE] = EntryArray;
|
||||
|
||||
// Get the __cudaRegisterFunction function declaration.
|
||||
PointerType *Int8PtrTy = PointerType::get(C, 0);
|
||||
@@ -339,7 +346,7 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
|
||||
IsHIP ? "__hipRegisterVar" : "__cudaRegisterVar", RegVarTy);
|
||||
|
||||
// Get the __cudaRegisterSurface function declaration.
|
||||
auto *RegSurfaceTy =
|
||||
FunctionType *RegSurfaceTy =
|
||||
FunctionType::get(Type::getVoidTy(C),
|
||||
{Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy,
|
||||
Type::getInt32Ty(C), Type::getInt32Ty(C)},
|
||||
@@ -348,7 +355,7 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
|
||||
IsHIP ? "__hipRegisterSurface" : "__cudaRegisterSurface", RegSurfaceTy);
|
||||
|
||||
// Get the __cudaRegisterTexture function declaration.
|
||||
auto *RegTextureTy = FunctionType::get(
|
||||
FunctionType *RegTextureTy = FunctionType::get(
|
||||
Type::getVoidTy(C),
|
||||
{Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Type::getInt32Ty(C),
|
||||
Type::getInt32Ty(C), Type::getInt32Ty(C)},
|
||||
@@ -454,19 +461,20 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
|
||||
Builder.CreateBr(IfEndBB);
|
||||
Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalManagedEntry),
|
||||
SwManagedBB);
|
||||
|
||||
// Create surface variable registration code.
|
||||
Builder.SetInsertPoint(SwSurfaceBB);
|
||||
Builder.CreateCall(
|
||||
RegSurface, {RegGlobalsFn->arg_begin(), Addr, Name, Name, Data, Extern});
|
||||
if (EmitSurfacesAndTextures)
|
||||
Builder.CreateCall(RegSurface, {RegGlobalsFn->arg_begin(), Addr, Name, Name,
|
||||
Data, Extern});
|
||||
Builder.CreateBr(IfEndBB);
|
||||
Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalSurfaceEntry),
|
||||
SwSurfaceBB);
|
||||
|
||||
// Create texture variable registration code.
|
||||
Builder.SetInsertPoint(SwTextureBB);
|
||||
Builder.CreateCall(RegTexture, {RegGlobalsFn->arg_begin(), Addr, Name, Name,
|
||||
Data, Normalized, Extern});
|
||||
if (EmitSurfacesAndTextures)
|
||||
Builder.CreateCall(RegTexture, {RegGlobalsFn->arg_begin(), Addr, Name, Name,
|
||||
Data, Normalized, Extern});
|
||||
Builder.CreateBr(IfEndBB);
|
||||
Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalTextureEntry),
|
||||
SwTextureBB);
|
||||
@@ -497,18 +505,20 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
|
||||
// Create the constructor and destructor to register the fatbinary with the CUDA
|
||||
// runtime.
|
||||
void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc,
|
||||
bool IsHIP) {
|
||||
bool IsHIP, EntryArrayTy EntryArray,
|
||||
StringRef Suffix,
|
||||
bool EmitSurfacesAndTextures) {
|
||||
LLVMContext &C = M.getContext();
|
||||
auto *CtorFuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
|
||||
auto *CtorFunc =
|
||||
Function::Create(CtorFuncTy, GlobalValue::InternalLinkage,
|
||||
IsHIP ? ".hip.fatbin_reg" : ".cuda.fatbin_reg", &M);
|
||||
auto *CtorFunc = Function::Create(
|
||||
CtorFuncTy, GlobalValue::InternalLinkage,
|
||||
(IsHIP ? ".hip.fatbin_reg" : ".cuda.fatbin_reg") + Suffix, &M);
|
||||
CtorFunc->setSection(".text.startup");
|
||||
|
||||
auto *DtorFuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
|
||||
auto *DtorFunc =
|
||||
Function::Create(DtorFuncTy, GlobalValue::InternalLinkage,
|
||||
IsHIP ? ".hip.fatbin_unreg" : ".cuda.fatbin_unreg", &M);
|
||||
auto *DtorFunc = Function::Create(
|
||||
DtorFuncTy, GlobalValue::InternalLinkage,
|
||||
(IsHIP ? ".hip.fatbin_unreg" : ".cuda.fatbin_unreg") + Suffix, &M);
|
||||
DtorFunc->setSection(".text.startup");
|
||||
|
||||
auto *PtrTy = PointerType::getUnqual(C);
|
||||
@@ -536,7 +546,7 @@ void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc,
|
||||
auto *BinaryHandleGlobal = new llvm::GlobalVariable(
|
||||
M, PtrTy, false, llvm::GlobalValue::InternalLinkage,
|
||||
llvm::ConstantPointerNull::get(PtrTy),
|
||||
IsHIP ? ".hip.binary_handle" : ".cuda.binary_handle");
|
||||
(IsHIP ? ".hip.binary_handle" : ".cuda.binary_handle") + Suffix);
|
||||
|
||||
// Create the constructor to register this image with the runtime.
|
||||
IRBuilder<> CtorBuilder(BasicBlock::Create(C, "entry", CtorFunc));
|
||||
@@ -546,7 +556,10 @@ void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc,
|
||||
CtorBuilder.CreateAlignedStore(
|
||||
Handle, BinaryHandleGlobal,
|
||||
Align(M.getDataLayout().getPointerTypeSize(PtrTy)));
|
||||
CtorBuilder.CreateCall(createRegisterGlobalsFunction(M, IsHIP), Handle);
|
||||
CtorBuilder.CreateCall(createRegisterGlobalsFunction(M, IsHIP, EntryArray,
|
||||
Suffix,
|
||||
EmitSurfacesAndTextures),
|
||||
Handle);
|
||||
if (!IsHIP)
|
||||
CtorBuilder.CreateCall(RegFatbinEnd, Handle);
|
||||
CtorBuilder.CreateCall(AtExit, DtorFunc);
|
||||
@@ -565,35 +578,43 @@ void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc,
|
||||
// Add this function to constructors.
|
||||
appendToGlobalCtors(M, CtorFunc, /*Priority*/ 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Error wrapOpenMPBinaries(Module &M, ArrayRef<ArrayRef<char>> Images) {
|
||||
GlobalVariable *Desc = createBinDesc(M, Images);
|
||||
Error offloading::wrapOpenMPBinaries(Module &M, ArrayRef<ArrayRef<char>> Images,
|
||||
EntryArrayTy EntryArray,
|
||||
llvm::StringRef Suffix) {
|
||||
GlobalVariable *Desc = createBinDesc(M, Images, EntryArray, Suffix);
|
||||
if (!Desc)
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"No binary descriptors created.");
|
||||
createRegisterFunction(M, Desc);
|
||||
createUnregisterFunction(M, Desc);
|
||||
createRegisterFunction(M, Desc, Suffix);
|
||||
createUnregisterFunction(M, Desc, Suffix);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error wrapCudaBinary(Module &M, ArrayRef<char> Image) {
|
||||
GlobalVariable *Desc = createFatbinDesc(M, Image, /* IsHIP */ false);
|
||||
Error offloading::wrapCudaBinary(Module &M, ArrayRef<char> Image,
|
||||
EntryArrayTy EntryArray,
|
||||
llvm::StringRef Suffix,
|
||||
bool EmitSurfacesAndTextures) {
|
||||
GlobalVariable *Desc = createFatbinDesc(M, Image, /*IsHip=*/false, Suffix);
|
||||
if (!Desc)
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"No fatinbary section created.");
|
||||
"No fatbin section created.");
|
||||
|
||||
createRegisterFatbinFunction(M, Desc, /* IsHIP */ false);
|
||||
createRegisterFatbinFunction(M, Desc, /*IsHip=*/false, EntryArray, Suffix,
|
||||
EmitSurfacesAndTextures);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error wrapHIPBinary(Module &M, ArrayRef<char> Image) {
|
||||
GlobalVariable *Desc = createFatbinDesc(M, Image, /* IsHIP */ true);
|
||||
Error offloading::wrapHIPBinary(Module &M, ArrayRef<char> Image,
|
||||
EntryArrayTy EntryArray, llvm::StringRef Suffix,
|
||||
bool EmitSurfacesAndTextures) {
|
||||
GlobalVariable *Desc = createFatbinDesc(M, Image, /*IsHip=*/true, Suffix);
|
||||
if (!Desc)
|
||||
return createStringError(inconvertibleErrorCode(),
|
||||
"No fatinbary section created.");
|
||||
"No fatbin section created.");
|
||||
|
||||
createRegisterFatbinFunction(M, Desc, /* IsHIP */ true);
|
||||
createRegisterFatbinFunction(M, Desc, /*IsHip=*/true, EntryArray, Suffix,
|
||||
EmitSurfacesAndTextures);
|
||||
return Error::success();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- Utility.cpp ------ Collection of geneirc offloading utilities ------===//
|
||||
//===- Utility.cpp ------ Collection of generic offloading utilities ------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -28,11 +28,10 @@ StructType *offloading::getEntryTy(Module &M) {
|
||||
}
|
||||
|
||||
// TODO: Rework this interface to be more generic.
|
||||
void offloading::emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,
|
||||
uint64_t Size, int32_t Flags, int32_t Data,
|
||||
StringRef SectionName) {
|
||||
llvm::Triple Triple(M.getTargetTriple());
|
||||
|
||||
std::pair<Constant *, GlobalVariable *>
|
||||
offloading::getOffloadingEntryInitializer(Module &M, Constant *Addr,
|
||||
StringRef Name, uint64_t Size,
|
||||
int32_t Flags, int32_t Data) {
|
||||
Type *Int8PtrTy = PointerType::getUnqual(M.getContext());
|
||||
Type *Int32Ty = Type::getInt32Ty(M.getContext());
|
||||
Type *SizeTy = M.getDataLayout().getIntPtrType(M.getContext());
|
||||
@@ -54,6 +53,16 @@ void offloading::emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,
|
||||
ConstantInt::get(Int32Ty, Data),
|
||||
};
|
||||
Constant *EntryInitializer = ConstantStruct::get(getEntryTy(M), EntryData);
|
||||
return {EntryInitializer, Str};
|
||||
}
|
||||
|
||||
void offloading::emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,
|
||||
uint64_t Size, int32_t Flags, int32_t Data,
|
||||
StringRef SectionName) {
|
||||
llvm::Triple Triple(M.getTargetTriple());
|
||||
|
||||
auto [EntryInitializer, NameGV] =
|
||||
getOffloadingEntryInitializer(M, Addr, Name, Size, Flags, Data);
|
||||
|
||||
auto *Entry = new GlobalVariable(
|
||||
M, getEntryTy(M),
|
||||
|
||||
Reference in New Issue
Block a user