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" |
| 16 | #include <map> |
| 17 | |
| 18 | // processModule - Driver function to call all of my subclasses virtual methods. |
| 19 | // |
| 20 | bool ModuleAnalyzer::processModule(const Module *M) { |
| 21 | // Loop over the constant pool, process all of the constants... |
| 22 | if (processConstPool(M->getConstantPool(), false)) |
| 23 | return true; |
| 24 | |
| 25 | return processMethods(M); |
| 26 | } |
| 27 | |
| 28 | inline bool ModuleAnalyzer::handleType(set<const Type *> &TypeSet, |
| 29 | const Type *T) { |
| 30 | if (!T->isDerivedType()) return false; // Boring boring types... |
| 31 | if (TypeSet.count(T) != 0) return false; // Already found this type... |
| 32 | TypeSet.insert(T); // Add it to the set |
| 33 | |
| 34 | // Recursively process interesting types... |
| 35 | switch (T->getPrimitiveID()) { |
| 36 | case Type::MethodTyID: { |
| 37 | const MethodType *MT = (const MethodType *)T; |
| 38 | if (handleType(TypeSet, MT->getReturnType())) return true; |
| 39 | const MethodType::ParamTypes &Params = MT->getParamTypes(); |
| 40 | |
| 41 | for (MethodType::ParamTypes::const_iterator I = Params.begin(); |
| 42 | I != Params.end(); ++I) |
| 43 | if (handleType(TypeSet, *I)) return true; |
| 44 | break; |
| 45 | } |
| 46 | |
| 47 | case Type::ArrayTyID: |
| 48 | if (handleType(TypeSet, ((const ArrayType *)T)->getElementType())) |
| 49 | return true; |
| 50 | break; |
| 51 | |
| 52 | case Type::StructTyID: { |
| 53 | const StructType *ST = (const StructType*)T; |
| 54 | const StructType::ElementTypes &Elements = ST->getElementTypes(); |
| 55 | for (StructType::ElementTypes::const_iterator I = Elements.begin(); |
| 56 | I != Elements.end(); ++I) |
| 57 | if (handleType(TypeSet, *I)) return true; |
| 58 | break; |
| 59 | } |
| 60 | |
| 61 | case Type::PointerTyID: |
| 62 | if (handleType(TypeSet, ((const PointerType *)T)->getValueType())) |
| 63 | return true; |
| 64 | break; |
| 65 | |
| 66 | default: |
| 67 | cerr << "ModuleAnalyzer::handleType, type unknown: '" |
| 68 | << T->getName() << "'\n"; |
| 69 | break; |
| 70 | } |
| 71 | |
| 72 | return processType(T); |
| 73 | } |
| 74 | |
| 75 | |
| 76 | bool ModuleAnalyzer::processConstPool(const ConstantPool &CP, bool isMethod) { |
| 77 | // TypeSet - Keep track of which types have already been processType'ed. We |
| 78 | // don't want to reprocess the same type more than once. |
| 79 | // |
| 80 | set<const Type *> TypeSet; |
| 81 | |
| 82 | for (ConstantPool::plane_const_iterator PI = CP.begin(); |
| 83 | PI != CP.end(); ++PI) { |
| 84 | const ConstantPool::PlaneType &Plane = **PI; |
| 85 | if (Plane.empty()) continue; // Skip empty type planes... |
| 86 | |
| 87 | if (processConstPoolPlane(CP, Plane, isMethod)) return true; |
| 88 | |
| 89 | for (ConstantPool::PlaneType::const_iterator CI = Plane.begin(); |
| 90 | CI != Plane.end(); CI++) { |
| 91 | if ((*CI)->getType() == Type::TypeTy) |
| 92 | if (handleType(TypeSet, ((const ConstPoolType*)(*CI))->getValue())) |
| 93 | return true; |
| 94 | if (handleType(TypeSet, (*CI)->getType())) return true; |
| 95 | |
| 96 | if (processConstant(*CI)) return true; |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | if (!isMethod) { |
| 101 | assert(CP.getParent()->getValueType() == Value::ModuleVal); |
| 102 | const Module *M = (const Module*)CP.getParent(); |
| 103 | // Process the method types after the constant pool... |
| 104 | for (Module::MethodListType::const_iterator I = M->getMethodList().begin(); |
| 105 | I != M->getMethodList().end(); I++) { |
| 106 | if (handleType(TypeSet, (*I)->getType())) return true; |
| 107 | if (visitMethod(*I)) return true; |
| 108 | } |
| 109 | } |
| 110 | return false; |
| 111 | } |
| 112 | |
| 113 | bool ModuleAnalyzer::processMethods(const Module *M) { |
| 114 | for (Module::MethodListType::const_iterator I = M->getMethodList().begin(); |
| 115 | I != M->getMethodList().end(); I++) |
| 116 | if (processMethod(*I)) return true; |
| 117 | |
| 118 | return false; |
| 119 | } |
| 120 | |
| 121 | bool ModuleAnalyzer::processMethod(const Method *M) { |
| 122 | // Loop over the arguments, processing them... |
| 123 | const Method::ArgumentListType &ArgList = M->getArgumentList(); |
| 124 | for (Method::ArgumentListType::const_iterator AI = ArgList.begin(); |
| 125 | AI != ArgList.end(); AI++) |
| 126 | if (processMethodArgument(*AI)) return true; |
| 127 | |
| 128 | // Loop over the constant pool, adding the constants to the table... |
| 129 | processConstPool(M->getConstantPool(), true); |
| 130 | |
| 131 | // Loop over all the basic blocks, in order... |
| 132 | Method::BasicBlocksType::const_iterator BBI = M->getBasicBlocks().begin(); |
| 133 | for (; BBI != M->getBasicBlocks().end(); BBI++) |
| 134 | if (processBasicBlock(*BBI)) return true; |
| 135 | return false; |
| 136 | } |
| 137 | |
| 138 | bool ModuleAnalyzer::processBasicBlock(const BasicBlock *BB) { |
| 139 | // Process all of the instructions in the basic block |
| 140 | BasicBlock::InstListType::const_iterator Inst = BB->getInstList().begin(); |
| 141 | for (; Inst != BB->getInstList().end(); Inst++) { |
| 142 | if (preProcessInstruction(*Inst) || processInstruction(*Inst)) return true; |
| 143 | } |
| 144 | return false; |
| 145 | } |
| 146 | |
| 147 | bool ModuleAnalyzer::preProcessInstruction(const Instruction *I) { |
| 148 | |
| 149 | return false; |
| 150 | } |