Skip to content

Commit 9c0e649

Browse files
authored
[Offloading][NFC] Refactor handling of offloading entries (#72544)
Summary: This patch is a simple refactoring of code out of the linker wrapper into a common location. The main motivation behind this change is to make it easier to change the handling in the future to accept a triple to be used to emit entries that function on that target.
1 parent b1e039f commit 9c0e649

File tree

5 files changed

+82
-115
lines changed

5 files changed

+82
-115
lines changed

clang/test/Driver/linker-wrapper-image.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
1111
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=OPENMP
1212

13-
// OPENMP: @__start_omp_offloading_entries = external hidden constant %__tgt_offload_entry
14-
// OPENMP-NEXT: @__stop_omp_offloading_entries = external hidden constant %__tgt_offload_entry
15-
// OPENMP-NEXT: @__dummy.omp_offloading.entry = hidden constant [0 x %__tgt_offload_entry] zeroinitializer, section "omp_offloading_entries"
13+
// OPENMP: @__start_omp_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
14+
// OPENMP-NEXT: @__stop_omp_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
15+
// OPENMP-NEXT: @__dummy.omp_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "omp_offloading_entries"
1616
// OPENMP-NEXT: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}"
1717
// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr @.omp_offloading.device_image, ptr getelementptr inbounds ([[[SIZE]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }]
1818
// OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }
@@ -39,10 +39,10 @@
3939

4040
// CUDA: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".nv_fatbin"
4141
// CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 8
42-
// CUDA-NEXT: @__dummy.cuda_offloading.entry = hidden constant [0 x %__tgt_offload_entry] zeroinitializer, section "cuda_offloading_entries"
4342
// CUDA-NEXT: @.cuda.binary_handle = internal global ptr null
44-
// CUDA-NEXT: @__start_cuda_offloading_entries = external hidden constant [0 x %__tgt_offload_entry]
45-
// CUDA-NEXT: @__stop_cuda_offloading_entries = external hidden constant [0 x %__tgt_offload_entry]
43+
// CUDA-NEXT: @__start_cuda_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
44+
// CUDA-NEXT: @__stop_cuda_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
45+
// CUDA-NEXT: @__dummy.cuda_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "cuda_offloading_entries"
4646
// CUDA-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.cuda.fatbin_reg, ptr null }]
4747

4848
// CUDA: define internal void @.cuda.fatbin_reg() section ".text.startup" {
@@ -68,13 +68,13 @@
6868

6969
// CUDA: while.entry:
7070
// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %7, %if.end ]
71-
// CUDA-NEXT: %1 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 0
71+
// CUDA-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0
7272
// CUDA-NEXT: %addr = load ptr, ptr %1, align 8
73-
// CUDA-NEXT: %2 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 1
73+
// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1
7474
// CUDA-NEXT: %name = load ptr, ptr %2, align 8
75-
// CUDA-NEXT: %3 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 2
75+
// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2
7676
// CUDA-NEXT: %size = load i64, ptr %3, align 4
77-
// CUDA-NEXT: %4 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 3
77+
// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3
7878
// CUDA-NEXT: %flag = load i32, ptr %4, align 4
7979
// CUDA-NEXT: %5 = icmp eq i64 %size, 0
8080
// CUDA-NEXT: br i1 %5, label %if.then, label %if.else
@@ -105,7 +105,7 @@
105105
// CUDA-NEXT: br label %if.end
106106

107107
// CUDA: if.end:
108-
// CUDA-NEXT: %7 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 1
108+
// CUDA-NEXT: %7 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1
109109
// CUDA-NEXT: %8 = icmp eq ptr %7, @__stop_cuda_offloading_entries
110110
// CUDA-NEXT: br i1 %8, label %while.end, label %while.entry
111111

@@ -121,10 +121,10 @@
121121

122122
// HIP: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".hip_fatbin"
123123
// HIP-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1212764230, i32 1, ptr @.fatbin_image, ptr null }, section ".hipFatBinSegment", align 8
124-
// HIP-NEXT: @__dummy.hip_offloading.entry = hidden constant [0 x %__tgt_offload_entry] zeroinitializer, section "hip_offloading_entries"
125124
// HIP-NEXT: @.hip.binary_handle = internal global ptr null
126-
// HIP-NEXT: @__start_hip_offloading_entries = external hidden constant [0 x %__tgt_offload_entry]
127-
// HIP-NEXT: @__stop_hip_offloading_entries = external hidden constant [0 x %__tgt_offload_entry]
125+
// HIP-NEXT: @__start_hip_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
126+
// HIP-NEXT: @__stop_hip_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
127+
// HIP-NEXT: @__dummy.hip_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "hip_offloading_entries"
128128
// HIP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.hip.fatbin_reg, ptr null }]
129129

130130
// HIP: define internal void @.hip.fatbin_reg() section ".text.startup" {
@@ -149,13 +149,13 @@
149149

150150
// HIP: while.entry:
151151
// HIP-NEXT: %entry1 = phi ptr [ @__start_hip_offloading_entries, %entry ], [ %7, %if.end ]
152-
// HIP-NEXT: %1 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 0
152+
// HIP-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0
153153
// HIP-NEXT: %addr = load ptr, ptr %1, align 8
154-
// HIP-NEXT: %2 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 1
154+
// HIP-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1
155155
// HIP-NEXT: %name = load ptr, ptr %2, align 8
156-
// HIP-NEXT: %3 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 2
156+
// HIP-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2
157157
// HIP-NEXT: %size = load i64, ptr %3, align 4
158-
// HIP-NEXT: %4 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 0, i32 3
158+
// HIP-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3
159159
// HIP-NEXT: %flag = load i32, ptr %4, align 4
160160
// HIP-NEXT: %5 = icmp eq i64 %size, 0
161161
// HIP-NEXT: br i1 %5, label %if.then, label %if.else
@@ -186,7 +186,7 @@
186186
// HIP-NEXT: br label %if.end
187187

188188
// HIP: if.end:
189-
// HIP-NEXT: %7 = getelementptr inbounds %__tgt_offload_entry, ptr %entry1, i64 1
189+
// HIP-NEXT: %7 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1
190190
// HIP-NEXT: %8 = icmp eq ptr %7, @__stop_hip_offloading_entries
191191
// HIP-NEXT: br i1 %8, label %while.end, label %while.entry
192192

clang/tools/clang-linker-wrapper/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
1515
TargetParser
1616
CodeGen
1717
LTO
18+
FrontendOffloading
1819
)
1920

