diff options
Diffstat (limited to 'lib/Module')
-rw-r--r-- | lib/Module/Checks.cpp | 87 | ||||
-rw-r--r-- | lib/Module/InstructionInfoTable.cpp | 36 | ||||
-rw-r--r-- | lib/Module/IntrinsicCleaner.cpp | 91 | ||||
-rw-r--r-- | lib/Module/KModule.cpp | 147 | ||||
-rw-r--r-- | lib/Module/LowerSwitch.cpp | 4 | ||||
-rw-r--r-- | lib/Module/ModuleUtil.cpp | 42 | ||||
-rw-r--r-- | lib/Module/Optimize.cpp | 25 | ||||
-rw-r--r-- | lib/Module/Passes.h | 53 | ||||
-rw-r--r-- | lib/Module/RaiseAsm.cpp | 41 |
9 files changed, 296 insertions, 230 deletions
diff --git a/lib/Module/Checks.cpp b/lib/Module/Checks.cpp index 18ef398a..79fd4afc 100644 --- a/lib/Module/Checks.cpp +++ b/lib/Module/Checks.cpp @@ -11,6 +11,19 @@ #include "klee/Config/Version.h" +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/DataLayout.h" +#else #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" @@ -18,19 +31,22 @@ #include "llvm/Instruction.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) -#include "llvm/LLVMContext.h" -#endif #include "llvm/Module.h" -#include "llvm/Pass.h" #include "llvm/Type.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" + +#include "llvm/LLVMContext.h" + #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) #include "llvm/Target/TargetData.h" #else #include "llvm/DataLayout.h" #endif +#endif +#include "llvm/Pass.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Support/CallSite.h" +#include <iostream> using namespace llvm; using namespace klee; @@ -76,3 +92,62 @@ bool DivCheckPass::runOnModule(Module &M) { } return moduleChanged; } + +char OvershiftCheckPass::ID; + +bool OvershiftCheckPass::runOnModule(Module &M) { + Function *overshiftCheckFunction = 0; + + bool moduleChanged = false; + + for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) { + for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b) { + for (BasicBlock::iterator i = b->begin(), ie = b->end(); i != ie; ++i) { + if (BinaryOperator* binOp = dyn_cast<BinaryOperator>(i)) { + // find all shift instructions + Instruction::BinaryOps opcode = binOp->getOpcode(); + + if (opcode == Instruction::Shl || + opcode == Instruction::LShr || + opcode == Instruction::AShr ) { + std::vector<llvm::Value*> args; + + // Determine bit width of first operand + uint64_t bitWidth=i->getOperand(0)->getType()->getScalarSizeInBits(); + + ConstantInt *bitWidthC = ConstantInt::get(Type::getInt64Ty(getGlobalContext()),bitWidth,false); + args.push_back(bitWidthC); + + CastInst *shift = + CastInst::CreateIntegerCast(i->getOperand(1), + Type::getInt64Ty(getGlobalContext()), + false, /* sign doesn't matter */ + "int_cast_to_i64", + i); + args.push_back(shift); + + + // Lazily bind the function to avoid always importing it. + if (!overshiftCheckFunction) { + Constant *fc = M.getOrInsertFunction("klee_overshift_check", + Type::getVoidTy(getGlobalContext()), + Type::getInt64Ty(getGlobalContext()), + Type::getInt64Ty(getGlobalContext()), + NULL); + overshiftCheckFunction = cast<Function>(fc); + } + + // Inject CallInstr to check if overshifting possible +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 0) + CallInst::Create(overshiftCheckFunction, args, "", &*i); +#else + CallInst::Create(overshiftCheckFunction, args.begin(), args.end(), "", &*i); +#endif + moduleChanged = true; + } + } + } + } + } + return moduleChanged; +} diff --git a/lib/Module/InstructionInfoTable.cpp b/lib/Module/InstructionInfoTable.cpp index d0ef52d0..301db1ff 100644 --- a/lib/Module/InstructionInfoTable.cpp +++ b/lib/Module/InstructionInfoTable.cpp @@ -10,23 +10,26 @@ #include "klee/Internal/Module/InstructionInfoTable.h" #include "klee/Config/Version.h" +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#else #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" -#include "llvm/Linker.h" #include "llvm/Module.h" -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) -#include "llvm/Assembly/AsmAnnotationWriter.h" -#else +#endif +#include "llvm/Linker.h" #include "llvm/Assembly/AssemblyAnnotationWriter.h" #include "llvm/Support/FormattedStream.h" -#endif #include "llvm/Support/CFG.h" #include "llvm/Support/InstIterator.h" #include "llvm/Support/raw_ostream.h" #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 2) #include "llvm/DebugInfo.h" -#elif LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) +#else #include "llvm/Analysis/DebugInfo.h" #endif #include "llvm/Analysis/ValueTracking.h" @@ -39,12 +42,8 @@ using namespace klee; class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter { public: -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - void emitInstructionAnnot(const Instruction *i, llvm::raw_ostream &os) { -#else void emitInstructionAnnot(const Instruction *i, llvm::formatted_raw_ostream &os) { -#endif os << "%%%"; os << (uintptr_t) i; } @@ -76,18 +75,9 @@ static void buildInstructionToLineMap(Module *m, } } -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 7) -static std::string getDSPIPath(const DbgStopPointInst *dspi) { - std::string dir, file; - bool res = GetConstantStringInfo(dspi->getDirectory(), dir); - assert(res && "GetConstantStringInfo failed"); - res = GetConstantStringInfo(dspi->getFileName(), file); - assert(res && "GetConstantStringInfo failed"); -#else static std::string getDSPIPath(DILocation Loc) { std::string dir = Loc.getDirectory(); std::string file = Loc.getFilename(); -#endif if (dir.empty() || file[0] == '/') { return file; } else if (*dir.rbegin() == '/') { @@ -100,20 +90,12 @@ static std::string getDSPIPath(DILocation Loc) { bool InstructionInfoTable::getInstructionDebugInfo(const llvm::Instruction *I, const std::string *&File, unsigned &Line) { -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 7) - if (const DbgStopPointInst *dspi = dyn_cast<DbgStopPointInst>(I)) { - File = internString(getDSPIPath(dspi)); - Line = dspi->getLine(); - return true; - } -#else if (MDNode *N = I->getMetadata("dbg")) { DILocation Loc(N); File = internString(getDSPIPath(Loc)); Line = Loc.getLineNumber(); return true; } -#endif return false; } diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp index 2f18c17e..0f095269 100644 --- a/lib/Module/IntrinsicCleaner.cpp +++ b/lib/Module/IntrinsicCleaner.cpp @@ -10,6 +10,19 @@ #include "Passes.h" #include "klee/Config/Version.h" +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/IRBuilder.h" + +#else #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" @@ -17,24 +30,23 @@ #include "llvm/Instruction.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) #include "llvm/LLVMContext.h" -#endif #include "llvm/Module.h" -#include "llvm/Pass.h" #include "llvm/Type.h" #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 2) #include "llvm/IRBuilder.h" #else #include "llvm/Support/IRBuilder.h" #endif -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) #include "llvm/Target/TargetData.h" #else #include "llvm/DataLayout.h" #endif +#endif +#include "llvm/Pass.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" using namespace llvm; @@ -46,11 +58,13 @@ bool IntrinsicCleanerPass::runOnModule(Module &M) { bool dirty = false; for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b) - dirty |= runOnBasicBlock(*b); + dirty |= runOnBasicBlock(*b, M); + if (Function *Declare = M.getFunction("llvm.trap")) + Declare->eraseFromParent(); return dirty; } -bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { +bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) { bool dirty = false; #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) @@ -74,13 +88,8 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { // FIXME: This is much more target dependent than just the word size, // however this works for x86-32 and x86-64. case Intrinsic::vacopy: { // (dst, src) -> *((i8**) dst) = *((i8**) src) -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - Value *dst = ii->getOperand(1); - Value *src = ii->getOperand(2); -#else Value *dst = ii->getArgOperand(0); Value *src = ii->getArgOperand(1); -#endif if (WordSize == 4) { Type *i8pp = PointerType::getUnqual(PointerType::getUnqual(Type::getInt8Ty(getGlobalContext()))); @@ -111,13 +120,8 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { case Intrinsic::umul_with_overflow: { IRBuilder<> builder(ii->getParent(), ii); -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - Value *op1 = ii->getOperand(1); - Value *op2 = ii->getOperand(2); -#else Value *op1 = ii->getArgOperand(0); Value *op2 = ii->getArgOperand(1); -#endif Value *result = 0; if (ii->getIntrinsicID() == Intrinsic::uadd_with_overflow) @@ -138,42 +142,7 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { break; } -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 7) - case Intrinsic::dbg_stoppoint: { - // We can remove this stoppoint if the next instruction is - // sure to be another stoppoint. This is nice for cleanliness - // but also important for switch statements where it can allow - // the targets to be joined. - bool erase = false; - if (isa<DbgStopPointInst>(i) || - isa<UnreachableInst>(i)) { - erase = true; - } else if (isa<BranchInst>(i) || - isa<SwitchInst>(i)) { - BasicBlock *bb = i->getParent(); - erase = true; - for (succ_iterator it=succ_begin(bb), ie=succ_end(bb); - it!=ie; ++it) { - if (!isa<DbgStopPointInst>(it->getFirstNonPHI())) { - erase = false; - break; - } - } - } - - if (erase) { - ii->eraseFromParent(); - dirty = true; - } - break; - } - - case Intrinsic::dbg_region_start: - case Intrinsic::dbg_region_end: - case Intrinsic::dbg_func_start: -#else case Intrinsic::dbg_value: -#endif case Intrinsic::dbg_declare: // Remove these regardless of lower intrinsics flag. This can // be removed once IntrinsicLowering is fixed to not have bad @@ -181,6 +150,24 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { ii->eraseFromParent(); dirty = true; break; + + case Intrinsic::trap: { + // Intrisic instruction "llvm.trap" found. Directly lower it to + // a call of the abort() function. + Function *F = cast<Function>( + M.getOrInsertFunction( + "abort", Type::getVoidTy(getGlobalContext()), NULL)); + F->setDoesNotReturn(); + F->setDoesNotThrow(); + + CallInst::Create(F, Twine(), ii); + new UnreachableInst(getGlobalContext(), ii); + + ii->eraseFromParent(); + + dirty = true; + break; + } default: if (LowerIntrinsics) diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 1629bb79..d889b51f 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -22,31 +22,37 @@ #include "klee/Internal/Support/ModuleUtil.h" #include "llvm/Bitcode/ReaderWriter.h" +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/ValueSymbolTable.h" +#include "llvm/IR/DataLayout.h" +#else #include "llvm/Instructions.h" -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) #include "llvm/LLVMContext.h" -#endif #include "llvm/Module.h" -#include "llvm/PassManager.h" #include "llvm/ValueSymbolTable.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/raw_ostream.h" -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) -#include "llvm/Support/raw_os_ostream.h" -#endif -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 9) -#include "llvm/System/Path.h" -#else -#include "llvm/Support/Path.h" -#endif #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) #include "llvm/Target/TargetData.h" #else #include "llvm/DataLayout.h" #endif + +#endif + +#include "llvm/PassManager.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/raw_os_ostream.h" +#include "llvm/Support/Path.h" #include "llvm/Transforms/Scalar.h" +#include <llvm/Transforms/Utils/Cloning.h> +#include <llvm/Support/InstIterator.h> +#include <llvm/Support/Debug.h> + #include <sstream> using namespace llvm; @@ -99,7 +105,6 @@ KModule::KModule(Module *_module) #else targetData(new DataLayout(module)), #endif - dbgStopPointFn(0), kleeMergeFn(0), infos(0), constantTable(0) { @@ -113,6 +118,10 @@ KModule::~KModule() { ie = functions.end(); it != ie; ++it) delete *it; + for (std::map<llvm::Constant*, KConstant*>::iterator it=constantMap.begin(), + itE=constantMap.end(); it!=itE;++it) + delete it->second; + delete targetData; delete module; } @@ -189,6 +198,7 @@ static void injectStaticConstructorsAndDestructors(Module *m) { } } +#if LLVM_VERSION_CODE < LLVM_VERSION(3, 3) static void forceImport(Module *m, const char *name, LLVM_TYPE_Q Type *retType, ...) { // If module lacks an externally visible symbol for the name then we @@ -211,6 +221,53 @@ static void forceImport(Module *m, const char *name, LLVM_TYPE_Q Type *retType, m->getOrInsertFunction(name, FunctionType::get(retType, argTypes, false)); } } +#endif + +/// This function will take try to inline all calls to \p functionName +/// in the module \p module . +/// +/// It is intended that this function be used for inling calls to +/// check functions like <tt>klee_div_zero_check()</tt> +static void inlineChecks(Module *module, const char * functionName) { + std::vector<CallInst*> checkCalls; + Function* runtimeCheckCall = module->getFunction(functionName); + if (runtimeCheckCall == 0) + { + DEBUG( klee_warning("Failed to inline %s because no calls were made to it in module", functionName) ); + return; + } + + // Iterate through instructions in module and collect all + // call instructions to "functionName" that we care about. + for (Module::iterator f = module->begin(), fe = module->end(); f != fe; ++f) { + for (inst_iterator i=inst_begin(f), ie = inst_end(f); i != ie; ++i) { + if ( CallInst* ci = dyn_cast<CallInst>(&*i) ) + { + if ( ci->getCalledFunction() == runtimeCheckCall) + checkCalls.push_back(ci); + } + } + } + + unsigned int successCount=0; + unsigned int failCount=0; + InlineFunctionInfo IFI(0,0); + for ( std::vector<CallInst*>::iterator ci = checkCalls.begin(), + cie = checkCalls.end(); + ci != cie; ++ci) + { + // Try to inline the function + if (InlineFunction(*ci,IFI)) + ++successCount; + else + { + ++failCount; + klee_warning("Failed to inline function %s", functionName); + } + } + + DEBUG( klee_message("Tried to inline calls to %s. %u successes, %u failures",functionName, successCount, failCount) ); +} void KModule::prepare(const Interpreter::ModuleOptions &opts, InterpreterHandler *ih) { @@ -272,6 +329,7 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, PassManager pm; pm.add(new RaiseAsmPass()); if (opts.CheckDivZero) pm.add(new DivCheckPass()); + if (opts.CheckOvershift) pm.add(new OvershiftCheckPass()); // FIXME: This false here is to work around a bug in // IntrinsicLowering which caches values which may eventually be // deleted (via RAUW). This can be removed once LLVM fixes this @@ -281,7 +339,7 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, if (opts.Optimize) Optimize(module); - +#if LLVM_VERSION_CODE < LLVM_VERSION(3, 3) // Force importing functions required by intrinsic lowering. Kind of // unfortunate clutter when we don't need them but we won't know // that until after all linking and intrinsic lowering is @@ -302,16 +360,33 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, PointerType::getUnqual(i8Ty), Type::getInt32Ty(getGlobalContext()), targetData->getIntPtrType(getGlobalContext()), (Type*) 0); - +#endif // 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. llvm::sys::Path path(opts.LibraryDir); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) + path.appendComponent("kleeRuntimeIntrinsic.bc"); +#else path.appendComponent("libkleeRuntimeIntrinsic.bca"); +#endif module = linkWithLibrary(module, path.c_str()); + /* In order for KLEE to report ALL errors at instrumented + * locations the instrumentation call (e.g. "klee_div_zero_check") + * must be inlined. Otherwise one of the instructions in the + * instrumentation function will be used as the the location of + * the error which means that the error cannot be recorded again + * ( unless -emit-all-errors is used). + */ + if (opts.CheckDivZero) + inlineChecks(module, "klee_div_zero_check"); + if (opts.CheckOvershift) + inlineChecks(module, "klee_overshift_check"); + + // Needs to happen after linking (since ctors/dtors can be modified) // and optimization (since global optimization can rewrite lists). injectStaticConstructorsAndDestructors(module); @@ -332,7 +407,7 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, pm3.add(new IntrinsicCleanerPass(*targetData)); pm3.add(new PhiCleanerPass()); pm3.run(*module); - +#if LLVM_VERSION_CODE < LLVM_VERSION(3, 3) // For cleanliness see if we can discard any of the functions we // forced to import. Function *f; @@ -342,7 +417,7 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, if (f && f->use_empty()) f->eraseFromParent(); f = module->getFunction("memset"); if (f && f->use_empty()) f->eraseFromParent(); - +#endif // Write out the .ll assembly file. We truncate long lines to work // around a kcachegrind parsing bug (it puts them on new lines), so @@ -351,38 +426,6 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, std::ostream *os = ih->openOutputFile("assembly.ll"); assert(os && os->good() && "unable to open source output"); -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 6) - // We have an option for this in case the user wants a .ll they - // can compile. - if (NoTruncateSourceLines) { - os << *module; - } else { - bool truncated = false; - std::string string; - llvm::raw_string_ostream rss(string); - rss << *module; - rss.flush(); - const char *position = string.c_str(); - - for (;;) { - const char *end = index(position, '\n'); - if (!end) { - os << position; - break; - } else { - unsigned count = (end - position) + 1; - if (count<255) { - os->write(position, count); - } else { - os->write(position, 254); - os << "\n"; - truncated = true; - } - position = end+1; - } - } - } -#else llvm::raw_os_ostream *ros = new llvm::raw_os_ostream(*os); // We have an option for this in case the user wants a .ll they @@ -414,7 +457,6 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, } } delete ros; -#endif delete os; } @@ -427,7 +469,6 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, delete f; } - dbgStopPointFn = module->getFunction("llvm.dbg.stoppoint"); kleeMergeFn = module->getFunction("klee_merge"); /* Build shadow structures */ diff --git a/lib/Module/LowerSwitch.cpp b/lib/Module/LowerSwitch.cpp index e5382c1a..a98b84ad 100644 --- a/lib/Module/LowerSwitch.cpp +++ b/lib/Module/LowerSwitch.cpp @@ -16,7 +16,9 @@ #include "Passes.h" #include "klee/Config/Version.h" -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/LLVMContext.h" +#else #include "llvm/LLVMContext.h" #endif #include <algorithm> diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp index 029540ae..fcdfa35a 100644 --- a/lib/Module/ModuleUtil.cpp +++ b/lib/Module/ModuleUtil.cpp @@ -10,26 +10,30 @@ #include "klee/Internal/Support/ModuleUtil.h" #include "klee/Config/Version.h" +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/DataStream.h" +#else #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" -#include "llvm/Linker.h" #include "llvm/Module.h" -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) -#include "llvm/Assembly/AsmAnnotationWriter.h" -#else -#include "llvm/Assembly/AssemblyAnnotationWriter.h" #endif + +#include "llvm/Linker.h" +#include "llvm/Assembly/AssemblyAnnotationWriter.h" #include "llvm/Support/CFG.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/InstIterator.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Analysis/ValueTracking.h" -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 9) -#include "llvm/System/Path.h" -#else #include "llvm/Support/Path.h" -#endif #include <map> #include <iostream> @@ -42,6 +46,20 @@ using namespace klee; Module *klee::linkWithLibrary(Module *module, const std::string &libraryName) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) + SMDiagnostic err; + std::string err_str; + sys::Path libraryPath(libraryName); + Module *new_mod = ParseIRFile(libraryPath.str(), err, +module->getContext()); + + if (Linker::LinkModules(module, new_mod, Linker::DestroySource, +&err_str)) { + assert(0 && "linked in library failed!"); + } + + return module; +#else Linker linker("klee", module, false); llvm::sys::Path libraryPath(libraryName); @@ -52,6 +70,7 @@ Module *klee::linkWithLibrary(Module *module, } return linker.releaseModule(); +#endif } Function *klee::getDirectCallTarget(CallSite cs) { @@ -72,13 +91,8 @@ Function *klee::getDirectCallTarget(CallSite cs) { } static bool valueIsOnlyCalled(const Value *v) { -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - for (Value::use_const_iterator it = v->use_begin(), ie = v->use_end(); - it != ie; ++it) { -#else for (Value::const_use_iterator it = v->use_begin(), ie = v->use_end(); it != ie; ++it) { -#endif if (const Instruction *instr = dyn_cast<Instruction>(*it)) { if (instr->getOpcode()==0) continue; // XXX function numbering inst if (!isa<CallInst>(instr) && !isa<InvokeInst>(instr)) return false; diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index 6da9a2c1..41a106f1 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -16,22 +16,25 @@ //===----------------------------------------------------------------------===// #include "klee/Config/Version.h" -#include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Support/CommandLine.h" -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 9) -#include "llvm/System/DynamicLibrary.h" -#else #include "llvm/Support/DynamicLibrary.h" -#endif + +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/Module.h" +#include "llvm/IR/DataLayout.h" +#else +#include "llvm/Module.h" #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) #include "llvm/Target/TargetData.h" #else #include "llvm/DataLayout.h" #endif +#endif + #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Scalar.h" @@ -105,9 +108,6 @@ static void AddStandardCompilePasses(PassManager &PM) { if (DisableOptimizations) return; -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 7) - addPass(PM, createRaiseAllocationsPass()); // call %malloc -> malloc inst -#endif addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas addPass(PM, createGlobalOptimizerPass()); // Optimize out global vars @@ -130,9 +130,6 @@ static void AddStandardCompilePasses(PassManager &PM) { addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas addPass(PM, createInstructionCombiningPass()); // Combine silly seq's -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 7) - addPass(PM, createCondPropagationPass()); // Propagate conditionals -#endif addPass(PM, createTailCallEliminationPass()); // Eliminate tail calls addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs @@ -140,9 +137,6 @@ static void AddStandardCompilePasses(PassManager &PM) { addPass(PM, createLoopRotatePass()); addPass(PM, createLICMPass()); // Hoist loop invariants addPass(PM, createLoopUnswitchPass()); // Unswitch loops. -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 9) - addPass(PM, createLoopIndexSplitPass()); // Index split loops. -#endif // FIXME : Removing instcombine causes nestedloop regression. addPass(PM, createInstructionCombiningPass()); addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars @@ -156,9 +150,6 @@ static void AddStandardCompilePasses(PassManager &PM) { // Run instcombine after redundancy elimination to exploit opportunities // opened up by them. addPass(PM, createInstructionCombiningPass()); -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 7) - addPass(PM, createCondPropagationPass()); // Propagate conditionals -#endif addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores addPass(PM, createAggressiveDCEPass()); // Delete dead instructions diff --git a/lib/Module/Passes.h b/lib/Module/Passes.h index b3c46124..accb64d0 100644 --- a/lib/Module/Passes.h +++ b/lib/Module/Passes.h @@ -12,9 +12,15 @@ #include "klee/Config/Version.h" +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#else #include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Module.h" +#endif #include "llvm/Pass.h" #include "llvm/CodeGen/IntrinsicLowering.h" @@ -38,9 +44,7 @@ namespace klee { class RaiseAsmPass : public llvm::ModulePass { static char ID; -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 9) const llvm::TargetLowering *TLI; -#endif llvm::Function *getIntrinsic(llvm::Module &M, unsigned IID, @@ -55,11 +59,7 @@ class RaiseAsmPass : public llvm::ModulePass { bool runOnInstruction(llvm::Module &M, llvm::Instruction *I); public: -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - RaiseAsmPass() : llvm::ModulePass((intptr_t) &ID) {} -#else - RaiseAsmPass() : llvm::ModulePass(ID) {} -#endif + RaiseAsmPass() : llvm::ModulePass(ID), TLI(0) {} virtual bool runOnModule(llvm::Module &M); }; @@ -76,7 +76,7 @@ class IntrinsicCleanerPass : public llvm::ModulePass { llvm::IntrinsicLowering *IL; bool LowerIntrinsics; - bool runOnBasicBlock(llvm::BasicBlock &b); + bool runOnBasicBlock(llvm::BasicBlock &b, llvm::Module &M); public: #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) IntrinsicCleanerPass(const llvm::TargetData &TD, @@ -84,11 +84,7 @@ public: IntrinsicCleanerPass(const llvm::DataLayout &TD, #endif bool LI=true) -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - : llvm::ModulePass((intptr_t) &ID), -#else : llvm::ModulePass(ID), -#endif #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) TargetData(TD), #else @@ -117,11 +113,7 @@ class PhiCleanerPass : public llvm::FunctionPass { static char ID; public: -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - PhiCleanerPass() : llvm::FunctionPass((intptr_t) &ID) {} -#else PhiCleanerPass() : llvm::FunctionPass(ID) {} -#endif virtual bool runOnFunction(llvm::Function &f); }; @@ -129,11 +121,28 @@ public: class DivCheckPass : public llvm::ModulePass { static char ID; public: -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - DivCheckPass(): ModulePass((intptr_t) &ID) {} -#else DivCheckPass(): ModulePass(ID) {} -#endif + virtual bool runOnModule(llvm::Module &M); +}; + +/// This pass injects checks to check for overshifting. +/// +/// Overshifting is where a Shl, LShr or AShr is performed +/// where the shift amount is greater than width of the bitvector +/// being shifted. +/// In LLVM (and in C/C++) this undefined behaviour! +/// +/// Example: +/// \code +/// unsigned char x=15; +/// x << 4 ; // Defined behaviour +/// x << 8 ; // Undefined behaviour +/// x << 255 ; // Undefined behaviour +/// \endcode +class OvershiftCheckPass : public llvm::ModulePass { + static char ID; +public: + OvershiftCheckPass(): ModulePass(ID) {} virtual bool runOnModule(llvm::Module &M); }; @@ -143,11 +152,7 @@ public: class LowerSwitchPass : public llvm::FunctionPass { public: static char ID; // Pass identification, replacement for typeid -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - LowerSwitchPass() : FunctionPass((intptr_t) &ID) {} -#else LowerSwitchPass() : FunctionPass(ID) {} -#endif virtual bool runOnFunction(llvm::Function &F); diff --git a/lib/Module/RaiseAsm.cpp b/lib/Module/RaiseAsm.cpp index b5526f35..d9145a1e 100644 --- a/lib/Module/RaiseAsm.cpp +++ b/lib/Module/RaiseAsm.cpp @@ -9,12 +9,14 @@ #include "Passes.h" #include "klee/Config/Version.h" - +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" +#else #include "llvm/InlineAsm.h" -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) #include "llvm/LLVMContext.h" #endif -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 9) + #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Target/TargetLowering.h" @@ -23,7 +25,6 @@ #else #include "llvm/Support/TargetRegistry.h" #endif -#endif using namespace llvm; using namespace klee; @@ -47,38 +48,8 @@ Function *RaiseAsmPass::getIntrinsic(llvm::Module &M, bool RaiseAsmPass::runOnInstruction(Module &M, Instruction *I) { if (CallInst *ci = dyn_cast<CallInst>(I)) { if (InlineAsm *ia = dyn_cast<InlineAsm>(ci->getCalledValue())) { -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 9) (void) ia; return TLI && TLI->ExpandInlineAsm(ci); -#else - const std::string &as = ia->getAsmString(); - const std::string &cs = ia->getConstraintString(); - const llvm::Type *T = ci->getType(); - - // bswaps -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - unsigned NumOperands = ci->getNumOperands(); - llvm::Value *Arg0 = NumOperands > 1 ? ci->getOperand(1) : 0; -#else - unsigned NumOperands = ci->getNumArgOperands() + 1; - llvm::Value *Arg0 = NumOperands > 1 ? ci->getArgOperand(0) : 0; -#endif - if (Arg0 && T == Arg0->getType() && - ((T == llvm::Type::getInt16Ty(getGlobalContext()) && - as == "rorw $$8, ${0:w}" && - cs == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") || - (T == llvm::Type::getInt32Ty(getGlobalContext()) && - as == "rorw $$8, ${0:w};rorl $$16, $0;rorw $$8, ${0:w}" && - cs == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}"))) { - Function *F = getIntrinsic(M, Intrinsic::bswap, Arg0->getType()); -#if LLVM_VERSION_CODE < LLVM_VERSION(2, 8) - ci->setOperand(0, F); -#else - ci->setCalledFunction(F); -#endif - return true; - } -#endif } } @@ -88,7 +59,6 @@ bool RaiseAsmPass::runOnInstruction(Module &M, Instruction *I) { bool RaiseAsmPass::runOnModule(Module &M) { bool changed = false; -#if LLVM_VERSION_CODE >= LLVM_VERSION(2, 9) std::string Err; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 1) std::string HostTriple = llvm::sys::getDefaultTargetTriple(); @@ -110,7 +80,6 @@ bool RaiseAsmPass::runOnModule(Module &M) { #endif TLI = TM->getTargetLowering(); } -#endif for (Module::iterator fi = M.begin(), fe = M.end(); fi != fe; ++fi) { for (Function::iterator bi = fi->begin(), be = fi->end(); bi != be; ++bi) { |