blob: 0f028d12ddeaf508295658cab29594e7c544d5f0 [file] [log] [blame]
Chris Lattner00950542001-06-06 20:29:01 +00001//===-- 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 Lattner7fc9fe32001-06-27 23:41:11 +000016#include "llvm/Tools/STLExtras.h"
Chris Lattner00950542001-06-06 20:29:01 +000017#include <map>
18
19// processModule - Driver function to call all of my subclasses virtual methods.
20//
21bool 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
29inline 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
77bool 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 Lattner7fc9fe32001-06-27 23:41:11 +000091 CI != Plane.end(); ++CI) {
Chris Lattner00950542001-06-06 20:29:01 +000092 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 Lattner7fc9fe32001-06-27 23:41:11 +0000102 const Module *M = CP.getParent()->castModuleAsserting();
Chris Lattner00950542001-06-06 20:29:01 +0000103 // Process the method types after the constant pool...
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000104 for (Module::const_iterator I = M->begin(); I != M->end(); ++I) {
Chris Lattner00950542001-06-06 20:29:01 +0000105 if (handleType(TypeSet, (*I)->getType())) return true;
106 if (visitMethod(*I)) return true;
107 }
108 }
109 return false;
110}
111
112bool ModuleAnalyzer::processMethods(const Module *M) {
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000113 return apply_until(M->begin(), M->end(),
114 bind_obj(this, &ModuleAnalyzer::processMethod));
Chris Lattner00950542001-06-06 20:29:01 +0000115}
116
117bool ModuleAnalyzer::processMethod(const Method *M) {
118 // Loop over the arguments, processing them...
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000119 if (apply_until(M->getArgumentList().begin(), M->getArgumentList().end(),
120 bind_obj(this, &ModuleAnalyzer::processMethodArgument)))
121 return true;
Chris Lattner00950542001-06-06 20:29:01 +0000122
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 Lattner7fc9fe32001-06-27 23:41:11 +0000127 return apply_until(M->begin(), M->end(),
128 bind_obj(this, &ModuleAnalyzer::processBasicBlock));
Chris Lattner00950542001-06-06 20:29:01 +0000129}
130
131bool ModuleAnalyzer::processBasicBlock(const BasicBlock *BB) {
132 // Process all of the instructions in the basic block
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000133 BasicBlock::const_iterator Inst = BB->begin();
134 for (; Inst != BB->end(); Inst++) {
Chris Lattner00950542001-06-06 20:29:01 +0000135 if (preProcessInstruction(*Inst) || processInstruction(*Inst)) return true;
136 }
137 return false;
138}
139
140bool ModuleAnalyzer::preProcessInstruction(const Instruction *I) {
141
142 return false;
143}