LLVM  6.0.0svn
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/Instructions.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Support/Debug.h"
23 
24 #define DEBUG_TYPE "ctor_utils"
25 
26 namespace llvm {
27 
28 namespace {
29 /// Given a specified llvm.global_ctors list, remove the listed elements.
30 void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
31  // Filter out the initializer elements to remove.
32  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
33  SmallVector<Constant *, 10> CAList;
34  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
35  if (!CtorsToRemove.test(I))
36  CAList.push_back(OldCA->getOperand(I));
37 
38  // Create the new array initializer.
39  ArrayType *ATy =
40  ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
41  Constant *CA = ConstantArray::get(ATy, CAList);
42 
43  // If we didn't change the number of elements, don't create a new GV.
44  if (CA->getType() == OldCA->getType()) {
45  GCL->setInitializer(CA);
46  return;
47  }
48 
49  // Create the new global and insert it next to the existing list.
50  GlobalVariable *NGV =
51  new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
52  CA, "", GCL->getThreadLocalMode());
53  GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV);
54  NGV->takeName(GCL);
55 
56  // Nuke the old list, replacing any uses with the new one.
57  if (!GCL->use_empty()) {
58  Constant *V = NGV;
59  if (V->getType() != GCL->getType())
60  V = ConstantExpr::getBitCast(V, GCL->getType());
61  GCL->replaceAllUsesWith(V);
62  }
63  GCL->eraseFromParent();
64 }
65 
66 /// Given a llvm.global_ctors list that we can understand,
67 /// return a list of the functions and null terminator as a vector.
68 std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
69  if (GV->getInitializer()->isNullValue())
70  return std::vector<Function *>();
71  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
72  std::vector<Function *> Result;
73  Result.reserve(CA->getNumOperands());
74  for (auto &V : CA->operands()) {
75  ConstantStruct *CS = cast<ConstantStruct>(V);
76  Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
77  }
78  return Result;
79 }
80 
81 /// Find the llvm.global_ctors list, verifying that all initializers have an
82 /// init priority of 65535.
83 GlobalVariable *findGlobalCtors(Module &M) {
84  GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
85  if (!GV)
86  return nullptr;
87 
88  // Verify that the initializer is simple enough for us to handle. We are
89  // only allowed to optimize the initializer if it is unique.
90  if (!GV->hasUniqueInitializer())
91  return nullptr;
92 
93  if (isa<ConstantAggregateZero>(GV->getInitializer()))
94  return GV;
95  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
96 
97  for (auto &V : CA->operands()) {
98  if (isa<ConstantAggregateZero>(V))
99  continue;
100  ConstantStruct *CS = cast<ConstantStruct>(V);
101  if (isa<ConstantPointerNull>(CS->getOperand(1)))
102  continue;
103 
104  // Must have a function or null ptr.
105  if (!isa<Function>(CS->getOperand(1)))
106  return nullptr;
107 
108  // Init priority must be standard.
109  ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
110  if (CI->getZExtValue() != 65535)
111  return nullptr;
112  }
113 
114  return GV;
115 }
116 } // namespace
117 
118 /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
119 /// entries for which it returns true. Return true if anything changed.
121  function_ref<bool(Function *)> ShouldRemove) {
122  GlobalVariable *GlobalCtors = findGlobalCtors(M);
123  if (!GlobalCtors)
124  return false;
125 
126  std::vector<Function *> Ctors = parseGlobalCtors(GlobalCtors);
127  if (Ctors.empty())
128  return false;
129 
130  bool MadeChange = false;
131 
132  // Loop over global ctors, optimizing them when we can.
133  unsigned NumCtors = Ctors.size();
134  BitVector CtorsToRemove(NumCtors);
135  for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
136  Function *F = Ctors[i];
137  // Found a null terminator in the middle of the list, prune off the rest of
138  // the list.
139  if (!F)
140  continue;
141 
142  DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
143 
144  // We cannot simplify external ctor functions.
145  if (F->empty())
146  continue;
147 
148  // If we can evaluate the ctor at compile time, do.
149  if (ShouldRemove(F)) {
150  Ctors[i] = nullptr;
151  CtorsToRemove.set(i);
152  NumCtors--;
153  MadeChange = true;
154  continue;
155  }
156  }
157 
158  if (!MadeChange)
159  return false;
160 
161  removeGlobalCtors(GlobalCtors, CtorsToRemove);
162  return true;
163 }
164 
165 } // End llvm namespace
BitVector & set()
Definition: BitVector.h:398
bool empty() const
Definition: Function.h:594
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:63
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:89
F(f)
static Constant * get(ArrayType *T, ArrayRef< Constant *> V)
Definition: Constants.cpp:888
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:430
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:1678
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
#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:568
#define DEBUG(X)
Definition: Debug.h:118
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:120