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" |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 10 | #include "llvm/Method.h" |
| 11 | #include "llvm/Module.h" |
| 12 | #include "llvm/BasicBlock.h" |
| 13 | #include "llvm/DerivedTypes.h" |
| 14 | #include "llvm/ConstPoolVals.h" |
Chris Lattner | cee8f9a | 2001-11-27 00:03:19 +0000 | [diff] [blame] | 15 | #include "Support/STLExtras.h" |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 16 | #include <map> |
| 17 | |
| 18 | // processModule - Driver function to call all of my subclasses virtual methods. |
| 19 | // |
| 20 | bool ModuleAnalyzer::processModule(const Module *M) { |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 21 | return processMethods(M); |
| 22 | } |
| 23 | |
| 24 | inline bool ModuleAnalyzer::handleType(set<const Type *> &TypeSet, |
| 25 | const Type *T) { |
| 26 | if (!T->isDerivedType()) return false; // Boring boring types... |
| 27 | if (TypeSet.count(T) != 0) return false; // Already found this type... |
| 28 | TypeSet.insert(T); // Add it to the set |
| 29 | |
| 30 | // Recursively process interesting types... |
| 31 | switch (T->getPrimitiveID()) { |
| 32 | case Type::MethodTyID: { |
| 33 | const MethodType *MT = (const MethodType *)T; |
| 34 | if (handleType(TypeSet, MT->getReturnType())) return true; |
| 35 | const MethodType::ParamTypes &Params = MT->getParamTypes(); |
| 36 | |
| 37 | for (MethodType::ParamTypes::const_iterator I = Params.begin(); |
| 38 | I != Params.end(); ++I) |
| 39 | if (handleType(TypeSet, *I)) return true; |
| 40 | break; |
| 41 | } |
| 42 | |
| 43 | case Type::ArrayTyID: |
| 44 | if (handleType(TypeSet, ((const ArrayType *)T)->getElementType())) |
| 45 | return true; |
| 46 | break; |
| 47 | |
| 48 | case Type::StructTyID: { |
Chris Lattner | b00c582 | 2001-10-02 03:41:24 +0000 | [diff] [blame] | 49 | const StructType *ST = cast<const StructType>(T); |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 50 | const StructType::ElementTypes &Elements = ST->getElementTypes(); |
| 51 | for (StructType::ElementTypes::const_iterator I = Elements.begin(); |
| 52 | I != Elements.end(); ++I) |
| 53 | if (handleType(TypeSet, *I)) return true; |
| 54 | break; |
| 55 | } |
| 56 | |
| 57 | case Type::PointerTyID: |
| 58 | if (handleType(TypeSet, ((const PointerType *)T)->getValueType())) |
| 59 | return true; |
| 60 | break; |
| 61 | |
| 62 | default: |
| 63 | cerr << "ModuleAnalyzer::handleType, type unknown: '" |
| 64 | << T->getName() << "'\n"; |
| 65 | break; |
| 66 | } |
| 67 | |
| 68 | return processType(T); |
| 69 | } |
| 70 | |
| 71 | |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 72 | bool ModuleAnalyzer::processMethods(const Module *M) { |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame] | 73 | return apply_until(M->begin(), M->end(), |
| 74 | bind_obj(this, &ModuleAnalyzer::processMethod)); |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 75 | } |
| 76 | |
| 77 | bool ModuleAnalyzer::processMethod(const Method *M) { |
| 78 | // Loop over the arguments, processing them... |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame] | 79 | if (apply_until(M->getArgumentList().begin(), M->getArgumentList().end(), |
| 80 | bind_obj(this, &ModuleAnalyzer::processMethodArgument))) |
| 81 | return true; |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 82 | |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 83 | // Loop over all the basic blocks, in order... |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame] | 84 | return apply_until(M->begin(), M->end(), |
| 85 | bind_obj(this, &ModuleAnalyzer::processBasicBlock)); |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | bool ModuleAnalyzer::processBasicBlock(const BasicBlock *BB) { |
| 89 | // Process all of the instructions in the basic block |
Chris Lattner | 7fc9fe3 | 2001-06-27 23:41:11 +0000 | [diff] [blame] | 90 | BasicBlock::const_iterator Inst = BB->begin(); |
| 91 | for (; Inst != BB->end(); Inst++) { |
Chris Lattner | 0095054 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 92 | if (preProcessInstruction(*Inst) || processInstruction(*Inst)) return true; |
| 93 | } |
| 94 | return false; |
| 95 | } |
| 96 | |
| 97 | bool ModuleAnalyzer::preProcessInstruction(const Instruction *I) { |
| 98 | |
| 99 | return false; |
| 100 | } |