From: =?UTF-8?q?Richard=20Trembeck=C3=BD?= Date: Sun, 1 May 2016 16:38:21 +0200 Subject: Make KLEE compile against LLVM 3.5 and 3.6 Patch-mainline: no Based on work by @ccadeptic23 and @delcypher. Formatting fixed by @snf. Fix compiler warning by @martijnthe. Further fixes by @mchalupa. Signed-off-by: Jiri Slaby --- Makefile.rules | 10 +- lib/Core/Executor.cpp | 43 ++++++-- lib/Core/ExternalDispatcher.cpp | 34 ++++-- lib/Core/ExternalDispatcher.h | 8 +- lib/Core/StatsTracker.cpp | 11 +- lib/Module/KModule.cpp | 27 +++-- lib/Module/ModuleUtil.cpp | 225 +++++++++++++++++++++++++++----------- lib/Module/Optimize.cpp | 17 ++- lib/Module/RaiseAsm.cpp | 17 ++- lib/Solver/QueryLoggingSolver.cpp | 5 +- lib/Solver/QueryLoggingSolver.h | 3 + lib/Support/CompressionStream.cpp | 19 +++- test/lit.cfg | 2 +- tools/klee/Makefile | 10 +- tools/klee/main.cpp | 31 +++++- 15 files changed, 341 insertions(+), 121 deletions(-) diff --git a/Makefile.rules b/Makefile.rules index d74b1c42b4aa..06cbbec683f2 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -1618,16 +1618,22 @@ $(ObjDir)/%.s: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(Compile.C) $< -o $@ -S +#which PARAM to send to LOPT +LOPT_PARAM = -std-compile-opts +ifeq ($(shell python -c "print($(LLVM_VERSION_MAJOR).$(LLVM_VERSION_MINOR) >= 3.6)"), True) +LOPT_PARAM = -std-link-opts +endif + # make the C and C++ compilers strip debug info out of bytecode libraries. ifdef DEBUG_RUNTIME $(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LLVMAS) $(LOPT) $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" - $(Verb) $(LLVMAS) $< -o - | $(LOPT) -std-compile-opts -o $@ + $(Verb) $(LLVMAS) $< -o - | $(LOPT) $(LOPT_PARAM) -o $@ else $(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LLVMAS) $(LOPT) $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" $(Verb) $(LLVMAS) $< -o - | \ - $(LOPT) -std-compile-opts -strip-debug -o $@ + $(LOPT) $(LOPT_PARAM) -strip-debug -o $@ endif diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 58603e7ca146..80b8289d1486 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -82,6 +82,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/FileSystem.h" #if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) #include "llvm/Support/CallSite.h" @@ -93,6 +94,10 @@ #include "klee/Internal/Support/CompressionStream.h" #endif +#if LLVM_VERSION_CODE > LLVM_VERSION(3, 5) +#include +#endif + #include #include #include @@ -376,12 +381,19 @@ Executor::Executor(const InterpreterOptions &opts, InterpreterHandler *ih) optionIsSet(DebugPrintInstructions, FILE_SRC)) { std::string debug_file_name = interpreterHandler->getOutputFilename("instructions.txt"); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + std::error_code EC; +#endif std::string ErrorInfo; + #ifdef HAVE_ZLIB_H if (!DebugCompressInstructions) { #endif -#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + debugInstFile = new llvm::raw_fd_ostream(debug_file_name.c_str(), EC, + llvm::sys::fs::OpenFlags::F_Text); +#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) debugInstFile = new llvm::raw_fd_ostream(debug_file_name.c_str(), ErrorInfo, llvm::sys::fs::OpenFlags::F_Text); #else @@ -394,7 +406,12 @@ Executor::Executor(const InterpreterOptions &opts, InterpreterHandler *ih) (debug_file_name + ".gz").c_str(), ErrorInfo); } #endif +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + if (EC) { + ErrorInfo = EC.message(); +#else if (ErrorInfo != "") { +#endif klee_error("Could not open file %s : %s", debug_file_name.c_str(), ErrorInfo.c_str()); } @@ -1471,9 +1488,13 @@ Function* Executor::getTargetFunction(Value *calledVal, ExecutionState &state) { while (true) { if (GlobalValue *gv = dyn_cast(c)) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + if (!Visited.insert(gv).second) + return 0; +#else if (!Visited.insert(gv)) return 0; - +#endif std::string alias = state.getFnAlias(gv->getName()); if (alias != "") { llvm::Module* currModule = kmodule->module; @@ -1484,7 +1505,7 @@ Function* Executor::getTargetFunction(Value *calledVal, ExecutionState &state) { old_gv->getName().str().c_str()); } } - + if (Function *f = dyn_cast(gv)) return f; else if (GlobalAlias *ga = dyn_cast(gv)) @@ -1646,8 +1667,8 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { if (ConstantExpr *CE = dyn_cast(cond)) { // Somewhat gross to create these all the time, but fine till we // switch to an internal rep. - LLVM_TYPE_Q llvm::IntegerType *Ty = - cast(si->getCondition()->getType()); + LLVM_TYPE_Q llvm::IntegerType *Ty = + cast(si->getCondition()->getType()); ConstantInt *ci = ConstantInt::get(Ty, CE->getZExtValue()); #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 1) unsigned index = si->findCaseValue(ci).getSuccessorIndex(); @@ -1703,7 +1724,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { bool result; bool success = solver->mayBeTrue(state, match, result); assert(success && "FIXME: Unhandled solver failure"); - (void) success; + (void)success; if (result) { BasicBlock *caseSuccessor = it->second; @@ -3072,8 +3093,16 @@ void Executor::callExternalFunction(ExecutionState &state, else klee_warning_once(function, "%s", os.str().c_str()); } - +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + // MCJIT needs unique module, so we create quick external dispatcher for call. + // reference: + // http://blog.llvm.org/2013/07/using-mcjit-with-kaleidoscope-tutorial.html + ExternalDispatcher *e = new ExternalDispatcher(); + bool success = e->executeCall(function, target->inst, args); + delete e; +#else bool success = externalDispatcher->executeCall(function, target->inst, args); +#endif if (!success) { terminateStateOnError(state, "failed external call: " + function->getName(), External); diff --git a/lib/Core/ExternalDispatcher.cpp b/lib/Core/ExternalDispatcher.cpp index ecc9912e9b57..09dd715a53ae 100644 --- a/lib/Core/ExternalDispatcher.cpp +++ b/lib/Core/ExternalDispatcher.cpp @@ -23,7 +23,12 @@ #include "llvm/Instructions.h" #include "llvm/LLVMContext.h" #endif +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) +#include "llvm/ExecutionEngine/MCJIT.h" +#else #include "llvm/ExecutionEngine/JIT.h" +#endif + #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/raw_ostream.h" @@ -89,7 +94,12 @@ ExternalDispatcher::ExternalDispatcher() { dispatchModule = new Module("ExternalDispatcher", getGlobalContext()); std::string error; +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + dispatchModule_uniptr.reset(dispatchModule); + executionEngine = EngineBuilder(std::move(dispatchModule_uniptr)).create(); +#else executionEngine = ExecutionEngine::createJIT(dispatchModule, &error); +#endif if (!executionEngine) { llvm::errs() << "unable to make jit: " << error << "\n"; abort(); @@ -98,6 +108,10 @@ ExternalDispatcher::ExternalDispatcher() { // If we have a native target, initialize it to ensure it is linked in and // usable by the JIT. llvm::InitializeNativeTarget(); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + llvm::InitializeNativeTargetAsmParser(); + llvm::InitializeNativeTargetAsmPrinter(); +#endif // from ExecutionEngine::create if (executionEngine) { @@ -146,7 +160,11 @@ bool ExternalDispatcher::executeCall(Function *f, Instruction *i, uint64_t *args // ensures that any errors or assertions in the compilation process will // trigger crashes instead of being caught as aborts in the external // function. +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + executionEngine->finalizeObject(); +#else executionEngine->recompileAndRelinkFunction(dispatcher); +#endif } } else { dispatcher = it->second; @@ -205,13 +223,12 @@ Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *in Value **args = new Value*[cs.arg_size()]; std::vector nullary; - - Function *dispatcher = Function::Create(FunctionType::get(Type::getVoidTy(getGlobalContext()), - nullary, false), - GlobalVariable::ExternalLinkage, - "", - dispatchModule); + // For MCJIT functions need unique names, or wrong func can be called + Function *dispatcher = Function::Create( + FunctionType::get(Type::getVoidTy(getGlobalContext()), nullary, false), + GlobalVariable::ExternalLinkage, "dispatcher_" + target->getName().str(), + dispatchModule); BasicBlock *dBB = BasicBlock::Create(getGlobalContext(), "entry", dispatcher); @@ -254,9 +271,8 @@ Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *in dispatchModule->getOrInsertFunction(target->getName(), FTy, target->getAttributes()); #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 0) - Instruction *result = CallInst::Create(dispatchTarget, - llvm::ArrayRef(args, args+i), - "", dBB); + Instruction *result = CallInst::Create( + dispatchTarget, llvm::ArrayRef(args, args + i), "", dBB); #else Instruction *result = CallInst::Create(dispatchTarget, args, args+i, "", dBB); #endif diff --git a/lib/Core/ExternalDispatcher.h b/lib/Core/ExternalDispatcher.h index d8d9dc58b089..e2fb63cd12b4 100644 --- a/lib/Core/ExternalDispatcher.h +++ b/lib/Core/ExternalDispatcher.h @@ -9,11 +9,11 @@ #ifndef KLEE_EXTERNALDISPATCHER_H #define KLEE_EXTERNALDISPATCHER_H - +#include "klee/Config/Version.h" #include #include #include - +#include namespace llvm { class ExecutionEngine; class Instruction; @@ -27,6 +27,10 @@ namespace klee { private: typedef std::map dispatchers_ty; dispatchers_ty dispatchers; + + #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + std::unique_ptr dispatchModule_uniptr; + #endif llvm::Module *dispatchModule; llvm::ExecutionEngine *executionEngine; std::map preboundFunctions; diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index dbd865248756..ded85f950fe4 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -206,13 +206,16 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, if (!sys::path::is_absolute(objectFilename)) { SmallString<128> current(objectFilename); if(sys::fs::make_absolute(current)) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + Twine current_twine(current.str()); // requires a twine for this. so silly + if (!sys::fs::exists(current_twine)) { +#elif LLVM_VERSION_CODE == LLVM_VERSION(3, 5) + bool exists = false; + if (!sys::fs::exists(current.str(), exists)) { +#elif LLVM_VERSION_CODE < LLVM_VERSION(3, 5) bool exists = false; - -#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) error_code ec = sys::fs::exists(current.str(), exists); if (ec == errc::success && exists) { -#else - if (!sys::fs::exists(current.str(), exists)) { #endif objectFilename = current.c_str(); } diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 57346a315a1b..598c439f9da0 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -144,11 +144,9 @@ static Function *getStubFunctionForCtorList(Module *m, std::vector nullary; - Function *fn = Function::Create(FunctionType::get(Type::getVoidTy(getGlobalContext()), - nullary, false), - GlobalVariable::InternalLinkage, - name, - m); + Function *fn = Function::Create( + FunctionType::get(Type::getVoidTy(getGlobalContext()), nullary, false), + GlobalVariable::InternalLinkage, name, m); BasicBlock *bb = BasicBlock::Create(getGlobalContext(), "entry", fn); // From lli: @@ -158,8 +156,15 @@ static Function *getStubFunctionForCtorList(Module *m, if (arr) { for (unsigned i=0; igetNumOperands(); i++) { ConstantStruct *cs = cast(arr->getOperand(i)); - assert(cs->getNumOperands()==2 && "unexpected element in ctor initializer list"); - +#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) + assert(cs->getNumOperands() == 2 && + "unexpected element in ctor initializer list"); +#else + // There is a third *optional* element in global_ctor elements (``i8 + // @data``). + assert((cs->getNumOperands() == 2 || cs->getNumOperands() == 3) && + "unexpected element in ctor initializer list"); +#endif Constant *fp = cs->getOperand(1); if (!fp->isNullValue()) { if (llvm::ConstantExpr *ce = dyn_cast(fp)) @@ -509,8 +514,12 @@ static int getOperandNum(Value *v, return registerMap[inst]; } else if (Argument *a = dyn_cast(v)) { return a->getArgNo(); - } else if (isa(v) || isa(v) || - isa(v)) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + // Metadata is no longer a Value + } else if (isa(v) || isa(v)) { +#else + } else if (isa(v) || isa(v) || isa(v)) { +#endif return -1; } else { assert(isa(v)); diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp index 2cd41c891181..537c9aba4b6f 100644 --- a/lib/Module/ModuleUtil.cpp +++ b/lib/Module/ModuleUtil.cpp @@ -212,78 +212,101 @@ static bool linkBCA(object::Archive* archive, Module* composite, std::string& er KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Loading modules\n"); // Load all bitcode files in to memory so we can examine their symbols +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) + for (object::Archive::child_iterator AI = archive->child_begin(), + AE = archive->child_end(); + AI != AE; ++AI) +#else + for (object::Archive::child_iterator AI = archive->begin_children(), - AE = archive->end_children(); AI != AE; ++AI) + AE = archive->end_children(); + AI != AE; ++AI) +#endif { - StringRef memberName; +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) + ErrorOr errorOr_memberName = AI->getName(); + std::error_code ec = errorOr_memberName.getError(); + if (!ec) + memberName = errorOr_memberName.get(); +#else error_code ec = AI->getName(memberName); - - if ( ec == errc::success ) - { +#endif + if (!ec) { KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Loading archive member " << memberName << "\n"); - } - else - { + } else { errorMessage="Archive member does not have a name!\n"; return false; } - +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) + ErrorOr > child = AI->getAsBinary(); + ec = child.getError(); +#else OwningPtr child; ec = AI->getAsBinary(child); - if (ec != object::object_error::success) - { +#endif + if (ec) { // If we can't open as a binary object file its hopefully a bitcode file - - OwningPtr buff; // Once this is destroyed will Module still be valid?? - Module *Result = 0; - - if (error_code ec = AI->getMemoryBuffer(buff)) - { - SS << "Failed to get MemoryBuffer: " <= LLVM_VERSION(3, 6) + ErrorOr buff = AI->getMemoryBufferRef(); + ec = buff.getError(); +#elif LLVM_VERSION_CODE == LLVM_VERSION(3, 5) + ErrorOr > errorOr_buff = + AI->getMemoryBuffer(); + std::unique_ptr buff = nullptr; + ec = errorOr_buff.getError(); + if (!ec) + buff = std::move(errorOr_buff.get()); +#else + OwningPtr buff; // Once this is destroyed will Module still + // be valid?? + ec = AI->getMemoryBuffer(buff); +#endif + if (ec) { + SS << "Failed to get MemoryBuffer: " << ec.message(); SS.flush(); return false; } - - if (buff) - { - // FIXME: Maybe load bitcode file lazily? Then if we need to link, materialise the module - Result = ParseBitcodeFile(buff.get(), getGlobalContext(), &errorMessage); - - if(!Result) - { + if (buff) { + Module *Result = 0; +// FIXME: Maybe load bitcode file lazily? Then if we need to link, materialise +// the module +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) + ErrorOr Result_error = + parseBitcodeFile(buff.get(), getGlobalContext()); + ec = Result_error.getError(); + if (ec) + errorMessage = ec.message(); + else + Result = Result_error.get(); +#else + Result = + ParseBitcodeFile(buff.get(), getGlobalContext(), &errorMessage); +#endif + if (!Result) { SS << "Loading module failed : " << errorMessage << "\n"; SS.flush(); return false; } archiveModules.push_back(Result); - } - else - { - errorMessage="Buffer was NULL!"; + } else { + errorMessage = "Buffer was NULL!"; return false; } - - } - else if (object::ObjectFile *o = dyn_cast(child.get())) - { - SS << "Object file " << o->getFileName().data() << - " in archive is not supported"; + } else if (child.get()->isObject()) { + SS << "Object file " << child.get()->getFileName().data() + << " in archive is not supported"; SS.flush(); return false; - } - else - { - SS << "Loading archive child with error "<< ec.message(); + } else { + SS << "Loading archive child with error " << ec.message(); SS.flush(); return false; } - } KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Loaded " << archiveModules.size() << " modules\n"); - std::set previouslyUndefinedSymbols; // Walk through the modules looking for definitions of undefined symbols @@ -315,9 +338,12 @@ static bool linkBCA(object::Archive* archive, Module* composite, std::string& er KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Found " << GV->getName() << " in " << M->getModuleIdentifier() << "\n"); - - - if (Linker::LinkModules(composite, M, Linker::DestroySource, &errorMessage)) +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + if (Linker::LinkModules(composite, M)) +#else + if (Linker::LinkModules(composite, M, Linker::DestroySource, + &errorMessage)) +#endif { // Linking failed SS << "Linking archive module with composite failed:" << errorMessage; @@ -358,8 +384,7 @@ static bool linkBCA(object::Archive* archive, Module* composite, std::string& er return true; } -#endif - +#endif // LLVM 3.3+ Module *klee::linkWithLibrary(Module *module, const std::string &libraryName) { @@ -369,11 +394,84 @@ Module *klee::linkWithLibrary(Module *module, klee_error("Link with library %s failed. No such file.", libraryName.c_str()); } +#endif +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) + ErrorOr > Buffer = + MemoryBuffer::getFile(libraryName); + std::error_code ec; + if ((ec = Buffer.getError())) { + klee_error("Link with library %s failed: %s", libraryName.c_str(), + ec.message().c_str()); + } + + sys::fs::file_magic magic = + sys::fs::identify_magic(Buffer.get()->getBuffer()); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + MemoryBufferRef buff = Buffer.get()->getMemBufferRef(); +#else // LLVM 3.5 + MemoryBuffer *buff = Buffer->get(); +#endif + LLVMContext &Context = getGlobalContext(); + std::string ErrorMessage; + + if (magic == sys::fs::file_magic::bitcode) { + ErrorOr Result = parseBitcodeFile(buff, Context); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + if ((ec = Buffer.getError()) || Linker::LinkModules(module, Result.get())) +#else // LLVM 3.5 + if ((ec = Buffer.getError()) || + Linker::LinkModules(module, Result.get(), Linker::DestroySource, + &ErrorMessage)) +#endif + klee_error("Link with library %s failed: %s", libraryName.c_str(), + ec.message().c_str()); + + delete Result.get(); + + } else if (magic == sys::fs::file_magic::archive) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + ErrorOr > arch = + object::createBinary(buff, &Context); +#else // LLVM 3.5 + ErrorOr arch = + object::createBinary(std::move(Buffer.get()), &Context); +#endif + if ((ec = arch.getError())) + klee_error("Link with library %s failed: %s", libraryName.c_str(), + arch.getError().message().c_str()); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + if (object::Archive *a = dyn_cast(arch->get())) { +#else // LLVM 3.5 + if (object::Archive *a = dyn_cast(arch.get())) { +#endif + // Handle in helper + if (!linkBCA(a, module, ErrorMessage)) + klee_error("Link with library %s failed: %s", libraryName.c_str(), + ErrorMessage.c_str()); + } else { + klee_error("Link with library %s failed: Cast to archive failed", + libraryName.c_str()); + } + + } else if (magic.is_object()) { + std::unique_ptr obj; + if (object::ObjectFile *o = dyn_cast(obj.get())) { + klee_warning("Link with library: Object file %s in archive %s found. " + "Currently not supported.", + o->getFileName().data(), libraryName.c_str()); + } + } else { + klee_error("Link with library %s failed: Unrecognized file type.", + libraryName.c_str()); + } + return module; +#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) + error_code ec; OwningPtr Buffer; - if (error_code ec = MemoryBuffer::getFile(libraryName,Buffer)) { + if (ec = MemoryBuffer::getFile(libraryName, Buffer)) { klee_error("Link with library %s failed: %s", libraryName.c_str(), - ec.message().c_str()); + ec.message().c_str()); } sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer()); @@ -385,53 +483,52 @@ Module *klee::linkWithLibrary(Module *module, Module *Result = 0; Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); - if (!Result || Linker::LinkModules(module, Result, Linker::DestroySource, - &ErrorMessage)) + &ErrorMessage)) klee_error("Link with library %s failed: %s", libraryName.c_str(), - ErrorMessage.c_str()); + ErrorMessage.c_str()); delete Result; } else if (magic == sys::fs::file_magic::archive) { OwningPtr arch; - if (error_code ec = object::createBinary(Buffer.take(), arch)) + if (ec = object::createBinary(Buffer.take(), arch)) klee_error("Link with library %s failed: %s", libraryName.c_str(), - ec.message().c_str()); + ec.message().c_str()); if (object::Archive *a = dyn_cast(arch.get())) { // Handle in helper if (!linkBCA(a, module, ErrorMessage)) klee_error("Link with library %s failed: %s", libraryName.c_str(), - ErrorMessage.c_str()); - } - else { - klee_error("Link with library %s failed: Cast to archive failed", libraryName.c_str()); + ErrorMessage.c_str()); + } else { + klee_error("Link with library %s failed: Cast to archive failed", + libraryName.c_str()); } } else if (magic.is_object()) { OwningPtr obj; if (object::ObjectFile *o = dyn_cast(obj.get())) { klee_warning("Link with library: Object file %s in archive %s found. " - "Currently not supported.", - o->getFileName().data(), libraryName.c_str()); + "Currently not supported.", + o->getFileName().data(), libraryName.c_str()); } } else { klee_error("Link with library %s failed: Unrecognized file type.", - libraryName.c_str()); + libraryName.c_str()); } return module; -#else +#else // LLVM 3.2- Linker linker("klee", module, false); llvm::sys::Path libraryPath(libraryName); bool native = false; - + if (linker.LinkInFile(libraryPath, native)) { klee_error("Linking library %s failed", libraryName.c_str()); } - + return linker.releaseModule(); #endif } diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index 3d9c8cc17bf3..8cd592069523 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -172,15 +172,20 @@ void Optimize(Module *M, const std::string &EntryPoint) { if (VerifyEach) Passes.add(createVerifierPass()); -#if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1) - // Add an appropriate TargetData instance for this module... - addPass(Passes, new TargetData(M)); -#elif LLVM_VERSION_CODE < LLVM_VERSION(3, 5) +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) // Add an appropriate DataLayout instance for this module... - addPass(Passes, new DataLayout(M)); -#else + DataLayoutPass *dlpass = new DataLayoutPass(); + dlpass->doInitialization(*M); + addPass(Passes, dlpass); +#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) // Add an appropriate DataLayout instance for this module... addPass(Passes, new DataLayoutPass(M)); +#elif LLVM_VERSION_CODE > LLVM_VERSION(3, 1) + // Add an appropriate DataLayout instance for this module... + addPass(Passes, new DataLayout(M)); +#else + // Add an appropriate TargetData instance for this module... + addPass(Passes, new TargetData(M)); #endif // DWD - Run the opt standard pass list as well. diff --git a/lib/Module/RaiseAsm.cpp b/lib/Module/RaiseAsm.cpp index e612ca636465..bde9fba93c3a 100644 --- a/lib/Module/RaiseAsm.cpp +++ b/lib/Module/RaiseAsm.cpp @@ -24,6 +24,10 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Target/TargetLowering.h" +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#endif #if LLVM_VERSION_CODE < LLVM_VERSION(3, 0) #include "llvm/Target/TargetRegistry.h" #else @@ -99,15 +103,20 @@ bool RaiseAsmPass::runOnModule(Module &M) { klee_warning("Warning: unable to select native target: %s", Err.c_str()); TLI = 0; } else { -#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 1) - TM = NativeTarget->createTargetMachine(HostTriple, "", "", - TargetOptions()); + +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + TM = NativeTarget->createTargetMachine(HostTriple, "", "", TargetOptions()); + TLI = TM->getSubtargetImpl()->getTargetLowering(); +#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 1) + TM = NativeTarget->createTargetMachine(HostTriple, "", "", TargetOptions()); + TLI = TM->getTargetLowering(); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 0) TM = NativeTarget->createTargetMachine(HostTriple, "", ""); + TLI = TM->getTargetLowering(); #else TM = NativeTarget->createTargetMachine(HostTriple, ""); -#endif TLI = TM->getTargetLowering(); +#endif triple = llvm::Triple(HostTriple); } diff --git a/lib/Solver/QueryLoggingSolver.cpp b/lib/Solver/QueryLoggingSolver.cpp index a858a7d7ed87..80b14c13fc7c 100644 --- a/lib/Solver/QueryLoggingSolver.cpp +++ b/lib/Solver/QueryLoggingSolver.cpp @@ -42,7 +42,10 @@ QueryLoggingSolver::QueryLoggingSolver(Solver *_solver, std::string path, #ifdef HAVE_ZLIB_H if (!CreateCompressedQueryLog) { #endif -#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + os = new llvm::raw_fd_ostream(path.c_str(), ec, + llvm::sys::fs::OpenFlags::F_Text); +#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) os = new llvm::raw_fd_ostream(path.c_str(), ErrorInfo, llvm::sys::fs::OpenFlags::F_Text); #else diff --git a/lib/Solver/QueryLoggingSolver.h b/lib/Solver/QueryLoggingSolver.h index 7ac783d1211c..ba185aa10863 100644 --- a/lib/Solver/QueryLoggingSolver.h +++ b/lib/Solver/QueryLoggingSolver.h @@ -27,6 +27,9 @@ protected: Solver *solver; std::string ErrorInfo; llvm::raw_ostream *os; +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + std::error_code ec; +#endif // @brief Buffer used by logBuffer std::string BufferString; // @brief buffer to store logs before flushing to file diff --git a/lib/Support/CompressionStream.cpp b/lib/Support/CompressionStream.cpp index eb208edfa395..58193c9a98a2 100644 --- a/lib/Support/CompressionStream.cpp +++ b/lib/Support/CompressionStream.cpp @@ -10,9 +10,11 @@ #include "klee/Config/Version.h" #ifdef HAVE_ZLIB_H #include "klee/Internal/Support/CompressionStream.h" -#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) +#if (LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) \ + && LLVM_VERSION_CODE <= LLVM_VERSION(3, 4)) #include "llvm/Support/system_error.h" #else +#include "llvm/Support/FileSystem.h" #include #include #include @@ -25,10 +27,19 @@ compressed_fd_ostream::compressed_fd_ostream(const char *Filename, std::string &ErrorInfo) : llvm::raw_ostream(), pos(0) { ErrorInfo = ""; -#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) // Open file in binary mode +#if LLVM_VERSION_CODE == LLVM_VERSION(3, 4) llvm::error_code EC = - llvm::sys::fs::openFileForWrite(Filename, FD, llvm::sys::fs::F_Binary); +#else + std::error_code EC = +#endif +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) + llvm::sys::fs::openFileForWrite(Filename, FD, +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) + llvm::sys::fs::F_None); +#else + llvm::sys::fs::F_Binary); +#endif if (EC) { ErrorInfo = EC.message(); @@ -116,4 +127,4 @@ void compressed_fd_ostream::write_file(const char *Ptr, size_t Size) { } while (Size > 0); } } -#endif +#endif // HAVE_ZLIB_H diff --git a/test/lit.cfg b/test/lit.cfg index 31552882c55e..6ce6dc955847 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -130,7 +130,7 @@ if int(config.llvm_version_major) == 2: # Add feature for the LLVM version in use, so it can be tested in REQUIRES and # XFAIL checks. We also add "not-XXX" variants, for the same reason. -known_llvm_versions = set(["2.9", "3.4", "3.5"]) +known_llvm_versions = set(["2.9", "3.4", "3.5", "3.6"]) current_llvm_version = "%s.%s" % (config.llvm_version_major, config.llvm_version_minor) config.available_features.add("llvm-" + current_llvm_version) diff --git a/tools/klee/Makefile b/tools/klee/Makefile index 8d50403fc1da..2930427c7bde 100644 --- a/tools/klee/Makefile +++ b/tools/klee/Makefile @@ -13,7 +13,13 @@ TOOLNAME = klee include $(LEVEL)/Makefile.config USEDLIBS = kleeCore.a kleeBasic.a kleeModule.a kleaverSolver.a kleaverExpr.a kleeSupport.a -LINK_COMPONENTS = jit bitreader bitwriter ipo linker engine +LINK_COMPONENTS = bitreader bitwriter ipo linker engine + +ifeq ($(shell python -c "print($(LLVM_VERSION_MAJOR).$(LLVM_VERSION_MINOR) >= 3.6)"), True) +LINK_COMPONENTS += mcjit +else +LINK_COMPONENTS += jit +endif ifeq ($(shell python -c "print($(LLVM_VERSION_MAJOR).$(LLVM_VERSION_MINOR) >= 3.3)"), True) LINK_COMPONENTS += irreader @@ -36,4 +42,4 @@ endif ifeq ($(HAVE_ZLIB),1) LIBS += -lz -endif \ No newline at end of file +endif diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index e95522a019ad..3747d69db0ed 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -385,7 +385,12 @@ llvm::raw_fd_ostream *KleeHandler::openOutputFile(const std::string &filename) { llvm::raw_fd_ostream *f; std::string Error; std::string path = getOutputFilename(filename); -#if LLVM_VERSION_CODE >= LLVM_VERSION(3,5) +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + std::error_code ec; + f = new llvm::raw_fd_ostream(path.c_str(), ec, llvm::sys::fs::F_None); + if (ec) + Error = ec.message(); +#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) f = new llvm::raw_fd_ostream(path.c_str(), Error, llvm::sys::fs::F_None); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3,4) f = new llvm::raw_fd_ostream(path.c_str(), Error, llvm::sys::fs::F_Binary); @@ -645,8 +650,13 @@ static std::string strip(std::string &in) { } static void parseArguments(int argc, char **argv) { + cl::SetVersionPrinter(klee::printVersion); -#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 2) + +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + cl::ParseCommandLineOptions(argc, (char **)argv, " klee\n"); // removes + // warning +#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 2) // This version always reads response files cl::ParseCommandLineOptions(argc, argv, " klee\n"); #else @@ -1036,9 +1046,14 @@ static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir) SmallString<128> uclibcBCA(libDir); llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_NAME); - bool uclibcExists=false; +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + Twine uclibcBCA_twine(uclibcBCA.c_str()); + if (!llvm::sys::fs::exists(uclibcBCA_twine)) +#else + bool uclibcExists = false; llvm::sys::fs::exists(uclibcBCA.c_str(), uclibcExists); if (!uclibcExists) +#endif klee_error("Cannot find klee-uclibc : %s", uclibcBCA.c_str()); Function *f; @@ -1261,9 +1276,13 @@ int main(int argc, char **argv, char **envp) { if (!Buffer) klee_error("error loading program '%s': %s", InputFile.c_str(), Buffer.getError().message().c_str()); - - auto mainModuleOrError = getLazyBitcodeModule(Buffer->get(), getGlobalContext()); - +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) + auto mainModuleOrError = + getLazyBitcodeModule(std::move(Buffer.get()), getGlobalContext()); +#else + auto mainModuleOrError = + getLazyBitcodeModule(Buffer->get(), getGlobalContext()); +#endif if (!mainModuleOrError) { klee_error("error loading program '%s': %s", InputFile.c_str(), mainModuleOrError.getError().message().c_str()); -- 2.11.1