Remove "fixers" for problems in GCC generated code that cannot be generated
[oota-llvm.git] / lib / Transforms / IPO / DeadTypeElimination.cpp
1 //===- CleanupGCCOutput.cpp - Cleanup GCC Output --------------------------===//
2 //
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:
6 //
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
10 //
11 // Note:  This code produces dead declarations, it is a good idea to run DCE
12 //        after this pass.
13 //
14 //===----------------------------------------------------------------------===//
15
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"
28 #include <algorithm>
29 #include <iostream>
30
31 static Statistic<> NumTypeSymtabEntriesKilled("cleangcc\t- Number of unused typenames removed from symtab");
32
33 using std::vector;
34
35 namespace {
36   struct CleanupGCCOutput : public FunctionPass {
37     const char *getPassName() const { return "Cleanup GCC Output"; }
38
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.
42     //
43     // Also, initialize instance variables.
44     //
45     bool doInitialization(Module &M);
46
47     // FIXME:
48     // FIXME: This FunctionPass should be a PASS!
49     // FIXME:
50     bool runOnFunction(Function &F) { return false; }
51     
52     // doPassFinalization - Strip out type names that are unused by the program
53     bool doFinalization(Module &M);
54     
55     // getAnalysisUsage - This function needs FindUsedTypes to do its job...
56     //
57     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
58       AU.addRequired(FindUsedTypes::ID);
59     }
60   };
61 }
62
63 Pass *createCleanupGCCOutputPass() {
64   return new CleanupGCCOutput();
65 }
66
67
68
69 // ShouldNukSymtabEntry - Return true if this module level symbol table entry
70 // should be eliminated.
71 //
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;
75
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;
79
80   return false;
81 }
82
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.
86 //
87 bool CleanupGCCOutput::doInitialization(Module &M) {
88   bool Changed = false;
89
90   if (SymbolTable *ST = M.getSymbolTable()) {
91     // Check the symbol table for superfluous type entries...
92     //
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!
102 #else
103           Plane.erase(PI);          // Alas, GCC 2.95.3 doesn't  *SIGH*
104           PI = Plane.begin();
105 #endif
106           ++NumTypeSymtabEntriesKilled;
107           Changed = true;
108         } else {
109           ++PI;
110         }
111     }
112   }
113
114   return Changed;
115 }
116
117
118 bool CleanupGCCOutput::doFinalization(Module &M) {
119   bool Changed = false;
120
121   if (SymbolTable *ST = M.getSymbolTable()) {
122     const std::set<const Type *> &UsedTypes =
123       getAnalysis<FindUsedTypes>().getTypes();
124
125     // Check the symbol table for superfluous type entries that aren't used in
126     // the program
127     //
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!
137 #else
138           Plane.erase(PI);          // Alas, GCC 2.95.3 doesn't  *SIGH*
139           PI = Plane.begin();       // N^2 algorithms are fun.  :(
140 #endif
141           Changed = true;
142         } else {
143           ++PI;
144         }
145     }
146   }
147   return Changed;
148 }