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 "Support/StatisticReporter.h"
23 static Statistic<> NumTypeSymtabEntriesKilled("cleangcc\t- Number of unused typenames removed from symtab");
28 struct CleanupGCCOutput : public FunctionPass {
29 // doPassInitialization - For this pass, it removes global symbol table
30 // entries for primitive types. These are never used for linking in GCC and
31 // they make the output uglier to look at, so we nuke them.
33 // Also, initialize instance variables.
35 bool doInitialization(Module &M);
38 // FIXME: This FunctionPass should be a PASS!
40 bool runOnFunction(Function &F) { return false; }
42 // doPassFinalization - Strip out type names that are unused by the program
43 bool doFinalization(Module &M);
45 // getAnalysisUsage - This function needs FindUsedTypes to do its job...
47 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
48 AU.addRequired(FindUsedTypes::ID);
51 RegisterPass<CleanupGCCOutput> X("cleangcc", "Cleanup GCC Output");
54 Pass *createCleanupGCCOutputPass() {
55 return new CleanupGCCOutput();
60 // ShouldNukSymtabEntry - Return true if this module level symbol table entry
61 // should be eliminated.
63 static inline bool ShouldNukeSymtabEntry(const std::pair<std::string,Value*>&E){
64 // Nuke all names for primitive types!
65 if (cast<Type>(E.second)->isPrimitiveType()) return true;
67 // Nuke all pointers to primitive types as well...
68 if (const PointerType *PT = dyn_cast<PointerType>(E.second))
69 if (PT->getElementType()->isPrimitiveType()) return true;
74 // doInitialization - For this pass, it removes global symbol table
75 // entries for primitive types. These are never used for linking in GCC and
76 // they make the output uglier to look at, so we nuke them.
78 bool CleanupGCCOutput::doInitialization(Module &M) {
81 if (SymbolTable *ST = M.getSymbolTable()) {
82 // Check the symbol table for superfluous type entries...
84 // Grab the 'type' plane of the module symbol...
85 SymbolTable::iterator STI = ST->find(Type::TypeTy);
86 if (STI != ST->end()) {
87 // Loop over all entries in the type plane...
88 SymbolTable::VarMap &Plane = STI->second;
89 for (SymbolTable::VarMap::iterator PI = Plane.begin(); PI != Plane.end();)
90 if (ShouldNukeSymtabEntry(*PI)) { // Should we remove this entry?
91 #if MAP_IS_NOT_BRAINDEAD
92 PI = Plane.erase(PI); // STD C++ Map should support this!
94 Plane.erase(PI); // Alas, GCC 2.95.3 doesn't *SIGH*
97 ++NumTypeSymtabEntriesKilled;
109 bool CleanupGCCOutput::doFinalization(Module &M) {
110 bool Changed = false;
112 if (SymbolTable *ST = M.getSymbolTable()) {
113 const std::set<const Type *> &UsedTypes =
114 getAnalysis<FindUsedTypes>().getTypes();
116 // Check the symbol table for superfluous type entries that aren't used in
119 // Grab the 'type' plane of the module symbol...
120 SymbolTable::iterator STI = ST->find(Type::TypeTy);
121 if (STI != ST->end()) {
122 // Loop over all entries in the type plane...
123 SymbolTable::VarMap &Plane = STI->second;
124 for (SymbolTable::VarMap::iterator PI = Plane.begin(); PI != Plane.end();)
125 if (!UsedTypes.count(cast<Type>(PI->second))) {
126 #if MAP_IS_NOT_BRAINDEAD
127 PI = Plane.erase(PI); // STD C++ Map should support this!
129 Plane.erase(PI); // Alas, GCC 2.95.3 doesn't *SIGH*
130 PI = Plane.begin(); // N^2 algorithms are fun. :(