1 //===- CleanupGCCOutput.cpp - Cleanup GCC Output --------------------------===//
3 // This pass is used to cleanup the output of GCC. GCC's output is
4 // unneccessarily gross for a couple of reasons. This pass does the following
5 // things to try to clean it up:
7 // * Eliminate names for GCC types that we know can't be needed by the user.
8 // * Eliminate names for types that are unused in the entire translation unit
9 // * Fix various problems that we might have in PHI nodes and casts
11 // Note: This code produces dead declarations, it is a good idea to run DCE
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Transforms/CleanupGCCOutput.h"
17 #include "llvm/Analysis/FindUsedTypes.h"
18 #include "llvm/Module.h"
19 #include "llvm/SymbolTable.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/iPHINode.h"
22 #include "llvm/iMemory.h"
23 #include "llvm/iTerminators.h"
24 #include "llvm/iOther.h"
25 #include "llvm/Support/CFG.h"
26 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
27 #include "Support/StatisticReporter.h"
31 static Statistic<> NumTypeSymtabEntriesKilled("cleangcc\t- Number of unused typenames removed from symtab");
36 struct CleanupGCCOutput : public FunctionPass {
37 const char *getPassName() const { return "Cleanup GCC Output"; }
39 // doPassInitialization - For this pass, it removes global symbol table
40 // entries for primitive types. These are never used for linking in GCC and
41 // they make the output uglier to look at, so we nuke them.
43 // Also, initialize instance variables.
45 bool doInitialization(Module &M);
48 // FIXME: This FunctionPass should be a PASS!
50 bool runOnFunction(Function &F) { return false; }
52 // doPassFinalization - Strip out type names that are unused by the program
53 bool doFinalization(Module &M);
55 // getAnalysisUsage - This function needs FindUsedTypes to do its job...
57 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
58 AU.addRequired(FindUsedTypes::ID);
63 Pass *createCleanupGCCOutputPass() {
64 return new CleanupGCCOutput();
69 // ShouldNukSymtabEntry - Return true if this module level symbol table entry
70 // should be eliminated.
72 static inline bool ShouldNukeSymtabEntry(const std::pair<std::string,Value*>&E){
73 // Nuke all names for primitive types!
74 if (cast<Type>(E.second)->isPrimitiveType()) return true;
76 // Nuke all pointers to primitive types as well...
77 if (const PointerType *PT = dyn_cast<PointerType>(E.second))
78 if (PT->getElementType()->isPrimitiveType()) return true;
83 // doInitialization - For this pass, it removes global symbol table
84 // entries for primitive types. These are never used for linking in GCC and
85 // they make the output uglier to look at, so we nuke them.
87 bool CleanupGCCOutput::doInitialization(Module &M) {
90 if (SymbolTable *ST = M.getSymbolTable()) {
91 // Check the symbol table for superfluous type entries...
93 // Grab the 'type' plane of the module symbol...
94 SymbolTable::iterator STI = ST->find(Type::TypeTy);
95 if (STI != ST->end()) {
96 // Loop over all entries in the type plane...
97 SymbolTable::VarMap &Plane = STI->second;
98 for (SymbolTable::VarMap::iterator PI = Plane.begin(); PI != Plane.end();)
99 if (ShouldNukeSymtabEntry(*PI)) { // Should we remove this entry?
100 #if MAP_IS_NOT_BRAINDEAD
101 PI = Plane.erase(PI); // STD C++ Map should support this!
103 Plane.erase(PI); // Alas, GCC 2.95.3 doesn't *SIGH*
106 ++NumTypeSymtabEntriesKilled;
118 bool CleanupGCCOutput::doFinalization(Module &M) {
119 bool Changed = false;
121 if (SymbolTable *ST = M.getSymbolTable()) {
122 const std::set<const Type *> &UsedTypes =
123 getAnalysis<FindUsedTypes>().getTypes();
125 // Check the symbol table for superfluous type entries that aren't used in
128 // Grab the 'type' plane of the module symbol...
129 SymbolTable::iterator STI = ST->find(Type::TypeTy);
130 if (STI != ST->end()) {
131 // Loop over all entries in the type plane...
132 SymbolTable::VarMap &Plane = STI->second;
133 for (SymbolTable::VarMap::iterator PI = Plane.begin(); PI != Plane.end();)
134 if (!UsedTypes.count(cast<Type>(PI->second))) {
135 #if MAP_IS_NOT_BRAINDEAD
136 PI = Plane.erase(PI); // STD C++ Map should support this!
138 Plane.erase(PI); // Alas, GCC 2.95.3 doesn't *SIGH*
139 PI = Plane.begin(); // N^2 algorithms are fun. :(