33#define DEBUG_TYPE "spirv-lower-ctor-dtor"
37 cl::desc(
"Override unique ID of ctor/dtor globals."),
42 cl::desc(
"Emit kernels to call ctor/dtor globals."),
46constexpr int SPIRV_GLOBAL_AS = 1;
58 F->addFnAttr(
"uniform-work-group-size",
"true");
63 IsCtor ?
"spirv$device$init" :
"spirv$device$fini";
64 if (M.getFunction(InitOrFiniKernelName))
70 addKernelAttrs(InitOrFiniKernel);
72 return InitOrFiniKernel;
98void createInitOrFiniCalls(
Function &
F,
bool IsCtor) {
105 Type *PtrTy = IRB.getPtrTy(SPIRV_GLOBAL_AS);
118 auto *Begin = M.getOrInsertGlobal(
119 IsCtor ?
"__init_array_start" :
"__fini_array_start",
121 return CreateGlobal(IsCtor ?
"__init_array_start"
122 :
"__fini_array_start");
124 auto *End = M.getOrInsertGlobal(
125 IsCtor ?
"__init_array_end" :
"__fini_array_end",
127 return CreateGlobal(IsCtor ?
"__init_array_end" :
"__fini_array_end");
133 Value *BeginVal = IRB.CreateLoad(Begin->getType(), Begin,
"begin");
134 Value *EndVal = IRB.CreateLoad(Begin->getType(), End,
"stop");
136 Value *OldBeginVal = BeginVal;
142 EndVal = OldBeginVal;
148 IRB.SetInsertPoint(LoopBB);
149 auto *CallBackPHI = IRB.CreatePHI(PtrTy, 2,
"ptr");
150 auto *CallBack = IRB.CreateLoad(IRB.getPtrTy(
F.getAddressSpace()),
151 CallBackPHI,
"callback");
152 IRB.CreateCall(CallBackTy, CallBack);
154 IRB.CreateConstGEP1_64(PtrTy, CallBackPHI, IsCtor ? 1 : -1,
"next");
156 NewCallBack, EndVal,
"end");
157 CallBackPHI->addIncoming(BeginVal, &
F.getEntryBlock());
158 CallBackPHI->addIncoming(NewCallBack, LoopBB);
159 IRB.CreateCondBr(EndCmp, ExitBB, LoopBB);
160 IRB.SetInsertPoint(ExitBB);
176 std::string PriorityStr =
"." + std::to_string(Priority);
180 std::string NameStr =
181 ((IsCtor ?
"__init_array_object_" :
"__fini_array_object_") +
182 F->getName() +
"_" + GlobalID +
"_" + std::to_string(Priority))
185 [](
char c) { return c ==
'.' ?
'_' : c; });
191 GV->
setSection(IsCtor ?
".init_array" + PriorityStr
192 :
".fini_array" + PriorityStr);
199bool createInitOrFiniKernel(
Module &M,
StringRef GlobalName,
bool IsCtor) {
204 if (!createInitOrFiniGlobals(M, GV, IsCtor))
210 Function *InitOrFiniKernel = createInitOrFiniKernelFunction(M, IsCtor);
211 if (!InitOrFiniKernel)
214 createInitOrFiniCalls(*InitOrFiniKernel, IsCtor);
220bool lowerCtorsAndDtors(
Module &M) {
226 Modified |= createInitOrFiniKernel(M,
"llvm.global_ctors",
true);
227 Modified |= createInitOrFiniKernel(M,
"llvm.global_dtors",
false);
231class SPIRVCtorDtorLoweringLegacy final :
public ModulePass {
234 SPIRVCtorDtorLoweringLegacy() : ModulePass(ID) {}
235 bool runOnModule(
Module &M)
override {
return lowerCtorsAndDtors(M); }
246char SPIRVCtorDtorLoweringLegacy::ID = 0;
248 "SPIRV lower ctors and dtors",
false,
false)
251 return new SPIRVCtorDtorLoweringLegacy();
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
static cl::opt< bool > CreateKernels("nvptx-emit-init-fini-kernel", cl::desc("Emit kernels to call ctor/dtor globals."), cl::init(true), cl::Hidden)
static cl::opt< std::string > GlobalStr("nvptx-lower-global-ctor-dtor-id", cl::desc("Override unique ID of ctor/dtor globals."), cl::init(""), cl::Hidden)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static cl::opt< std::string > GlobalStr("spirv-lower-global-ctor-dtor-id", cl::desc("Override unique ID of ctor/dtor globals."), cl::init(""), cl::Hidden)
static cl::opt< bool > CreateKernels("spirv-emit-init-fini-kernel", cl::desc("Emit kernels to call ctor/dtor globals."), cl::init(true), cl::Hidden)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
@ ICMP_UGE
unsigned greater or equal
@ ICMP_ULT
unsigned less than
ConstantArray - Constant Array Declarations.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * createWithDefaultAttr(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Creates a function with some attributes recorded in llvm.module.flags and the LLVMContext applied.
LLVM_ABI void setSection(StringRef S)
Change the section for this global.
@ ProtectedVisibility
The GV is protected.
void setVisibility(VisibilityTypes V)
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This is an important class for using LLVM in a threaded context.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
unsigned getNumOperands() const
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
@ SPIR_KERNEL
Used for SPIR kernel functions.
initializer< Ty > init(const Ty &Val)
LLVM_ABI bool isOpenMPDevice(Module &M)
Helper to determine if M is a OpenMP target offloading device module.
This is an optimization pass for GlobalISel generic memory operations.
ModulePass * createSPIRVCtorDtorLoweringLegacyPass()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.