Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Frontend/Offloading/Utility.cpp
35271 views
1
//===- Utility.cpp ------ Collection of generic offloading utilities ------===//
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
#include "llvm/Frontend/Offloading/Utility.h"
10
#include "llvm/IR/Constants.h"
11
#include "llvm/IR/GlobalValue.h"
12
#include "llvm/IR/GlobalVariable.h"
13
#include "llvm/IR/Value.h"
14
#include "llvm/Transforms/Utils/ModuleUtils.h"
15
16
using namespace llvm;
17
using namespace llvm::offloading;
18
19
StructType *offloading::getEntryTy(Module &M) {
20
LLVMContext &C = M.getContext();
21
StructType *EntryTy =
22
StructType::getTypeByName(C, "struct.__tgt_offload_entry");
23
if (!EntryTy)
24
EntryTy = StructType::create(
25
"struct.__tgt_offload_entry", PointerType::getUnqual(C),
26
PointerType::getUnqual(C), M.getDataLayout().getIntPtrType(C),
27
Type::getInt32Ty(C), Type::getInt32Ty(C));
28
return EntryTy;
29
}
30
31
// TODO: Rework this interface to be more generic.
32
std::pair<Constant *, GlobalVariable *>
33
offloading::getOffloadingEntryInitializer(Module &M, Constant *Addr,
34
StringRef Name, uint64_t Size,
35
int32_t Flags, int32_t Data) {
36
llvm::Triple Triple(M.getTargetTriple());
37
Type *Int8PtrTy = PointerType::getUnqual(M.getContext());
38
Type *Int32Ty = Type::getInt32Ty(M.getContext());
39
Type *SizeTy = M.getDataLayout().getIntPtrType(M.getContext());
40
41
Constant *AddrName = ConstantDataArray::getString(M.getContext(), Name);
42
43
StringRef Prefix =
44
Triple.isNVPTX() ? "$offloading$entry_name" : ".offloading.entry_name";
45
46
// Create the constant string used to look up the symbol in the device.
47
auto *Str =
48
new GlobalVariable(M, AddrName->getType(), /*isConstant=*/true,
49
GlobalValue::InternalLinkage, AddrName, Prefix);
50
Str->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
51
52
// Construct the offloading entry.
53
Constant *EntryData[] = {
54
ConstantExpr::getPointerBitCastOrAddrSpaceCast(Addr, Int8PtrTy),
55
ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, Int8PtrTy),
56
ConstantInt::get(SizeTy, Size),
57
ConstantInt::get(Int32Ty, Flags),
58
ConstantInt::get(Int32Ty, Data),
59
};
60
Constant *EntryInitializer = ConstantStruct::get(getEntryTy(M), EntryData);
61
return {EntryInitializer, Str};
62
}
63
64
void offloading::emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,
65
uint64_t Size, int32_t Flags, int32_t Data,
66
StringRef SectionName) {
67
llvm::Triple Triple(M.getTargetTriple());
68
69
auto [EntryInitializer, NameGV] =
70
getOffloadingEntryInitializer(M, Addr, Name, Size, Flags, Data);
71
72
StringRef Prefix =
73
Triple.isNVPTX() ? "$offloading$entry$" : ".offloading.entry.";
74
auto *Entry = new GlobalVariable(
75
M, getEntryTy(M),
76
/*isConstant=*/true, GlobalValue::WeakAnyLinkage, EntryInitializer,
77
Prefix + Name, nullptr, GlobalValue::NotThreadLocal,
78
M.getDataLayout().getDefaultGlobalsAddressSpace());
79
80
// The entry has to be created in the section the linker expects it to be.
81
if (Triple.isOSBinFormatCOFF())
82
Entry->setSection((SectionName + "$OE").str());
83
else
84
Entry->setSection(SectionName);
85
Entry->setAlignment(Align(1));
86
}
87
88
std::pair<GlobalVariable *, GlobalVariable *>
89
offloading::getOffloadEntryArray(Module &M, StringRef SectionName) {
90
llvm::Triple Triple(M.getTargetTriple());
91
92
auto *ZeroInitilaizer =
93
ConstantAggregateZero::get(ArrayType::get(getEntryTy(M), 0u));
94
auto *EntryInit = Triple.isOSBinFormatCOFF() ? ZeroInitilaizer : nullptr;
95
auto *EntryType = ArrayType::get(getEntryTy(M), 0);
96
auto Linkage = Triple.isOSBinFormatCOFF() ? GlobalValue::WeakODRLinkage
97
: GlobalValue::ExternalLinkage;
98
99
auto *EntriesB =
100
new GlobalVariable(M, EntryType, /*isConstant=*/true, Linkage, EntryInit,
101
"__start_" + SectionName);
102
EntriesB->setVisibility(GlobalValue::HiddenVisibility);
103
auto *EntriesE =
104
new GlobalVariable(M, EntryType, /*isConstant=*/true, Linkage, EntryInit,
105
"__stop_" + SectionName);
106
EntriesE->setVisibility(GlobalValue::HiddenVisibility);
107
108
if (Triple.isOSBinFormatELF()) {
109
// We assume that external begin/end symbols that we have created above will
110
// be defined by the linker. This is done whenever a section name with a
111
// valid C-identifier is present. We define a dummy variable here to force
112
// the linker to always provide these symbols.
113
auto *DummyEntry = new GlobalVariable(
114
M, ZeroInitilaizer->getType(), true, GlobalVariable::InternalLinkage,
115
ZeroInitilaizer, "__dummy." + SectionName);
116
DummyEntry->setSection(SectionName);
117
appendToCompilerUsed(M, DummyEntry);
118
} else {
119
// The COFF linker will merge sections containing a '$' together into a
120
// single section. The order of entries in this section will be sorted
121
// alphabetically by the characters following the '$' in the name. Set the
122
// sections here to ensure that the beginning and end symbols are sorted.
123
EntriesB->setSection((SectionName + "$OA").str());
124
EntriesE->setSection((SectionName + "$OZ").str());
125
}
126
127
return std::make_pair(EntriesB, EntriesE);
128
}
129
130