zcov: / lib/Module/KModule.cpp


Files: 1 Branches Taken: 67.3% 152 / 226
Generated: 2009-05-17 22:47 Branches Executed: 69.0% 156 / 226
Line Coverage: 84.8% 190 / 224


Programs: 1 Runs 371


       1                 : /* -*- mode: c++; c-basic-offset: 2; -*- */
       2                 : 
       3                 : // FIXME: This does not belong here.
       4                 : #include "../Core/Common.h"
       5                 : 
       6                 : #include "klee/Internal/Module/KModule.h"
       7                 : 
       8                 : #include "Passes.h"
       9                 : 
      10                 : #include "klee/Interpreter.h"
      11                 : #include "klee/Internal/Module/Cell.h"
      12                 : #include "klee/Internal/Module/KInstruction.h"
      13                 : #include "klee/Internal/Module/InstructionInfoTable.h"
      14                 : #include "klee/Internal/Support/ModuleUtil.h"
      15                 : 
      16                 : #include "llvm/Bitcode/ReaderWriter.h"
      17                 : #include "llvm/Instructions.h"
      18                 : #include "llvm/Module.h"
      19                 : #include "llvm/PassManager.h"
      20                 : #include "llvm/ValueSymbolTable.h"
      21                 : #include "llvm/Support/CommandLine.h"
      22                 : #include "llvm/Target/TargetData.h"
      23                 : #include "llvm/Transforms/Scalar.h"
      24                 : 
      25                 : #include <sstream>
      26                 : 
      27                 : #include "klee/Internal/FIXME/sugar.h"
      28                 : 
      29                 : using namespace llvm;
      30                 : using namespace klee;
      31                 : 
      32                 : namespace {
      33                 :   enum SwitchImplType {
      34                 :     eSwitchTypeSimple,
      35                 :     eSwitchTypeLLVM,
      36                 :     eSwitchTypeInternal
      37                 :   };
      38                 : 
      39                 :   cl::list<std::string>
      40              103:   MergeAtExit("merge-at-exit");
      41                 :     
      42                 :   cl::opt<bool>
      43              103:   NoTruncateSourceLines("no-truncate-source-lines",
      44                 :                         cl::desc("Don't truncate long lines in the output source"));
      45                 : 
      46                 :   cl::opt<bool>
      47              103:   OutputSource("output-source",
      48                 :                cl::desc("Write the assembly for the final transformed source"),
      49              206:                cl::init(true));
      50                 : 
      51                 :   cl::opt<bool>
      52              103:   OutputModule("output-module",
      53                 :                cl::desc("Write the bitcode for the final transformed module"),
      54              206:                cl::init(false));
      55                 : 
      56                 :   cl::opt<SwitchImplType>
      57              103:   SwitchType("switch-type", cl::desc("Select the implementation of switch"),
      58                 :              cl::values(clEnumValN(eSwitchTypeSimple, "simple", 
      59                 :                                    "lower to ordered branches"),
      60                 :                         clEnumValN(eSwitchTypeLLVM, "llvm", 
      61                 :                                    "lower using LLVM"),
      62                 :                         clEnumValN(eSwitchTypeInternal, "internal", 
      63                 :                                    "execute switch internally"),
      64                 :                         clEnumValEnd),
      65              206:              cl::init(eSwitchTypeInternal));
      66                 :   
      67                 :   cl::opt<bool>
      68              103:   DebugPrintEscapingFunctions("debug-print-escaping-functions", 
      69                 :                               cl::desc("Print functions whose address is taken."));
      70                 : }
      71                 : 
      72              103: KModule::KModule(Module *_module) 
      73                 :   : module(_module),
      74                 :     targetData(new TargetData(module)),
      75                 :     dbgStopPointFn(0),
      76                 :     kleeMergeFn(0),
      77                 :     infos(0),
      78              618:     constantTable(0) {
      79              103: }
      80                 : 
      81              103: KModule::~KModule() {
                      103: branch 0 taken
                        0: branch 1 not taken
                     4762: branch 2 taken
                      103: branch 3 taken
                      103: branch 5 taken
                      103: branch 6 taken
                      103: branch 7 taken
                      103: branch 8 taken
      82              206:   delete[] constantTable;
                      103: branch 0 taken
                        0: branch 1 not taken
                      103: branch 4 taken
                      103: branch 5 taken
      83              103:   delete infos;
      84                 : 
                      520: branch 0 taken
                      103: branch 1 taken
                      103: branch 2 taken
                      103: branch 3 taken
      85              829:   foreach(it, functions.begin(), functions.end())
                      520: branch 0 taken
                        0: branch 1 not taken
                      520: branch 4 taken
                      520: branch 5 taken
      86              520:     delete *it;
      87                 : 
                      103: branch 0 taken
                        0: branch 1 not taken
                      103: branch 3 taken
                      103: branch 4 taken
      88              103:   delete targetData;
                      103: branch 0 taken
                        0: branch 1 not taken
                      103: branch 4 taken
                      103: branch 5 taken
      89              103:   delete module;
      90              618: }
      91                 : 
      92                 : /***/
      93                 : 
      94                 : namespace llvm {
      95                 : extern void Optimize(Module*);
      96                 : }
      97                 : 
      98                 : // what a hack
      99                 : static Function *getStubFunctionForCtorList(Module *m,
     100                 :                                             GlobalVariable *gv, 
     101                4:                                             std::string name) {
     102                 :   assert(!gv->isDeclaration() && !gv->hasInternalLinkage() &&
                        4: branch 1 taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        4: branch 4 taken
     103                8:          "do not support old LLVM style constructor/destructor lists");
     104                 :   
     105                 :   std::vector<const Type*> nullary;
     106                 : 
     107                 :   Function *fn = Function::Create(FunctionType::get(Type::VoidTy, 
     108                 : 						    nullary, false),
     109                 : 				  GlobalVariable::InternalLinkage, 
     110                 : 				  name,
     111                8:                               m);
     112                8:   BasicBlock *bb = BasicBlock::Create("entry", fn);
     113                 :   
     114                 :   // From lli:
     115                 :   // Should be an array of '{ int, void ()* }' structs.  The first value is
     116                 :   // the init priority, which we ignore.
     117                8:   ConstantArray *arr = dyn_cast<ConstantArray>(gv->getInitializer());
                        4: branch 0 taken
                        0: branch 1 not taken
     118                4:   if (arr) {
                        4: branch 0 taken
                        4: branch 1 taken
     119               16:     for (unsigned i=0; i<arr->getNumOperands(); i++) {
     120                4:       ConstantStruct *cs = cast<ConstantStruct>(arr->getOperand(i));
                        0: branch 0 not taken
                        4: branch 1 taken
     121                4:       assert(cs->getNumOperands()==2 && "unexpected element in ctor initializer list");
     122                 :       
     123                4:       Constant *fp = cs->getOperand(1);      
                        4: branch 1 taken
                        0: branch 2 not taken
     124                4:       if (!fp->isNullValue()) {
                        0: branch 0 not taken
                        4: branch 1 taken
     125                4:         if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp))
     126                0:           fp = ce->getOperand(0);
     127                 : 
                        4: branch 0 taken
                        0: branch 1 not taken
     128                4:         if (Function *f = dyn_cast<Function>(fp)) {
     129                4: 	  CallInst::Create(f, "", bb);
     130                 :         } else {
     131                0:           assert(0 && "unable to get function pointer from ctor initializer list");
     132                 :         }
     133                 :       }
     134                 :     }
     135                 :   }
     136                 :   
     137                 :   ReturnInst::Create(bb);
     138                 : 
     139                4:   return fn;
     140                 : }
     141                 : 
     142              103: static void injectStaticConstructorsAndDestructors(Module *m) {
     143              206:   GlobalVariable *ctors = m->getNamedGlobal("llvm.global_ctors");
     144              206:   GlobalVariable *dtors = m->getNamedGlobal("llvm.global_dtors");
     145                 :   
                        2: branch 0 taken
                      101: branch 1 taken
     146              103:   if (ctors || dtors) {
     147                2:     Function *mainFn = m->getFunction("main");
                        0: branch 0 not taken
                        2: branch 1 taken
     148                2:     assert(mainFn && "unable to find main function");
     149                 : 
                        2: branch 0 taken
                        0: branch 1 not taken
     150                2:     if (ctors)
     151                 :     CallInst::Create(getStubFunctionForCtorList(m, ctors, "klee.ctor_stub"),
     152                8: 		     "", mainFn->begin()->begin());
                        2: branch 0 taken
                        0: branch 1 not taken
     153                2:     if (dtors) {
     154                2:       Function *dtorStub = getStubFunctionForCtorList(m, dtors, "klee.dtor_stub");
                        6: branch 1 taken
                        2: branch 2 taken
     155               14:       foreach(bbIt, mainFn->begin(), mainFn->end()) {
                        2: branch 1 taken
                        4: branch 2 taken
     156               12:         if (isa<ReturnInst>(bbIt->getTerminator()))
     157                4: 	  CallInst::Create(dtorStub, "", bbIt->getTerminator());
     158                 :       }
     159                 :     }
     160                 :   }
     161              103: }
     162                 : 
     163              309: static void forceImport(Module *m, const char *name, const Type *retType, ...) {
     164                 :   // If module lacks an externally visible symbol for the name then we
     165                 :   // need to create one. We have to look in the symbol table because
     166                 :   // we want to check everything (global variables, functions, and
     167                 :   // aliases).
     168                 : 
     169              618:   Value *v = m->getValueSymbolTable().lookup(name);
     170              309:   GlobalValue *gv = dyn_cast_or_null<GlobalValue>(v);
     171                 : 
                        4: branch 0 taken
                      305: branch 1 taken
                        0: branch 2 not taken
                        4: branch 3 taken
                      305: branch 4 taken
                        4: branch 5 taken
     172              313:   if (!gv || gv->hasInternalLinkage()) {
     173                 :     va_list ap;
     174                 : 
     175              305:     va_start(ap, retType);
     176                 :     std::vector<const Type *> argTypes;
                      915: branch 0 taken
                      305: branch 1 taken
     177             1220:     while (const Type *t = va_arg(ap, const Type*))
     178                 :       argTypes.push_back(t);
     179              305:     va_end(ap);
     180                 : 
     181              915:     m->getOrInsertFunction(name, FunctionType::get(retType, argTypes, false));
     182                 :   }
     183              309: }
     184                 : 
     185                 : // FIXME: I don't belong here (or anywhere?)
     186                 : 
     187                 : #include <sys/stat.h>
     188                 : static const char *mostRecent(const char *a, const char *b) {
     189                 :   struct stat a_st, b_st;
                        0: branch 0 not taken
                      103: branch 1 taken
     190              103:   if (stat(a, &a_st)==-1) return b;
                        0: branch 0 not taken
                      103: branch 1 taken
     191              103:   if (stat(b, &b_st)==-1) return a;
                        0: branch 0 not taken
                      103: branch 1 taken
     192              103:   return (a_st.st_mtime < b_st.st_mtime) ? b : a;
     193                 : }
     194                 : 
     195                 : void KModule::prepare(const Interpreter::ModuleOptions &opts,
     196              103:                       InterpreterHandler *ih) {
                        0: branch 0 not taken
                      103: branch 1 taken
     197              103:   if (!MergeAtExit.empty()) {
     198                0:     Function *mergeFn = module->getFunction("klee_merge");
                        0: branch 0 not taken
                        0: branch 1 not taken
     199                0:     if (!mergeFn) {
     200                 :       mergeFn = Function::Create(FunctionType::get(Type::VoidTy,
     201                 : 						   std::vector<const Type*>(), false),
     202                 : 				 GlobalVariable::ExternalLinkage,
     203                 : 				 "klee_merge",
     204                0: 				 module);
     205                 :     }
     206                 : 
                        0: branch 0 not taken
                        0: branch 1 not taken
     207                0:     foreach(it, MergeAtExit.begin(), MergeAtExit.end()) {
     208                0:       std::string &name = *it;
     209                0:       Function *f = module->getFunction(name);
                        0: branch 0 not taken
                        0: branch 1 not taken
     210                0:       if (!f) {
     211                 :         klee_error("cannot insert merge-at-exit for: %s (cannot find)",
     212                0:                    name.c_str());
                        0: branch 1 not taken
                        0: branch 2 not taken
     213                0:       } else if (f->isDeclaration()) {
     214                 :         klee_error("cannot insert merge-at-exit for: %s (external)",
     215                0:                    name.c_str());
     216                 :       }
     217                 : 
     218                0:       BasicBlock *exit = BasicBlock::Create("exit", f);
     219                0:       PHINode *result = 0;
                        0: branch 1 not taken
                        0: branch 2 not taken
     220                0:       if (f->getReturnType() != Type::VoidTy)
     221                0:         result = PHINode::Create(f->getReturnType(), "retval", exit);
     222                0:       CallInst::Create(mergeFn, "", exit);
     223                0:       ReturnInst::Create(result, exit);
     224                 : 
     225                 :       llvm::cerr << "KLEE: adding klee_merge at exit of: " << name << "\n";
                        0: branch 1 not taken
                        0: branch 2 not taken
     226                0:       foreach(bb, f->begin(), f->end()) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     227                0:         if (&*bb != exit) {
     228                0:           Instruction *i = bb->getTerminator();
                        0: branch 0 not taken
                        0: branch 1 not taken
     229                0:           if (i->getOpcode()==Instruction::Ret) {
                        0: branch 0 not taken
                        0: branch 1 not taken
     230                0:             if (result) {
     231                0:               result->addIncoming(i->getOperand(0), bb);
     232                 :             }
     233                0:             i->eraseFromParent();
     234                0: 	    BranchInst::Create(exit, bb);
     235                 :           }
     236                 :         }
     237                 :       }
     238                 :     }
     239                 :   }
     240                 : 
     241                 :   // Inject checks prior to optimization... we also perform the
     242                 :   // invariant transformations that we will end up doing later so that
     243                 :   // optimize is seeing what is as close as possible to the final
     244                 :   // module.
     245              103:   PassManager pm;
     246              206:   pm.add(new RaiseAsmPass());
                      103: branch 0 taken
                        0: branch 1 not taken
     247              206:   if (opts.CheckDivZero) pm.add(new DivCheckPass());
     248                 :   // FIXME: This false here is to work around a bug in
     249                 :   // IntrinsicLowering which caches values which may eventually be
     250                 :   // deleted (via RAUW). This can be removed once LLVM fixes this
     251                 :   // issue.
     252              103:   pm.add(new IntrinsicCleanerPass(*targetData, false));
     253              103:   pm.run(*module);
     254                 : 
                        3: branch 0 taken
                      100: branch 1 taken
     255              103:   if (opts.Optimize)
     256                3:     Optimize(module);
     257                 : 
     258                 :   // Force importing functions required by intrinsic lowering. Kind of
     259                 :   // unfortunate clutter when we don't need them but we won't know
     260                 :   // that until after all linking and intrinsic lowering is
     261                 :   // done. After linking and passes we just try to manually trim these
     262                 :   // by name. We only add them if such a function doesn't exist to
     263                 :   // avoid creating stale uses.
     264                 : 
     265                 :   forceImport(module, "memcpy", PointerType::getUnqual(Type::Int8Ty),
     266                 :               PointerType::getUnqual(Type::Int8Ty),
     267                 :               PointerType::getUnqual(Type::Int8Ty),
     268              412:               targetData->getIntPtrType(), (Type*) 0);
     269                 :   forceImport(module, "memmove", PointerType::getUnqual(Type::Int8Ty),
     270                 :               PointerType::getUnqual(Type::Int8Ty),
     271                 :               PointerType::getUnqual(Type::Int8Ty),
     272              412:               targetData->getIntPtrType(), (Type*) 0);
     273                 :   forceImport(module, "memset", PointerType::getUnqual(Type::Int8Ty),
     274                 :               PointerType::getUnqual(Type::Int8Ty),
     275                 :               Type::Int32Ty,
     276              309:               targetData->getIntPtrType(), (Type*) 0);
     277                 : 
     278                 :   // FIXME: Missing force import for various math functions.
     279                 : 
     280                 :   // FIXME: Find a way that we can test programs without requiring
     281                 :   // this to be linked in, it makes low level debugging much more
     282                 :   // annoying.
     283                 :   module = linkWithLibrary(module,
     284                 :                            mostRecent(KLEE_DIR"/Release/lib/libintrinsic.bca",
     285              103:                                       KLEE_DIR"/Debug/lib/libintrinsic.bca"));
     286                 : 
     287                 :   // Needs to happen after linking (since ctors/dtors can be modified)
     288                 :   // and optimization (since global optimization can rewrite lists).
     289              103:   injectStaticConstructorsAndDestructors(module);
     290                 : 
     291                 :   // Finally, run the passes that maintain invariants we expect during
     292                 :   // interpretation. We run the intrinsic cleaner just in case we
     293                 :   // linked in something with intrinsics but any external calls are
     294                 :   // going to be unresolved. We really need to handle the intrinsics
     295                 :   // directly I think?
     296              103:   PassManager pm3;
     297              103:   pm3.add(createCFGSimplificationPass());
                        1: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                      102: branch 3 taken
     298              103:   switch(SwitchType) {
     299                 :   case eSwitchTypeInternal: break;
     300                2:   case eSwitchTypeSimple: pm3.add(new LowerSwitchPass()); break;
     301                0:   case eSwitchTypeLLVM:  pm3.add(createLowerSwitchPass()); break;
     302                0:   default: klee_error("invalid --switch-type");
     303                 :   }
     304              103:   pm3.add(new IntrinsicCleanerPass(*targetData));
     305              206:   pm3.add(new PhiCleanerPass());
     306              103:   pm3.run(*module);
     307                 : 
     308                 :   // For cleanliness see if we can discard any of the functions we
     309                 :   // forced to import.
     310                 :   Function *f;
     311              103:   f = module->getFunction("memcpy");
                      103: branch 0 taken
                        0: branch 1 not taken
                       95: branch 2 taken
                        8: branch 3 taken
                       95: branch 4 taken
                        8: branch 5 taken
     312              206:   if (f && f->use_empty()) f->eraseFromParent();
     313              103:   f = module->getFunction("memmove");
                      103: branch 0 taken
                        0: branch 1 not taken
                       97: branch 2 taken
                        6: branch 3 taken
                       97: branch 4 taken
                        6: branch 5 taken
     314              206:   if (f && f->use_empty()) f->eraseFromParent();
     315              103:   f = module->getFunction("memset");
                      103: branch 0 taken
                        0: branch 1 not taken
                       94: branch 2 taken
                        9: branch 3 taken
                       94: branch 4 taken
                        9: branch 5 taken
     316              206:   if (f && f->use_empty()) f->eraseFromParent();
     317                 : 
                      103: branch 0 taken
                        0: branch 1 not taken
     318              103:   if (OutputSource) {
     319              206:     std::ostream *os = ih->openOutputFile("assembly.ll");
                      103: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                      103: branch 3 taken
     320              206:     assert(os && os->good() && "unable to open source output");
     321                 : 
                        0: branch 0 not taken
                      103: branch 1 taken
     322              103:     if (NoTruncateSourceLines) {
     323                0:       *os << *module;
     324                 :     } else {
     325              103:       bool truncated = false;
     326              103:       std::stringstream buffer;
     327              103:       buffer << *module;
     328              103:       std::string string = buffer.str();
     329              103:       const char *position = string.c_str();
     330                 : 
     331           124270:       for (;;) {
     332           124373:         const char *end = index(position, '\n');
                      103: branch 0 taken
                   124270: branch 1 taken
     333           124373:         if (!end) {
     334              103:           *os << position;
     335                 :           break;
     336                 :         } else {
     337           124270:           unsigned count = (end - position) + 1;
                   120384: branch 0 taken
                     3886: branch 1 taken
     338           124270:           if (count<255) {
     339           120384:             os->write(position, count);
     340                 :           } else {
     341             3886:             os->write(position, 254);
     342             3886:             *os << "\n";
     343             3886:             truncated = true;
     344                 :           }
     345           124270:           position = end+1;
     346                 :         }
     347                 :       }
                       35: branch 0 taken
                       68: branch 1 taken
     348              103:       if (truncated)
     349              103:         llvm::cerr << "KLEE: truncated long lines in output source, use --no-truncate-source-lines to disable\n";
     350                 :     }
     351                 : 
                      103: branch 0 taken
                        0: branch 1 not taken
     352              103:     delete os;
     353                 :   }
     354                 : 
                        0: branch 0 not taken
                      103: branch 1 taken
     355              103:   if (OutputModule) {
     356                0:     std::ostream *f = ih->openOutputFile("final.bc");
     357                0:     WriteBitcodeToFile(module, *f);
                        0: branch 0 not taken
                        0: branch 1 not taken
     358                0:     delete f;
     359                 :   }
     360                 : 
     361              103:   dbgStopPointFn = module->getFunction("llvm.dbg.stoppoint");
     362              103:   kleeMergeFn = module->getFunction("klee_merge");
     363                 : 
     364                 :   /* Build shadow structures */
     365                 : 
     366              103:   infos = new InstructionInfoTable(module);  
     367                 : 
                     1088: branch 1 taken
                      103: branch 2 taken
     368             2485:   foreach(it, module->begin(), module->end()) {
                      568: branch 1 taken
                      520: branch 2 taken
     369             1088:     if (it->isDeclaration())
     370              568:       continue;
     371                 : 
     372              520:     KFunction *kf = new KFunction(it, this);
     373                 :     
                    92853: branch 0 taken
                      520: branch 1 taken
     374            93373:     for (unsigned i=0; i<kf->numInstructions; ++i) {
     375            92853:       KInstruction *ki = kf->instructions[i];
     376            92853:       ki->info = &infos->getInfo(ki->inst);
     377                 :     }
     378                 : 
     379              520:     functions.push_back(kf);
     380             1040:     functionMap.insert(std::make_pair(it, kf));
     381                 :   }
     382                 : 
     383                 :   /* Compute various interesting properties */
     384                 : 
                      520: branch 0 taken
                      103: branch 1 taken
     385              829:   foreach(it, functions.begin(), functions.end()) {
     386              520:     KFunction *kf = *it;
                       22: branch 1 taken
                      498: branch 2 taken
     387              520:     if (functionEscapes(kf->function))
     388               22:       escapingFunctions.insert(kf->function);
     389                 :   }
     390                 : 
                        0: branch 0 not taken
                      103: branch 1 taken
                      103: branch 2 taken
                      103: branch 3 taken
                        0: branch 4 not taken
                      103: branch 5 taken
     391              103:   if (DebugPrintEscapingFunctions && !escapingFunctions.empty()) {
     392                 :     llvm::cerr << "KLEE: escaping functions: [";
                        0: branch 0 not taken
                        0: branch 1 not taken
     393                0:     foreach(it, escapingFunctions.begin(), escapingFunctions.end()) {
     394                0:       llvm::cerr << (*it)->getName() << ", ";
     395                 :     }
     396                 :     llvm::cerr << "]\n";
     397              103:   }
     398              103: }
     399                 : 
     400            35850: KConstant* KModule::getKConstant(Constant *c) {
     401            35850:   std::map<llvm::Constant*, KConstant*>::iterator it = constantMap.find(c);
                    31088: branch 0 taken
                     4762: branch 1 taken
     402            71700:   if (it != constantMap.end())
     403            31088:     return it->second;
     404             4762:   return NULL;
     405                 : }
     406                 : 
     407            35850: unsigned KModule::getConstantID(Constant *c, KInstruction* ki) {
     408            35850:   KConstant *kc = getKConstant(c);
                    31088: branch 0 taken
                     4762: branch 1 taken
     409            35850:   if (kc)
     410            31088:     return kc->id;  
     411                 : 
     412             9524:   unsigned id = constants.size();
     413             4762:   kc = new KConstant(c, id, ki);
     414             9524:   constantMap.insert(std::make_pair(c, kc));
     415             4762:   constants.push_back(c);
     416             4762:   return id;
     417                 : 
     418                 : #if 0
     419                 :   let(res, constantMap.insert(std::make_pair(c, constants.size())));
     420                 :   if (res.second)
     421                 :     constants.push_back(c);
     422                 :   return res.first->second;
     423                 : #endif  
     424                 : }
     425                 : 
     426                 : /***/
     427                 : 
     428             4762: KConstant::KConstant(llvm::Constant* _ct, unsigned _id, KInstruction* _ki) {
     429             4762:   ct = _ct;
     430             4762:   id = _id;
     431             4762:   ki = _ki;
     432             4762: }
     433                 : 
     434                 : /***/
     435                 : 
     436                 : KFunction::KFunction(llvm::Function *_function,
     437              520:                      KModule *km) 
     438                 :   : function(_function),
     439                 :     numArgs(function->arg_size()),
     440                 :     numInstructions(0),
     441             1040:     trackCoverage(true) {
                     8981: branch 1 taken
                      520: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     442            19522:   foreach(bbit, function->begin(), function->end()) {
     443             8981:     BasicBlock *bb = bbit;
     444             8981:     basicBlockEntry[bb] = numInstructions;
     445             8981:     numInstructions += bb->size();
     446                 :   }
     447                 : 
     448              520:   instructions = new KInstruction*[numInstructions];
     449                 : 
     450                 :   std::map<Instruction*, unsigned> registerMap;
     451                 : 
     452                 :   // The first arg_size() registers are reserved for formals.
     453              520:   unsigned rnum = numArgs;
                     8981: branch 1 taken
                      520: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     454            19522:   foreach(bbit, function->begin(), function->end()) {
                    92853: branch 1 taken
                     8981: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     455           203668:     foreach(it, bbit->begin(), bbit->end()) {
     456            92853:       registerMap[it] = rnum++;
     457                 :     }
     458                 :   }
     459              520:   numRegisters = rnum;
     460                 :   
     461              520:   unsigned i = 0;
                     8981: branch 1 taken
                      520: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     462            19522:   foreach(bbit, function->begin(), function->end()) {
                    92853: branch 1 taken
                     8981: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     463           203668:     foreach(it, bbit->begin(), bbit->end()) {
     464                 :       KInstruction *ki;
     465                 : 
                     4061: branch 0 taken
                    88792: branch 1 taken
                    88792: branch 2 taken
                    88792: branch 3 taken
     466            92853:       switch(it->getOpcode()) {
     467                 :       case Instruction::GetElementPtr:
     468             8122:         ki = new KGEPInstruction(); break;
     469                 :       default:
     470           177584:         ki = new KInstruction(); break;
     471                 :       }
     472                 : 
     473           185706:       unsigned numOperands = it->getNumOperands();
     474            92853:       ki->inst = it;      
     475            92853:       ki->operands = new int[numOperands];
     476            92853:       ki->dest = registerMap[it];
                   147219: branch 0 taken
                    92853: branch 1 taken
                    92853: branch 2 taken
                    92853: branch 3 taken
     477           240072:       for (unsigned j=0; j<numOperands; j++) {
     478           147219:         Value *v = it->getOperand(j);
     479                 :         
                    96666: branch 0 taken
                    50553: branch 1 taken
                    50553: branch 2 taken
                    50553: branch 3 taken
     480           147219:         if (Instruction *inst = dyn_cast<Instruction>(v)) {
     481            96666:           ki->operands[j] = registerMap[inst];
                     1055: branch 0 taken
                    49498: branch 1 taken
                    49498: branch 2 taken
                    49498: branch 3 taken
     482            50553:         } else if (Argument *a = dyn_cast<Argument>(v)) {
     483             1055:           ki->operands[j] = a->getArgNo();
                    35850: branch 0 taken
                    13648: branch 1 taken
                        0: branch 2 not taken
                    35850: branch 3 taken
                    13648: branch 4 taken
                    35850: branch 5 taken
                    35850: branch 6 taken
                    35850: branch 7 taken
                    35850: branch 8 taken
                    35850: branch 9 taken
                    35850: branch 10 taken
                    35850: branch 11 taken
     484            85348:         } else if (isa<BasicBlock>(v) || isa<InlineAsm>(v)) {
     485            13648:           ki->operands[j] = -1;
     486                 :         } else {
                        0: branch 0 not taken
                    35850: branch 1 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     487            35850:           assert(isa<Constant>(v));
     488            35850:           Constant *c = cast<Constant>(v);
     489            35850:           ki->operands[j] = -(km->getConstantID(c, ki) + 2);
     490                 :         }
     491                 :       }
     492                 : 
     493            92853:       instructions[i++] = ki;
     494                 :     }
     495                 :   }
     496              520: }
     497                 : 
     498              520: KFunction::~KFunction() {
                    92853: branch 0 taken
                      520: branch 1 taken
                      520: branch 2 taken
                      520: branch 3 taken
     499            93373:   for (unsigned i=0; i<numInstructions; ++i)
                    92853: branch 0 taken
                        0: branch 1 not taken
                    92853: branch 3 taken
                    92853: branch 4 taken
     500            92853:     delete instructions[i];
                      520: branch 0 taken
                        0: branch 1 not taken
                      520: branch 3 taken
                      520: branch 4 taken
     501              520:   delete[] instructions;
                      103: branch 0 taken
                        0: branch 1 not taken
                      103: branch 2 taken
                        0: branch 3 not taken
     502             1349: }

Generated: 2009-05-17 22:47 by zcov