Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 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" |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 16 | #include "llvm/Tools/STLExtras.h" |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 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(); |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 91 | CI != Plane.end(); ++CI) { |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 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) { |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 102 | const Module *M = CP.getParent()->castModuleAsserting(); |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 103 | // Process the method types after the constant pool... |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 104 | for (Module::const_iterator I = M->begin(); I != M->end(); ++I) { |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 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) { |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 113 | return apply_until(M->begin(), M->end(), |
| 114 | bind_obj(this, &ModuleAnalyzer::processMethod)); |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | bool ModuleAnalyzer::processMethod(const Method *M) { |
| 118 | // Loop over the arguments, processing them... |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 119 | if (apply_until(M->getArgumentList().begin(), M->getArgumentList().end(), |
| 120 | bind_obj(this, &ModuleAnalyzer::processMethodArgument))) |
| 121 | return true; |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 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... |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 127 | return apply_until(M->begin(), M->end(), |
| 128 | bind_obj(this, &ModuleAnalyzer::processBasicBlock)); |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | bool ModuleAnalyzer::processBasicBlock(const BasicBlock *BB) { |
| 132 | // Process all of the instructions in the basic block |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame^] | 133 | BasicBlock::const_iterator Inst = BB->begin(); |
| 134 | for (; Inst != BB->end(); Inst++) { |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 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 | } |