diff options
author | Martin Nowack <martin.nowack@gmail.com> | 2018-05-15 15:12:12 +0100 |
---|---|---|
committer | Cristian Cadar <c.cadar@imperial.ac.uk> | 2018-07-04 15:13:02 +0100 |
commit | ef90f1e219fec27a3d594158ae5f380a9e9a2f37 (patch) | |
tree | 0a02b5da762b4bc59f7f6bd2453a2a6591f00062 /lib/Module/KModule.cpp | |
parent | 6803c37be83f0c97c95870a18cb230e135a131c9 (diff) | |
download | klee-ef90f1e219fec27a3d594158ae5f380a9e9a2f37.tar.gz |
Reorder linking and optimizations
Link intrinsic library before executing optimizations. This makes sure that any optimization run by KLEE on the module is executed for the intrinsic library as well. Support .ll files as input for KLEE as well.
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]; |