|  | //===- AMDGPUExportKernelRuntimeHandles.cpp - Lower enqueued block --------===// | 
|  | // | 
|  | // 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 | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // \file | 
|  | // | 
|  | // Give any globals used for OpenCL block enqueue runtime handles external | 
|  | // linkage so the runtime may access them. These should behave like internal | 
|  | // functions for purposes of linking, but need to have an external symbol in the | 
|  | // final object for the runtime to access them. | 
|  | // | 
|  | // TODO: This could be replaced with a new linkage type or global object | 
|  | // metadata that produces an external symbol in the final object, but allows | 
|  | // rename on IR linking. Alternatively if we can rely on | 
|  | // GlobalValue::getGlobalIdentifier we can just make these external symbols to | 
|  | // begin with. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "AMDGPUExportKernelRuntimeHandles.h" | 
|  | #include "AMDGPU.h" | 
|  | #include "llvm/IR/Module.h" | 
|  | #include "llvm/Pass.h" | 
|  |  | 
|  | #define DEBUG_TYPE "amdgpu-export-kernel-runtime-handles" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | /// Lower enqueued blocks. | 
|  | class AMDGPUExportKernelRuntimeHandlesLegacy : public ModulePass { | 
|  | public: | 
|  | static char ID; | 
|  |  | 
|  | explicit AMDGPUExportKernelRuntimeHandlesLegacy() : ModulePass(ID) {} | 
|  |  | 
|  | private: | 
|  | bool runOnModule(Module &M) override; | 
|  | }; | 
|  |  | 
|  | } // end anonymous namespace | 
|  |  | 
|  | char AMDGPUExportKernelRuntimeHandlesLegacy::ID = 0; | 
|  |  | 
|  | char &llvm::AMDGPUExportKernelRuntimeHandlesLegacyID = | 
|  | AMDGPUExportKernelRuntimeHandlesLegacy::ID; | 
|  |  | 
|  | INITIALIZE_PASS(AMDGPUExportKernelRuntimeHandlesLegacy, DEBUG_TYPE, | 
|  | "Externalize enqueued block runtime handles", false, false) | 
|  |  | 
|  | ModulePass *llvm::createAMDGPUExportKernelRuntimeHandlesLegacyPass() { | 
|  | return new AMDGPUExportKernelRuntimeHandlesLegacy(); | 
|  | } | 
|  |  | 
|  | static bool exportKernelRuntimeHandles(Module &M) { | 
|  | bool Changed = false; | 
|  |  | 
|  | const StringLiteral HandleSectionName(".amdgpu.kernel.runtime.handle"); | 
|  |  | 
|  | for (GlobalVariable &GV : M.globals()) { | 
|  | if (GV.getSection() == HandleSectionName) { | 
|  | GV.setLinkage(GlobalValue::ExternalLinkage); | 
|  | GV.setDSOLocal(false); | 
|  | Changed = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (!Changed) | 
|  | return false; | 
|  |  | 
|  | // FIXME: We shouldn't really need to export the kernel address. We can | 
|  | // initialize the runtime handle with the kernel descriptor. | 
|  | for (Function &F : M) { | 
|  | if (F.getCallingConv() != CallingConv::AMDGPU_KERNEL) | 
|  | continue; | 
|  |  | 
|  | const MDNode *Associated = F.getMetadata(LLVMContext::MD_associated); | 
|  | if (!Associated) | 
|  | continue; | 
|  |  | 
|  | auto *VM = cast<ValueAsMetadata>(Associated->getOperand(0)); | 
|  | auto *Handle = dyn_cast<GlobalObject>(VM->getValue()); | 
|  | if (Handle && Handle->getSection() == HandleSectionName) { | 
|  | F.setLinkage(GlobalValue::ExternalLinkage); | 
|  | F.setVisibility(GlobalValue::ProtectedVisibility); | 
|  | } | 
|  | } | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | bool AMDGPUExportKernelRuntimeHandlesLegacy::runOnModule(Module &M) { | 
|  | return exportKernelRuntimeHandles(M); | 
|  | } | 
|  |  | 
|  | PreservedAnalyses | 
|  | AMDGPUExportKernelRuntimeHandlesPass::run(Module &M, | 
|  | ModuleAnalysisManager &MAM) { | 
|  | if (!exportKernelRuntimeHandles(M)) | 
|  | return PreservedAnalyses::all(); | 
|  |  | 
|  | PreservedAnalyses PA; | 
|  | PA.preserveSet<AllAnalysesOn<Function>>(); | 
|  | return PA; | 
|  | } |