15173854fSReshabh Sharma //===-- AMDGPUCtorDtorLowering.cpp - Handle global ctors and dtors --------===//
25173854fSReshabh Sharma //
35173854fSReshabh Sharma // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45173854fSReshabh Sharma // See https://llvm.org/LICENSE.txt for license information.
55173854fSReshabh Sharma // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65173854fSReshabh Sharma //
75173854fSReshabh Sharma //===----------------------------------------------------------------------===//
85173854fSReshabh Sharma ///
95173854fSReshabh Sharma /// \file
105173854fSReshabh Sharma /// This pass creates a unified init and fini kernel with the required metadata
115173854fSReshabh Sharma //===----------------------------------------------------------------------===//
125173854fSReshabh Sharma
135173854fSReshabh Sharma #include "AMDGPU.h"
145173854fSReshabh Sharma #include "llvm/IR/Constants.h"
155173854fSReshabh Sharma #include "llvm/IR/Function.h"
165173854fSReshabh Sharma #include "llvm/IR/GlobalVariable.h"
175173854fSReshabh Sharma #include "llvm/IR/IRBuilder.h"
185173854fSReshabh Sharma #include "llvm/IR/Module.h"
195173854fSReshabh Sharma #include "llvm/IR/Value.h"
205173854fSReshabh Sharma #include "llvm/Pass.h"
215173854fSReshabh Sharma #include "llvm/Transforms/Utils/ModuleUtils.h"
225173854fSReshabh Sharma
235173854fSReshabh Sharma using namespace llvm;
245173854fSReshabh Sharma
255173854fSReshabh Sharma #define DEBUG_TYPE "amdgpu-lower-ctor-dtor"
265173854fSReshabh Sharma
275173854fSReshabh Sharma namespace {
285173854fSReshabh Sharma class AMDGPUCtorDtorLowering final : public ModulePass {
295173854fSReshabh Sharma bool runOnModule(Module &M) override;
305173854fSReshabh Sharma
315173854fSReshabh Sharma public:
createInitOrFiniKernelFunction(Module & M,bool IsCtor)325173854fSReshabh Sharma Function *createInitOrFiniKernelFunction(Module &M, bool IsCtor) {
335173854fSReshabh Sharma StringRef InitOrFiniKernelName = "amdgcn.device.init";
345173854fSReshabh Sharma if (!IsCtor)
355173854fSReshabh Sharma InitOrFiniKernelName = "amdgcn.device.fini";
365173854fSReshabh Sharma
375173854fSReshabh Sharma Function *InitOrFiniKernel = Function::createWithDefaultAttr(
385173854fSReshabh Sharma FunctionType::get(Type::getVoidTy(M.getContext()), false),
39e90b512cSPraveen Velliengiri GlobalValue::ExternalLinkage, 0, InitOrFiniKernelName, &M);
405173854fSReshabh Sharma BasicBlock *InitOrFiniKernelBB =
415173854fSReshabh Sharma BasicBlock::Create(M.getContext(), "", InitOrFiniKernel);
425173854fSReshabh Sharma ReturnInst::Create(M.getContext(), InitOrFiniKernelBB);
435173854fSReshabh Sharma
445173854fSReshabh Sharma InitOrFiniKernel->setCallingConv(CallingConv::AMDGPU_KERNEL);
455173854fSReshabh Sharma if (IsCtor)
465173854fSReshabh Sharma InitOrFiniKernel->addFnAttr("device-init");
475173854fSReshabh Sharma else
485173854fSReshabh Sharma InitOrFiniKernel->addFnAttr("device-fini");
495173854fSReshabh Sharma return InitOrFiniKernel;
505173854fSReshabh Sharma }
515173854fSReshabh Sharma
createInitOrFiniKernel(Module & M,GlobalVariable * GV,bool IsCtor)525173854fSReshabh Sharma bool createInitOrFiniKernel(Module &M, GlobalVariable *GV, bool IsCtor) {
53*49b8ca3fSRuiling Song if (!GV || !GV->hasInitializer())
545173854fSReshabh Sharma return false;
5530b29db7SJon Chesterfield ConstantArray *GA = dyn_cast<ConstantArray>(GV->getInitializer());
5630b29db7SJon Chesterfield if (!GA || GA->getNumOperands() == 0)
575173854fSReshabh Sharma return false;
585173854fSReshabh Sharma Function *InitOrFiniKernel = createInitOrFiniKernelFunction(M, IsCtor);
595173854fSReshabh Sharma IRBuilder<> IRB(InitOrFiniKernel->getEntryBlock().getTerminator());
605173854fSReshabh Sharma for (Value *V : GA->operands()) {
615173854fSReshabh Sharma auto *CS = cast<ConstantStruct>(V);
625173854fSReshabh Sharma if (Function *F = dyn_cast<Function>(CS->getOperand(1))) {
635173854fSReshabh Sharma FunctionCallee Ctor =
645173854fSReshabh Sharma M.getOrInsertFunction(F->getName(), IRB.getVoidTy());
655173854fSReshabh Sharma IRB.CreateCall(Ctor);
665173854fSReshabh Sharma }
675173854fSReshabh Sharma }
685173854fSReshabh Sharma appendToUsed(M, {InitOrFiniKernel});
695173854fSReshabh Sharma return true;
705173854fSReshabh Sharma }
715173854fSReshabh Sharma
725173854fSReshabh Sharma static char ID;
AMDGPUCtorDtorLowering()735173854fSReshabh Sharma AMDGPUCtorDtorLowering() : ModulePass(ID) {}
745173854fSReshabh Sharma };
755173854fSReshabh Sharma } // End anonymous namespace
765173854fSReshabh Sharma
775173854fSReshabh Sharma char AMDGPUCtorDtorLowering::ID = 0;
785173854fSReshabh Sharma char &llvm::AMDGPUCtorDtorLoweringID = AMDGPUCtorDtorLowering::ID;
795173854fSReshabh Sharma INITIALIZE_PASS(AMDGPUCtorDtorLowering, DEBUG_TYPE,
805173854fSReshabh Sharma "Lower ctors and dtors for AMDGPU", false, false)
815173854fSReshabh Sharma
createAMDGPUCtorDtorLoweringPass()825173854fSReshabh Sharma ModulePass *llvm::createAMDGPUCtorDtorLoweringPass() {
835173854fSReshabh Sharma return new AMDGPUCtorDtorLowering();
845173854fSReshabh Sharma }
855173854fSReshabh Sharma
runOnModule(Module & M)865173854fSReshabh Sharma bool AMDGPUCtorDtorLowering::runOnModule(Module &M) {
875173854fSReshabh Sharma bool Modified = false;
885173854fSReshabh Sharma Modified |=
895173854fSReshabh Sharma createInitOrFiniKernel(M, M.getGlobalVariable("llvm.global_ctors"),
905173854fSReshabh Sharma /*IsCtor =*/true);
915173854fSReshabh Sharma Modified |=
925173854fSReshabh Sharma createInitOrFiniKernel(M, M.getGlobalVariable("llvm.global_dtors"),
935173854fSReshabh Sharma /*IsCtor =*/false);
945173854fSReshabh Sharma return Modified;
955173854fSReshabh Sharma }
96