Path: blob/main/contrib/llvm-project/llvm/lib/Frontend/Offloading/Utility.cpp
35271 views
//===- Utility.cpp ------ Collection of generic offloading utilities ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Frontend/Offloading/Utility.h"9#include "llvm/IR/Constants.h"10#include "llvm/IR/GlobalValue.h"11#include "llvm/IR/GlobalVariable.h"12#include "llvm/IR/Value.h"13#include "llvm/Transforms/Utils/ModuleUtils.h"1415using namespace llvm;16using namespace llvm::offloading;1718StructType *offloading::getEntryTy(Module &M) {19LLVMContext &C = M.getContext();20StructType *EntryTy =21StructType::getTypeByName(C, "struct.__tgt_offload_entry");22if (!EntryTy)23EntryTy = StructType::create(24"struct.__tgt_offload_entry", PointerType::getUnqual(C),25PointerType::getUnqual(C), M.getDataLayout().getIntPtrType(C),26Type::getInt32Ty(C), Type::getInt32Ty(C));27return EntryTy;28}2930// TODO: Rework this interface to be more generic.31std::pair<Constant *, GlobalVariable *>32offloading::getOffloadingEntryInitializer(Module &M, Constant *Addr,33StringRef Name, uint64_t Size,34int32_t Flags, int32_t Data) {35llvm::Triple Triple(M.getTargetTriple());36Type *Int8PtrTy = PointerType::getUnqual(M.getContext());37Type *Int32Ty = Type::getInt32Ty(M.getContext());38Type *SizeTy = M.getDataLayout().getIntPtrType(M.getContext());3940Constant *AddrName = ConstantDataArray::getString(M.getContext(), Name);4142StringRef Prefix =43Triple.isNVPTX() ? "$offloading$entry_name" : ".offloading.entry_name";4445// Create the constant string used to look up the symbol in the device.46auto *Str =47new GlobalVariable(M, AddrName->getType(), /*isConstant=*/true,48GlobalValue::InternalLinkage, AddrName, Prefix);49Str->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);5051// Construct the offloading entry.52Constant *EntryData[] = {53ConstantExpr::getPointerBitCastOrAddrSpaceCast(Addr, Int8PtrTy),54ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, Int8PtrTy),55ConstantInt::get(SizeTy, Size),56ConstantInt::get(Int32Ty, Flags),57ConstantInt::get(Int32Ty, Data),58};59Constant *EntryInitializer = ConstantStruct::get(getEntryTy(M), EntryData);60return {EntryInitializer, Str};61}6263void offloading::emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name,64uint64_t Size, int32_t Flags, int32_t Data,65StringRef SectionName) {66llvm::Triple Triple(M.getTargetTriple());6768auto [EntryInitializer, NameGV] =69getOffloadingEntryInitializer(M, Addr, Name, Size, Flags, Data);7071StringRef Prefix =72Triple.isNVPTX() ? "$offloading$entry$" : ".offloading.entry.";73auto *Entry = new GlobalVariable(74M, getEntryTy(M),75/*isConstant=*/true, GlobalValue::WeakAnyLinkage, EntryInitializer,76Prefix + Name, nullptr, GlobalValue::NotThreadLocal,77M.getDataLayout().getDefaultGlobalsAddressSpace());7879// The entry has to be created in the section the linker expects it to be.80if (Triple.isOSBinFormatCOFF())81Entry->setSection((SectionName + "$OE").str());82else83Entry->setSection(SectionName);84Entry->setAlignment(Align(1));85}8687std::pair<GlobalVariable *, GlobalVariable *>88offloading::getOffloadEntryArray(Module &M, StringRef SectionName) {89llvm::Triple Triple(M.getTargetTriple());9091auto *ZeroInitilaizer =92ConstantAggregateZero::get(ArrayType::get(getEntryTy(M), 0u));93auto *EntryInit = Triple.isOSBinFormatCOFF() ? ZeroInitilaizer : nullptr;94auto *EntryType = ArrayType::get(getEntryTy(M), 0);95auto Linkage = Triple.isOSBinFormatCOFF() ? GlobalValue::WeakODRLinkage96: GlobalValue::ExternalLinkage;9798auto *EntriesB =99new GlobalVariable(M, EntryType, /*isConstant=*/true, Linkage, EntryInit,100"__start_" + SectionName);101EntriesB->setVisibility(GlobalValue::HiddenVisibility);102auto *EntriesE =103new GlobalVariable(M, EntryType, /*isConstant=*/true, Linkage, EntryInit,104"__stop_" + SectionName);105EntriesE->setVisibility(GlobalValue::HiddenVisibility);106107if (Triple.isOSBinFormatELF()) {108// We assume that external begin/end symbols that we have created above will109// be defined by the linker. This is done whenever a section name with a110// valid C-identifier is present. We define a dummy variable here to force111// the linker to always provide these symbols.112auto *DummyEntry = new GlobalVariable(113M, ZeroInitilaizer->getType(), true, GlobalVariable::InternalLinkage,114ZeroInitilaizer, "__dummy." + SectionName);115DummyEntry->setSection(SectionName);116appendToCompilerUsed(M, DummyEntry);117} else {118// The COFF linker will merge sections containing a '$' together into a119// single section. The order of entries in this section will be sorted120// alphabetically by the characters following the '$' in the name. Set the121// sections here to ensure that the beginning and end symbols are sorted.122EntriesB->setSection((SectionName + "$OA").str());123EntriesE->setSection((SectionName + "$OZ").str());124}125126return std::make_pair(EntriesB, EntriesE);127}128129130