CtorUtils.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. #include "llvm/Transforms/Utils/CtorUtils.h"
  13. #include "llvm/ADT/BitVector.h"
  14. #include "llvm/IR/Constants.h"
  15. #include "llvm/IR/Function.h"
  16. #include "llvm/IR/GlobalVariable.h"
  17. #include "llvm/IR/Module.h"
  18. #include "llvm/Support/Debug.h"
  19. #include "llvm/Support/raw_ostream.h"
  20. #define DEBUG_TYPE "ctor_utils"
  21. using namespace llvm;
  22. /// Given a specified llvm.global_ctors list, remove the listed elements.
  23. static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
  24. // Filter out the initializer elements to remove.
  25. ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
  26. SmallVector<Constant *, 10> CAList;
  27. for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
  28. if (!CtorsToRemove.test(I))
  29. CAList.push_back(OldCA->getOperand(I));
  30. // Create the new array initializer.
  31. ArrayType *ATy =
  32. ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
  33. Constant *CA = ConstantArray::get(ATy, CAList);
  34. // If we didn't change the number of elements, don't create a new GV.
  35. if (CA->getType() == OldCA->getType()) {
  36. GCL->setInitializer(CA);
  37. return;
  38. }
  39. // Create the new global and insert it next to the existing list.
  40. GlobalVariable *NGV =
  41. new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
  42. CA, "", GCL->getThreadLocalMode());
  43. GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV);
  44. NGV->takeName(GCL);
  45. // Nuke the old list, replacing any uses with the new one.
  46. if (!GCL->use_empty()) {
  47. Constant *V = NGV;
  48. if (V->getType() != GCL->getType())
  49. V = ConstantExpr::getBitCast(V, GCL->getType());
  50. GCL->replaceAllUsesWith(V);
  51. }
  52. GCL->eraseFromParent();
  53. }
  54. /// Given a llvm.global_ctors list that we can understand,
  55. /// return a list of the functions and null terminator as a vector.
  56. static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
  57. if (GV->getInitializer()->isNullValue())
  58. return std::vector<Function *>();
  59. ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
  60. std::vector<Function *> Result;
  61. Result.reserve(CA->getNumOperands());
  62. for (auto &V : CA->operands()) {
  63. ConstantStruct *CS = cast<ConstantStruct>(V);
  64. Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
  65. }
  66. return Result;
  67. }
  68. /// Find the llvm.global_ctors list, verifying that all initializers have an
  69. /// init priority of 65535.
  70. static GlobalVariable *findGlobalCtors(Module &M) {
  71. GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
  72. if (!GV)
  73. return nullptr;
  74. // Verify that the initializer is simple enough for us to handle. We are
  75. // only allowed to optimize the initializer if it is unique.
  76. if (!GV->hasUniqueInitializer())
  77. return nullptr;
  78. if (isa<ConstantAggregateZero>(GV->getInitializer()))
  79. return GV;
  80. ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
  81. for (auto &V : CA->operands()) {
  82. if (isa<ConstantAggregateZero>(V))
  83. continue;
  84. ConstantStruct *CS = cast<ConstantStruct>(V);
  85. if (isa<ConstantPointerNull>(CS->getOperand(1)))
  86. continue;
  87. // Must have a function or null ptr.
  88. if (!isa<Function>(CS->getOperand(1)))
  89. return nullptr;
  90. // Init priority must be standard.
  91. ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
  92. if (CI->getZExtValue() != 65535)
  93. return nullptr;
  94. }
  95. return GV;
  96. }
  97. /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
  98. /// entries for which it returns true. Return true if anything changed.
  99. bool llvm::optimizeGlobalCtorsList(
  100. Module &M, function_ref<bool(Function *)> ShouldRemove) {
  101. GlobalVariable *GlobalCtors = findGlobalCtors(M);
  102. if (!GlobalCtors)
  103. return false;
  104. std::vector<Function *> Ctors = parseGlobalCtors(GlobalCtors);
  105. if (Ctors.empty())
  106. return false;
  107. bool MadeChange = false;
  108. // Loop over global ctors, optimizing them when we can.
  109. unsigned NumCtors = Ctors.size();
  110. BitVector CtorsToRemove(NumCtors);
  111. for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
  112. Function *F = Ctors[i];
  113. // Found a null terminator in the middle of the list, prune off the rest of
  114. // the list.
  115. if (!F)
  116. continue;
  117. LLVM_DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
  118. // We cannot simplify external ctor functions.
  119. if (F->empty())
  120. continue;
  121. // If we can evaluate the ctor at compile time, do.
  122. if (ShouldRemove(F)) {
  123. Ctors[i] = nullptr;
  124. CtorsToRemove.set(i);
  125. NumCtors--;
  126. MadeChange = true;
  127. continue;
  128. }
  129. }
  130. if (!MadeChange)
  131. return false;
  132. removeGlobalCtors(GlobalCtors, CtorsToRemove);
  133. return true;
  134. }