LLVM  10.0.0svn
CtorUtils.cpp
Go to the documentation of this file.
1 //===- CtorUtils.cpp - Helpers for working with global_ctors ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines functions that are used to process llvm.global_ctors.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "llvm/ADT/BitVector.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/GlobalVariable.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Support/Debug.h"
21 
22 #define DEBUG_TYPE "ctor_utils"
23 
24 using namespace llvm;
25 
26 /// Given a specified llvm.global_ctors list, remove the listed elements.
27 static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
28  // Filter out the initializer elements to remove.
29  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
31  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
32  if (!CtorsToRemove.test(I))
33  CAList.push_back(OldCA->getOperand(I));
34 
35  // Create the new array initializer.
36  ArrayType *ATy =
37  ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
38  Constant *CA = ConstantArray::get(ATy, CAList);
39 
40  // If we didn't change the number of elements, don't create a new GV.
41  if (CA->getType() == OldCA->getType()) {
42  GCL->setInitializer(CA);
43  return;
44  }
45 
46  // Create the new global and insert it next to the existing list.
47  GlobalVariable *NGV =
48  new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
49  CA, "", GCL->getThreadLocalMode());
50  GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV);
51  NGV->takeName(GCL);
52 
53  // Nuke the old list, replacing any uses with the new one.
54  if (!GCL->use_empty()) {
55  Constant *V = NGV;
56  if (V->getType() != GCL->getType())
57  V = ConstantExpr::getBitCast(V, GCL->getType());
58  GCL->replaceAllUsesWith(V);
59  }
60  GCL->eraseFromParent();
61 }
62 
63 /// Given a llvm.global_ctors list that we can understand,
64 /// return a list of the functions and null terminator as a vector.
65 static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
66  if (GV->getInitializer()->isNullValue())
67  return std::vector<Function *>();
68  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
69  std::vector<Function *> Result;
70  Result.reserve(CA->getNumOperands());
71  for (auto &V : CA->operands()) {
72  ConstantStruct *CS = cast<ConstantStruct>(V);
73  Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
74  }
75  return Result;
76 }
77 
78 /// Find the llvm.global_ctors list, verifying that all initializers have an
79 /// init priority of 65535.
81  GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
82  if (!GV)
83  return nullptr;
84 
85  // Verify that the initializer is simple enough for us to handle. We are
86  // only allowed to optimize the initializer if it is unique.
87  if (!GV->hasUniqueInitializer())
88  return nullptr;
89 
90  if (isa<ConstantAggregateZero>(GV->getInitializer()))
91  return GV;
92  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
93 
94  for (auto &V : CA->operands()) {
95  if (isa<ConstantAggregateZero>(V))
96  continue;
97  ConstantStruct *CS = cast<ConstantStruct>(V);
98  if (isa<ConstantPointerNull>(CS->getOperand(1)))
99  continue;
100 
101  // Must have a function or null ptr.
102  if (!isa<Function>(CS->getOperand(1)))
103  return nullptr;
104 
105  // Init priority must be standard.
106  ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
107  if (CI->getZExtValue() != 65535)
108  return nullptr;
109  }
110 
111  return GV;
112 }
113 
114 /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
115 /// entries for which it returns true. Return true if anything changed.
117  Module &M, function_ref<bool(Function *)> ShouldRemove) {
118  GlobalVariable *GlobalCtors = findGlobalCtors(M);
119  if (!GlobalCtors)
120  return false;
121 
122  std::vector<Function *> Ctors = parseGlobalCtors(GlobalCtors);
123  if (Ctors.empty())
124  return false;
125 
126  bool MadeChange = false;
127 
128  // Loop over global ctors, optimizing them when we can.
129  unsigned NumCtors = Ctors.size();
130  BitVector CtorsToRemove(NumCtors);
131  for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
132  Function *F = Ctors[i];
133  // Found a null terminator in the middle of the list, prune off the rest of
134  // the list.
135  if (!F)
136  continue;
137 
138  LLVM_DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
139 
140  // We cannot simplify external ctor functions.
141  if (F->empty())
142  continue;
143 
144  // If we can evaluate the ctor at compile time, do.
145  if (ShouldRemove(F)) {
146  Ctors[i] = nullptr;
147  CtorsToRemove.set(i);
148  NumCtors--;
149  MadeChange = true;
150  continue;
151  }
152  }
153 
154  if (!MadeChange)
155  return false;
156 
157  removeGlobalCtors(GlobalCtors, CtorsToRemove);
158  return true;
159 }
BitVector & set()
Definition: BitVector.h:397
ThreadLocalMode getThreadLocalMode() const
Definition: GlobalValue.h:258
bool empty() const
Definition: Function.h:686
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
void push_back(const T &Elt)
Definition: SmallVector.h:211
bool test(unsigned Idx) const
Definition: BitVector.h:501
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:104
GlobalVariable * getGlobalVariable(StringRef Name) const
Look up the specified global variable in the module symbol table.
Definition: Module.h:390
F(f)
const GlobalListType & getGlobalList() const
Get the Module&#39;s list of global variables (constant).
Definition: Module.h:524
static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove)
Given a specified llvm.global_ctors list, remove the listed elements.
Definition: CtorUtils.cpp:27
static Constant * get(ArrayType *T, ArrayRef< Constant *> V)
Definition: Constants.cpp:1014
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Definition: Globals.cpp:388
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
static std::vector< Function * > parseGlobalCtors(GlobalVariable *GV)
Given a llvm.global_ctors list that we can understand, return a list of the functions and null termin...
Definition: CtorUtils.cpp:65
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition: Constants.cpp:85
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
Class to represent array types.
Definition: DerivedTypes.h:403
LinkageTypes getLinkage() const
Definition: GlobalValue.h:460
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:429
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:291
Value * getOperand(unsigned i) const
Definition: User.h:169
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:1804
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:148
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:41
This file contains the declarations for the subclasses of Constant, which represent the different fla...
bool hasUniqueInitializer() const
hasUniqueInitializer - Whether the global variable has an initializer, and any changes made to the in...
void eraseFromParent()
eraseFromParent - This method unlinks &#39;this&#39; from the containing module and deletes it...
Definition: Globals.cpp:384
op_range operands()
Definition: User.h:237
self_iterator getIterator()
Definition: ilist_node.h:81
unsigned getNumOperands() const
Definition: User.h:191
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
Module.h This file contains the declarations for the Module class.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
ConstantArray - Constant Array Declarations.
Definition: Constants.h:413
ArrayType * getType() const
Specialize the getType() method to always return an ArrayType, which reduces the amount of casting ne...
Definition: Constants.h:432
iterator insert(iterator where, pointer New)
Definition: ilist.h:226
#define I(x, y, z)
Definition: MD5.cpp:58
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:582
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:575
Type * getElementType() const
Definition: DerivedTypes.h:394
static GlobalVariable * findGlobalCtors(Module &M)
Find the llvm.global_ctors list, verifying that all initializers have an init priority of 65535...
Definition: CtorUtils.cpp:80
bool optimizeGlobalCtorsList(Module &M, function_ref< bool(Function *)> ShouldRemove)
Call "ShouldRemove" for every entry in M&#39;s global_ctor list and remove the entries for which it retur...
Definition: CtorUtils.cpp:116
#define LLVM_DEBUG(X)
Definition: Debug.h:122
bool use_empty() const
Definition: Value.h:342
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:277