32#define DEBUG_TYPE "lower-global-dtors"
35class LowerGlobalDtorsLegacyPass final :
public ModulePass {
37 return "Lower @llvm.global_dtors via `__cxa_atexit`";
55char LowerGlobalDtorsLegacyPass::ID = 0;
57 "Lower @llvm.global_dtors via `__cxa_atexit`",
false,
false)
60 return new LowerGlobalDtorsLegacyPass();
64bool LowerGlobalDtorsLegacyPass::runOnModule(
Module &M) {
return runImpl(M); }
88 if (!ETy || ETy->getNumElements() != 3 ||
89 !ETy->getTypeAtIndex(0U)->isIntegerTy() ||
90 !ETy->getTypeAtIndex(1U)->isPointerTy() ||
91 !ETy->getTypeAtIndex(2U)->isPointerTy())
99 std::vector<std::pair<Constant *, std::vector<Constant *>>>
102 auto *CS = dyn_cast<ConstantStruct>(O);
106 auto *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
109 uint16_t PriorityValue = Priority->getLimitedValue(UINT16_MAX);
118 auto &AtThisPriority = DtorFuncs[PriorityValue];
119 if (AtThisPriority.empty() || AtThisPriority.back().first != Associated) {
120 std::vector<Constant *> NewList;
121 NewList.push_back(DtorFunc);
122 AtThisPriority.push_back(std::make_pair(Associated, NewList));
124 AtThisPriority.back().second.push_back(DtorFunc);
127 if (DtorFuncs.empty())
133 Type *AtExitFuncArgs[] = {VoidStar};
148 if (
auto F = dyn_cast<Function>(AtExit.
getCallee())) {
149 if (
F &&
F->hasExactDefinition() &&
F->getArg(0)->getNumUses() == 0) {
157 Constant *DsoHandle = M.getOrInsertGlobal(
"__dso_handle", DsoHandleTy, [&] {
168 for (
auto &PriorityAndMore : DtorFuncs) {
169 uint16_t Priority = PriorityAndMore.first;
171 auto &AtThisPriority = PriorityAndMore.second;
172 for (
auto &AssociatedAndMore : AtThisPriority) {
173 Constant *Associated = AssociatedAndMore.first;
179 (Priority != UINT16_MAX ? (
Twine(
".") +
Twine(Priority))
181 (AtThisPriority.size() > 1 ?
Twine(
"$") +
Twine(ThisId)
190 for (
auto *Dtor :
reverse(AssociatedAndMore.second))
196 "register_call_dtors" +
197 (Priority != UINT16_MAX ? (
Twine(
".") +
Twine(Priority))
199 (AtThisPriority.size() > 1 ?
Twine(
"$") +
Twine(ThisId)
209 Value *Args[] = {CallDtors,
Null, DsoHandle};
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runImpl(Function &F, const TargetLowering &TLI)
static bool runImpl(Module &M)
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Type * getElementType() const
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
Represents analyses that only rely on functions' control flow.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
ConstantArray - Constant Array Declarations.
ArrayType * getType() const
Specialize the getType() method to always return an ArrayType, which reduces the amount of casting ne...
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
This is an important base class in LLVM.
const Constant * stripPointerCasts() const
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ ExternalWeakLinkage
ExternalWeak linkage description.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
This instruction compares its operands according to the predicate given to the constructor.
This is an important class for using LLVM in a threaded context.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
This function has undefined behavior.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
StringRef getName() const
Return a constant reference to the value's name.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
ModulePass * createLowerGlobalDtorsLegacyPass()
void initializeLowerGlobalDtorsLegacyPassPass(PassRegistry &)
void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.