7b624ad007c593a22906c335038c7a13e42c0f14
[oota-llvm.git] / lib / Transforms / Instrumentation / EmitFunctions.cpp
1 //===-- EmitFunctions.cpp - interface to insert instrumentation -----------===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This inserts a global constant table with function pointers all along.
11 //
12 // NOTE: This pass is used by the reoptimizer only.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/Constants.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Module.h"
19 #include "llvm/Pass.h"
20 #include "llvm/Support/CFG.h"
21 using namespace llvm;
22
23 namespace llvm { 
24
25 namespace {
26   enum Color{
27     WHITE,
28     GREY,
29     BLACK
30   };
31   
32   struct EmitFunctionTable : public ModulePass {
33     bool runOnModule(Module &M);
34   };
35   
36   RegisterOpt<EmitFunctionTable>
37   X("emitfuncs", "Emit a function table for the reoptimizer");
38 }
39
40 static char doDFS(BasicBlock * node,std::map<BasicBlock *, Color > &color){
41   color[node] = GREY;
42
43   for(succ_iterator vl = succ_begin(node), ve = succ_end(node); vl != ve; ++vl){
44    
45     BasicBlock *BB = *vl; 
46     
47     if(color[BB]!=GREY && color[BB]!=BLACK){
48       if(!doDFS(BB, color)){
49         return 0;
50       }
51     }
52
53     //if has backedge
54     else if(color[BB]==GREY)
55       return 0;
56
57   }
58
59   color[node] = BLACK;
60   return 1;
61 }
62
63 static char hasBackEdge(Function *F){
64   std::map<BasicBlock *, Color > color;
65   return doDFS(F->begin(), color);
66 }
67
68 // Per Module pass for inserting function table
69 bool EmitFunctionTable::runOnModule(Module &M){
70   std::vector<const Type*> vType;
71  
72   std::vector<Constant *> vConsts;
73   std::vector<Constant *> sBCons;
74
75   unsigned int counter = 0;
76   for(Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
77     if (!MI->isExternal()) {
78       vType.push_back(MI->getType());
79     
80       //std::cerr<<MI;
81
82       vConsts.push_back(MI);
83       sBCons.push_back(ConstantInt::get(Type::SByteTy, hasBackEdge(MI)));
84       
85       counter++;
86     }
87   
88   StructType *sttype = StructType::get(vType);
89   Constant *cstruct = ConstantStruct::get(sttype, vConsts);
90
91   GlobalVariable *gb = new GlobalVariable(cstruct->getType(), true,
92                                           GlobalValue::ExternalLinkage, 
93                                           cstruct, "llvmFunctionTable");
94   M.getGlobalList().push_back(gb);
95
96   Constant *constArray = ConstantArray::get(ArrayType::get(Type::SByteTy, 
97                                                                 sBCons.size()),
98                                                  sBCons);
99
100   GlobalVariable *funcArray = new GlobalVariable(constArray->getType(), true,
101                                               GlobalValue::ExternalLinkage,
102                                               constArray, "llvmSimpleFunction");
103
104   M.getGlobalList().push_back(funcArray);
105
106   ConstantInt *cnst = ConstantSInt::get(Type::IntTy, counter); 
107   GlobalVariable *fnCount = new GlobalVariable(Type::IntTy, true, 
108                                                GlobalValue::ExternalLinkage, 
109                                                cnst, "llvmFunctionCount");
110   M.getGlobalList().push_back(fnCount);
111   return true;  // Always modifies program
112 }
113
114 ModulePass *createEmitFunctionTablePass () {
115   return new EmitFunctionTable();
116 }
117
118 } // end namespace llvm