Allow vararg method types with 0 fixed types
[oota-llvm.git] / lib / Analysis / ModuleAnalyzer.cpp
1 //===-- llvm/Analysis/ModuleAnalyzer.cpp - Module analysis driver ----------==//
2 //
3 // This class provides a nice interface to traverse a module in a predictable
4 // way.  This is used by the AssemblyWriter, BytecodeWriter, and SlotCalculator
5 // to do analysis of a module.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Analysis/ModuleAnalyzer.h"
10 #include "llvm/ConstantPool.h"
11 #include "llvm/Method.h"
12 #include "llvm/Module.h"
13 #include "llvm/BasicBlock.h"
14 #include "llvm/DerivedTypes.h"
15 #include "llvm/ConstPoolVals.h"
16 #include "llvm/Support/STLExtras.h"
17 #include <map>
18
19 // processModule - Driver function to call all of my subclasses virtual methods.
20 //
21 bool ModuleAnalyzer::processModule(const Module *M) {
22   // Loop over the constant pool, process all of the constants...
23   if (processConstPool(M->getConstantPool(), false))
24     return true;
25
26   return processMethods(M);
27 }
28
29 inline bool ModuleAnalyzer::handleType(set<const Type *> &TypeSet, 
30                                        const Type *T) {
31   if (!T->isDerivedType()) return false;    // Boring boring types...
32   if (TypeSet.count(T) != 0) return false;  // Already found this type...
33   TypeSet.insert(T);                        // Add it to the set
34   
35   // Recursively process interesting types...
36   switch (T->getPrimitiveID()) {
37   case Type::MethodTyID: {
38     const MethodType *MT = (const MethodType *)T;
39     if (handleType(TypeSet, MT->getReturnType())) return true;
40     const MethodType::ParamTypes &Params = MT->getParamTypes();
41
42     for (MethodType::ParamTypes::const_iterator I = Params.begin();
43          I != Params.end(); ++I)
44       if (handleType(TypeSet, *I)) return true;
45     break;
46   }
47
48   case Type::ArrayTyID:
49     if (handleType(TypeSet, ((const ArrayType *)T)->getElementType()))
50       return true;
51     break;
52
53   case Type::StructTyID: {
54     const StructType *ST = (const StructType*)T;
55     const StructType::ElementTypes &Elements = ST->getElementTypes();
56     for (StructType::ElementTypes::const_iterator I = Elements.begin();
57          I != Elements.end(); ++I)
58       if (handleType(TypeSet, *I)) return true;
59     break;
60   }
61
62   case Type::PointerTyID:
63     if (handleType(TypeSet, ((const PointerType *)T)->getValueType()))
64       return true;
65     break;
66
67   default:
68     cerr << "ModuleAnalyzer::handleType, type unknown: '" 
69          << T->getName() << "'\n";
70     break;
71   }
72
73   return processType(T);
74 }
75
76
77 bool ModuleAnalyzer::processConstPool(const ConstantPool &CP, bool isMethod) {
78   // TypeSet - Keep track of which types have already been processType'ed.  We 
79   // don't want to reprocess the same type more than once.
80   //
81   set<const Type *> TypeSet;
82
83   for (ConstantPool::plane_const_iterator PI = CP.begin(); 
84        PI != CP.end(); ++PI) {
85     const ConstantPool::PlaneType &Plane = **PI;
86     if (Plane.empty()) continue;        // Skip empty type planes...
87
88     if (processConstPoolPlane(CP, Plane, isMethod)) return true;
89
90     for (ConstantPool::PlaneType::const_iterator CI = Plane.begin(); 
91          CI != Plane.end(); ++CI) {
92       if ((*CI)->getType() == Type::TypeTy)
93         if (handleType(TypeSet, ((const ConstPoolType*)(*CI))->getValue())) 
94           return true;
95       if (handleType(TypeSet, (*CI)->getType())) return true;
96
97       if (processConstant(*CI)) return true;
98     }
99   }
100   
101   if (!isMethod) {
102     const Module *M = CP.getParentV()->castModuleAsserting();
103     // Process the method types after the constant pool...
104     for (Module::const_iterator I = M->begin(); I != M->end(); ++I) {
105       if (handleType(TypeSet, (*I)->getType())) return true;
106       if (visitMethod(*I)) return true;
107     }
108   }
109   return false;
110 }
111
112 bool ModuleAnalyzer::processMethods(const Module *M) {
113   return apply_until(M->begin(), M->end(),
114                      bind_obj(this, &ModuleAnalyzer::processMethod));
115 }
116
117 bool ModuleAnalyzer::processMethod(const Method *M) {
118   // Loop over the arguments, processing them...
119   if (apply_until(M->getArgumentList().begin(), M->getArgumentList().end(),
120                   bind_obj(this, &ModuleAnalyzer::processMethodArgument)))
121     return true;
122
123   // Loop over the constant pool, adding the constants to the table...
124   processConstPool(M->getConstantPool(), true);
125   
126   // Loop over all the basic blocks, in order...
127   return apply_until(M->begin(), M->end(),
128                      bind_obj(this, &ModuleAnalyzer::processBasicBlock));
129 }
130
131 bool ModuleAnalyzer::processBasicBlock(const BasicBlock *BB) {
132   // Process all of the instructions in the basic block
133   BasicBlock::const_iterator Inst = BB->begin();
134   for (; Inst != BB->end(); Inst++) {
135     if (preProcessInstruction(*Inst) || processInstruction(*Inst)) return true;
136   }
137   return false;
138 }
139
140 bool ModuleAnalyzer::preProcessInstruction(const Instruction *I) {
141   
142   return false;
143 }