// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// This pass loops over all of the functions and variables in the input module.
+// If the function or variable does not need to be preserved according to the
+// client supplied callback, it is marked as internal.
+//
+// This transformation would not be legal in a regular compilation, but it gets
+// extra information from the linker about what is safe.
+//
+// For example: Internalizing a function with external linkage. Only if we are
+// told it is only used from within this module, it is safe to do it.
+//
+//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_IPO_INTERNALIZE_H
#define LLVM_TRANSFORMS_IPO_INTERNALIZE_H
+#include "llvm/ADT/StringSet.h"
#include "llvm/IR/GlobalValue.h"
-
+#include "llvm/IR/PassManager.h"
#include <functional>
+#include <set>
namespace llvm {
class Module;
class CallGraph;
-bool internalizeModule(
+/// A pass that internalizes all functions and variables other than those that
+/// must be preserved according to \c MustPreserveGV.
+class InternalizePass : public PassInfoMixin<InternalizePass> {
+ /// Client supplied callback to control wheter a symbol must be preserved.
+ const std::function<bool(const GlobalValue &)> MustPreserveGV;
+ /// Set of symbols private to the compiler that this pass should not touch.
+ StringSet<> AlwaysPreserved;
+
+ /// Return false if we're allowed to internalize this GV.
+ bool shouldPreserveGV(const GlobalValue &GV);
+ /// Internalize GV if it is possible to do so, i.e. it is not externally
+ /// visible and is not a member of an externally visible comdat.
+ bool maybeInternalize(GlobalValue &GV,
+ const std::set<const Comdat *> &ExternalComdats);
+ /// If GV is part of a comdat and is externally visible, keep track of its
+ /// comdat so that we don't internalize any of its members.
+ void checkComdatVisibility(GlobalValue &GV,
+ std::set<const Comdat *> &ExternalComdats);
+
+public:
+ InternalizePass();
+ InternalizePass(
+ const std::function<bool(const GlobalValue &)> MustPreserveGV)
+ : MustPreserveGV(std::move(MustPreserveGV)) {}
+
+ /// Run the internalizer on \p TheModule, returns true if any changes was
+ /// made.
+ ///
+ /// If the CallGraph \p CG is supplied, it will be updated when
+ /// internalizing a function (by removing any edge from the "external node")
+ bool internalizeModule(Module &TheModule, CallGraph *CG = nullptr);
+
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+};
+
+/// Helper function to internalize functions and variables in a Module.
+inline bool internalizeModule(
Module &TheModule,
- const std::function<bool(const GlobalValue &)> &MustPreserveGV,
- CallGraph *CG = nullptr);
+ const std::function<bool(const GlobalValue &)> MustPreserveGV,
+ CallGraph *CG = nullptr) {
+ return InternalizePass(std::move(MustPreserveGV))
+ .internalizeModule(TheModule, CG);
}
+} // end namespace llvm
#endif // LLVM_TRANSFORMS_IPO_INTERNALIZE_H
//===----------------------------------------------------------------------===//
//
// This pass loops over all of the functions and variables in the input module.
-// If the function or variable is not in the list of external names given to
-// the pass it is marked as internal.
+// If the function or variable does not need to be preserved according to the
+// client supplied callback, it is marked as internal.
//
// This transformation would not be legal in a regular compilation, but it gets
// extra information from the linker about what is safe.
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/Internalize.h"
-#include "llvm/Transforms/IPO.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
#include <fstream>
#include <set>
cl::desc("A list of symbol names to preserve"), cl::CommaSeparated);
namespace {
-
// Helper to load an API list to preserve from file and expose it as a functor
// for internalization.
class PreserveAPIList {
}
}
};
+} // end anonymous namespace
-// Internalization exposed as a pass
-class InternalizePass : public ModulePass {
- // Client supplied callback to control wheter a symbol must be preserved.
- std::function<bool(const GlobalValue &)> MustPreserveGV;
-
-public:
- static char ID; // Pass identification, replacement for typeid
-
- InternalizePass() : ModulePass(ID), MustPreserveGV(PreserveAPIList()) {}
-
- InternalizePass(std::function<bool(const GlobalValue &)> MustPreserveGV)
- : ModulePass(ID), MustPreserveGV(std::move(MustPreserveGV)) {
- initializeInternalizePassPass(*PassRegistry::getPassRegistry());
- }
-
- bool runOnModule(Module &M) override {
- if (skipModule(M))
- return false;
-
- CallGraphWrapperPass *CGPass =
- getAnalysisIfAvailable<CallGraphWrapperPass>();
- CallGraph *CG = CGPass ? &CGPass->getCallGraph() : nullptr;
- return internalizeModule(M, MustPreserveGV, CG);
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
- AU.addPreserved<CallGraphWrapperPass>();
- }
-};
-
-// Helper class to perform internalization.
-class Internalizer {
- // Client supplied callback to control wheter a symbol must be preserved.
- const std::function<bool(const GlobalValue &)> &MustPreserveGV;
-
- // Set of symbols private to the compiler that this pass should not touch.
- StringSet<> AlwaysPreserved;
-
- // Return false if we're allowed to internalize this GV.
- bool ShouldPreserveGV(const GlobalValue &GV) {
- // Function must be defined here
- if (GV.isDeclaration())
- return true;
+bool InternalizePass::shouldPreserveGV(const GlobalValue &GV) {
+ // Function must be defined here
+ if (GV.isDeclaration())
+ return true;
- // Available externally is really just a "declaration with a body".
- if (GV.hasAvailableExternallyLinkage())
- return true;
+ // Available externally is really just a "declaration with a body".
+ if (GV.hasAvailableExternallyLinkage())
+ return true;
- // Assume that dllexported symbols are referenced elsewhere
- if (GV.hasDLLExportStorageClass())
- return true;
+ // Assume that dllexported symbols are referenced elsewhere
+ if (GV.hasDLLExportStorageClass())
+ return true;
- // Already local, has nothing to do.
- if (GV.hasLocalLinkage())
- return false;
+ // Already local, has nothing to do.
+ if (GV.hasLocalLinkage())
+ return false;
- // Check some special cases
- if (AlwaysPreserved.count(GV.getName()))
- return true;
+ // Check some special cases
+ if (AlwaysPreserved.count(GV.getName()))
+ return true;
- return MustPreserveGV(GV);
- }
-
- bool maybeInternalize(GlobalValue &GV,
- const std::set<const Comdat *> &ExternalComdats);
- void checkComdatVisibility(GlobalValue &GV,
- std::set<const Comdat *> &ExternalComdats);
-
-public:
- Internalizer(const std::function<bool(const GlobalValue &)> &MustPreserveGV)
- : MustPreserveGV(MustPreserveGV) {}
-
- /// Run the internalizer on \p TheModule, returns true if any changes was
- /// made.
- ///
- /// If the CallGraph \p CG is supplied, it will be updated when
- /// internalizing a function (by removing any edge from the "external node")
- bool internalizeModule(Module &TheModule, CallGraph *CG = nullptr);
-};
+ return MustPreserveGV(GV);
+}
-// Internalize GV if it is possible to do so, i.e. it is not externally visible
-// and is not a member of an externally visible comdat.
-bool Internalizer::maybeInternalize(
+bool InternalizePass::maybeInternalize(
GlobalValue &GV, const std::set<const Comdat *> &ExternalComdats) {
if (Comdat *C = GV.getComdat()) {
if (ExternalComdats.count(C))
if (GV.hasLocalLinkage())
return false;
- if (ShouldPreserveGV(GV))
+ if (shouldPreserveGV(GV))
return false;
}
// If GV is part of a comdat and is externally visible, keep track of its
// comdat so that we don't internalize any of its members.
-void Internalizer::checkComdatVisibility(
+void InternalizePass::checkComdatVisibility(
GlobalValue &GV, std::set<const Comdat *> &ExternalComdats) {
Comdat *C = GV.getComdat();
if (!C)
return;
- if (ShouldPreserveGV(GV))
+ if (shouldPreserveGV(GV))
ExternalComdats.insert(C);
}
-bool Internalizer::internalizeModule(Module &M, CallGraph *CG) {
+bool InternalizePass::internalizeModule(Module &M, CallGraph *CG) {
bool Changed = false;
CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : nullptr;
return Changed;
}
-} // end anonymous namespace
+InternalizePass::InternalizePass() : MustPreserveGV(PreserveAPIList()) {}
+
+PreservedAnalyses InternalizePass::run(Module &M, AnalysisManager<Module> &AM) {
+ if (!internalizeModule(M, AM.getCachedResult<CallGraphAnalysis>(M)))
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA;
+ PA.preserve<CallGraphAnalysis>();
+ return PA;
+}
-char InternalizePass::ID = 0;
-INITIALIZE_PASS(InternalizePass, "internalize", "Internalize Global Symbols",
- false, false)
+namespace {
+class InternalizeLegacyPass : public ModulePass {
+ // Client supplied callback to control wheter a symbol must be preserved.
+ std::function<bool(const GlobalValue &)> MustPreserveGV;
-/// Public API below
+public:
+ static char ID; // Pass identification, replacement for typeid
+
+ InternalizeLegacyPass() : ModulePass(ID), MustPreserveGV(PreserveAPIList()) {}
+
+ InternalizeLegacyPass(std::function<bool(const GlobalValue &)> MustPreserveGV)
+ : ModulePass(ID), MustPreserveGV(std::move(MustPreserveGV)) {
+ initializeInternalizeLegacyPassPass(*PassRegistry::getPassRegistry());
+ }
-bool llvm::internalizeModule(
- Module &TheModule,
- const std::function<bool(const GlobalValue &)> &MustPreserveGV,
- CallGraph *CG) {
- return Internalizer(MustPreserveGV).internalizeModule(TheModule, CG);
+ bool runOnModule(Module &M) override {
+ if (skipModule(M))
+ return false;
+
+ CallGraphWrapperPass *CGPass =
+ getAnalysisIfAvailable<CallGraphWrapperPass>();
+ CallGraph *CG = CGPass ? &CGPass->getCallGraph() : nullptr;
+ return internalizeModule(M, MustPreserveGV, CG);
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesCFG();
+ AU.addPreserved<CallGraphWrapperPass>();
+ }
+};
}
-ModulePass *llvm::createInternalizePass() { return new InternalizePass(); }
+char InternalizeLegacyPass::ID = 0;
+INITIALIZE_PASS(InternalizeLegacyPass, "internalize",
+ "Internalize Global Symbols", false, false)
+
+ModulePass *llvm::createInternalizePass() {
+ return new InternalizeLegacyPass();
+}
ModulePass *llvm::createInternalizePass(
std::function<bool(const GlobalValue &)> MustPreserveGV) {
- return new InternalizePass(std::move(MustPreserveGV));
+ return new InternalizeLegacyPass(std::move(MustPreserveGV));
}