2021
set(LLVM_TARGET_DEFINITIONS LinkerWrapperOpts.td)

clang/tools/clang-linker-wrapper/OffloadWrapper.cpp

Lines changed: 22 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "OffloadWrapper.h"
1010
#include "llvm/ADT/ArrayRef.h"
11+
#include "llvm/Frontend/Offloading/Utility.h"
1112
#include "llvm/IR/Constants.h"
1213
#include "llvm/IR/GlobalVariable.h"
1314
#include "llvm/IR/IRBuilder.h"
@@ -39,36 +40,7 @@ enum OffloadEntryKindFlag : uint32_t {
3940
};
4041

4142
IntegerType *getSizeTTy(Module &M) {
42-
LLVMContext &C = M.getContext();
43-
switch (M.getDataLayout().getPointerTypeSize(PointerType::getUnqual(C))) {
44-
case 4u:
45-
return Type::getInt32Ty(C);
46-
case 8u:
47-
return Type::getInt64Ty(C);
48-
}
49-
llvm_unreachable("unsupported pointer type size");
50-
}
51-
52-
// struct __tgt_offload_entry {
53-
// void *addr;
54-
// char *name;
55-
// size_t size;
56-
// int32_t flags;
57-
// int32_t reserved;
58-
// };
59-
StructType *getEntryTy(Module &M) {
60-
LLVMContext &C = M.getContext();
61-
StructType *EntryTy = StructType::getTypeByName(C, "__tgt_offload_entry");
62-
if (!EntryTy)
63-
EntryTy =
64-
StructType::create("__tgt_offload_entry", PointerType::getUnqual(C),
65-
PointerType::getUnqual(C), getSizeTTy(M),
66-
Type::getInt32Ty(C), Type::getInt32Ty(C));
67-
return EntryTy;
68-
}
69-
70-
PointerType *getEntryPtrTy(Module &M) {
71-
return PointerType::getUnqual(getEntryTy(M));
43+
return M.getDataLayout().getIntPtrType(M.getContext());
7244
}
7345

