Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 1 | // $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. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 22 | #include "llvm/iMemory.h" |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 23 | #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 Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 29 | #include "llvm/Assembly/Writer.h" |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 30 | #include <sstream> |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 31 | |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 32 | static inline GlobalVariable *GetStringRef(Module *M, const string &str) { |
| 33 | ConstPoolArray *Init = ConstPoolArray::get(str); |
| 34 | GlobalVariable *GV = new GlobalVariable(Init->getType(), /*Const*/true, Init); |
| 35 | M->getGlobalList().push_back(GV); |
| 36 | return GV; |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 37 | } |
| 38 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 39 | |
Chris Lattner | 1afbdc0 | 2001-10-15 13:07:21 +0000 | [diff] [blame] | 40 | static inline bool |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 41 | TraceThisOpCode(unsigned opCode) |
| 42 | { |
| 43 | // Explicitly test for opCodes *not* to trace so that any new opcodes will |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 44 | // be traced by default (VoidTy's are already excluded) |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 45 | // |
| 46 | return (opCode < Instruction::FirstOtherOp && |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 47 | opCode != Instruction::Alloca && |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 48 | opCode != Instruction::PHINode && |
| 49 | opCode != Instruction::Cast); |
| 50 | } |
| 51 | |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 52 | // |
| 53 | // Check if this instruction has any uses outside its basic block |
| 54 | // |
| 55 | static inline bool |
| 56 | LiveAtBBExit(Instruction* I) |
| 57 | { |
| 58 | BasicBlock* bb = I->getParent(); |
| 59 | bool isLive = false; |
| 60 | for (Value::use_const_iterator U = I->use_begin(); U != I->use_end(); ++U) |
| 61 | { |
| 62 | const Instruction* userI = dyn_cast<Instruction>(*U); |
| 63 | if (userI == NULL || userI->getParent() != bb) |
| 64 | isLive = true; |
| 65 | } |
| 66 | |
| 67 | return isLive; |
| 68 | } |
| 69 | |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 70 | |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 71 | static void |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 72 | FindValuesToTraceInBB(BasicBlock* bb, vector<Instruction*>& valuesToTraceInBB) |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 73 | { |
| 74 | for (BasicBlock::iterator II = bb->begin(); II != bb->end(); ++II) |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 75 | if ((*II)->getOpcode() == Instruction::Store |
| 76 | || (LiveAtBBExit(*II) && |
| 77 | (*II)->getType()->isPrimitiveType() && |
| 78 | (*II)->getType() != Type::VoidTy && |
| 79 | TraceThisOpCode((*II)->getOpcode()))) |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 80 | { |
| 81 | valuesToTraceInBB.push_back(*II); |
| 82 | } |
| 83 | } |
| 84 | |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 85 | #if 0 // Code is disabled for now |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 86 | // |
| 87 | // Let's save this code for future use; it has been tested and works: |
| 88 | // |
| 89 | // The signatures of the printf methods supported are: |
| 90 | // int printf(ubyte*, ubyte*, ubyte*, ubyte*, int intValue) |
| 91 | // int printf(ubyte*, ubyte*, ubyte*, ubyte*, unsigned uintValue) |
| 92 | // int printf(ubyte*, ubyte*, ubyte*, ubyte*, float floatValue) |
| 93 | // int printf(ubyte*, ubyte*, ubyte*, ubyte*, double doubleValue) |
| 94 | // int printf(ubyte*, ubyte*, ubyte*, ubyte*, char* stringValue) |
| 95 | // int printf(ubyte*, ubyte*, ubyte*, ubyte*, void* ptrValue) |
| 96 | // |
| 97 | // The invocation should be: |
| 98 | // call "printf"(fmt, bbName, valueName, valueTypeName, value). |
| 99 | // |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 100 | Value *GetPrintfMethodForType(Module* module, const Type* valueType) |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 101 | { |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 102 | PointerType *ubytePtrTy = PointerType::get(ArrayType::get(Type::UByteTy)); |
| 103 | vector<const Type*> argTypesVec(4, ubytePtrTy); |
| 104 | argTypesVec.push_back(valueType); |
| 105 | |
| 106 | MethodType *printMethodTy = MethodType::get(Type::IntTy, argTypesVec, |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 107 | /*isVarArg*/ false); |
| 108 | |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 109 | SymbolTable *ST = module->getSymbolTable(); |
| 110 | if (Value *Meth = ST->lookup(PointerType::get(printMethodTy), "printf")) |
| 111 | return Meth; |
| 112 | |
| 113 | // Create a new method and add it to the module |
| 114 | Method *printMethod = new Method(printMethodTy, "printf"); |
| 115 | module->getMethodList().push_back(printMethod); |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 116 | |
| 117 | return printMethod; |
| 118 | } |
| 119 | |
| 120 | |
| 121 | Instruction* |
| 122 | CreatePrintfInstr(Value* val, |
| 123 | const BasicBlock* bb, |
| 124 | Module* module, |
| 125 | unsigned int indent, |
| 126 | bool isMethodExit) |
| 127 | { |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 128 | ostringstream fmtString, scopeNameString, valNameString; |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 129 | vector<Value*> paramList; |
| 130 | const Type* valueType = val->getType(); |
| 131 | Method* printMethod = GetPrintfMethodForType(module, valueType); |
| 132 | |
| 133 | if (! valueType->isPrimitiveType() || |
| 134 | valueType->getPrimitiveID() == Type::VoidTyID || |
| 135 | valueType->getPrimitiveID() == Type::TypeTyID || |
| 136 | valueType->getPrimitiveID() == Type::LabelTyID) |
| 137 | { |
| 138 | assert(0 && "Unsupported type for printing"); |
| 139 | return NULL; |
| 140 | } |
| 141 | |
| 142 | const Value* scopeToUse = (isMethodExit)? (const Value*) bb->getParent() |
| 143 | : (const Value*) bb; |
| 144 | if (scopeToUse->hasName()) |
| 145 | scopeNameString << scopeToUse->getName() << ends; |
| 146 | else |
| 147 | scopeNameString << scopeToUse << ends; |
| 148 | |
| 149 | if (val->hasName()) |
| 150 | valNameString << val->getName() << ends; |
| 151 | else |
| 152 | valNameString << val << ends; |
| 153 | |
| 154 | for (unsigned i=0; i < indent; i++) |
| 155 | fmtString << " "; |
| 156 | |
| 157 | fmtString << " At exit of " |
| 158 | << ((isMethodExit)? "Method " : "BB ") |
| 159 | << "%s : val %s = %s "; |
| 160 | |
| 161 | GlobalVariable* scopeNameVal = GetStringRef(module, scopeNameString.str()); |
| 162 | GlobalVariable* valNameVal = GetStringRef(module,valNameString.str()); |
| 163 | GlobalVariable* typeNameVal = GetStringRef(module, |
| 164 | val->getType()->getDescription().c_str()); |
| 165 | |
| 166 | switch(valueType->getPrimitiveID()) |
| 167 | { |
| 168 | case Type::BoolTyID: |
| 169 | case Type::UByteTyID: case Type::UShortTyID: |
| 170 | case Type::UIntTyID: case Type::ULongTyID: |
| 171 | case Type::SByteTyID: case Type::ShortTyID: |
| 172 | case Type::IntTyID: case Type::LongTyID: |
| 173 | fmtString << " %d\0A"; |
| 174 | break; |
| 175 | |
| 176 | case Type::FloatTyID: case Type::DoubleTyID: |
| 177 | fmtString << " %g\0A"; |
| 178 | break; |
| 179 | |
| 180 | case Type::PointerTyID: |
| 181 | fmtString << " %p\0A"; |
| 182 | break; |
| 183 | |
| 184 | default: |
| 185 | assert(0 && "Should not get here. Check the IF expression above"); |
| 186 | return NULL; |
| 187 | } |
| 188 | |
| 189 | fmtString << ends; |
| 190 | GlobalVariable* fmtVal = GetStringRef(module, fmtString.str()); |
| 191 | |
| 192 | paramList.push_back(fmtVal); |
| 193 | paramList.push_back(scopeNameVal); |
| 194 | paramList.push_back(valNameVal); |
| 195 | paramList.push_back(typeNameVal); |
| 196 | paramList.push_back(val); |
| 197 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 198 | return new CallInst(printMethod, paramList); |
| 199 | } |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 200 | #endif |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 201 | |
| 202 | |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 203 | // The invocation should be: |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 204 | // call "printVal"(value). |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 205 | // |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 206 | static Value *GetPrintMethodForType(Module *Mod, const Type *VTy) { |
| 207 | MethodType *MTy = MethodType::get(Type::VoidTy, vector<const Type*>(1, VTy), |
| 208 | /*isVarArg*/ false); |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 209 | |
| 210 | SymbolTable *ST = Mod->getSymbolTableSure(); |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 211 | if (Value *V = ST->lookup(PointerType::get(MTy), "printVal")) |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 212 | return V; |
| 213 | |
| 214 | // Create a new method and add it to the module |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 215 | Method *M = new Method(MTy, "printVal"); |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 216 | Mod->getMethodList().push_back(M); |
| 217 | return M; |
| 218 | } |
| 219 | |
| 220 | |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 221 | static void |
| 222 | InsertPrintInsts(Value *Val, |
| 223 | BasicBlock* BB, |
| 224 | BasicBlock::iterator &BBI, |
| 225 | Module *Mod, |
| 226 | unsigned int indent, |
| 227 | bool isMethodExit) |
| 228 | { |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 229 | const Type* ValTy = Val->getType(); |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 230 | |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 231 | assert(ValTy->isPrimitiveType() && |
| 232 | ValTy->getPrimitiveID() != Type::VoidTyID && |
| 233 | ValTy->getPrimitiveID() != Type::TypeTyID && |
| 234 | ValTy->getPrimitiveID() != Type::LabelTyID && |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 235 | "Unsupported type for printing"); |
| 236 | |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 237 | const Value* scopeToUse = |
| 238 | isMethodExit ? (const Value*)BB->getParent() : (const Value*)BB; |
| 239 | |
| 240 | // Create the marker string... |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 241 | ostringstream scopeNameString; |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 242 | WriteAsOperand(scopeNameString, scopeToUse) << " : "; |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 243 | WriteAsOperand(scopeNameString, Val) << " = " << ends; |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 244 | string fmtString(indent, ' '); |
| 245 | |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 246 | fmtString += string(" At exit of") + scopeNameString.str(); |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 247 | |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 248 | // Turn the marker string into a global variable... |
| 249 | GlobalVariable *fmtVal = GetStringRef(Mod, fmtString); |
| 250 | |
| 251 | // Insert the first print instruction to print the string flag: |
| 252 | Instruction *I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()), |
| 253 | vector<Value*>(1, fmtVal)); |
| 254 | BBI = BB->getInstList().insert(BBI, I)+1; |
| 255 | |
| 256 | // Insert the next print instruction to print the value: |
| 257 | I = new CallInst(GetPrintMethodForType(Mod, ValTy), |
| 258 | vector<Value*>(1, Val)); |
| 259 | BBI = BB->getInstList().insert(BBI, I)+1; |
| 260 | |
| 261 | // Print out a newline |
| 262 | fmtVal = GetStringRef(Mod, "\n"); |
| 263 | I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()), |
| 264 | vector<Value*>(1, fmtVal)); |
| 265 | BBI = BB->getInstList().insert(BBI, I)+1; |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 266 | } |
| 267 | |
| 268 | |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 269 | static LoadInst* |
| 270 | InsertLoadInst(StoreInst* storeInst, |
| 271 | BasicBlock *bb, |
| 272 | BasicBlock::iterator &BBI) |
| 273 | { |
| 274 | LoadInst* loadInst = new LoadInst(storeInst->getPtrOperand(), |
| 275 | storeInst->getIndexVec()); |
| 276 | BBI = bb->getInstList().insert(BBI, loadInst) + 1; |
| 277 | return loadInst; |
| 278 | } |
| 279 | |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 280 | |
| 281 | // |
| 282 | // Insert print instructions at the end of the basic block *bb |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 283 | // for each value in valueVec[] that is live at the end of that basic block, |
| 284 | // or that is stored to memory in this basic block. |
| 285 | // If the value is stored to memory, we load it back before printing |
| 286 | // We also return all such loaded values in the vector valuesStoredInMethod |
| 287 | // for printing at the exit from the method. (Note that in each invocation |
| 288 | // of the method, this will only get the last value stored for each static |
| 289 | // store instruction). |
| 290 | // *bb must be the block in which the value is computed; |
| 291 | // this is not checked here. |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 292 | // |
| 293 | static void |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 294 | TraceValuesAtBBExit(const vector<Instruction*>& valueVec, |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 295 | BasicBlock* bb, |
| 296 | Module* module, |
| 297 | unsigned int indent, |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 298 | bool isMethodExit, |
| 299 | vector<Instruction*>* valuesStoredInMethod) |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 300 | { |
| 301 | // Get an iterator to point to the insertion location |
| 302 | // |
| 303 | BasicBlock::InstListType& instList = bb->getInstList(); |
Chris Lattner | 5309e10 | 2001-10-18 06:03:05 +0000 | [diff] [blame] | 304 | BasicBlock::iterator here = instList.end()-1; |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 305 | assert((*here)->isTerminator()); |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 306 | |
| 307 | // Insert a print instruction for each value. |
| 308 | // |
| 309 | for (unsigned i=0, N=valueVec.size(); i < N; i++) |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 310 | { |
| 311 | Instruction* I = valueVec[i]; |
| 312 | if (I->getOpcode() == Instruction::Store) |
| 313 | { |
| 314 | assert(valuesStoredInMethod != NULL && |
| 315 | "Should not be printing a store instruction at method exit"); |
| 316 | I = InsertLoadInst((StoreInst*) I, bb, here); |
| 317 | valuesStoredInMethod->push_back(I); |
| 318 | } |
| 319 | InsertPrintInsts(I, bb, here, module, indent, isMethodExit); |
| 320 | } |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 321 | } |
| 322 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 323 | |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 324 | |
| 325 | static Instruction* |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 326 | CreateMethodTraceInst(Method* method, |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 327 | unsigned int indent, |
| 328 | const string& msg) |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 329 | { |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 330 | string fmtString(indent, ' '); |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 331 | ostringstream methodNameString; |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 332 | WriteAsOperand(methodNameString, method) << ends; |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 333 | fmtString += msg + methodNameString.str(); |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 334 | |
| 335 | GlobalVariable *fmtVal = GetStringRef(method->getParent(), fmtString); |
| 336 | Instruction *printInst = |
| 337 | new CallInst(GetPrintMethodForType(method->getParent(), fmtVal->getType()), |
| 338 | vector<Value*>(1, fmtVal)); |
| 339 | |
| 340 | return printInst; |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 341 | } |
| 342 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 343 | |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 344 | static inline void |
| 345 | InsertCodeToShowMethodEntry(Method* method, |
| 346 | BasicBlock* entryBB, |
| 347 | unsigned int indent) |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 348 | { |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 349 | // Get an iterator to point to the insertion location |
| 350 | BasicBlock::InstListType& instList = entryBB->getInstList(); |
| 351 | BasicBlock::iterator here = instList.begin(); |
| 352 | |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 353 | Instruction *printInst = CreateMethodTraceInst(method, indent, |
| 354 | "Entering Method"); |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 355 | |
| 356 | here = entryBB->getInstList().insert(here, printInst) + 1; |
| 357 | } |
| 358 | |
| 359 | |
| 360 | static inline void |
| 361 | InsertCodeToShowMethodExit(Method* method, |
| 362 | BasicBlock* exitBB, |
| 363 | unsigned int indent) |
| 364 | { |
| 365 | // Get an iterator to point to the insertion location |
| 366 | BasicBlock::InstListType& instList = exitBB->getInstList(); |
| 367 | BasicBlock::iterator here = instList.end()-1; |
| 368 | assert((*here)->isTerminator()); |
| 369 | |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 370 | Instruction *printInst = CreateMethodTraceInst(method, indent, |
| 371 | "Leaving Method"); |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 372 | |
Chris Lattner | e2c6126 | 2001-10-18 20:06:03 +0000 | [diff] [blame^] | 373 | exitBB->getInstList().insert(here, printInst) + 1; |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 374 | } |
| 375 | |
| 376 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 377 | //************************** External Functions ****************************/ |
| 378 | |
| 379 | |
| 380 | bool |
| 381 | InsertTraceCode::doInsertTraceCode(Method *M, |
| 382 | bool traceBasicBlockExits, |
| 383 | bool traceMethodExits) |
| 384 | { |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 385 | vector<Instruction*> valuesStoredInMethod; |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 386 | Module* module = M->getParent(); |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 387 | vector<BasicBlock*> exitBlocks; |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 388 | |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 389 | if (M->isExternal() || |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 390 | (! traceBasicBlockExits && ! traceMethodExits)) |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 391 | return false; |
| 392 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 393 | if (traceMethodExits) |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 394 | InsertCodeToShowMethodEntry(M, M->getEntryNode(), /*indent*/ 0); |
| 395 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 396 | for (Method::iterator BI = M->begin(); BI != M->end(); ++BI) |
| 397 | { |
| 398 | BasicBlock* bb = *BI; |
| 399 | bool isExitBlock = false; |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 400 | vector<Instruction*> valuesToTraceInBB; |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 401 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 402 | FindValuesToTraceInBB(bb, valuesToTraceInBB); |
| 403 | |
| 404 | if (bb->succ_begin() == bb->succ_end()) |
| 405 | { // record this as an exit block |
| 406 | exitBlocks.push_back(bb); |
| 407 | isExitBlock = true; |
| 408 | } |
| 409 | |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 410 | if (traceBasicBlockExits) |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 411 | TraceValuesAtBBExit(valuesToTraceInBB, bb, module, |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 412 | /*indent*/ 4, /*isMethodExit*/ false, |
| 413 | &valuesStoredInMethod); |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 414 | } |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 415 | |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 416 | if (traceMethodExits) |
| 417 | for (unsigned i=0; i < exitBlocks.size(); ++i) |
| 418 | { |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 419 | TraceValuesAtBBExit(valuesStoredInMethod, exitBlocks[i], module, |
| 420 | /*indent*/ 0, /*isMethodExit*/ true, |
| 421 | /*valuesStoredInMethod*/ NULL); |
| 422 | InsertCodeToShowMethodExit(M, exitBlocks[i], /*indent*/ 0); |
Vikram S. Adve | 7ac553a | 2001-10-18 13:49:22 +0000 | [diff] [blame] | 423 | } |
Vikram S. Adve | a0db1c9 | 2001-10-18 18:16:11 +0000 | [diff] [blame] | 424 | |
Chris Lattner | a0a8b5b | 2001-10-18 05:28:08 +0000 | [diff] [blame] | 425 | return true; |
Vikram S. Adve | a200a6c | 2001-10-14 23:18:45 +0000 | [diff] [blame] | 426 | } |