summaryrefslogtreecommitdiff
path: root/lib/Analysis/ModuleAnalyzer.cpp
blob: 1c3464e48ce104d2a58376bc394f248d69eeae65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//===-- llvm/Analysis/ModuleAnalyzer.cpp - Module analysis driver ----------==//
//
// This class provides a nice interface to traverse a module in a predictable
// way.  This is used by the AssemblyWriter, BytecodeWriter, and SlotCalculator
// to do analysis of a module.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/ModuleAnalyzer.h"
#include "llvm/ConstantPool.h"
#include "llvm/Method.h"
#include "llvm/Module.h"
#include "llvm/BasicBlock.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ConstPoolVals.h"
#include <map>

// processModule - Driver function to call all of my subclasses virtual methods.
//
bool ModuleAnalyzer::processModule(const Module *M) {
  // Loop over the constant pool, process all of the constants...
  if (processConstPool(M->getConstantPool(), false))
    return true;

  return processMethods(M);
}

inline bool ModuleAnalyzer::handleType(set<const Type *> &TypeSet, 
				       const Type *T) {
  if (!T->isDerivedType()) return false;    // Boring boring types...
  if (TypeSet.count(T) != 0) return false;  // Already found this type...
  TypeSet.insert(T);                        // Add it to the set
  
  // Recursively process interesting types...
  switch (T->getPrimitiveID()) {
  case Type::MethodTyID: {
    const MethodType *MT = (const MethodType *)T;
    if (handleType(TypeSet, MT->getReturnType())) return true;
    const MethodType::ParamTypes &Params = MT->getParamTypes();

    for (MethodType::ParamTypes::const_iterator I = Params.begin();
	 I != Params.end(); ++I)
      if (handleType(TypeSet, *I)) return true;
    break;
  }

  case Type::ArrayTyID:
    if (handleType(TypeSet, ((const ArrayType *)T)->getElementType()))
      return true;
    break;

  case Type::StructTyID: {
    const StructType *ST = (const StructType*)T;
    const StructType::ElementTypes &Elements = ST->getElementTypes();
    for (StructType::ElementTypes::const_iterator I = Elements.begin();
	 I != Elements.end(); ++I)
      if (handleType(TypeSet, *I)) return true;
    break;
  }

  case Type::PointerTyID:
    if (handleType(TypeSet, ((const PointerType *)T)->getValueType()))
      return true;
    break;

  default:
    cerr << "ModuleAnalyzer::handleType, type unknown: '" 
	 << T->getName() << "'\n";
    break;
  }

  return processType(T);
}


bool ModuleAnalyzer::processConstPool(const ConstantPool &CP, bool isMethod) {
  // TypeSet - Keep track of which types have already been processType'ed.  We 
  // don't want to reprocess the same type more than once.
  //
  set<const Type *> TypeSet;

  for (ConstantPool::plane_const_iterator PI = CP.begin(); 
       PI != CP.end(); ++PI) {
    const ConstantPool::PlaneType &Plane = **PI;
    if (Plane.empty()) continue;        // Skip empty type planes...

    if (processConstPoolPlane(CP, Plane, isMethod)) return true;

    for (ConstantPool::PlaneType::const_iterator CI = Plane.begin(); 
	 CI != Plane.end(); CI++) {
      if ((*CI)->getType() == Type::TypeTy)
	if (handleType(TypeSet, ((const ConstPoolType*)(*CI))->getValue())) 
	  return true;
      if (handleType(TypeSet, (*CI)->getType())) return true;

      if (processConstant(*CI)) return true;
    }
  }
  
  if (!isMethod) {
    assert(CP.getParent()->getValueType() == Value::ModuleVal);
    const Module *M = (const Module*)CP.getParent();
    // Process the method types after the constant pool...
    for (Module::MethodListType::const_iterator I = M->getMethodList().begin();
	 I != M->getMethodList().end(); I++) {
      if (handleType(TypeSet, (*I)->getType())) return true;
      if (visitMethod(*I)) return true;
    }
  }
  return false;
}

bool ModuleAnalyzer::processMethods(const Module *M) {
  for (Module::MethodListType::const_iterator I = M->getMethodList().begin();
       I != M->getMethodList().end(); I++)
    if (processMethod(*I)) return true;

  return false;
}

bool ModuleAnalyzer::processMethod(const Method *M) {
  // Loop over the arguments, processing them...
  const Method::ArgumentListType &ArgList = M->getArgumentList();
  for (Method::ArgumentListType::const_iterator AI = ArgList.begin(); 
       AI != ArgList.end(); AI++)
    if (processMethodArgument(*AI)) return true;

  // Loop over the constant pool, adding the constants to the table...
  processConstPool(M->getConstantPool(), true);
  
  // Loop over all the basic blocks, in order...
  Method::BasicBlocksType::const_iterator BBI = M->getBasicBlocks().begin();
  for (; BBI != M->getBasicBlocks().end(); BBI++) 
    if (processBasicBlock(*BBI)) return true;
  return false;
}

bool ModuleAnalyzer::processBasicBlock(const BasicBlock *BB) {
  // Process all of the instructions in the basic block
  BasicBlock::InstListType::const_iterator Inst = BB->getInstList().begin();
  for (; Inst != BB->getInstList().end(); Inst++) {
    if (preProcessInstruction(*Inst) || processInstruction(*Inst)) return true;
  }
  return false;
}

bool ModuleAnalyzer::preProcessInstruction(const Instruction *I) {
  
  return false;
}