aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Frontend/Offloading/Utility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Frontend/Offloading/Utility.cpp')
-rw-r--r--llvm/lib/Frontend/Offloading/Utility.cpp110
1 files changed, 110 insertions, 0 deletions
diff --git a/llvm/lib/Frontend/Offloading/Utility.cpp b/llvm/lib/Frontend/Offloading/Utility.cpp
new file mode 100644
index 000000000000..25f609517ebe
--- /dev/null
+++ b/llvm/lib/Frontend/Offloading/Utility.cpp
@@ -0,0 +1,110 @@
+//===- Utility.cpp ------ Collection of geneirc 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/Offloading/Utility.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Value.h"
+
+using namespace llvm;
+using namespace llvm::offloading;
+
+StructType *offloading::getEntryTy(Module &M) {
+ LLVMContext &C = M.getContext();
+ StructType *EntryTy =
+ StructType::getTypeByName(C, "struct.__tgt_offload_entry");
+ if (!EntryTy)
+ EntryTy = StructType::create(
+ "struct.__tgt_offload_entry", PointerType::getUnqual(C),
+ PointerType::getUnqual(C), M.getDataLayout().getIntPtrType(C),
+ Type::getInt32Ty(C), Type::getInt32Ty(C));
+ return EntryTy;
+}
+
+// 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());
+
+ Type *Int8PtrTy = PointerType::getUnqual(M.getContext());
+ Type *Int32Ty = Type::getInt32Ty(M.getContext());
+ Type *SizeTy = M.getDataLayout().getIntPtrType(M.getContext());
+
+ Constant *AddrName = ConstantDataArray::getString(M.getContext(), Name);
+
+ // Create the constant string used to look up the symbol in the device.
+ auto *Str = new GlobalVariable(M, AddrName->getType(), /*isConstant=*/true,
+ GlobalValue::InternalLinkage, AddrName,
+ ".omp_offloading.entry_name");
+ Str->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
+
+ // Construct the offloading entry.
+ Constant *EntryData[] = {
+ ConstantExpr::getPointerBitCastOrAddrSpaceCast(Addr, Int8PtrTy),
+ ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, Int8PtrTy),
+ ConstantInt::get(SizeTy, Size),
+ ConstantInt::get(Int32Ty, Flags),
+ ConstantInt::get(Int32Ty, Data),
+ };
+ Constant *EntryInitializer = ConstantStruct::get(getEntryTy(M), EntryData);
+
+ auto *Entry = new GlobalVariable(
+ M, getEntryTy(M),
+ /*isConstant=*/true, GlobalValue::WeakAnyLinkage, EntryInitializer,
+ ".omp_offloading.entry." + Name, nullptr, GlobalValue::NotThreadLocal,
+ M.getDataLayout().getDefaultGlobalsAddressSpace());
+
+ // The entry has to be created in the section the linker expects it to be.
+ if (Triple.isOSBinFormatCOFF())
+ Entry->setSection((SectionName + "$OE").str());
+ else
+ Entry->setSection(SectionName);
+ Entry->setAlignment(Align(1));
+}
+
+std::pair<GlobalVariable *, GlobalVariable *>
+offloading::getOffloadEntryArray(Module &M, StringRef SectionName) {
+ llvm::Triple Triple(M.getTargetTriple());
+
+ auto *ZeroInitilaizer =
+ ConstantAggregateZero::get(ArrayType::get(getEntryTy(M), 0u));
+ auto *EntryInit = Triple.isOSBinFormatCOFF() ? ZeroInitilaizer : nullptr;
+ auto *EntryType = ArrayType::get(getEntryTy(M), 0);
+
+ auto *EntriesB = new GlobalVariable(M, EntryType, /*isConstant=*/true,
+ GlobalValue::ExternalLinkage, EntryInit,
+ "__start_" + SectionName);
+ EntriesB->setVisibility(GlobalValue::HiddenVisibility);
+ auto *EntriesE = new GlobalVariable(M, EntryType, /*isConstant=*/true,
+ GlobalValue::ExternalLinkage, EntryInit,
+ "__stop_" + SectionName);
+ EntriesE->setVisibility(GlobalValue::HiddenVisibility);
+
+ if (Triple.isOSBinFormatELF()) {
+ // We assume that external begin/end symbols that we have created above will
+ // be defined by the linker. This is done whenever a section name with a
+ // valid C-identifier is present. We define a dummy variable here to force
+ // the linker to always provide these symbols.
+ auto *DummyEntry = new GlobalVariable(
+ M, ZeroInitilaizer->getType(), true, GlobalVariable::ExternalLinkage,
+ ZeroInitilaizer, "__dummy." + SectionName);
+ DummyEntry->setSection(SectionName);
+ DummyEntry->setVisibility(GlobalValue::HiddenVisibility);
+ } else {
+ // The COFF linker will merge sections containing a '$' together into a
+ // single section. The order of entries in this section will be sorted
+ // alphabetically by the characters following the '$' in the name. Set the
+ // sections here to ensure that the beginning and end symbols are sorted.
+ EntriesB->setSection((SectionName + "$OA").str());
+ EntriesE->setSection((SectionName + "$OZ").str());
+ }
+
+ return std::make_pair(EntriesB, EntriesE);
+}