7446
// struct __tgt_device_image {
@@ -81,9 +53,10 @@ StructType *getDeviceImageTy(Module &M) {
8153
LLVMContext &C = M.getContext();
8254
StructType *ImageTy = StructType::getTypeByName(C, "__tgt_device_image");
8355
if (!ImageTy)
84-
ImageTy = StructType::create(
85-
"__tgt_device_image", PointerType::getUnqual(C),
86-
PointerType::getUnqual(C), getEntryPtrTy(M), getEntryPtrTy(M));
56+
ImageTy =
57+
StructType::create("__tgt_device_image", PointerType::getUnqual(C),
58+
PointerType::getUnqual(C), PointerType::getUnqual(C),
59+
PointerType::getUnqual(C));
8760
return ImageTy;
8861
}
8962

@@ -101,9 +74,9 @@ StructType *getBinDescTy(Module &M) {
10174
LLVMContext &C = M.getContext();
10275
StructType *DescTy = StructType::getTypeByName(C, "__tgt_bin_desc");
10376
if (!DescTy)
104-
DescTy = StructType::create("__tgt_bin_desc", Type::getInt32Ty(C),
105-
getDeviceImagePtrTy(M), getEntryPtrTy(M),
106-
getEntryPtrTy(M));
77+
DescTy = StructType::create(
78+
"__tgt_bin_desc", Type::getInt32Ty(C), getDeviceImagePtrTy(M),
79+
PointerType::getUnqual(C), PointerType::getUnqual(C));
10780
return DescTy;
10881
}
10982

@@ -151,28 +124,8 @@ PointerType *getBinDescPtrTy(Module &M) {
151124
/// Global variable that represents BinDesc is returned.
152125
GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs) {
153126
LLVMContext &C = M.getContext();
154-
// Create external begin/end symbols for the offload entries table.
155-
auto *EntriesB = new GlobalVariable(
156-
M, getEntryTy(M), /*isConstant*/ true, GlobalValue::ExternalLinkage,
157-
/*Initializer*/ nullptr, "__start_omp_offloading_entries");
158-
EntriesB->setVisibility(GlobalValue::HiddenVisibility);
159-
auto *EntriesE = new GlobalVariable(
160-
M, getEntryTy(M), /*isConstant*/ true, GlobalValue::ExternalLinkage,
161-
/*Initializer*/ nullptr, "__stop_omp_offloading_entries");
162-
EntriesE->setVisibility(GlobalValue::HiddenVisibility);
163-
164-
// We assume that external begin/end symbols that we have created above will
165-
// be defined by the linker. But linker will do that only if linker inputs
166-
// have section with "omp_offloading_entries" name which is not guaranteed.
167-
// So, we just create dummy zero sized object in the offload entries section
168-
// to force linker to define those symbols.
169-
auto *DummyInit =
170-
ConstantAggregateZero::get(ArrayType::get(getEntryTy(M), 0u));
171-
auto *DummyEntry = new GlobalVariable(
172-
M, DummyInit->getType(), true, GlobalVariable::ExternalLinkage, DummyInit,
173-
"__dummy.omp_offloading.entry");
174-
DummyEntry->setSection("omp_offloading_entries");
175-
DummyEntry->setVisibility(GlobalValue::HiddenVisibility);
127+
auto [EntriesB, EntriesE] =
128+
offloading::getOffloadEntryArray(M, "omp_offloading_entries");
176129

177130
auto *Zero = ConstantInt::get(getSizeTTy(M), 0u);
178131
Constant *ZeroZero[] = {Zero, Zero};
@@ -328,18 +281,6 @@ GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP) {
328281
FatbinDesc->setSection(FatbinWrapperSection);
329282
FatbinDesc->setAlignment(Align(8));
330283

331-
// We create a dummy entry to ensure the linker will define the begin / end
332-
// symbols. The CUDA runtime should ignore the null address if we attempt to
333-
// register it.
334-
auto *DummyInit =
335-
ConstantAggregateZero::get(ArrayType::get(getEntryTy(M), 0u));
336-
auto *DummyEntry = new GlobalVariable(
337-
M, DummyInit->getType(), true, GlobalVariable::ExternalLinkage, DummyInit,
338-
IsHIP ? "__dummy.hip_offloading.entry" : "__dummy.cuda_offloading.entry");
339-
DummyEntry->setVisibility(GlobalValue::HiddenVisibility);
340-
DummyEntry->setSection(IsHIP ? "hip_offloading_entries"
341-
: "cuda_offloading_entries");
342-
343284
return FatbinDesc;
344285
}
345286

