blob: 4917eca96724914037ad7eade992515c8d985e3b [file] [log] [blame]
Vikram S. Advea200a6c2001-10-14 23:18:45 +00001// $Id$
2//***************************************************************************
3// File:
4// TraceValues.cpp
5//
6// Purpose:
7// Support for inserting LLVM code to print values at basic block
8// and method exits. Also exports functions to create a call
9// "printf" instruction with one of the signatures listed below.
10//
11// History:
12// 10/11/01 - Vikram Adve - Created
13//**************************************************************************/
14
15
16#include "llvm/Transforms/Instrumentation/TraceValues.h"
17#include "llvm/GlobalVariable.h"
18#include "llvm/ConstPoolVals.h"
19#include "llvm/Type.h"
20#include "llvm/DerivedTypes.h"
21#include "llvm/Instruction.h"
22#include "llvm/iTerminators.h"
23#include "llvm/iOther.h"
24#include "llvm/BasicBlock.h"
25#include "llvm/Method.h"
26#include "llvm/Module.h"
27#include "llvm/SymbolTable.h"
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000028#include <strstream>
29#include "llvm/Assembly/Writer.h"
Vikram S. Advea200a6c2001-10-14 23:18:45 +000030
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000031static inline GlobalVariable *
32GetStringRef(Module *M, const string &str)
Vikram S. Advea200a6c2001-10-14 23:18:45 +000033{
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000034 ConstPoolArray *Init = ConstPoolArray::get(str);
35 GlobalVariable *V = new GlobalVariable(Init->getType(), /*Const*/true, Init);
36 M->getGlobalList().push_back(V);
Vikram S. Advea200a6c2001-10-14 23:18:45 +000037
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000038 return V;
Vikram S. Advea200a6c2001-10-14 23:18:45 +000039}
40
Chris Lattner1afbdc02001-10-15 13:07:21 +000041static inline bool
Vikram S. Advea200a6c2001-10-14 23:18:45 +000042TraceThisOpCode(unsigned opCode)
43{
44 // Explicitly test for opCodes *not* to trace so that any new opcodes will
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000045 // be traced by default (VoidTy's are already excluded)
Vikram S. Advea200a6c2001-10-14 23:18:45 +000046 //
47 return (opCode < Instruction::FirstOtherOp &&
Vikram S. Advea200a6c2001-10-14 23:18:45 +000048 opCode != Instruction::Alloca &&
Vikram S. Advea200a6c2001-10-14 23:18:45 +000049 opCode != Instruction::PHINode &&
50 opCode != Instruction::Cast);
51}
52
53
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000054static void
55FindValuesToTraceInBB(BasicBlock* bb, vector<Value*>& valuesToTraceInBB)
Vikram S. Advea200a6c2001-10-14 23:18:45 +000056{
57 for (BasicBlock::iterator II = bb->begin(); II != bb->end(); ++II)
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000058 if ((*II)->getType()->isPrimitiveType() &&
59 (*II)->getType() != Type::VoidTy &&
Vikram S. Advea200a6c2001-10-14 23:18:45 +000060 TraceThisOpCode((*II)->getOpcode()))
61 {
62 valuesToTraceInBB.push_back(*II);
63 }
64}
65
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000066// The invocation should be:
Chris Lattner5309e102001-10-18 06:03:05 +000067// call "printVal"(value).
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000068//
Chris Lattner5309e102001-10-18 06:03:05 +000069static Value *GetPrintMethodForType(Module *Mod, const Type *VTy) {
70 MethodType *MTy = MethodType::get(Type::VoidTy, vector<const Type*>(1, VTy),
71 /*isVarArg*/ false);
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000072
73 SymbolTable *ST = Mod->getSymbolTableSure();
Chris Lattner5309e102001-10-18 06:03:05 +000074 if (Value *V = ST->lookup(PointerType::get(MTy), "printVal"))
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000075 return V;
76
77 // Create a new method and add it to the module
Chris Lattner5309e102001-10-18 06:03:05 +000078 Method *M = new Method(MTy, "printVal");
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000079 Mod->getMethodList().push_back(M);
80 return M;
81}
82
83
Chris Lattner5309e102001-10-18 06:03:05 +000084static void InsertPrintInsts(Value *Val,
85 BasicBlock::iterator &BBI,
86 Module *Mod,
87 unsigned int indent,
88 bool isMethodExit) {
89 const Type* ValTy = Val->getType();
90 BasicBlock *BB = (*BBI)->getParent();
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000091
Chris Lattner5309e102001-10-18 06:03:05 +000092 assert(ValTy->isPrimitiveType() &&
93 ValTy->getPrimitiveID() != Type::VoidTyID &&
94 ValTy->getPrimitiveID() != Type::TypeTyID &&
95 ValTy->getPrimitiveID() != Type::LabelTyID &&
Chris Lattnera0a8b5b2001-10-18 05:28:08 +000096 "Unsupported type for printing");
97
Chris Lattner5309e102001-10-18 06:03:05 +000098 const Value* scopeToUse =
99 isMethodExit ? (const Value*)BB->getParent() : (const Value*)BB;
100
101 // Create the marker string...
102 strstream scopeNameString;
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000103 WriteAsOperand(scopeNameString, scopeToUse) << " : ";
Chris Lattner5309e102001-10-18 06:03:05 +0000104 WriteAsOperand(scopeNameString, Val) << " = " << ends;
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000105 string fmtString(indent, ' ');
106
Chris Lattner5309e102001-10-18 06:03:05 +0000107 fmtString += string(" At exit of") + scopeNameString.str();
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000108
Chris Lattner5309e102001-10-18 06:03:05 +0000109 // Turn the marker string into a global variable...
110 GlobalVariable *fmtVal = GetStringRef(Mod, fmtString);
111
112 // Insert the first print instruction to print the string flag:
113 Instruction *I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()),
114 vector<Value*>(1, fmtVal));
115 BBI = BB->getInstList().insert(BBI, I)+1;
116
117 // Insert the next print instruction to print the value:
118 I = new CallInst(GetPrintMethodForType(Mod, ValTy),
119 vector<Value*>(1, Val));
120 BBI = BB->getInstList().insert(BBI, I)+1;
121
122 // Print out a newline
123 fmtVal = GetStringRef(Mod, "\n");
124 I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()),
125 vector<Value*>(1, fmtVal));
126 BBI = BB->getInstList().insert(BBI, I)+1;
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000127}
128
129
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000130
131//
132// Insert print instructions at the end of the basic block *bb
133// for each value in valueVec[]. *bb must postdominate the block
134// in which the value is computed; this is not checked here.
135//
136static void
137TraceValuesAtBBExit(const vector<Value*>& valueVec,
138 BasicBlock* bb,
139 Module* module,
140 unsigned int indent,
141 bool isMethodExit)
142{
143 // Get an iterator to point to the insertion location
144 //
145 BasicBlock::InstListType& instList = bb->getInstList();
146 TerminatorInst* termInst = bb->getTerminator();
Chris Lattner5309e102001-10-18 06:03:05 +0000147 BasicBlock::iterator here = instList.end()-1;
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000148 assert((*here)->isTerminator());
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000149
150 // Insert a print instruction for each value.
151 //
152 for (unsigned i=0, N=valueVec.size(); i < N; i++)
Chris Lattner5309e102001-10-18 06:03:05 +0000153 InsertPrintInsts(valueVec[i], here, module, indent, isMethodExit);
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000154}
155
Chris Lattner1afbdc02001-10-15 13:07:21 +0000156static void
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000157InsertCodeToShowMethodEntry(BasicBlock* entryBB)
158{
159}
160
Chris Lattner1afbdc02001-10-15 13:07:21 +0000161static void
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000162InsertCodeToShowMethodExit(BasicBlock* exitBB)
163{
164}
165
166
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000167bool InsertTraceCode::doInsertTraceCode(Method *M, bool traceBasicBlockExits,
168 bool traceMethodExits) {
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000169 vector<Value*> valuesToTraceInMethod;
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000170 Module* module = M->getParent();
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000171 BasicBlock* exitBB = NULL;
172
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000173 if (M->isExternal() ||
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000174 (! traceBasicBlockExits && ! traceMethodExits))
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000175 return false;
176
177 if (traceMethodExits) {
178 InsertCodeToShowMethodEntry(M->getEntryNode());
179 exitBB = M->getBasicBlocks().front(); //getExitNode();
180 }
181
182 for (Method::iterator BI = M->begin(); BI != M->end(); ++BI) {
183 BasicBlock* bb = *BI;
184
185 vector<Value*> valuesToTraceInBB;
186 FindValuesToTraceInBB(bb, valuesToTraceInBB);
187
188 if (traceBasicBlockExits && bb != exitBB)
189 TraceValuesAtBBExit(valuesToTraceInBB, bb, module,
190 /*indent*/ 4, /*isMethodExit*/ false);
191
192 if (traceMethodExits) {
193 valuesToTraceInMethod.insert(valuesToTraceInMethod.end(),
194 valuesToTraceInBB.begin(),
195 valuesToTraceInBB.end());
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000196 }
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000197 }
Chris Lattner5309e102001-10-18 06:03:05 +0000198
199#if 0
200 // Disable this code until we have a proper exit node.
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000201 if (traceMethodExits) {
202 TraceValuesAtBBExit(valuesToTraceInMethod, exitBB, module,
203 /*indent*/ 0, /*isMethodExit*/ true);
204 InsertCodeToShowMethodExit(exitBB);
205 }
Chris Lattner5309e102001-10-18 06:03:05 +0000206#endif
Chris Lattnera0a8b5b2001-10-18 05:28:08 +0000207 return true;
Vikram S. Advea200a6c2001-10-14 23:18:45 +0000208}