diff options
Diffstat (limited to 'lib/Module/KModule.cpp')
-rw-r--r-- | lib/Module/KModule.cpp | 139 |
1 files changed, 24 insertions, 115 deletions
diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index eed922f8..cb8b4539 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -9,40 +9,27 @@ #define DEBUG_TYPE "KModule" +#include "klee/Module/KModule.h" + +#include "ModuleHelper.h" #include "Passes.h" #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" -#include "klee/Support/OptionCategories.h" #include "klee/Module/Cell.h" #include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" -#include "klee/Module/KModule.h" #include "klee/Support/Debug.h" #include "klee/Support/ErrorHandling.h" #include "klee/Support/ModuleUtil.h" +#include "klee/Support/OptionCategories.h" #include "klee/Support/CompilerWarning.h" + DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeWriter.h" -#include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/ValueSymbolTable.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Linker/Linker.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/raw_os_ostream.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Scalar/Scalarizer.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Transforms/Utils.h" DISABLE_WARNING_POP #include <sstream> @@ -57,12 +44,6 @@ cl::OptionCategory } namespace { - enum SwitchImplType { - eSwitchTypeSimple, - eSwitchTypeLLVM, - eSwitchTypeInternal - }; - cl::opt<bool> OutputSource("output-source", cl::desc("Write the assembly for the final transformed source (default=true)"), @@ -75,16 +56,6 @@ namespace { cl::init(false), cl::cat(ModuleCat)); - cl::opt<SwitchImplType> - SwitchType("switch-type", cl::desc("Select the implementation of switch (default=internal)"), - cl::values(clEnumValN(eSwitchTypeSimple, "simple", - "lower to ordered branches"), - clEnumValN(eSwitchTypeLLVM, "llvm", - "lower using LLVM"), - clEnumValN(eSwitchTypeInternal, "internal", - "execute switch internally")), - cl::init(eSwitchTypeInternal), - cl::cat(ModuleCat)); cl::opt<bool> DebugPrintEscapingFunctions("debug-print-escaping-functions", @@ -102,14 +73,21 @@ namespace { cl::desc("Allow optimization of functions that " "contain KLEE calls (default=true)"), cl::init(true), cl::cat(ModuleCat)); -} +cl::opt<SwitchImplType> SwitchType( + "switch-type", + cl::desc("Select the implementation of switch (default=internal)"), + cl::values(clEnumValN(SwitchImplType::eSwitchTypeSimple, "simple", + "lower to ordered branches"), + clEnumValN(SwitchImplType::eSwitchTypeLLVM, "llvm", + "lower using LLVM"), + clEnumValN(SwitchImplType::eSwitchTypeInternal, "internal", + "execute switch internally")), + cl::init(SwitchImplType::eSwitchTypeInternal), cl::cat(ModuleCat)); + +} // namespace /***/ -namespace llvm { -extern void Optimize(Module *, llvm::ArrayRef<const char *> preservedFunctions); -} - // what a hack static Function *getStubFunctionForCtorList(Module *m, GlobalVariable *gv, @@ -156,9 +134,8 @@ static Function *getStubFunctionForCtorList(Module *m, return fn; } -static void -injectStaticConstructorsAndDestructors(Module *m, - llvm::StringRef entryFunction) { +void klee::injectStaticConstructorsAndDestructors( + Module *m, llvm::StringRef entryFunction) { GlobalVariable *ctors = m->getNamedGlobal("llvm.global_ctors"); GlobalVariable *dtors = m->getNamedGlobal("llvm.global_dtors"); @@ -216,44 +193,12 @@ bool KModule::link(std::vector<std::unique_ptr<llvm::Module>> &modules, } 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. - legacy::PassManager 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. - // - // NOTE: Must come before division/overshift checks because those passes - // don't know how to handle vector instructions. - pm.add(createScalarizerPass()); - - // This pass will replace atomic instructions with non-atomic operations - pm.add(createLowerAtomicPass()); - if (opts.CheckDivZero) pm.add(new DivCheckPass()); - if (opts.CheckOvershift) pm.add(new OvershiftCheckPass()); - - pm.add(new IntrinsicCleanerPass(*targetData)); - pm.run(*module); + klee::instrument(opts.CheckDivZero, opts.CheckOvershift, module.get()); } void KModule::optimiseAndPrepare( const Interpreter::ModuleOptions &opts, llvm::ArrayRef<const char *> preservedFunctions) { - // Preserve all functions containing klee-related function calls from being - // optimised around - if (!OptimiseKLEECall) { - legacy::PassManager pm; - pm.add(new OptNonePass()); - pm.run(*module); - } - - if (opts.Optimize) - Optimize(module.get(), preservedFunctions); - // Add internal functions which are not used to check if instructions // have been already visited if (opts.CheckDivZero) @@ -261,28 +206,8 @@ void KModule::optimiseAndPrepare( 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.get(), opts.EntryPoint); - - // Finally, run the passes that maintain invariants we expect during - // interpretation. We run the intrinsic cleaner just in case we - // linked in something with intrinsics but any external calls are - // going to be unresolved. We really need to handle the intrinsics - // directly I think? - legacy::PassManager pm3; - pm3.add(createCFGSimplificationPass()); - switch(SwitchType) { - case eSwitchTypeInternal: break; - case eSwitchTypeSimple: pm3.add(new LowerSwitchPass()); break; - case eSwitchTypeLLVM: pm3.add(createLowerSwitchPass()); break; - default: klee_error("invalid --switch-type"); - } - pm3.add(new IntrinsicCleanerPass(*targetData)); - pm3.add(createScalarizerPass()); - pm3.add(new PhiCleanerPass()); - pm3.add(new FunctionAliasPass()); - pm3.run(*module); + klee::optimiseAndPrepare(OptimiseKLEECall, opts.Optimize, SwitchType, + opts.EntryPoint, preservedFunctions, module.get()); } void KModule::manifest(InterpreterHandler *ih, bool forceSourceOutput) { @@ -294,7 +219,7 @@ void KModule::manifest(InterpreterHandler *ih, bool forceSourceOutput) { if (OutputModule) { std::unique_ptr<llvm::raw_fd_ostream> f(ih->openOutputFile("final.bc")); - WriteBitcodeToFile(*module, *f); + llvm::WriteBitcodeToFile(*module, *f); } /* Build shadow structures */ @@ -343,23 +268,7 @@ void KModule::manifest(InterpreterHandler *ih, bool forceSourceOutput) { } } -void KModule::checkModule() { - InstructionOperandTypeCheckPass *operandTypeCheckPass = - new InstructionOperandTypeCheckPass(); - - legacy::PassManager pm; - if (!DontVerify) - pm.add(createVerifierPass()); - pm.add(operandTypeCheckPass); - pm.run(*module); - - // Enforce the operand type invariants that the Executor expects. This - // implicitly depends on the "Scalarizer" pass to be run in order to succeed - // in the presence of vector instructions. - if (!operandTypeCheckPass->checkPassed()) { - klee_error("Unexpected instruction operand types detected"); - } -} +void KModule::checkModule() { klee::checkModule(DontVerify, module.get()); } KConstant* KModule::getKConstant(const Constant *c) { auto it = constantMap.find(c); |