@@ -368,6 +309,9 @@ GlobalVariable *createFatbinDesc(Module &M, ArrayRef<char> Image, bool IsHIP) {
368309
/// }
369310
Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
370311
LLVMContext &C = M.getContext();
312+
auto [EntriesB, EntriesE] = offloading::getOffloadEntryArray(
313+
M, IsHIP ? "hip_offloading_entries" : "cuda_offloading_entries");
314+
371315
// Get the __cudaRegisterFunction function declaration.
372316
PointerType *Int8PtrTy = PointerType::get(C, 0);
373317
PointerType *Int8PtrPtrTy = PointerType::get(C, 0);
@@ -389,22 +333,6 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
389333
FunctionCallee RegVar = M.getOrInsertFunction(
390334
IsHIP ? "__hipRegisterVar" : "__cudaRegisterVar", RegVarTy);
391335

392-
// Create the references to the start / stop symbols defined by the linker.
393-
auto *EntriesB =
394-
new GlobalVariable(M, ArrayType::get(getEntryTy(M), 0),
395-
/*isConstant*/ true, GlobalValue::ExternalLinkage,
396-
/*Initializer*/ nullptr,
397-
IsHIP ? "__start_hip_offloading_entries"
398-
: "__start_cuda_offloading_entries");
399-
EntriesB->setVisibility(GlobalValue::HiddenVisibility);
400-
auto *EntriesE =
401-
new GlobalVariable(M, ArrayType::get(getEntryTy(M), 0),
402-
/*isConstant*/ true, GlobalValue::ExternalLinkage,
403-
/*Initializer*/ nullptr,
404-
IsHIP ? "__stop_hip_offloading_entries"
405-
: "__stop_cuda_offloading_entries");
406-
EntriesE->setVisibility(GlobalValue::HiddenVisibility);
407-
408336
auto *RegGlobalsTy = FunctionType::get(Type::getVoidTy(C), Int8PtrPtrTy,
409337
/*isVarArg*/ false);
410338
auto *RegGlobalsFn =
@@ -427,24 +355,24 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
427355
auto *EntryCmp = Builder.CreateICmpNE(EntriesB, EntriesE);
428356
Builder.CreateCondBr(EntryCmp, EntryBB, ExitBB);
429357
Builder.SetInsertPoint(EntryBB);
430-
auto *Entry = Builder.CreatePHI(getEntryPtrTy(M), 2, "entry");
358+
auto *Entry = Builder.CreatePHI(PointerType::getUnqual(C), 2, "entry");
431359
auto *AddrPtr =
432-
Builder.CreateInBoundsGEP(getEntryTy(M), Entry,
360+
Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
433361
{ConstantInt::get(getSizeTTy(M), 0),
434362
ConstantInt::get(Type::getInt32Ty(C), 0)});
435363
auto *Addr = Builder.CreateLoad(Int8PtrTy, AddrPtr, "addr");
436364
auto *NamePtr =
437-
Builder.CreateInBoundsGEP(getEntryTy(M), Entry,
365+
Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
438366
{ConstantInt::get(getSizeTTy(M), 0),
439367
ConstantInt::get(Type::getInt32Ty(C), 1)});
440368
auto *Name = Builder.CreateLoad(Int8PtrTy, NamePtr, "name");
441369
auto *SizePtr =
442-
Builder.CreateInBoundsGEP(getEntryTy(M), Entry,
370+
Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
443371
{ConstantInt::get(getSizeTTy(M), 0),
444372
ConstantInt::get(Type::getInt32Ty(C), 2)});
445373
auto *Size = Builder.CreateLoad(getSizeTTy(M), SizePtr, "size");
446374
auto *FlagsPtr =
447-
Builder.CreateInBoundsGEP(getEntryTy(M), Entry,
375+
Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry,
448376
{ConstantInt::get(getSizeTTy(M), 0),
449377
ConstantInt::get(Type::getInt32Ty(C), 3)});
450378
auto *Flags = Builder.CreateLoad(Type::getInt32Ty(C), FlagsPtr, "flag");
@@ -491,16 +419,16 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) {
491419

492420
Builder.SetInsertPoint(IfEndBB);
493421
auto *NewEntry = Builder.CreateInBoundsGEP(
494-
getEntryTy(M), Entry, ConstantInt::get(getSizeTTy(M), 1));
422+
offloading::getEntryTy(M), Entry, ConstantInt::get(getSizeTTy(M), 1));
495423
auto *Cmp = Builder.CreateICmpEQ(
496424
NewEntry,
497425
ConstantExpr::getInBoundsGetElementPtr(
498-
ArrayType::get(getEntryTy(M), 0), EntriesE,
426+
ArrayType::get(offloading::getEntryTy(M), 0), EntriesE,
499427
ArrayRef<Constant *>({ConstantInt::get(getSizeTTy(M), 0),
500428
ConstantInt::get(getSizeTTy(M), 0)})));
501429
Entry->addIncoming(
502430
ConstantExpr::getInBoundsGetElementPtr(
503-
ArrayType::get(getEntryTy(M), 0), EntriesB,
431+
ArrayType::get(offloading::getEntryTy(M), 0), EntriesB,
504432
ArrayRef<Constant *>({ConstantInt::get(getSizeTTy(M), 0),
505433
ConstantInt::get(getSizeTTy(M), 0)})),
506434
&RegGlobalsFn->getEntryBlock());

