LLVM  8.0.1
CtorUtils.cpp
Go to the documentation of this file.
1 //===- CtorUtils.cpp - Helpers for working with global_ctors ----*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines functions that are used to process llvm.global_ctors.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/BitVector.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/GlobalVariable.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/Support/Debug.h"
22 
23 #define DEBUG_TYPE "ctor_utils"
24 
25 using namespace llvm;
26 
27 /// Given a specified llvm.global_ctors list, remove the listed elements.
28 static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
29  // Filter out the initializer elements to remove.
30  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
32  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
33  if (!CtorsToRemove.test(I))
34  CAList.push_back(OldCA->getOperand(I));
35 
36  // Create the new array initializer.
37  ArrayType *ATy =
38  ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
39  Constant *CA = ConstantArray::get(ATy, CAList);
40 
41  // If we didn't change the number of elements, don't create a new GV.
42  if (CA->getType() == OldCA->getType()) {
43  GCL->setInitializer(CA);
44  return;
45  }
46 
47  // Create the new global and insert it next to the existing list.
48  GlobalVariable *NGV =
49  new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
50  CA, "", GCL->getThreadLocalMode());
51  GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV);
52  NGV->takeName(GCL);
53 
54  // Nuke the old list, replacing any uses with the new one.
55  if (!GCL->use_empty()) {
56  Constant *V = NGV;
57  if (V->getType() != GCL->getType())
58  V = ConstantExpr::getBitCast(V, GCL->getType());
59  GCL->replaceAllUsesWith(V);
60  }
61  GCL->eraseFromParent();
62 }
63 
64 /// Given a llvm.global_ctors list that we can understand,
65 /// return a list of the functions and null terminator as a vector.
66 static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
67  if (GV->getInitializer()->isNullValue())
68  return std::vector<Function *>();
69  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
70  std::vector<Function *> Result;
71  Result.reserve(CA->getNumOperands());
72  for (auto &V : CA->operands()) {
73  ConstantStruct *CS = cast<ConstantStruct>(V);
74  Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
75  }
76  return Result;
77 }
78 
79 /// Find the llvm.global_ctors list, verifying that all initializers have an
80 /// init priority of 65535.
82  GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
83  if (!GV)
84  return nullptr;
85 
86  // Verify that the initializer is simple enough for us to handle. We are
87  // only allowed to optimize the initializer if it is unique.
88  if (!GV->hasUniqueInitializer())
89  return nullptr;
90 
91  if (isa<ConstantAggregateZero>(GV->getInitializer()))
92  return GV;
93  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
94 
95  for (auto &V : CA->operands()) {
96  if (isa<ConstantAggregateZero>(V))
97  continue;
98  ConstantStruct *CS = cast<ConstantStruct>(V);
99  if (isa<ConstantPointerNull>(CS->getOperand(1)))
100  continue;
101 
102  // Must have a function or null ptr.
103  if (!isa<Function>(CS->getOperand(1)))
104  return nullptr;
105 
106  // Init priority must be standard.
107  ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
108  if (CI->getZExtValue() != 65535)
109  return nullptr;
110  }
111 
112  return GV;
113 }
114 
115 /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
116 /// entries for which it returns true. Return true if anything changed.
118  Module &M, function_ref<bool(Function *)> ShouldRemove) {
119  GlobalVariable *GlobalCtors = findGlobalCtors(M);
120  if (!GlobalCtors)
121  return false;
122 
123  std::vector<Function *> Ctors = parseGlobalCtors(GlobalCtors);
124  if (Ctors.empty())
125  return false;
126 
127  bool MadeChange = false;
128 
129  // Loop over global ctors, optimizing them when we can.
130  unsigned NumCtors = Ctors.size();
131  BitVector CtorsToRemove(NumCtors);
132  for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
133  Function *F = Ctors[i];
134  // Found a null terminator in the middle of the list, prune off the rest of
135  // the list.
136  if (!F)
137  continue;
138 
139  LLVM_DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
140 
141  // We cannot simplify external ctor functions.
142  if (F->empty())
143  continue;
144 
145  // If we can evaluate the ctor at compile time, do.
146  if (ShouldRemove(F)) {
147  Ctors[i] = nullptr;
148  CtorsToRemove.set(i);
149  NumCtors--;
150  MadeChange = true;
151  continue;
152  }
153  }
154 
155  if (!MadeChange)
156  return false;
157 
158  removeGlobalCtors(GlobalCtors, CtorsToRemove);
159  return true;
160 }
BitVector & set()
Definition: BitVector.h:398
ThreadLocalMode getThreadLocalMode() const
Definition: GlobalValue.h:255
bool empty() const
Definition: Function.h:662
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
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:218
bool test(unsigned Idx) const
Definition: BitVector.h:502
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:117
GlobalVariable * getGlobalVariable(StringRef Name) const
Look up the specified global variable in the module symbol table.
Definition: Module.h:387
F(f)
const GlobalListType & getGlobalList() const
Get the Module&#39;s list of global variables (constant).
Definition: Module.h:521
static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove)
Given a specified llvm.global_ctors list, remove the listed elements.
Definition: CtorUtils.cpp:28
static Constant * get(ArrayType *T, ArrayRef< Constant *> V)
Definition: Constants.cpp:983
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Definition: Globals.cpp:363
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:66
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:369
LinkageTypes getLinkage() const
Definition: GlobalValue.h:451
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:170
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:1773
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:149
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:42
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:359
op_range operands()
Definition: User.h:238
self_iterator getIterator()
Definition: ilist_node.h:82
unsigned getNumOperands() const
Definition: User.h:192
This is the shared class of boolean and integer constants.
Definition: Constants.h:84
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
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:133
ConstantArray - Constant Array Declarations.
Definition: Constants.h:414
ArrayType * getType() const
Specialize the getType() method to always return an ArrayType, which reduces the amount of casting ne...
Definition: Constants.h:433
iterator insert(iterator where, pointer New)
Definition: ilist.h:228
#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:581
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:566
Type * getElementType() const
Definition: DerivedTypes.h:360
static GlobalVariable * findGlobalCtors(Module &M)
Find the llvm.global_ctors list, verifying that all initializers have an init priority of 65535...
Definition: CtorUtils.cpp:81
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:117
#define LLVM_DEBUG(X)
Definition: Debug.h:123
bool use_empty() const
Definition: Value.h:323
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:274