diff options
Diffstat (limited to 'lib/Module/KModule.cpp')
-rw-r--r-- | lib/Module/KModule.cpp | 128 |
1 files changed, 55 insertions, 73 deletions
diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 75e71c0a..d185f687 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -29,9 +29,12 @@ #include "llvm/IR/DataLayout.h" #if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) +#include "llvm/Analysis/Verifier.h" +#include "llvm/Linker.h" #include "llvm/Support/CallSite.h" #else #include "llvm/IR/CallSite.h" +#include "llvm/Linker/Linker.h" #endif #include "klee/Internal/Module/LLVMPassManager.h" @@ -81,33 +84,10 @@ namespace { cl::desc("Print functions whose address is taken.")); } -KModule::KModule(Module *_module) - : module(_module), - targetData(new DataLayout(module)), - infos(0), - constantTable(0) { -} - -KModule::~KModule() { - delete[] constantTable; - delete infos; - - for (std::vector<KFunction*>::iterator it = functions.begin(), - ie = functions.end(); it != ie; ++it) - delete *it; - - for (std::map<const llvm::Constant*, KConstant*>::iterator it=constantMap.begin(), - itE=constantMap.end(); it!=itE;++it) - delete it->second; - - delete targetData; - delete module; -} - /***/ namespace llvm { -extern void Optimize(Module *, const std::string &EntryPoint); +extern void Optimize(Module *, llvm::ArrayRef<const char *> preservedFunctions); } // what a hack @@ -194,14 +174,31 @@ void KModule::addInternalFunction(const char* functionName){ internalFunctions.insert(internalFunction); } -void KModule::prepare(const Interpreter::ModuleOptions &opts, - InterpreterHandler *ih) { +bool KModule::link(std::vector<std::unique_ptr<llvm::Module>> &modules, + const std::string &entryPoint) { + auto numRemainingModules = modules.size(); + // Add the currently active module to the list of linkables + modules.push_back(std::move(module)); + std::string error; + module = std::unique_ptr<llvm::Module>( + klee::linkModules(modules, entryPoint, error)); + if (!module) + klee_error("Could not link KLEE files %s", error.c_str()); + + targetData = std::unique_ptr<llvm::DataLayout>(new DataLayout(module.get())); + + // Check if we linked anything + return modules.size() != numRemainingModules; +} + +void KModule::instrument(const Interpreter::ModuleOptions &opts) { // Inject checks prior to optimization... we also perform the // invariant transformations that we will end up doing later so that // optimize is seeing what is as close as possible to the final // module. LegacyLLVMPassManagerTy pm; pm.add(new RaiseAsmPass()); + // This pass will scalarize as much code as possible so that the Executor // does not need to handle operands of vector type for most instructions // other than InsertElementInst and ExtractElementInst. @@ -214,21 +211,13 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, pm.add(new IntrinsicCleanerPass(*targetData)); pm.run(*module); +} +void KModule::optimiseAndPrepare( + const Interpreter::ModuleOptions &opts, + llvm::ArrayRef<const char *> preservedFunctions) { if (opts.Optimize) - Optimize(module, opts.EntryPoint); - - // FIXME: Missing force import for various math functions. - - // FIXME: Find a way that we can test programs without requiring - // this to be linked in, it makes low level debugging much more - // annoying. - - SmallString<128> LibPath(opts.LibraryDir); - llvm::sys::path::append(LibPath, - "kleeRuntimeIntrinsic.bc" - ); - module = linkWithLibrary(module, LibPath.str()); + Optimize(module.get(), preservedFunctions); // Add internal functions which are not used to check if instructions // have been already visited @@ -237,10 +226,9 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, if (opts.CheckOvershift) addInternalFunction("klee_overshift_check"); - // Needs to happen after linking (since ctors/dtors can be modified) // and optimization (since global optimization can rewrite lists). - injectStaticConstructorsAndDestructors(module); + injectStaticConstructorsAndDestructors(module.get()); // Finally, run the passes that maintain invariants we expect during // interpretation. We run the intrinsic cleaner just in case we @@ -268,74 +256,69 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, if (!operandTypeCheckPass->checkPassed()) { klee_error("Unexpected instruction operand types detected"); } +} - if (OutputSource) { +void KModule::manifest(InterpreterHandler *ih, bool forceSourceOutput) { + if (OutputSource || forceSourceOutput) { std::unique_ptr<llvm::raw_fd_ostream> os(ih->openOutputFile("assembly.ll")); assert(os && !os->has_error() && "unable to open source output"); *os << *module; } if (OutputModule) { - llvm::raw_fd_ostream *f = ih->openOutputFile("final.bc"); - WriteBitcodeToFile(module, *f); - delete f; + std::unique_ptr<llvm::raw_fd_ostream> f(ih->openOutputFile("final.bc")); + WriteBitcodeToFile(module.get(), *f); } /* Build shadow structures */ - infos = new InstructionInfoTable(module); - - for (Module::iterator it = module->begin(), ie = module->end(); - it != ie; ++it) { - if (it->isDeclaration()) + infos = std::unique_ptr<InstructionInfoTable>( + new InstructionInfoTable(module.get())); + + for (auto &Function : *module) { + if (Function.isDeclaration()) continue; - Function *fn = &*it; - KFunction *kf = new KFunction(fn, this); - + auto kf = std::unique_ptr<KFunction>(new KFunction(&Function, this)); + for (unsigned i=0; i<kf->numInstructions; ++i) { KInstruction *ki = kf->instructions[i]; ki->info = &infos->getInfo(ki->inst); } - functions.push_back(kf); - functionMap.insert(std::make_pair(fn, kf)); + functionMap.insert(std::make_pair(&Function, kf.get())); + functions.push_back(std::move(kf)); } /* Compute various interesting properties */ - for (std::vector<KFunction*>::iterator it = functions.begin(), - ie = functions.end(); it != ie; ++it) { - KFunction *kf = *it; + for (auto &kf : functions) { if (functionEscapes(kf->function)) escapingFunctions.insert(kf->function); } if (DebugPrintEscapingFunctions && !escapingFunctions.empty()) { llvm::errs() << "KLEE: escaping functions: ["; - for (std::set<Function*>::iterator it = escapingFunctions.begin(), - ie = escapingFunctions.end(); it != ie; ++it) { - llvm::errs() << (*it)->getName() << ", "; - } + for (auto &Function : escapingFunctions) + llvm::errs() << Function->getName() << ", "; llvm::errs() << "]\n"; } } KConstant* KModule::getKConstant(const Constant *c) { - std::map<const llvm::Constant*, KConstant*>::iterator it = constantMap.find(c); + auto it = constantMap.find(c); if (it != constantMap.end()) - return it->second; + return it->second.get(); return NULL; } unsigned KModule::getConstantID(Constant *c, KInstruction* ki) { - KConstant *kc = getKConstant(c); - if (kc) + if (KConstant *kc = getKConstant(c)) return kc->id; unsigned id = constants.size(); - kc = new KConstant(c, id, ki); - constantMap.insert(std::make_pair(c, kc)); + auto kc = std::unique_ptr<KConstant>(new KConstant(c, id, ki)); + constantMap.insert(std::make_pair(c, std::move(kc))); constants.push_back(c); return id; } @@ -379,11 +362,10 @@ KFunction::KFunction(llvm::Function *_function, numArgs(function->arg_size()), numInstructions(0), trackCoverage(true) { - for (llvm::Function::iterator bbit = function->begin(), - bbie = function->end(); bbit != bbie; ++bbit) { - BasicBlock *bb = &*bbit; - basicBlockEntry[bb] = numInstructions; - numInstructions += bb->size(); + // Assign unique instruction IDs to each basic block + for (auto &BasicBlock : *function) { + basicBlockEntry[&BasicBlock] = numInstructions; + numInstructions += BasicBlock.size(); } instructions = new KInstruction*[numInstructions]; |