blob: 3547b298c16e1062996e63f7af6b706962d131a5 [file] [log] [blame]
Vikram S. Advedf1892f2001-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"
Vikram S. Adve631b9a32001-10-18 18:16:11 +000022#include "llvm/iMemory.h"
Vikram S. Advedf1892f2001-10-14 23:18:45 +000023#include "llvm/iTerminators.h"
24#include "llvm/iOther.h"
25#include "llvm/BasicBlock.h"
26#include "llvm/Method.h"
27#include "llvm/Module.h"
28#include "llvm/SymbolTable.h"
Chris Lattner8d9e3772001-10-18 05:28:08 +000029#include "llvm/Assembly/Writer.h"
Vikram S. Adved8893302001-10-28 21:37:25 +000030#include "llvm/Support/HashExtras.h"
31#include <hash_set>
Chris Lattnerb81a0bf2001-10-18 20:06:03 +000032#include <sstream>
Vikram S. Advebedb00d2001-10-18 13:49:22 +000033
Vikram S. Adved8893302001-10-28 21:37:25 +000034
35static const char*
36PrintMethodNameForType(const Type* type)
37{
38 if (PointerType* pty = dyn_cast<PointerType>(type))
39 {
40 const Type* elemTy;
41 if (ArrayType* aty = dyn_cast<ArrayType>(pty->getValueType()))
42 elemTy = aty->getElementType();
43 else
44 elemTy = pty->getValueType();
45 if (elemTy == Type::SByteTy || elemTy == Type::UByteTy)
46 return "printString";
47 }
48
49 switch (type->getPrimitiveID())
50 {
51 case Type::BoolTyID: return "printBool";
52 case Type::UByteTyID: return "printUByte";
53 case Type::SByteTyID: return "printSByte";
54 case Type::UShortTyID: return "printUShort";
55 case Type::ShortTyID: return "printShort";
56 case Type::UIntTyID: return "printUInt";
57 case Type::IntTyID: return "printInt";
58 case Type::ULongTyID: return "printULong";
59 case Type::LongTyID: return "printLong";
60 case Type::FloatTyID: return "printFloat";
61 case Type::DoubleTyID: return "printDouble";
62 case Type::PointerTyID: return "printPointer";
Vikram S. Adved8893302001-10-28 21:37:25 +000063 default:
64 assert(0 && "Unsupported type for printing");
65 return NULL;
66 }
67}
68
Chris Lattnerb81a0bf2001-10-18 20:06:03 +000069static inline GlobalVariable *GetStringRef(Module *M, const string &str) {
70 ConstPoolArray *Init = ConstPoolArray::get(str);
71 GlobalVariable *GV = new GlobalVariable(Init->getType(), /*Const*/true, Init);
72 M->getGlobalList().push_back(GV);
73 return GV;
Vikram S. Advedf1892f2001-10-14 23:18:45 +000074}
75
Vikram S. Advebedb00d2001-10-18 13:49:22 +000076
Chris Lattnerf84b9bc2001-10-15 13:07:21 +000077static inline bool
Vikram S. Advedf1892f2001-10-14 23:18:45 +000078TraceThisOpCode(unsigned opCode)
79{
80 // Explicitly test for opCodes *not* to trace so that any new opcodes will
Chris Lattner8d9e3772001-10-18 05:28:08 +000081 // be traced by default (VoidTy's are already excluded)
Vikram S. Advedf1892f2001-10-14 23:18:45 +000082 //
83 return (opCode < Instruction::FirstOtherOp &&
Vikram S. Advedf1892f2001-10-14 23:18:45 +000084 opCode != Instruction::Alloca &&
Vikram S. Advedf1892f2001-10-14 23:18:45 +000085 opCode != Instruction::PHINode &&
86 opCode != Instruction::Cast);
87}
88
Vikram S. Adve631b9a32001-10-18 18:16:11 +000089//
Vikram S. Adved8893302001-10-28 21:37:25 +000090// Check if this instruction has any uses outside its basic block,
91// or if it used by either a Call or Return instruction.
Vikram S. Adve631b9a32001-10-18 18:16:11 +000092//
93static inline bool
94LiveAtBBExit(Instruction* I)
95{
96 BasicBlock* bb = I->getParent();
97 bool isLive = false;
98 for (Value::use_const_iterator U = I->use_begin(); U != I->use_end(); ++U)
99 {
100 const Instruction* userI = dyn_cast<Instruction>(*U);
Vikram S. Adved8893302001-10-28 21:37:25 +0000101 if (userI == NULL
102 || userI->getParent() != bb
103 || userI->getOpcode() == Instruction::Call
104 || userI->getOpcode() == Instruction::Ret)
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000105 isLive = true;
106 }
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000107 return isLive;
108}
109
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000110
Chris Lattner8d9e3772001-10-18 05:28:08 +0000111static void
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000112FindValuesToTraceInBB(BasicBlock* bb, vector<Instruction*>& valuesToTraceInBB)
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000113{
114 for (BasicBlock::iterator II = bb->begin(); II != bb->end(); ++II)
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000115 if ((*II)->getOpcode() == Instruction::Store
116 || (LiveAtBBExit(*II) &&
117 (*II)->getType()->isPrimitiveType() &&
118 (*II)->getType() != Type::VoidTy &&
119 TraceThisOpCode((*II)->getOpcode())))
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000120 {
121 valuesToTraceInBB.push_back(*II);
122 }
123}
124
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000125//
126// Let's save this code for future use; it has been tested and works:
127//
128// The signatures of the printf methods supported are:
129// int printf(ubyte*, ubyte*, ubyte*, ubyte*, int intValue)
130// int printf(ubyte*, ubyte*, ubyte*, ubyte*, unsigned uintValue)
131// int printf(ubyte*, ubyte*, ubyte*, ubyte*, float floatValue)
132// int printf(ubyte*, ubyte*, ubyte*, ubyte*, double doubleValue)
133// int printf(ubyte*, ubyte*, ubyte*, ubyte*, char* stringValue)
134// int printf(ubyte*, ubyte*, ubyte*, ubyte*, void* ptrValue)
135//
136// The invocation should be:
137// call "printf"(fmt, bbName, valueName, valueTypeName, value).
138//
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000139Value *GetPrintfMethodForType(Module* module, const Type* valueType)
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000140{
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000141 PointerType *ubytePtrTy = PointerType::get(ArrayType::get(Type::UByteTy));
142 vector<const Type*> argTypesVec(4, ubytePtrTy);
143 argTypesVec.push_back(valueType);
144
145 MethodType *printMethodTy = MethodType::get(Type::IntTy, argTypesVec,
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000146 /*isVarArg*/ false);
147
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000148 SymbolTable *ST = module->getSymbolTable();
149 if (Value *Meth = ST->lookup(PointerType::get(printMethodTy), "printf"))
150 return Meth;
151
152 // Create a new method and add it to the module
153 Method *printMethod = new Method(printMethodTy, "printf");
154 module->getMethodList().push_back(printMethod);
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000155
156 return printMethod;
157}
158
159
160Instruction*
161CreatePrintfInstr(Value* val,
162 const BasicBlock* bb,
163 Module* module,
164 unsigned int indent,
165 bool isMethodExit)
166{
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000167 ostringstream fmtString, scopeNameString, valNameString;
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000168 vector<Value*> paramList;
169 const Type* valueType = val->getType();
Vikram S. Adved8893302001-10-28 21:37:25 +0000170 Method* printMethod = cast<Method>(GetPrintfMethodForType(module,valueType));
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000171
172 if (! valueType->isPrimitiveType() ||
173 valueType->getPrimitiveID() == Type::VoidTyID ||
174 valueType->getPrimitiveID() == Type::TypeTyID ||
175 valueType->getPrimitiveID() == Type::LabelTyID)
176 {
177 assert(0 && "Unsupported type for printing");
178 return NULL;
179 }
180
181 const Value* scopeToUse = (isMethodExit)? (const Value*) bb->getParent()
182 : (const Value*) bb;
183 if (scopeToUse->hasName())
184 scopeNameString << scopeToUse->getName() << ends;
185 else
186 scopeNameString << scopeToUse << ends;
187
188 if (val->hasName())
189 valNameString << val->getName() << ends;
190 else
191 valNameString << val << ends;
192
193 for (unsigned i=0; i < indent; i++)
194 fmtString << " ";
195
196 fmtString << " At exit of "
197 << ((isMethodExit)? "Method " : "BB ")
198 << "%s : val %s = %s ";
199
200 GlobalVariable* scopeNameVal = GetStringRef(module, scopeNameString.str());
201 GlobalVariable* valNameVal = GetStringRef(module,valNameString.str());
202 GlobalVariable* typeNameVal = GetStringRef(module,
203 val->getType()->getDescription().c_str());
204
205 switch(valueType->getPrimitiveID())
206 {
207 case Type::BoolTyID:
208 case Type::UByteTyID: case Type::UShortTyID:
209 case Type::UIntTyID: case Type::ULongTyID:
210 case Type::SByteTyID: case Type::ShortTyID:
211 case Type::IntTyID: case Type::LongTyID:
Vikram S. Advec426c632001-10-28 22:44:02 +0000212 fmtString << " %d\n";
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000213 break;
214
215 case Type::FloatTyID: case Type::DoubleTyID:
Vikram S. Advec426c632001-10-28 22:44:02 +0000216 fmtString << " %g\n";
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000217 break;
218
219 case Type::PointerTyID:
Vikram S. Advec426c632001-10-28 22:44:02 +0000220 fmtString << " %p\n";
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000221 break;
222
223 default:
224 assert(0 && "Should not get here. Check the IF expression above");
225 return NULL;
226 }
227
228 fmtString << ends;
229 GlobalVariable* fmtVal = GetStringRef(module, fmtString.str());
230
231 paramList.push_back(fmtVal);
232 paramList.push_back(scopeNameVal);
233 paramList.push_back(valNameVal);
234 paramList.push_back(typeNameVal);
235 paramList.push_back(val);
236
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000237 return new CallInst(printMethod, paramList);
238}
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000239
240
Chris Lattner8d9e3772001-10-18 05:28:08 +0000241// The invocation should be:
Vikram S. Adved8893302001-10-28 21:37:25 +0000242// call "printString"([ubyte*] or [sbyte*] or ubyte* or sbyte*).
243// call "printLong"(long)
244// call "printInt"(int) ...
Chris Lattner8d9e3772001-10-18 05:28:08 +0000245//
Chris Lattner44571632001-10-18 06:03:05 +0000246static Value *GetPrintMethodForType(Module *Mod, const Type *VTy) {
247 MethodType *MTy = MethodType::get(Type::VoidTy, vector<const Type*>(1, VTy),
248 /*isVarArg*/ false);
Chris Lattner8d9e3772001-10-18 05:28:08 +0000249
Vikram S. Adved8893302001-10-28 21:37:25 +0000250 const char* printMethodName = PrintMethodNameForType(VTy);
Chris Lattner8d9e3772001-10-18 05:28:08 +0000251 SymbolTable *ST = Mod->getSymbolTableSure();
Vikram S. Adved8893302001-10-28 21:37:25 +0000252 if (Value *V = ST->lookup(PointerType::get(MTy), printMethodName))
Chris Lattner8d9e3772001-10-18 05:28:08 +0000253 return V;
254
255 // Create a new method and add it to the module
Vikram S. Adved8893302001-10-28 21:37:25 +0000256 Method *M = new Method(MTy, printMethodName);
Chris Lattner8d9e3772001-10-18 05:28:08 +0000257 Mod->getMethodList().push_back(M);
258 return M;
259}
260
261
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000262static void
263InsertPrintInsts(Value *Val,
264 BasicBlock* BB,
265 BasicBlock::iterator &BBI,
266 Module *Mod,
267 unsigned int indent,
268 bool isMethodExit)
269{
Chris Lattner44571632001-10-18 06:03:05 +0000270 const Type* ValTy = Val->getType();
Chris Lattner8d9e3772001-10-18 05:28:08 +0000271
Chris Lattner111bd012001-10-29 17:27:38 +0000272 assert((ValTy->isPrimitiveType() || isa<PointerType>(ValTy)) &&
273 ValTy != Type::VoidTy && ValTy != Type::TypeTy &&
274 ValTy != Type::LabelTy && "Unsupported type for printing");
Chris Lattner8d9e3772001-10-18 05:28:08 +0000275
Chris Lattner44571632001-10-18 06:03:05 +0000276 const Value* scopeToUse =
277 isMethodExit ? (const Value*)BB->getParent() : (const Value*)BB;
278
279 // Create the marker string...
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000280 ostringstream scopeNameString;
Chris Lattner8d9e3772001-10-18 05:28:08 +0000281 WriteAsOperand(scopeNameString, scopeToUse) << " : ";
Vikram S. Adved8893302001-10-28 21:37:25 +0000282 WriteAsOperand(scopeNameString, Val) << " = ";
Chris Lattner8d9e3772001-10-18 05:28:08 +0000283
Vikram S. Adved8893302001-10-28 21:37:25 +0000284 string fmtString(indent, ' ');
Chris Lattner44571632001-10-18 06:03:05 +0000285 fmtString += string(" At exit of") + scopeNameString.str();
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000286
Chris Lattner44571632001-10-18 06:03:05 +0000287 // Turn the marker string into a global variable...
288 GlobalVariable *fmtVal = GetStringRef(Mod, fmtString);
289
290 // Insert the first print instruction to print the string flag:
291 Instruction *I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()),
292 vector<Value*>(1, fmtVal));
293 BBI = BB->getInstList().insert(BBI, I)+1;
294
295 // Insert the next print instruction to print the value:
296 I = new CallInst(GetPrintMethodForType(Mod, ValTy),
297 vector<Value*>(1, Val));
298 BBI = BB->getInstList().insert(BBI, I)+1;
299
300 // Print out a newline
Vikram S. Advec426c632001-10-28 22:44:02 +0000301 fmtVal = GetStringRef(Mod, "\n");
Chris Lattner44571632001-10-18 06:03:05 +0000302 I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()),
303 vector<Value*>(1, fmtVal));
304 BBI = BB->getInstList().insert(BBI, I)+1;
Chris Lattner8d9e3772001-10-18 05:28:08 +0000305}
306
307
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000308static LoadInst*
309InsertLoadInst(StoreInst* storeInst,
310 BasicBlock *bb,
311 BasicBlock::iterator &BBI)
312{
313 LoadInst* loadInst = new LoadInst(storeInst->getPtrOperand(),
314 storeInst->getIndexVec());
315 BBI = bb->getInstList().insert(BBI, loadInst) + 1;
316 return loadInst;
317}
318
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000319
320//
321// Insert print instructions at the end of the basic block *bb
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000322// for each value in valueVec[] that is live at the end of that basic block,
323// or that is stored to memory in this basic block.
324// If the value is stored to memory, we load it back before printing
325// We also return all such loaded values in the vector valuesStoredInMethod
326// for printing at the exit from the method. (Note that in each invocation
327// of the method, this will only get the last value stored for each static
328// store instruction).
329// *bb must be the block in which the value is computed;
330// this is not checked here.
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000331//
332static void
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000333TraceValuesAtBBExit(const vector<Instruction*>& valueVec,
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000334 BasicBlock* bb,
335 Module* module,
336 unsigned int indent,
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000337 bool isMethodExit,
338 vector<Instruction*>* valuesStoredInMethod)
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000339{
Vikram S. Adved8893302001-10-28 21:37:25 +0000340 // Get an iterator to point to the insertion location, which is
341 // just before the terminator instruction.
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000342 //
343 BasicBlock::InstListType& instList = bb->getInstList();
Chris Lattner44571632001-10-18 06:03:05 +0000344 BasicBlock::iterator here = instList.end()-1;
Chris Lattner8d9e3772001-10-18 05:28:08 +0000345 assert((*here)->isTerminator());
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000346
Vikram S. Adved8893302001-10-28 21:37:25 +0000347 // If the terminator is a conditional branch, insert the trace code just
348 // before the instruction that computes the branch condition (just to
349 // avoid putting a call between the CC-setting instruction and the branch).
350 // Use laterInstrSet to mark instructions that come after the setCC instr
351 // because those cannot be traced at the location we choose.
352 //
353 hash_set<Instruction*> laterInstrSet;
354 if (BranchInst* brInst = dyn_cast<BranchInst>(*here))
355 if (! brInst->isUnconditional())
356 if (Instruction* setCC = dyn_cast<Instruction>(brInst->getCondition()))
357 if (setCC->getParent() == bb)
358 {
359 while ((*here) != setCC && here != instList.begin())
360 {
361 --here;
362 laterInstrSet.insert(*here);
363 }
364 assert((*here) == setCC && "Missed the setCC instruction?");
365 laterInstrSet.insert(*here);
366 }
367
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000368 // Insert a print instruction for each value.
369 //
370 for (unsigned i=0, N=valueVec.size(); i < N; i++)
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000371 {
372 Instruction* I = valueVec[i];
373 if (I->getOpcode() == Instruction::Store)
374 {
375 assert(valuesStoredInMethod != NULL &&
376 "Should not be printing a store instruction at method exit");
377 I = InsertLoadInst((StoreInst*) I, bb, here);
378 valuesStoredInMethod->push_back(I);
379 }
Vikram S. Adved8893302001-10-28 21:37:25 +0000380 if (laterInstrSet.find(I) == laterInstrSet.end())
381 InsertPrintInsts(I, bb, here, module, indent, isMethodExit);
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000382 }
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000383}
384
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000385
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000386
387static Instruction*
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000388CreateMethodTraceInst(Method* method,
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000389 unsigned int indent,
390 const string& msg)
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000391{
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000392 string fmtString(indent, ' ');
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000393 ostringstream methodNameString;
Vikram S. Adved8893302001-10-28 21:37:25 +0000394 WriteAsOperand(methodNameString, method);
Vikram S. Advec426c632001-10-28 22:44:02 +0000395 fmtString += msg + methodNameString.str() + '\n';
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000396
397 GlobalVariable *fmtVal = GetStringRef(method->getParent(), fmtString);
398 Instruction *printInst =
399 new CallInst(GetPrintMethodForType(method->getParent(), fmtVal->getType()),
400 vector<Value*>(1, fmtVal));
401
402 return printInst;
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000403}
404
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000405
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000406static inline void
407InsertCodeToShowMethodEntry(Method* method,
408 BasicBlock* entryBB,
409 unsigned int indent)
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000410{
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000411 // Get an iterator to point to the insertion location
412 BasicBlock::InstListType& instList = entryBB->getInstList();
413 BasicBlock::iterator here = instList.begin();
414
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000415 Instruction *printInst = CreateMethodTraceInst(method, indent,
416 "Entering Method");
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000417
418 here = entryBB->getInstList().insert(here, printInst) + 1;
419}
420
421
422static inline void
423InsertCodeToShowMethodExit(Method* method,
424 BasicBlock* exitBB,
425 unsigned int indent)
426{
427 // Get an iterator to point to the insertion location
428 BasicBlock::InstListType& instList = exitBB->getInstList();
429 BasicBlock::iterator here = instList.end()-1;
430 assert((*here)->isTerminator());
431
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000432 Instruction *printInst = CreateMethodTraceInst(method, indent,
433 "Leaving Method");
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000434
Chris Lattnerb81a0bf2001-10-18 20:06:03 +0000435 exitBB->getInstList().insert(here, printInst) + 1;
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000436}
437
438
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000439//************************** External Functions ****************************/
440
441
442bool
443InsertTraceCode::doInsertTraceCode(Method *M,
444 bool traceBasicBlockExits,
445 bool traceMethodExits)
446{
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000447 vector<Instruction*> valuesStoredInMethod;
Chris Lattner8d9e3772001-10-18 05:28:08 +0000448 Module* module = M->getParent();
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000449 vector<BasicBlock*> exitBlocks;
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000450
Chris Lattner8d9e3772001-10-18 05:28:08 +0000451 if (M->isExternal() ||
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000452 (! traceBasicBlockExits && ! traceMethodExits))
Chris Lattner8d9e3772001-10-18 05:28:08 +0000453 return false;
Vikram S. Adved8893302001-10-28 21:37:25 +0000454
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000455 if (traceMethodExits)
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000456 InsertCodeToShowMethodEntry(M, M->getEntryNode(), /*indent*/ 0);
457
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000458 for (Method::iterator BI = M->begin(); BI != M->end(); ++BI)
459 {
460 BasicBlock* bb = *BI;
461 bool isExitBlock = false;
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000462 vector<Instruction*> valuesToTraceInBB;
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000463
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000464 FindValuesToTraceInBB(bb, valuesToTraceInBB);
465
466 if (bb->succ_begin() == bb->succ_end())
467 { // record this as an exit block
468 exitBlocks.push_back(bb);
469 isExitBlock = true;
470 }
471
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000472 if (traceBasicBlockExits)
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000473 TraceValuesAtBBExit(valuesToTraceInBB, bb, module,
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000474 /*indent*/ 4, /*isMethodExit*/ false,
475 &valuesStoredInMethod);
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000476 }
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000477
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000478 if (traceMethodExits)
479 for (unsigned i=0; i < exitBlocks.size(); ++i)
480 {
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000481 TraceValuesAtBBExit(valuesStoredInMethod, exitBlocks[i], module,
482 /*indent*/ 0, /*isMethodExit*/ true,
483 /*valuesStoredInMethod*/ NULL);
484 InsertCodeToShowMethodExit(M, exitBlocks[i], /*indent*/ 0);
Vikram S. Advebedb00d2001-10-18 13:49:22 +0000485 }
Vikram S. Adve631b9a32001-10-18 18:16:11 +0000486
Chris Lattner8d9e3772001-10-18 05:28:08 +0000487 return true;
Vikram S. Advedf1892f2001-10-14 23:18:45 +0000488}