llvm/include/llvm/Frontend/Offloading/Utility.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@
1212
namespace llvm {
1313
namespace offloading {
1414

15+
/// Returns the type of the offloading entry we use to store kernels and
16+
/// globals that will be registered with the offloading runtime.
17+
StructType *getEntryTy(Module &M);
18+
1519
/// Create an offloading section struct used to register this global at
1620
/// runtime.
1721
///
18-
/// Type struct __tgt_offload_entry{
22+
/// Type struct __tgt_offload_entry {
1923
/// void *addr; // Pointer to the offload entry info.
2024
/// // (function or global)
2125
/// char *name; // Name of the function or global.
@@ -33,5 +37,10 @@ namespace offloading {
3337
void emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,
3438
uint64_t Size, int32_t Flags, StringRef SectionName);
3539

40+
/// Creates a pair of globals used to iterate the array of offloading entries by
41+
/// accessing the section variables provided by the linker.
42+
std::pair<GlobalVariable *, GlobalVariable *>
43+
getOffloadEntryArray(Module &M, StringRef SectionName);
44+
3645
} // namespace offloading
3746
} // namespace llvm

llvm/lib/Frontend/Offloading/Utility.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ using namespace llvm;
1616
using namespace llvm::offloading;
1717

1818
// TODO: Export this to the linker wrapper code registration.
19-
static StructType *getEntryTy(Module &M) {
19+
StructType *offloading::getEntryTy(Module &M) {
2020
LLVMContext &C = M.getContext();
2121
StructType *EntryTy =
2222
StructType::getTypeByName(C, "struct.__tgt_offload_entry");
@@ -65,3 +65,32 @@ void offloading::emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,
6565
Entry->setSection(SectionName);
6666
Entry->setAlignment(Align(1));
6767
}
68+
69+
std::pair<GlobalVariable *, GlobalVariable *>
70+
offloading::getOffloadEntryArray(Module &M, StringRef SectionName) {
71+
auto *EntriesB =
72+
new GlobalVariable(M, ArrayType::get(getEntryTy(M), 0),
73+
/*isConstant=*/true, GlobalValue::ExternalLinkage,
74+
/*Initializer=*/nullptr, "__start_" + SectionName);
75+
EntriesB->setVisibility(GlobalValue::HiddenVisibility);
76+
auto *EntriesE =
77+
new GlobalVariable(M, ArrayType::get(getEntryTy(M), 0),
78+
/*isConstant=*/true, GlobalValue::ExternalLinkage,
79+
/*Initializer=*/nullptr, "__stop_" + SectionName);
80+
EntriesE->setVisibility(GlobalValue::HiddenVisibility);
81+
82+
// We assume that external begin/end symbols that we have created above will
83+
// be defined by the linker. But linker will do that only if linker inputs
84+
// have section with "omp_offloading_entries" name which is not guaranteed.
85+
// So, we just create dummy zero sized object in the offload entries section
86+
// to force linker to define those symbols.
87+
auto *DummyInit =
88+
ConstantAggregateZero::get(ArrayType::get(getEntryTy(M), 0u));
89+
auto *DummyEntry = new GlobalVariable(M, DummyInit->getType(), true,
90+
GlobalVariable::ExternalLinkage,
91+
DummyInit, "__dummy." + SectionName);
92+
DummyEntry->setSection(SectionName);
93+
DummyEntry->setVisibility(GlobalValue::HiddenVisibility);
94+
95+
return std::make_pair(EntriesB, EntriesE);
96+
}

0 commit comments

Comments
 (0)