[llvm-commits] [klee] r72205 [1/3] - in /klee/trunk: ./ autoconf/ docs/ docs/SMT-COMP/ examples/ examples/regexp/ examples/sort/ include/ include/expr/ include/klee/ include/klee/Config/ include/klee/Internal/ include/klee/Internal/ADT/ include/klee/Internal/Module/ include/klee/Internal/Support/ include/klee/Internal/System/ include/klee/util/ lib/ lib/Basic/ lib/Core/ lib/Expr/ lib/Module/ lib/Solver/ lib/Support/ runtime/ runtime/Intrinsic/ runtime/POSIX/ runtime/POSIX/testing-dir/ runtime/POSIX/testing-dir/e/ runti...
Daniel Dunbar
daniel at zuster.org
Wed May 20 21:36:47 PDT 2009
Author: ddunbar
Date: Wed May 20 23:36:41 2009
New Revision: 72205
URL: http://llvm.org/viewvc/llvm-project?rev=72205&view=rev
Log:
Initial KLEE checkin.
- Lots more tweaks, documentation, and web page content is needed,
but this should compile & work on OS X & Linux.
Added:
klee/trunk/Makefile
klee/trunk/Makefile.common
klee/trunk/Makefile.config.in
klee/trunk/TODO.txt
klee/trunk/autoconf/
klee/trunk/autoconf/AutoRegen.sh (with props)
klee/trunk/autoconf/config.guess (with props)
klee/trunk/autoconf/config.sub (with props)
klee/trunk/autoconf/configure.ac
klee/trunk/autoconf/install-sh (with props)
klee/trunk/configure (with props)
klee/trunk/docs/
klee/trunk/docs/SMT-COMP/
klee/trunk/docs/SMT-COMP/BitVector_ArraysEx.smt
klee/trunk/docs/SMT-COMP/BitVectors.smt
klee/trunk/docs/SMT-COMP/QF_AUFBV.smt
klee/trunk/docs/SMT-COMP/QF_BV.smt
klee/trunk/docs/doxygen.cfg
klee/trunk/docs/intro
klee/trunk/docs/overview
klee/trunk/examples/
klee/trunk/examples/regexp/
klee/trunk/examples/regexp/Regexp.c
klee/trunk/examples/regexp/notes.txt
klee/trunk/examples/sort/
klee/trunk/examples/sort/sort.c
klee/trunk/include/
klee/trunk/include/expr/
klee/trunk/include/expr/Lexer.h
klee/trunk/include/expr/Parser.h
klee/trunk/include/klee/
klee/trunk/include/klee/Config/
klee/trunk/include/klee/Config/config.h.in
klee/trunk/include/klee/Constraints.h
klee/trunk/include/klee/ExecutionState.h
klee/trunk/include/klee/Expr.h
klee/trunk/include/klee/IncompleteSolver.h
klee/trunk/include/klee/Internal/
klee/trunk/include/klee/Internal/ADT/
klee/trunk/include/klee/Internal/ADT/BOut.h
klee/trunk/include/klee/Internal/ADT/DiscretePDF.h
klee/trunk/include/klee/Internal/ADT/DiscretePDF.inc
klee/trunk/include/klee/Internal/ADT/ImmutableMap.h
klee/trunk/include/klee/Internal/ADT/ImmutableSet.h
klee/trunk/include/klee/Internal/ADT/ImmutableTree.h
klee/trunk/include/klee/Internal/ADT/MapOfSets.h
klee/trunk/include/klee/Internal/ADT/RNG.h
klee/trunk/include/klee/Internal/ADT/TreeStream.h
klee/trunk/include/klee/Internal/Module/
klee/trunk/include/klee/Internal/Module/Cell.h
klee/trunk/include/klee/Internal/Module/InstructionInfoTable.h
klee/trunk/include/klee/Internal/Module/KInstIterator.h
klee/trunk/include/klee/Internal/Module/KInstruction.h
klee/trunk/include/klee/Internal/Module/KModule.h
klee/trunk/include/klee/Internal/README.txt
klee/trunk/include/klee/Internal/Support/
klee/trunk/include/klee/Internal/Support/FloatEvaluation.h
klee/trunk/include/klee/Internal/Support/IntEvaluation.h
klee/trunk/include/klee/Internal/Support/ModuleUtil.h
klee/trunk/include/klee/Internal/Support/QueryLog.h
klee/trunk/include/klee/Internal/Support/Timer.h
klee/trunk/include/klee/Internal/System/
klee/trunk/include/klee/Internal/System/Time.h
klee/trunk/include/klee/Interpreter.h
klee/trunk/include/klee/Machine.h
klee/trunk/include/klee/Solver.h
klee/trunk/include/klee/SolverImpl.h
klee/trunk/include/klee/Statistic.h
klee/trunk/include/klee/Statistics.h
klee/trunk/include/klee/TimerStatIncrementer.h
klee/trunk/include/klee/klee.h
klee/trunk/include/klee/util/
klee/trunk/include/klee/util/Assignment.h
klee/trunk/include/klee/util/BitArray.h
klee/trunk/include/klee/util/Bits.h
klee/trunk/include/klee/util/ExprEvaluator.h
klee/trunk/include/klee/util/ExprHashMap.h
klee/trunk/include/klee/util/ExprPPrinter.h
klee/trunk/include/klee/util/ExprRangeEvaluator.h
klee/trunk/include/klee/util/ExprUtil.h
klee/trunk/include/klee/util/ExprVisitor.h
klee/trunk/include/klee/util/Ref.h
klee/trunk/lib/
klee/trunk/lib/Basic/
klee/trunk/lib/Basic/BOut.cpp
klee/trunk/lib/Basic/Makefile
klee/trunk/lib/Basic/README.txt
klee/trunk/lib/Basic/Statistics.cpp
klee/trunk/lib/Core/
klee/trunk/lib/Core/AddressSpace.cpp
klee/trunk/lib/Core/AddressSpace.h
klee/trunk/lib/Core/CallPathManager.cpp
klee/trunk/lib/Core/CallPathManager.h
klee/trunk/lib/Core/Common.cpp
klee/trunk/lib/Core/Common.h
klee/trunk/lib/Core/CoreStats.cpp
klee/trunk/lib/Core/CoreStats.h
klee/trunk/lib/Core/ExecutionState.cpp
klee/trunk/lib/Core/Executor.cpp
klee/trunk/lib/Core/Executor.h
klee/trunk/lib/Core/ExecutorTimers.cpp
klee/trunk/lib/Core/ExecutorUtil.cpp
klee/trunk/lib/Core/ExternalDispatcher.cpp
klee/trunk/lib/Core/ExternalDispatcher.h
klee/trunk/lib/Core/ImpliedValue.cpp
klee/trunk/lib/Core/ImpliedValue.h
klee/trunk/lib/Core/Makefile (with props)
klee/trunk/lib/Core/Memory.cpp
klee/trunk/lib/Core/Memory.h
klee/trunk/lib/Core/MemoryManager.cpp
klee/trunk/lib/Core/MemoryManager.h
klee/trunk/lib/Core/ObjectHolder.h
klee/trunk/lib/Core/PTree.cpp
klee/trunk/lib/Core/PTree.h
klee/trunk/lib/Core/Searcher.cpp
klee/trunk/lib/Core/Searcher.h
klee/trunk/lib/Core/SeedInfo.cpp
klee/trunk/lib/Core/SeedInfo.h
klee/trunk/lib/Core/SpecialFunctionHandler.cpp
klee/trunk/lib/Core/SpecialFunctionHandler.h
klee/trunk/lib/Core/StatsTracker.cpp
klee/trunk/lib/Core/StatsTracker.h
klee/trunk/lib/Core/TimingSolver.cpp
klee/trunk/lib/Core/TimingSolver.h
klee/trunk/lib/Core/UserSearcher.cpp
klee/trunk/lib/Core/UserSearcher.h
klee/trunk/lib/Expr/
klee/trunk/lib/Expr/Constraints.cpp
klee/trunk/lib/Expr/Expr.cpp
klee/trunk/lib/Expr/ExprEvaluator.cpp
klee/trunk/lib/Expr/ExprPPrinter.cpp
klee/trunk/lib/Expr/ExprUtil.cpp
klee/trunk/lib/Expr/ExprVisitor.cpp
klee/trunk/lib/Expr/Lexer.cpp
klee/trunk/lib/Expr/Makefile
klee/trunk/lib/Expr/Parser.cpp
klee/trunk/lib/Expr/Updates.cpp
klee/trunk/lib/Makefile
klee/trunk/lib/Module/
klee/trunk/lib/Module/Checks.cpp
klee/trunk/lib/Module/InstructionInfoTable.cpp
klee/trunk/lib/Module/IntrinsicCleaner.cpp
klee/trunk/lib/Module/KInstruction.cpp
klee/trunk/lib/Module/KModule.cpp
klee/trunk/lib/Module/LowerSwitch.cpp
klee/trunk/lib/Module/Makefile (with props)
klee/trunk/lib/Module/ModuleUtil.cpp
klee/trunk/lib/Module/Optimize.cpp
klee/trunk/lib/Module/Passes.h
klee/trunk/lib/Module/PhiCleaner.cpp
klee/trunk/lib/Module/RaiseAsm.cpp
klee/trunk/lib/README.txt
klee/trunk/lib/Solver/
klee/trunk/lib/Solver/CachingSolver.cpp
klee/trunk/lib/Solver/CexCachingSolver.cpp
klee/trunk/lib/Solver/ConstantDivision.cpp
klee/trunk/lib/Solver/ConstantDivision.h
klee/trunk/lib/Solver/FastCexSolver.cpp
klee/trunk/lib/Solver/IncompleteSolver.cpp
klee/trunk/lib/Solver/IndependentSolver.cpp
klee/trunk/lib/Solver/Makefile (with props)
klee/trunk/lib/Solver/PCLoggingSolver.cpp
klee/trunk/lib/Solver/STPBuilder.cpp
klee/trunk/lib/Solver/STPBuilder.h
klee/trunk/lib/Solver/Solver.cpp
klee/trunk/lib/Solver/SolverStats.cpp
klee/trunk/lib/Solver/SolverStats.h
klee/trunk/lib/Support/
klee/trunk/lib/Support/Makefile
klee/trunk/lib/Support/README.txt
klee/trunk/lib/Support/RNG.cpp
klee/trunk/lib/Support/Time.cpp
klee/trunk/lib/Support/Timer.cpp
klee/trunk/lib/Support/TreeStream.cpp
klee/trunk/runtime/
klee/trunk/runtime/Intrinsic/
klee/trunk/runtime/Intrinsic/Makefile
klee/trunk/runtime/Intrinsic/klee_div_zero_check.c
klee/trunk/runtime/Intrinsic/klee_int.c
klee/trunk/runtime/Intrinsic/klee_make_symbolic.c
klee/trunk/runtime/Intrinsic/klee_range.c
klee/trunk/runtime/Intrinsic/memcpy.c
klee/trunk/runtime/Intrinsic/memmove.c
klee/trunk/runtime/Intrinsic/mempcpy.c
klee/trunk/runtime/Intrinsic/memset.c
klee/trunk/runtime/Makefile (with props)
klee/trunk/runtime/POSIX/
klee/trunk/runtime/POSIX/Makefile
klee/trunk/runtime/POSIX/fd.c
klee/trunk/runtime/POSIX/fd.h
klee/trunk/runtime/POSIX/fd_32.c
klee/trunk/runtime/POSIX/fd_64.c
klee/trunk/runtime/POSIX/fd_init.c
klee/trunk/runtime/POSIX/illegal.c
klee/trunk/runtime/POSIX/klee_init_env.c
klee/trunk/runtime/POSIX/misc.c
klee/trunk/runtime/POSIX/selinux.c
klee/trunk/runtime/POSIX/stubs.c
klee/trunk/runtime/POSIX/testing-dir/
klee/trunk/runtime/POSIX/testing-dir/a (with props)
klee/trunk/runtime/POSIX/testing-dir/b (with props)
klee/trunk/runtime/POSIX/testing-dir/c (with props)
klee/trunk/runtime/POSIX/testing-dir/d
klee/trunk/runtime/POSIX/testing-dir/e/
klee/trunk/runtime/POSIX/testing-env
klee/trunk/runtime/Runtest/
klee/trunk/runtime/Runtest/Makefile
klee/trunk/runtime/Runtest/intrinsics.c
klee/trunk/runtime/klee-libc/
klee/trunk/runtime/klee-libc/Makefile (with props)
klee/trunk/runtime/klee-libc/__cxa_atexit.c
klee/trunk/runtime/klee-libc/abort.c
klee/trunk/runtime/klee-libc/atexit.c
klee/trunk/runtime/klee-libc/atoi.c
klee/trunk/runtime/klee-libc/calloc.c
klee/trunk/runtime/klee-libc/htonl.c
klee/trunk/runtime/klee-libc/klee-choose.c
klee/trunk/runtime/klee-libc/memchr.c
klee/trunk/runtime/klee-libc/memcmp.c
klee/trunk/runtime/klee-libc/memcpy.c
klee/trunk/runtime/klee-libc/memmove.c
klee/trunk/runtime/klee-libc/mempcpy.c
klee/trunk/runtime/klee-libc/memset.c
klee/trunk/runtime/klee-libc/putchar.c
klee/trunk/runtime/klee-libc/stpcpy.c
klee/trunk/runtime/klee-libc/strcat.c
klee/trunk/runtime/klee-libc/strchr.c
klee/trunk/runtime/klee-libc/strcmp.c
klee/trunk/runtime/klee-libc/strcoll.c
klee/trunk/runtime/klee-libc/strcpy.c
klee/trunk/runtime/klee-libc/strlen.c
klee/trunk/runtime/klee-libc/strncmp.c
klee/trunk/runtime/klee-libc/strncpy.c
klee/trunk/runtime/klee-libc/strrchr.c
klee/trunk/runtime/klee-libc/strtol.c
klee/trunk/runtime/klee-libc/strtoul.c
klee/trunk/runtime/klee-libc/tolower.c
klee/trunk/runtime/klee-libc/toupper.c
klee/trunk/scripts/
klee/trunk/scripts/IStatsMerge.py (with props)
klee/trunk/scripts/IStatsSum.py (with props)
klee/trunk/scripts/PrintStats.py (with props)
klee/trunk/scripts/klee-control (with props)
klee/trunk/scripts/objdump (with props)
klee/trunk/stp/
klee/trunk/stp/AST/
klee/trunk/stp/AST/AST.cpp
klee/trunk/stp/AST/AST.h
klee/trunk/stp/AST/ASTKind.kinds
klee/trunk/stp/AST/ASTUtil.cpp
klee/trunk/stp/AST/ASTUtil.h
klee/trunk/stp/AST/BitBlast.cpp
klee/trunk/stp/AST/Makefile
klee/trunk/stp/AST/STLport_config.h
klee/trunk/stp/AST/SimpBool.cpp
klee/trunk/stp/AST/ToCNF.cpp
klee/trunk/stp/AST/ToSAT.cpp
klee/trunk/stp/AST/Transform.cpp
klee/trunk/stp/AST/asttest.cpp
klee/trunk/stp/AST/bbtest.cpp
klee/trunk/stp/AST/cnftest.cpp
klee/trunk/stp/AST/genkinds.pl (with props)
klee/trunk/stp/INSTALL
klee/trunk/stp/LICENSE
klee/trunk/stp/Makefile
klee/trunk/stp/Makefile.common.in
klee/trunk/stp/README
klee/trunk/stp/bitvec/
klee/trunk/stp/bitvec/Makefile
klee/trunk/stp/bitvec/consteval.cpp
klee/trunk/stp/c_interface/
klee/trunk/stp/c_interface/Makefile
klee/trunk/stp/c_interface/c_interface.cpp
klee/trunk/stp/c_interface/c_interface.h
klee/trunk/stp/c_interface/fdstream.h
klee/trunk/stp/constantbv/
klee/trunk/stp/constantbv/Makefile
klee/trunk/stp/constantbv/constantbv.cpp
klee/trunk/stp/constantbv/constantbv.h
klee/trunk/stp/parser/
klee/trunk/stp/parser/Makefile
klee/trunk/stp/parser/PL.lex
klee/trunk/stp/parser/PL.y
klee/trunk/stp/parser/let-funcs.cpp
klee/trunk/stp/parser/main.cpp
klee/trunk/stp/parser/smtlib.lex
klee/trunk/stp/parser/smtlib.y
klee/trunk/stp/sat/
klee/trunk/stp/sat/Global.h
klee/trunk/stp/sat/Heap.h
klee/trunk/stp/sat/LICENSE
klee/trunk/stp/sat/Makefile
klee/trunk/stp/sat/Simplifier.C
klee/trunk/stp/sat/Solver.C
klee/trunk/stp/sat/Solver.h
klee/trunk/stp/sat/SolverTypes.h
klee/trunk/stp/sat/Sort.h
klee/trunk/stp/sat/VarOrder.h
klee/trunk/stp/simplifier/
klee/trunk/stp/simplifier/Makefile
klee/trunk/stp/simplifier/bvsolver.cpp
klee/trunk/stp/simplifier/bvsolver.h
klee/trunk/stp/simplifier/simplifier.cpp
klee/trunk/test/
klee/trunk/test/CXX/
klee/trunk/test/CXX/ArrayNew.cpp
klee/trunk/test/CXX/New.cpp
klee/trunk/test/CXX/SimpleVirtual.cpp
klee/trunk/test/CXX/StaticConstructor.cpp
klee/trunk/test/CXX/StaticDestructor.cpp
klee/trunk/test/CXX/Trivial.cpp
klee/trunk/test/CXX/dg.exp
klee/trunk/test/Concrete/
klee/trunk/test/Concrete/BitwiseOps.ll
klee/trunk/test/Concrete/BoolReadWrite.ll
klee/trunk/test/Concrete/Casts.ll (with props)
klee/trunk/test/Concrete/CmpEq.ll
klee/trunk/test/Concrete/ConcreteTest.py (with props)
klee/trunk/test/Concrete/ConstantExpr.ll
klee/trunk/test/Concrete/FloatingPointOps.ll
klee/trunk/test/Concrete/GlobalInitializers.ll (with props)
klee/trunk/test/Concrete/GlobalVariable.ll
klee/trunk/test/Concrete/ICmp.ll
klee/trunk/test/Concrete/InvokeAndReturn.ll
klee/trunk/test/Concrete/InvokeAndUnwindOnce.ll
klee/trunk/test/Concrete/InvokeAndUnwindTwice.ll
klee/trunk/test/Concrete/Makefile
klee/trunk/test/Concrete/OneCall.ll
klee/trunk/test/Concrete/OverlappingPhiNodes.ll
klee/trunk/test/Concrete/Select.ll
klee/trunk/test/Concrete/Shifts.ll
klee/trunk/test/Concrete/SimpleStoreAndLoad.ll
klee/trunk/test/Concrete/UnconditionalBranch.ll
klee/trunk/test/Concrete/UnconditionalBranchWithSimplePhi.ll
klee/trunk/test/Concrete/UnorderedPhiNodes.ll
klee/trunk/test/Concrete/_testingUtils.c
klee/trunk/test/Concrete/ackermann.c
klee/trunk/test/Concrete/arith_test.ll
klee/trunk/test/Coverage/
klee/trunk/test/Coverage/ReadArgs.c
klee/trunk/test/Coverage/ReplayOutDir.c
klee/trunk/test/Coverage/dg.exp
klee/trunk/test/Dogfood/
klee/trunk/test/Dogfood/ImmutableSet.cpp
klee/trunk/test/Dogfood/dg.exp
klee/trunk/test/Expr/
klee/trunk/test/Expr/Lexer/
klee/trunk/test/Expr/Parser/
klee/trunk/test/Expr/dg.exp
klee/trunk/test/Feature/
klee/trunk/test/Feature/Alias.c
klee/trunk/test/Feature/AliasFunction.c
klee/trunk/test/Feature/AliasFunctionExit.c
klee/trunk/test/Feature/AsmAddresses.c
klee/trunk/test/Feature/ByteSwap.c
klee/trunk/test/Feature/CallToUndefinedExternal.cpp
klee/trunk/test/Feature/CheckForImpliedValue.c.failing
klee/trunk/test/Feature/CheckMemoryAccess.c
klee/trunk/test/Feature/CopyOnWrite.c
klee/trunk/test/Feature/DanglingConcreteReadExpr.c
klee/trunk/test/Feature/DefineFixedObject.c
klee/trunk/test/Feature/DoubleFree.c
klee/trunk/test/Feature/DumpStatesOnHalt.c
klee/trunk/test/Feature/Envp.c
klee/trunk/test/Feature/ExprLogging.c
klee/trunk/test/Feature/ExternalWeakLinkage.c
klee/trunk/test/Feature/FunctionPointer.c
klee/trunk/test/Feature/GetValue.c
klee/trunk/test/Feature/ImpliedValue.c.failing
klee/trunk/test/Feature/InAndOutOfBounds.c
klee/trunk/test/Feature/IndirectCallToBuiltin.c
klee/trunk/test/Feature/IndirectCallToExternal.c
klee/trunk/test/Feature/InvalidBitfieldAccess.c.failing
klee/trunk/test/Feature/IsSymbolic.c
klee/trunk/test/Feature/KleeReportError.c
klee/trunk/test/Feature/LongDoubleSupport.c
klee/trunk/test/Feature/LowerSwitch.c
klee/trunk/test/Feature/MakeConcreteSymbolic.c
klee/trunk/test/Feature/MakeSymbolicName.c
klee/trunk/test/Feature/MemoryLimit.c
klee/trunk/test/Feature/MultipleFreeResolution.c
klee/trunk/test/Feature/MultipleReadResolution.c
klee/trunk/test/Feature/MultipleReallocResolution.c
klee/trunk/test/Feature/MultipleWriteResolution.c
klee/trunk/test/Feature/NamedSeedMatching.c
klee/trunk/test/Feature/OneFreeError.c
klee/trunk/test/Feature/OneOutOfBounds.c
klee/trunk/test/Feature/Optimize.c
klee/trunk/test/Feature/OverlappedError.c
klee/trunk/test/Feature/PreferCex.c
klee/trunk/test/Feature/RaiseAsm.c
klee/trunk/test/Feature/ReallocFailure.c
klee/trunk/test/Feature/ReplayPath.c
klee/trunk/test/Feature/Searchers.c
klee/trunk/test/Feature/SetForking.c
klee/trunk/test/Feature/Vararg.c
klee/trunk/test/Feature/WithLibc.c
klee/trunk/test/Feature/WriteCov.c
klee/trunk/test/Feature/_utils._ll
klee/trunk/test/Feature/const_array_opt1.c
klee/trunk/test/Feature/dg.exp
klee/trunk/test/Feature/utils.h
klee/trunk/test/Makefile
klee/trunk/test/Makefile.tests
klee/trunk/test/README
klee/trunk/test/Runtime/
klee/trunk/test/Runtime/POSIX/
klee/trunk/test/Runtime/POSIX/DirConsistency.c
klee/trunk/test/Runtime/POSIX/DirSeek.c
klee/trunk/test/Runtime/POSIX/FDNumbers.c
klee/trunk/test/Runtime/POSIX/FD_Fail.c
klee/trunk/test/Runtime/POSIX/FD_Fail2.c
klee/trunk/test/Runtime/POSIX/Fcntl.c
klee/trunk/test/Runtime/POSIX/FilePerm.c
klee/trunk/test/Runtime/POSIX/FreeArgv.c
klee/trunk/test/Runtime/POSIX/Getenv.c
klee/trunk/test/Runtime/POSIX/Ioctl.c
klee/trunk/test/Runtime/POSIX/Isatty.c
klee/trunk/test/Runtime/POSIX/PrgName.c
klee/trunk/test/Runtime/POSIX/Read1.c
klee/trunk/test/Runtime/POSIX/SELinux.c
klee/trunk/test/Runtime/POSIX/SeedAndFail.c
klee/trunk/test/Runtime/POSIX/Stdin.c
klee/trunk/test/Runtime/POSIX/Write1.c
klee/trunk/test/Runtime/POSIX/Write2.c
klee/trunk/test/Runtime/POSIX/dg.exp
klee/trunk/test/Runtime/Uclibc/
klee/trunk/test/Runtime/Uclibc/2007-10-08-optimization-calls-wrong-libc-functions.c
klee/trunk/test/Runtime/Uclibc/2008-03-04-libc-atexit-uses-dso-handle.c
klee/trunk/test/Runtime/Uclibc/Environ.c
klee/trunk/test/Runtime/Uclibc/dg.exp
klee/trunk/test/TestRunner.sh (with props)
klee/trunk/test/lib/
klee/trunk/test/lib/llvm.exp
klee/trunk/test/regression/
klee/trunk/test/regression/2007-07-25-invalid-stp-array-binding-to-objectstate.c
klee/trunk/test/regression/2007-07-30-unflushed-byte.c
klee/trunk/test/regression/2007-08-01-bool-zext-in-call.ll
klee/trunk/test/regression/2007-08-01-cache-unclear-on-overwrite-flushed.c
klee/trunk/test/regression/2007-08-06-64bit-shift.c
klee/trunk/test/regression/2007-08-06-access-after-free.c
klee/trunk/test/regression/2007-08-08-free-zero.c
klee/trunk/test/regression/2007-08-16-invalid-constant-value.c
klee/trunk/test/regression/2007-08-16-valid-write-to-freed-object.c
klee/trunk/test/regression/2007-10-11-free-of-alloca.c
klee/trunk/test/regression/2007-10-11-illegal-access-after-free-and-branch.c
klee/trunk/test/regression/2007-10-12-failed-make-symbolic-after-copy.c
klee/trunk/test/regression/2008-02-11-phi-nodes-after-invoke.ll
klee/trunk/test/regression/2008-03-04-free-of-global.c
klee/trunk/test/regression/2008-03-11-free-of-malloc-zero.c
klee/trunk/test/regression/2008-04-10-bad-alloca-free.c
klee/trunk/test/regression/2008-05-23-gep-with-global-const.c
klee/trunk/test/regression/dg.exp
klee/trunk/tools/
klee/trunk/tools/Makefile
klee/trunk/tools/gen-random-bout/
klee/trunk/tools/gen-random-bout/Makefile
klee/trunk/tools/gen-random-bout/gen-random-bout.cpp
klee/trunk/tools/kleaver/
klee/trunk/tools/kleaver/Makefile
klee/trunk/tools/kleaver/main.cpp
klee/trunk/tools/klee/
klee/trunk/tools/klee-bout-tool/
klee/trunk/tools/klee-bout-tool/Makefile
klee/trunk/tools/klee-bout-tool/klee-bout-tool (with props)
klee/trunk/tools/klee/Debug.cpp
klee/trunk/tools/klee/Makefile
klee/trunk/tools/klee/main.cpp
klee/trunk/unittests/
klee/trunk/unittests/Expr/
klee/trunk/unittests/Expr/ExprTest.cpp
klee/trunk/unittests/Expr/Makefile
klee/trunk/unittests/Makefile (with props)
klee/trunk/unittests/Solver/
klee/trunk/unittests/Solver/Makefile
klee/trunk/unittests/Solver/SolverTest.cpp
klee/trunk/unittests/TestMain.cpp
klee/trunk/utils/
klee/trunk/utils/emacs/
klee/trunk/utils/emacs/klee-pc-mode.el
klee/trunk/utils/valgrind/
klee/trunk/utils/valgrind/README.txt
klee/trunk/utils/valgrind/valgrind-llvm.supp
klee/trunk/utils/valgrind/valgrind-stp.supp
klee/trunk/www/Examples.html
klee/trunk/www/GetInvolved.html
klee/trunk/www/GetStarted.html
Modified:
klee/trunk/LICENSE.TXT
klee/trunk/README.txt
klee/trunk/www/bugs.html
klee/trunk/www/content.css
klee/trunk/www/index.html
klee/trunk/www/install.html
klee/trunk/www/menu.html.incl
klee/trunk/www/tutorials.html
Modified: klee/trunk/LICENSE.TXT
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/LICENSE.TXT?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/LICENSE.TXT (original)
+++ klee/trunk/LICENSE.TXT Wed May 20 23:36:41 2009
@@ -11,8 +11,7 @@
klee Team
- Stanford Checking Group: Daniel Dunbar, Cristian Cadar, Peter
- Pawlowki, Dawson Engler.
+ Stanford Checking Group
http://klee.llvm.org
@@ -30,10 +29,10 @@
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
- * Neither the names of the LLVM Team, University of Illinois at
- Urbana-Champaign, nor the names of its contributors may be used to
- endorse or promote products derived from this Software without specific
- prior written permission.
+ * Neither the names of the klee Team, Stanford University, nor the
+ names of its contributors may be used to endorse or promote
+ products derived from this Software without specific prior
+ written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
@@ -50,10 +49,9 @@
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the klee Distribution, and nothing in any of the
-other licenses gives permission to use the names of the klee Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
+applies to all code in the klee Distribution, and nothing in any of the other
+licenses gives permission to use the names of the klee Team or Stanford
+University to endorse or promote products derived from this Software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
@@ -61,4 +59,5 @@
Program Directory
------- ---------
STP klee/stp
+klee-libc runtime/klee-libc
Added: klee/trunk/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/Makefile (added)
+++ klee/trunk/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,57 @@
+#===-- klee/Makefile ---------------------------------------*- Makefile -*--===#
+#
+# The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+#
+# Indicates our relative path to the top of the project's root directory.
+#
+LEVEL = .
+
+DIRS = stp lib tools runtime
+EXTRA_DIST = include
+
+# Only build support directories when building unittests.
+ifeq ($(MAKECMDGOALS),unittests)
+ DIRS := $(filter-out tools runtime, $(DIRS)) unittests
+ OPTIONAL_DIRS :=
+endif
+
+#
+# Include the Master Makefile that knows how to build all.
+#
+include $(LEVEL)/Makefile.common
+
+.PHONY: doxygen
+doxygen:
+ doxygen docs/doxygen.cfg
+
+.PHONY: cscope.files
+cscope.files:
+ find \
+ lib include stp tools runtime examples unittests \
+ -name Makefile -or \
+ -name \*.in -or \
+ -name \*.c -or \
+ -name \*.cpp -or \
+ -name \*.exp -or \
+ -name \*.inc -or \
+ -name \*.h | sort > cscope.files
+
+test::
+ -(cd test/ && make)
+
+.PHONY: klee-cov
+klee-cov:
+ rm -rf klee-cov
+ zcov-scan --look-up-dirs=1 klee.zcov .
+ zcov-genhtml --root $$(pwd) klee.zcov klee-cov
+
+clean::
+ $(MAKE) -C test clean
+ $(MAKE) -C unittests clean
+ rm -rf docs/doxygen
Added: klee/trunk/Makefile.common
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/Makefile.common?rev=72205&view=auto
==============================================================================
--- klee/trunk/Makefile.common (added)
+++ klee/trunk/Makefile.common Wed May 20 23:36:41 2009
@@ -0,0 +1,26 @@
+# -*- Makefile -*-
+
+include $(LEVEL)/Makefile.config
+
+# Include LLVM's Master Makefile config and rules.
+include $(LLVM_OBJ_ROOT)/Makefile.config
+
+ifeq ($(BYTECODE_LIBRARY), 1)
+#
+# Override make variables based on the runtime configuration. We want
+# to override whatever the user may have said on the command line,
+# hence the use of override.
+#
+
+override ENABLE_OPTIMIZED := $(RUNTIME_ENABLE_OPTIMIZED)
+override DISABLE_ASSERTIONS := $(RUNTIME_DISABLE_ASSERTIONS)
+override ENABLE_PROFILING := $(RUNTIME_ENABLE_PROFILING)
+override ENABLE_COVERAGE := $(RUNTIME_ENABLE_COVERAGE)
+endif
+
+include $(LLVM_OBJ_ROOT)/Makefile.rules
+
+LD.Flags += -L$(PROJ_SRC_ROOT)/stp/lib
+CXX.Flags += -DLLVM_23
+CXX.Flags += -I$(PROJ_SRC_ROOT)/stp/include
+CXX.Flags += -DKLEE_DIR=\"$(PROJ_SRC_ROOT)\"
Added: klee/trunk/Makefile.config.in
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/Makefile.config.in?rev=72205&view=auto
==============================================================================
--- klee/trunk/Makefile.config.in (added)
+++ klee/trunk/Makefile.config.in Wed May 20 23:36:41 2009
@@ -0,0 +1,45 @@
+# -*- Makefile -*-
+
+# Set the name of the project here
+PROJECT_NAME := klee
+PROJ_VERSION := 0.01
+
+# Set this variable to the top of the LLVM source tree.
+LLVM_SRC_ROOT = @LLVM_SRC@
+
+# Set this variable to the top level directory where LLVM was built
+# (this is *not* the same as OBJ_ROOT as defined in LLVM's Makefile.config).
+LLVM_OBJ_ROOT = @LLVM_OBJ@
+
+# Set the directory root of this project's source files
+PROJ_SRC_ROOT := $(subst //,/, at abs_top_srcdir@)
+
+# Set the root directory of this project's object files
+PROJ_OBJ_ROOT := $(subst //,/, at abs_top_objdir@)
+
+# Set the root directory of this project's install prefix
+PROJ_INSTALL_ROOT := @prefix@
+
+ENABLE_POSIX_RUNTIME := @ENABLE_POSIX_RUNTIME@
+ENABLE_STPLOG := @ENABLE_STPLOG@
+ENABLE_UCLIBC := @ENABLE_UCLIBC@
+
+HAVE_SELINUX := @HAVE_SELINUX@
+
+RUNTIME_ENABLE_OPTIMIZED := @RUNTIME_ENABLE_OPTIMIZED@
+RUNTIME_DISABLE_ASSERTIONS :=
+RUNTIME_ENABLE_COVERAGE :=
+RUNTIME_ENABLE_PROFILING :=
+
+# A list of "features" which tests can check for in XFAIL:
+TEST_FEATURE_LIST :=
+
+ifeq ($(HAVE_SELINUX_SELINUX_H),1)
+ TEST_FEATURE_LIST += have-selinux
+else
+ TEST_FEATURE_LIST += no-selinux
+endif
+
+CFLAGS := @CFLAGS@
+CXXFLAGS := @CXXFLAGS@
+LDFLAGS := @LDFLAGS@
Modified: klee/trunk/README.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/README.txt?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/README.txt (original)
+++ klee/trunk/README.txt Wed May 20 23:36:41 2009
@@ -1,24 +1,24 @@
//===----------------------------------------------------------------------===//
// Klee Symbolic Virtual Machine
//===----------------------------------------------------------------------===//
- Daniel Dunbar
klee is a symbolic virtual machine built on top of the LLVM compiler
-infrastructure. Currently, there are two primary components.
+infrastructure. Currently, there are two primary components:
-1. The core symbolic virtual machine engine; this is responsible for
-executing LLVM bitcode modules with support for symbolic values. This
-is comprised of the code in lib/.
+ 1. The core symbolic virtual machine engine; this is responsible for
+ executing LLVM bitcode modules with support for symbolic
+ values. This is comprised of the code in lib/.
-2. An emulation layer for the Linux system call interface, with
-additional support for making parts of the operating environment
-symbolic. This is found in models/simple.
+ 2. A POSIX/Linux emulation layer oriented towards supporting uClibc,
+ with additional support for making parts of the operating system
+ environment symbolic.
-Additionally, there is a simple library in runtime/ which supports
-replaying computed inputs on native code. There is a more complicated
-library in replay/ which supports running inputs computed as part of
-the system call emulation layer natively -- setting up files, pipes,
-etc. on the native system to match the inputs that the emulation layer
-provided.
+Additionally, there is a simple library for replaying computed inputs
+on native code (for closed programs). There is also a more complicated
+infrastructure for replaying the inputs generated for the POSIX/Linux
+emulation layer, which handles running native programs in an
+environment that matches a computed test input, including setting up
+files, pipes, environment variables, and passing command line
+arguments.
-For further information, see the docs in www/.
+For further information, see the webpage or docs in www/.
Added: klee/trunk/TODO.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/TODO.txt?rev=72205&view=auto
==============================================================================
--- klee/trunk/TODO.txt (added)
+++ klee/trunk/TODO.txt Wed May 20 23:36:41 2009
@@ -0,0 +1,59 @@
+TODO
+--
+
+Build System / Configure / Release Cleanups
+--
+ o Rename .bout to .ktest (klee test)
+
+ o Rename .pc to .kquery (kleaver query)
+
+ o Configure doesn't check for bison / flex, we don't really use these
+ for anything important (just the command line STP tool), it would
+ be nice if they weren't required.
+
+ o Need a way to hide LLVM options in "klee --help".
+
+Klee Internal
+--
+ o Make sure that namespaces and .cpp locations match with reorganized
+ include locations.
+
+ o Add replay framework for POSIX model tests.
+
+Kleaver Internal
+--
+ o We need to fix the constants-in-exprs problem, this makes
+ separating out a Kleaver expr library much more difficult. There
+ are two parts:
+
+ 1. Pull fast (pure constant) path operations out of Expr.cpp,
+ into Executor.cpp.
+
+ 2. Lift constants-are-immediate optimization out of ref<Expr>
+ into Cell. Expressions in memory already have the concrete
+ cache, so we get that part for free.
+
+ We will need a way to distinguish if a cell has an expr or a
+ constant. Incidentally, this gives us an extra sentinel value
+ (is-expr == true and Expr* == null) we can use to mark
+ uninitialized-value of a register.
+
+ It may be worth sinking Expr construction into a Builder class
+ while we are at it.
+
+ There is a also a nice cleanup/perf win where we can work with
+ registers (Cells) directly, now that we build the constant table,
+ it might be worth doing this at the same time. This exposes a win
+ for IVC where it can write back a constant value into a register,
+ which needs to be done with care but would be a big improvement for
+ IVC.
+
+ o The stpArray field of an UpdateNode needs to die. This isn't as
+ easy as dropping it from the map, because we also need a
+ notification to free it. I think probably what we should do is
+ introduce an ExprContext can be used to deal with such things.
+ o The ExprContext could also have the default builder, for
+ example, which would make it easy to swap in an optimizing
+ builder.
+
+
Added: klee/trunk/autoconf/AutoRegen.sh
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/autoconf/AutoRegen.sh?rev=72205&view=auto
==============================================================================
--- klee/trunk/autoconf/AutoRegen.sh (added)
+++ klee/trunk/autoconf/AutoRegen.sh Wed May 20 23:36:41 2009
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+if ([ "$#" != 1 ] ||
+ [ ! -d "$1" ] ||
+ [ ! -d "$1/autoconf/m4" ]); then
+ echo "usage: $0 <llvmsrc-dir>" 1>& 2
+ exit 1
+fi
+
+llvm_src_root=$(cd $1; pwd)
+llvm_m4=$llvm_src_root/autoconf/m4
+die () {
+ echo "$@" 1>&2
+ exit 1
+}
+test -d autoconf && test -f autoconf/configure.ac && cd autoconf
+test -f configure.ac || die "Can't find 'autoconf' dir; please cd into it first"
+autoconf --version | egrep '2\.60' > /dev/null
+if test $? -ne 0 ; then
+ die "Your autoconf was not detected as being 2.60"
+fi
+# Patch LLVM_SRC_ROOT in configure.ac
+sed -e "s#^LLVM_SRC_ROOT=.*#LLVM_SRC_ROOT=\"$llvm_src_root\"#" \
+ configure.ac > configure.tmp.ac
+echo "Regenerating aclocal.m4 with aclocal"
+rm -f aclocal.m4
+echo aclocal -I $llvm_m4 -I "$llvm_m4/.." || die "aclocal failed"
+aclocal -I $llvm_m4 -I "$llvm_m4/.." || die "aclocal failed"
+echo "Regenerating configure with autoconf 2.60"
+echo autoconf --warnings=all -o ../configure configure.tmp.ac || die "autoconf failed"
+autoconf --warnings=all -o ../configure configure.tmp.ac || die "autoconf failed"
+cp ../configure ../configure.bak
+sed -e "s#^LLVM_SRC_ROOT=.*#LLVM_SRC_ROOT=\".\"#" \
+ ../configure.bak > ../configure
+cd ..
+echo "Regenerating config.h.in with autoheader"
+autoheader --warnings=all \
+ -I autoconf -I autoconf/m4 \
+ autoconf/configure.tmp.ac || die "autoheader failed"
+rm -f autoconf/configure.tmp.ac configure.bak
+exit 0
Propchange: klee/trunk/autoconf/AutoRegen.sh
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/autoconf/config.guess
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/autoconf/config.guess?rev=72205&view=auto
==============================================================================
--- klee/trunk/autoconf/config.guess (added)
+++ klee/trunk/autoconf/config.guess Wed May 20 23:36:41 2009
@@ -0,0 +1,1447 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-09-07'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per at bothner.com>.
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit 0 ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel at ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes at openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf at swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms && exit 0 ;;
+ I*) echo ia64-dec-vms && exit 0 ;;
+ V*) echo vax-dec-vms && exit 0 ;;
+ esac
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Propchange: klee/trunk/autoconf/config.guess
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/autoconf/config.sub
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/autoconf/config.sub?rev=72205&view=auto
==============================================================================
--- klee/trunk/autoconf/config.sub (added)
+++ klee/trunk/autoconf/config.sub Wed May 20 23:36:41 2009
@@ -0,0 +1,1555 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-08-29'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Propchange: klee/trunk/autoconf/config.sub
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/autoconf/configure.ac
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/autoconf/configure.ac?rev=72205&view=auto
==============================================================================
--- klee/trunk/autoconf/configure.ac (added)
+++ klee/trunk/autoconf/configure.ac Wed May 20 23:36:41 2009
@@ -0,0 +1,253 @@
+dnl **************************************************************************
+dnl * Initialize
+dnl **************************************************************************
+AC_INIT([[KLEE]],[[0.01]],[daniel at minormatter.com])
+
+dnl Identify where LLVM source tree is (this is patched by
+dnl AutoRegen.sh)
+LLVM_SRC_ROOT=XXX
+
+dnl Tell autoconf that the auxilliary files are actually located in
+dnl the LLVM autoconf directory, not here.
+AC_CONFIG_AUX_DIR($LLVM_SRC_ROOT/autoconf)
+
+dnl Tell autoconf that this is an LLVM project being configured
+dnl This provides the --with-llvmsrc and --with-llvmobj options
+LLVM_CONFIG_PROJECT("","")
+
+dnl Verify that the source directory is valid
+AC_CONFIG_SRCDIR(["Makefile.config.in"])
+
+dnl Configure a common Makefile
+AC_CONFIG_FILES(Makefile.config)
+AC_CONFIG_FILES(stp/Makefile.common)
+
+dnl Configure project makefiles
+dnl List every Makefile that exists within your source tree
+AC_CONFIG_HEADERS([include/klee/Config/config.h])
+
+dnl FIXME: Make out of tree builds work.
+
+AC_LANG([C++])
+
+dnl **************************************************************************
+dnl Find the host
+
+AC_CANONICAL_TARGET
+
+dnl Determine the platform type and cache its value. This helps us configure
+dnl the System library to the correct build platform.
+AC_CACHE_CHECK([type of operating system we're going to host on],
+ [klee_cv_os_type],
+[case $host in
+ *-*-linux*)
+ host_supports_posix_runtime=yes ;;
+ *)
+ host_supports_posix_runtime=no ;;
+esac])
+
+dnl **************************************************************************
+dnl Verify that we can find llvm
+
+dnl --with-llvm is a shortcut for setting srcdir and objdir.
+AC_ARG_WITH(llvm,
+ AS_HELP_STRING([--with-llvm],
+ [Location of LLVM Source and Object code]),,)
+
+AC_MSG_CHECKING([llvm source dir])
+
+if test X${with_llvm} != X; then
+ dnl Verify that --with-llvm{src,obj} were not given.
+ if test X${with_llvmsrc} != X; then
+ AC_MSG_ERROR([--with-llvmsrc cannot be specified when using --with-llvm])
+ fi
+ if test X${with_llvmobj} != X; then
+ AC_MSG_ERROR([--with-llvmobj cannot be specified when using --with-llvm])
+ fi
+ with_llvmsrc=$with_llvm
+ with_llvmobj=$with_llvm
+fi
+
+dnl If one of with_llvmsrc or with_llvmobj was given, we must have both.
+if (test X${with_llvmsrc} != X || test X${with_llvmobj} != X); then
+ dnl Verify that with_llvmobj was given as well.
+ if test X${with_llvmsrc} = X; then
+ AC_MSG_ERROR([--with-llvmsrc must be specified when using --with-llvmobj])
+ fi
+ if test X${with_llvmobj} = X; then
+ AC_MSG_ERROR([--with-llvmobj must be specified when using --with-llvmsrc])
+ fi
+else
+ dnl Otherwise try and use llvm-config to find.
+ llvm_version=`llvm-config --version`
+ if test X${llvm_version} = X; then
+ AC_MSG_ERROR([unable to find llvm, use --with-llvmsrc and --with-llvmobj])
+ fi
+
+ with_llvmsrc=`llvm-config --src-root`
+ with_llvmobj=`llvm-config --obj-root`
+fi
+
+dnl Try to validate directories
+if test ! -f ${with_llvmsrc}/Makefile.rules; then
+ AC_MSG_ERROR([invalid llvmsrc directory: ${with_llvmsrc}])
+fi
+if test ! -f ${with_llvmobj}/Makefile.config; then
+ AC_MSG_ERROR([invalid llvmobj directory: ${with_llvmobj}])
+fi
+
+dnl Make the paths absolute
+llvm_src=`cd $with_llvmsrc 2> /dev/null; pwd`
+llvm_obj=`cd $with_llvmobj 2> /dev/null; pwd`
+
+AC_MSG_RESULT([$llvm_src])
+
+dnl Report obj dir as well.
+AC_MSG_CHECKING([llvm obj dir])
+AC_MSG_RESULT([$llvm_obj])
+
+AC_SUBST(LLVM_SRC,$llvm_src)
+AC_SUBST(LLVM_OBJ,$llvm_obj)
+
+dnl **************************************************************************
+dnl User option to enable uClibc support.
+
+AC_ARG_WITH(uclibc,
+ AS_HELP_STRING([--with-uclibc],
+ [Enable use of the klee uclibc at the given path]),,)
+
+dnl If uclibc wasn't given, check for a uclibc in the current
+dnl directory.
+if (test X${with_uclibc} = X && test -d uclibc); then
+ with_uclibc=uclibc
+fi
+
+dnl Validate uclibc if given.
+
+AC_MSG_CHECKING([uclibc])
+if (test X${with_uclibc} != X); then
+ if test ! -d ${with_uclibc}; then
+ AC_MSG_ERROR([invalid uclibc directory: ${with_uclibc}])
+ fi
+
+ dnl Make the path absolute
+ with_uclibc=`cd $with_uclibc 2> /dev/null; pwd`
+
+ AC_MSG_RESULT([$with_uclibc])
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_DEFINE_UNQUOTED(KLEE_UCLIBC, "$with_uclibc", [Path to KLEE's uClibc])
+AC_SUBST(KLEE_UCLIBC)
+
+if test X${with_uclibc} != X ; then
+ AC_SUBST(ENABLE_UCLIBC,[[1]])
+else
+ AC_SUBST(ENABLE_UCLIBC,[[0]])
+fi
+
+dnl **************************************************************************
+dnl User option to enable the POSIX runtime
+
+AC_ARG_ENABLE(posix-runtime,
+ AS_HELP_STRING([--enable-posix-runtime],
+ [Enable the POSIX runtime]),
+ ,enableval=default)
+
+AC_MSG_CHECKING([POSIX runtime])
+if test ${enableval} = "default" ; then
+ if test X${with_uclibc} != X; then
+ enableval=$host_supports_posix_runtime
+ if test ${enableval} = "yes"; then
+ AC_MSG_RESULT([default (enabled)])
+ else
+ AC_MSG_RESULT([default (disabled, unsupported target)])
+ fi
+ else
+ enableval="no"
+ AC_MSG_RESULT([default (disabled, no uclibc)])
+ fi
+else
+ if test ${enableval} = "yes" ; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+fi
+
+if test ${enableval} = "yes" ; then
+ AC_SUBST(ENABLE_POSIX_RUNTIME,[[1]])
+else
+ AC_SUBST(ENABLE_POSIX_RUNTIME,[[0]])
+fi
+
+dnl **************************************************************************
+dnl User option to select runtime version
+
+AC_ARG_WITH(runtime,
+ AS_HELP_STRING([--with-runtime],
+ [Select build configuration for runtime libraries (default [Release])]),,
+ withval=default)
+
+if test X"${withval}" = Xdefault; then
+ with_runtime=Release
+fi
+
+AC_MSG_CHECKING([runtime configuration])
+if test X${with_runtime} = XRelease; then
+ AC_MSG_RESULT([Release])
+ AC_SUBST(RUNTIME_ENABLE_OPTIMIZED,[[1]])
+elif test X${with_runtime} = XDebug; then
+ AC_MSG_RESULT([Debug])
+ AC_SUBST(RUNTIME_ENABLE_OPTIMIZED,[[0]])
+else
+ AC_MSG_ERROR([invalid configuration: ${with_runtime}])
+fi
+
+AC_DEFINE_UNQUOTED(RUNTIME_CONFIGURATION, "$with_runtime", [Configuration for runtime libraries])
+AC_SUBST(RUNTIME_CONFIGURATION)
+
+dnl **************************************************************************
+dnl See if we should support __ctype_b_loc externals.
+
+dnl FIXME: Do the proper test if we continue to need this.
+case $host in
+ *-*-linux*)
+ AC_DEFINE_UNQUOTED(HAVE_CTYPE_EXTERNALS, 1, [Does the platform use __ctype_b_loc, etc.])
+esac
+
+dnl **************************************************************************
+dnl Checks for header files.
+
+dnl NOTE: This is mostly just to force autoconf to make CFLAGS defines
+dnl for us.
+AC_LANG_PUSH([C])
+
+AC_CHECK_HEADERS([sys/acl.h])
+
+AC_LANG_POP([C])
+
+AC_CHECK_HEADERS([selinux/selinux.h],
+ AC_SUBST(HAVE_SELINUX, 1),
+ AC_SUBST(HAVE_SELINUX, 0))
+
+dnl User option to use stplog.
+
+AC_ARG_ENABLE(stplog,
+ AS_HELP_STRING([--enable-stplog],
+ [Compile with the stplog library [[disabled]]]),
+ ,enableval=no)
+if test ${enableval} = "yes" ; then
+ AC_SUBST(ENABLE_STPLOG,[[1]])
+else
+ AC_SUBST(ENABLE_STPLOG,[[0]])
+fi
+AC_DEFINE_UNQUOTED([ENABLE_STPLOG],$ENABLE_STPLOG,[Define if stplog enabled])
+
+dnl **************************************************************************
+dnl * Create the output files
+dnl **************************************************************************
+
+dnl This must be last
+AC_OUTPUT
Added: klee/trunk/autoconf/install-sh
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/autoconf/install-sh?rev=72205&view=auto
==============================================================================
--- klee/trunk/autoconf/install-sh (added)
+++ klee/trunk/autoconf/install-sh Wed May 20 23:36:41 2009
@@ -0,0 +1,322 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2004-09-10.20
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+chmodcmd="$chmodprog 0755"
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c (ignored)
+-d create directories instead of installing files.
+-g GROUP $chgrpprog installed files to GROUP.
+-m MODE $chmodprog installed files to MODE.
+-o USER $chownprog installed files to USER.
+-s $stripprog installed files.
+-t DIRECTORY install into DIRECTORY.
+-T report an error if DSTFILE is a directory.
+--help display this help and exit.
+--version display version info and exit.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test -n "$1"; do
+ case $1 in
+ -c) shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ --help) echo "$usage"; exit 0;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd=$stripprog
+ shift
+ continue;;
+
+ -t) dstarg=$2
+ shift
+ shift
+ continue;;
+
+ -T) no_target_directory=true
+ shift
+ continue;;
+
+ --version) echo "$0 $scriptversion"; exit 0;;
+
+ *) # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ test -n "$dir_arg$dstarg" && break
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dstarg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dstarg"
+ shift # fnord
+ fi
+ shift # arg
+ dstarg=$arg
+ done
+ break;;
+ esac
+done
+
+if test -z "$1"; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src ;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ src=
+
+ if test -d "$dst"; then
+ mkdircmd=:
+ chmodcmd=
+ else
+ mkdircmd=$mkdirprog
+ fi
+ else
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dstarg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dstarg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst ;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dstarg: Is a directory" >&2
+ exit 1
+ fi
+ dst=$dst/`basename "$src"`
+ fi
+ fi
+
+ # This sed command emulates the dirname command.
+ dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+ # Make sure that the destination directory exists.
+
+ # Skip lots of stat calls in the usual case.
+ if test ! -d "$dstdir"; then
+ defaultIFS='
+ '
+ IFS="${IFS-$defaultIFS}"
+
+ oIFS=$IFS
+ # Some sh's can't handle IFS=/ for some reason.
+ IFS='%'
+ set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+ IFS=$oIFS
+
+ pathcomp=
+
+ while test $# -ne 0 ; do
+ pathcomp=$pathcomp$1
+ shift
+ if test ! -d "$pathcomp"; then
+ $mkdirprog "$pathcomp"
+ # mkdir can fail with a `File exist' error in case several
+ # install-sh are creating the directory concurrently. This
+ # is OK.
+ test -d "$pathcomp" || exit
+ fi
+ pathcomp=$pathcomp/
+ done
+ fi
+
+ if test -n "$dir_arg"; then
+ $doit $mkdircmd "$dst" \
+ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
+ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
+
+ else
+ dstfile=`basename "$dst"`
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Copy the file name to the temp name.
+ $doit $cpprog "$src" "$dsttmp" &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
+
+ # Now rename the file to the real destination.
+ { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
+ || {
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ if test -f "$dstdir/$dstfile"; then
+ $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
+ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
+ || {
+ echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+ (exit 1); exit
+ }
+ else
+ :
+ fi
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+ }
+ }
+ fi || { (exit 1); exit; }
+done
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+{
+ (exit 0); exit
+}
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Propchange: klee/trunk/autoconf/install-sh
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/configure
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/configure?rev=72205&view=auto
==============================================================================
--- klee/trunk/configure (added)
+++ klee/trunk/configure Wed May 20 23:36:41 2009
@@ -0,0 +1,6039 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.60 for KLEE 0.01.
+#
+# Report bugs to <daniel at minormatter.com>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf at gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+# Find out whether ``test -x'' works. Don't use a zero-byte file, as
+# systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+ as_executable_p="test -x"
+else
+ as_executable_p=:
+fi
+rm -f conf$$.file
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='KLEE'
+PACKAGE_TARNAME='-klee-'
+PACKAGE_VERSION='0.01'
+PACKAGE_STRING='KLEE 0.01'
+PACKAGE_BUGREPORT='daniel at minormatter.com'
+
+ac_unique_file=""Makefile.config.in""
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+LLVM_SRC
+LLVM_OBJ
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+KLEE_UCLIBC
+ENABLE_UCLIBC
+ENABLE_POSIX_RUNTIME
+RUNTIME_ENABLE_OPTIMIZED
+RUNTIME_CONFIGURATION
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+HAVE_SELINUX
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXCPP
+ENABLE_STPLOG
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+CPP
+CXX
+CXXFLAGS
+CCC
+CXXCPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures KLEE 0.01 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/-klee-]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of KLEE 0.01:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-posix-runtime Enable the POSIX runtime
+ --enable-stplog Compile with the stplog library [disabled]
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-llvmsrc Location of LLVM Source Code
+ --with-llvmobj Location of LLVM Object Code
+ --with-llvm Location of LLVM Source and Object code
+ --with-uclibc Enable use of the klee uclibc at the given path
+ --with-runtime Select build configuration for runtime libraries
+ (default Release)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <daniel at minormatter.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+KLEE configure 0.01
+generated by GNU Autoconf 2.60
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by KLEE $as_me 0.01, which was
+generated by GNU Autoconf 2.60. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+LLVM_SRC_ROOT="."
+
+ac_aux_dir=
+for ac_dir in $LLVM_SRC_ROOT/autoconf "$srcdir"/$LLVM_SRC_ROOT/autoconf; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $LLVM_SRC_ROOT/autoconf \"$srcdir\"/$LLVM_SRC_ROOT/autoconf" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $LLVM_SRC_ROOT/autoconf \"$srcdir\"/$LLVM_SRC_ROOT/autoconf" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+
+
+# Check whether --with-llvmsrc was given.
+if test "${with_llvmsrc+set}" = set; then
+ withval=$with_llvmsrc; llvm_src="$withval"
+else
+ llvm_src=""""
+fi
+
+ LLVM_SRC=$llvm_src
+
+
+# Check whether --with-llvmobj was given.
+if test "${with_llvmobj+set}" = set; then
+ withval=$with_llvmobj; llvm_obj="$withval"
+else
+ llvm_obj=""""
+fi
+
+ LLVM_OBJ=$llvm_obj
+
+ ac_config_commands="$ac_config_commands setup"
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile.config"
+
+ac_config_files="$ac_config_files stp/Makefile.common"
+
+
+ac_config_headers="$ac_config_headers include/klee/Config/config.h"
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+{ echo "$as_me:$LINENO: checking type of operating system we're going to host on" >&5
+echo $ECHO_N "checking type of operating system we're going to host on... $ECHO_C" >&6; }
+if test "${klee_cv_os_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $host in
+ *-*-linux*)
+ host_supports_posix_runtime=yes ;;
+ *)
+ host_supports_posix_runtime=no ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $klee_cv_os_type" >&5
+echo "${ECHO_T}$klee_cv_os_type" >&6; }
+
+
+
+# Check whether --with-llvm was given.
+if test "${with_llvm+set}" = set; then
+ withval=$with_llvm;
+fi
+
+
+{ echo "$as_me:$LINENO: checking llvm source dir" >&5
+echo $ECHO_N "checking llvm source dir... $ECHO_C" >&6; }
+
+if test X${with_llvm} != X; then
+ if test X${with_llvmsrc} != X; then
+ { { echo "$as_me:$LINENO: error: --with-llvmsrc cannot be specified when using --with-llvm" >&5
+echo "$as_me: error: --with-llvmsrc cannot be specified when using --with-llvm" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ if test X${with_llvmobj} != X; then
+ { { echo "$as_me:$LINENO: error: --with-llvmobj cannot be specified when using --with-llvm" >&5
+echo "$as_me: error: --with-llvmobj cannot be specified when using --with-llvm" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ with_llvmsrc=$with_llvm
+ with_llvmobj=$with_llvm
+fi
+
+if (test X${with_llvmsrc} != X || test X${with_llvmobj} != X); then
+ if test X${with_llvmsrc} = X; then
+ { { echo "$as_me:$LINENO: error: --with-llvmsrc must be specified when using --with-llvmobj" >&5
+echo "$as_me: error: --with-llvmsrc must be specified when using --with-llvmobj" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ if test X${with_llvmobj} = X; then
+ { { echo "$as_me:$LINENO: error: --with-llvmobj must be specified when using --with-llvmsrc" >&5
+echo "$as_me: error: --with-llvmobj must be specified when using --with-llvmsrc" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+else
+ llvm_version=`llvm-config --version`
+ if test X${llvm_version} = X; then
+ { { echo "$as_me:$LINENO: error: unable to find llvm, use --with-llvmsrc and --with-llvmobj" >&5
+echo "$as_me: error: unable to find llvm, use --with-llvmsrc and --with-llvmobj" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ with_llvmsrc=`llvm-config --src-root`
+ with_llvmobj=`llvm-config --obj-root`
+fi
+
+if test ! -f ${with_llvmsrc}/Makefile.rules; then
+ { { echo "$as_me:$LINENO: error: invalid llvmsrc directory: ${with_llvmsrc}" >&5
+echo "$as_me: error: invalid llvmsrc directory: ${with_llvmsrc}" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test ! -f ${with_llvmobj}/Makefile.config; then
+ { { echo "$as_me:$LINENO: error: invalid llvmobj directory: ${with_llvmobj}" >&5
+echo "$as_me: error: invalid llvmobj directory: ${with_llvmobj}" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+llvm_src=`cd $with_llvmsrc 2> /dev/null; pwd`
+llvm_obj=`cd $with_llvmobj 2> /dev/null; pwd`
+
+{ echo "$as_me:$LINENO: result: $llvm_src" >&5
+echo "${ECHO_T}$llvm_src" >&6; }
+
+{ echo "$as_me:$LINENO: checking llvm obj dir" >&5
+echo $ECHO_N "checking llvm obj dir... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $llvm_obj" >&5
+echo "${ECHO_T}$llvm_obj" >&6; }
+
+LLVM_SRC=$llvm_src
+
+LLVM_OBJ=$llvm_obj
+
+
+
+
+# Check whether --with-uclibc was given.
+if test "${with_uclibc+set}" = set; then
+ withval=$with_uclibc;
+fi
+
+
+if (test X${with_uclibc} = X && test -d uclibc); then
+ with_uclibc=uclibc
+fi
+
+
+{ echo "$as_me:$LINENO: checking uclibc" >&5
+echo $ECHO_N "checking uclibc... $ECHO_C" >&6; }
+if (test X${with_uclibc} != X); then
+ if test ! -d ${with_uclibc}; then
+ { { echo "$as_me:$LINENO: error: invalid uclibc directory: ${with_uclibc}" >&5
+echo "$as_me: error: invalid uclibc directory: ${with_uclibc}" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ with_uclibc=`cd $with_uclibc 2> /dev/null; pwd`
+
+ { echo "$as_me:$LINENO: result: $with_uclibc" >&5
+echo "${ECHO_T}$with_uclibc" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define KLEE_UCLIBC "$with_uclibc"
+_ACEOF
+
+
+
+if test X${with_uclibc} != X ; then
+ ENABLE_UCLIBC=1
+
+else
+ ENABLE_UCLIBC=0
+
+fi
+
+
+# Check whether --enable-posix-runtime was given.
+if test "${enable_posix_runtime+set}" = set; then
+ enableval=$enable_posix_runtime;
+else
+ enableval=default
+fi
+
+
+{ echo "$as_me:$LINENO: checking POSIX runtime" >&5
+echo $ECHO_N "checking POSIX runtime... $ECHO_C" >&6; }
+if test ${enableval} = "default" ; then
+ if test X${with_uclibc} != X; then
+ enableval=$host_supports_posix_runtime
+ if test ${enableval} = "yes"; then
+ { echo "$as_me:$LINENO: result: default (enabled)" >&5
+echo "${ECHO_T}default (enabled)" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: default (disabled, unsupported target)" >&5
+echo "${ECHO_T}default (disabled, unsupported target)" >&6; }
+ fi
+ else
+ enableval="no"
+ { echo "$as_me:$LINENO: result: default (disabled, no uclibc)" >&5
+echo "${ECHO_T}default (disabled, no uclibc)" >&6; }
+ fi
+else
+ if test ${enableval} = "yes" ; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+fi
+
+if test ${enableval} = "yes" ; then
+ ENABLE_POSIX_RUNTIME=1
+
+else
+ ENABLE_POSIX_RUNTIME=0
+
+fi
+
+
+
+# Check whether --with-runtime was given.
+if test "${with_runtime+set}" = set; then
+ withval=$with_runtime;
+else
+ withval=default
+fi
+
+
+if test X"${withval}" = Xdefault; then
+ with_runtime=Release
+fi
+
+{ echo "$as_me:$LINENO: checking runtime configuration" >&5
+echo $ECHO_N "checking runtime configuration... $ECHO_C" >&6; }
+if test X${with_runtime} = XRelease; then
+ { echo "$as_me:$LINENO: result: Release" >&5
+echo "${ECHO_T}Release" >&6; }
+ RUNTIME_ENABLE_OPTIMIZED=1
+
+elif test X${with_runtime} = XDebug; then
+ { echo "$as_me:$LINENO: result: Debug" >&5
+echo "${ECHO_T}Debug" >&6; }
+ RUNTIME_ENABLE_OPTIMIZED=0
+
+else
+ { { echo "$as_me:$LINENO: error: invalid configuration: ${with_runtime}" >&5
+echo "$as_me: error: invalid configuration: ${with_runtime}" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define RUNTIME_CONFIGURATION "$with_runtime"
+_ACEOF
+
+
+
+
+case $host in
+ *-*-linux*)
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CTYPE_EXTERNALS 1
+_ACEOF
+
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in sys/acl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ------------------------------------- ##
+## Report this to daniel at minormatter.com ##
+## ------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+for ac_header in selinux/selinux.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ------------------------------------- ##
+## Report this to daniel at minormatter.com ##
+## ------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ HAVE_SELINUX=1
+
+else
+ HAVE_SELINUX=0
+
+fi
+
+done
+
+
+
+# Check whether --enable-stplog was given.
+if test "${enable_stplog+set}" = set; then
+ enableval=$enable_stplog;
+else
+ enableval=no
+fi
+
+if test ${enableval} = "yes" ; then
+ ENABLE_STPLOG=1
+
+else
+ ENABLE_STPLOG=0
+
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_STPLOG $ENABLE_STPLOG
+_ACEOF
+
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+# Find out whether ``test -x'' works. Don't use a zero-byte file, as
+# systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+ as_executable_p="test -x"
+else
+ as_executable_p=:
+fi
+rm -f conf$$.file
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by KLEE $as_me 0.01, which was
+generated by GNU Autoconf 2.60. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf at gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+KLEE config.status 0.01
+configured by $0, generated by GNU Autoconf 2.60,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+llvm_src="${LLVM_SRC}"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "setup") CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;;
+ "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;;
+ "stp/Makefile.common") CONFIG_FILES="$CONFIG_FILES stp/Makefile.common" ;;
+ "include/klee/Config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/klee/Config/config.h" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+LLVM_SRC!$LLVM_SRC$ac_delim
+LLVM_OBJ!$LLVM_OBJ$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+KLEE_UCLIBC!$KLEE_UCLIBC$ac_delim
+ENABLE_UCLIBC!$ENABLE_UCLIBC$ac_delim
+ENABLE_POSIX_RUNTIME!$ENABLE_POSIX_RUNTIME$ac_delim
+RUNTIME_ENABLE_OPTIMIZED!$RUNTIME_ENABLE_OPTIMIZED$ac_delim
+RUNTIME_CONFIGURATION!$RUNTIME_CONFIGURATION$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+HAVE_SELINUX!$HAVE_SELINUX$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXCPP!$CXXCPP$ac_delim
+ENABLE_STPLOG!$ENABLE_STPLOG$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 74; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
Propchange: klee/trunk/configure
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/docs/SMT-COMP/BitVector_ArraysEx.smt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/docs/SMT-COMP/BitVector_ArraysEx.smt?rev=72205&view=auto
==============================================================================
--- klee/trunk/docs/SMT-COMP/BitVector_ArraysEx.smt (added)
+++ klee/trunk/docs/SMT-COMP/BitVector_ArraysEx.smt Wed May 20 23:36:41 2009
@@ -0,0 +1,74 @@
+(theory BitVector_ArraysEx
+
+ :written_by {Clark Barrett}
+ :date {May 7, 2007}
+
+:sorts_description {
+ All sort symbols of the form BitVec[m],
+ where m is a numeral greater than 0.
+
+ All sort symbols of the form Array[m:n],
+ where m and n are numerals with m > 0 and n > 0.
+}
+
+:funs_description {
+ All functions from the theory Fixed_Size_Bitvectors.
+}
+
+:funs_description {
+ All function symbols with arity of the form
+
+ (select Array[m:n] BitVec[m] BitVec[n])
+
+ where
+ - m,n are numerals
+ - m > 0, n > 0
+}
+
+:funs_description {
+ All function symbols with arity of the form
+
+ (store Array[m:n] BitVec[m] BitVec[n] Array[m:n])
+
+ where
+ - m,n are numerals
+ - m > 0, n > 0
+}
+
+:preds_description {
+ All predicates from the theory Fixed_Size_Bitvectors.
+}
+
+
+ :definition
+ "This is a theory containing an infinite number of copies of the theory of
+ functional arrays with extensionality: one for each pair of bitvector sorts.
+ It can be formally defined as the union of the SMT-LIB theory
+ Fixed_Size_Bitvectors and an infinite number of variants of the SMT-LIB
+ theory ArraysEx: one for each distinct signature morphism mapping the sort Index
+ to BitVec[m] and the sort Element to Bitvec[n] where m and n range over all
+ positive numerals. In each of the copies of ArraysEx, the sort Array is
+ renamed to Array[m:n] and each copy of ArraysEx contributes exactly one select
+ function and one store function to the infinite polymorphic family of select
+ and store functions described above.
+ "
+
+ :notes
+ "As in the theory Fixed_Size_Bitvectors, this theory does not
+ provide a value for the formal attributes :sorts, :funs, and :preds because
+ there are an infinite number of them. See the notes in theory
+ Fixed_Size_Bitvectors for details.
+
+ If for i=1,2, T_i is an SMT-LIB theory with sorts S_i, function symbols F_i,
+ predicate symbols P_i, and axioms A_i, by \"union\" of T_1 and T_2
+ we mean the theory T with sorts S_1 U S_2, function symbols F_1 U F_2,
+ predicate symbols P_1 U P_2, and axioms A_1 U A_2 (where U stands for set
+ theoretic union).
+
+ The theory T is a well-defined SMT-LIB theory whenever S_1, S_2, F_1, F_2,
+ P_1, P_2 are all pairwise disjoint, as is the case for the component theories
+ considered here.
+ "
+)
+
+
Added: klee/trunk/docs/SMT-COMP/BitVectors.smt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/docs/SMT-COMP/BitVectors.smt?rev=72205&view=auto
==============================================================================
--- klee/trunk/docs/SMT-COMP/BitVectors.smt (added)
+++ klee/trunk/docs/SMT-COMP/BitVectors.smt Wed May 20 23:36:41 2009
@@ -0,0 +1,187 @@
+(theory Fixed_Size_BitVectors
+
+:written_by {Silvio Ranise, Cesare Tinelli, and Clark Barrett}
+
+:date {May 7, 2007}
+
+:notes
+ "Against the requirements of the current SMT-LIB standard this theory does
+ not provide a value for the formal attributes :sorts, :funs, and :preds.
+ The reason is that the theory has an infinite number of sort, function, and
+ predicate symbols, and so they cannot be specified formally in the current
+ SMT-LIB language. While extending SMT-LIB's type system with dependent
+ types would allow a finitary formal specification of all the symbols in
+ this theory's signature, such an extension does not seem to be worth the
+ trouble at the moment. As a temporary ad-hoc solution, this theory
+ declaration specifies the signature, in English, in the user-defined
+ attributes :sorts_description, :funs_description, and :preds_description.
+ "
+
+:sorts_description {
+ All sort symbols of the form BitVec[m],
+ where m is a numeral greater than 0.
+}
+
+:funs_description {
+ Constant symbols bit0 and bit1 of sort BitVec[1]
+}
+
+:funs_description {
+ All function symbols with arity of the form
+
+ (concat BitVec[i] BitVec[j] BitVec[m])
+
+ where
+ - i,j,m are numerals
+ - i,j > 0
+ - i + j = m
+}
+
+:funs_description {
+ All function symbols with arity of the form
+
+ (extract[i:j] BitVec[m] BitVec[n])
+
+ where
+ - i,j,m,n are numerals
+ - m > i >= j >= 0,
+ - n = i-j+1.
+}
+
+:funs_description {
+ All function symbols with arity of the form
+
+ (op1 BitVec[m] BitVec[m])
+ or
+ (op2 BitVec[m] BitVec[m] BitVec[m])
+
+ where
+ - op1 is from {bvnot, bvneg}
+ - op2 is from {bvand, bvor, bvadd, bvmul, bvudiv, bvurem, bvshl, bvlshr}
+ - m is a numeral greater than 0
+}
+
+:preds_description {
+ All predicate symbols with arity of the form
+
+ (pred BitVec[m] BitVec[m])
+
+ where
+ - pred is from {bvult}
+ - m is a numeral greater than 0
+}
+
+:definition
+ "This is a core theory for fixed-size bitvectors where the operations
+ of concatenation and extraction of bitvectors as well as the usual
+ logical and arithmetic operations are overloaded.
+ The theory is defined semantically as follows.
+
+ The sort BitVec[m] (for m > 0) is the set of finite functions
+ whose domain is the initial segment of the naturals [0...m), meaning
+ that 0 is included and m is excluded, and the co-domain is {0,1}.
+
+ The semantic interpretation [[_]] of well-sorted BitVec-terms is
+ inductively defined as follows.
+
+ - Variables
+
+ If v is a variable of sort BitVec[m] with 0 < m, then
+ [[v]] is some element of [{0,...,m-1} -> {0,1}], the set of total
+ functions from {0,...,m-1} to {0,1}.
+
+ - Constant symbols bit0 and bit1 of sort BitVec[1]
+
+ [[bit0]] := \lambda x : [0,1). 0
+ [[bit1]] := \lambda x : [0,1). 1
+
+ - Function symbols for concatenation
+
+ [[(concat s t)]] := \lambda x : [0...n+m).
+ if (x<m) then [[t]](x) else [[s]](x-m)
+ where
+ s and t are terms of sort BitVec[n] and BitVec[m], respectively,
+ 0 < n, 0 < m.
+
+ - Function symbols for extraction
+
+ [[(extract[i:j] s)]] := \lambda x : [0...i-j+1). [[s]](j+x)
+ where s is of sort BitVec[l], 0 <= j <= i < l.
+
+ - Bit-wise operations
+
+ [[(bvnot s)]] := \lambda x : [0...m). if [[s]](x) = 0 then 1 else 0
+
+ [[(bvand s t)]] := \lambda x : [0...m).
+ if [[s]](x) = 0 then 0 else [[t]](x)
+
+ [[(bvor s t)]] := \lambda x : [0...m).
+ if [[s]](x) = 1 then 1 else [[t]](x)
+
+ where s and t are both of sort BitVec[m] and 0 < m.
+
+ - Arithmetic operations
+
+ To define the semantics of the bitvector arithmetic operators, we first
+ introduce some additional definitions:
+
+ o (x div y) where x and y are integers with x >= 0 and y > 0 returns the
+ integer part of x divided by y (i.e., truncated integer division).
+
+ o (x rem y) where x and y are integers with x >= 0 and y > 0 returns the
+ remainder when x is divided by y. Note that we always have the following
+ equivalence (for y > 0): (x div y) * y + (x rem y) = x.
+
+ o bv2nat which takes a bitvector b: [0...m) --> {0,1}
+ with 0 < m, and returns an integer in the range [0...2^m),
+ and is defined as follows:
+
+ bv2nat(b) := b(m-1)*2^{m-1} + b(m-2)*2^{m-2} + ... + b(0)*2^0
+
+ o nat2bv[m], with 0 < m, which takes a non-negative integer
+ n and returns the (unique) bitvector b: [0,...,m) -> {0,1}
+ such that
+
+ b(m-1)*2^{m-1} + ... + b(0)*2^0 = n rem 2^m
+
+ Now, we can define the following operations. Suppose s and t are both terms
+ of sort BitVec[m], m > 0.
+
+ [[(bvneg s)]] := nat2bv[m](2^m - bv2nat([[s]]))
+
+ [[(bvadd s t)]] := nat2bv[m](bv2nat([[s]]) + bv2nat([[t]]))
+
+ [[(bvmul s t)]] := nat2bv[m](bv2nat([[s]]) * bv2nat([[t]]))
+
+ [[(bvudiv s t)]] := if bv2nat([[t]]) != 0 then
+ nat2bv[m](bv2nat([[s]]) div bv2nat([[t]]))
+
+ [[(bvurem s t)]] := if bv2nat([[t]]) != 0 then
+ nat2bv[m](bv2nat([[s]]) rem bv2nat([[t]]))
+
+ - Shift operations
+
+ Suppose s and t are both terms of sort BitVec[m], m > 0. We make use of the
+ definitions given for the arithmetic operations, above.
+
+ [[(bvshl s t)]] := nat2bv[m](bv2nat([[s]]) * 2^(bv2nat([[t]])))
+
+ [[(bvlshr s t)]] := nat2bv[m](bv2nat([[s]]) div 2^(bv2nat([[t]])))
+
+ Finally, we can define the binary predicate bvult:
+
+ (bvult s t) is interpreted to be true iff bv2nat([[s]]) < bv2nat([[t]])
+
+ Note that the semantic interpretation above is underspecified because it
+ does not specify the meaning of (bvudiv s t) or (bvurem s t) in case
+ bv2nat([[t]]) is 0. Since the semantics of SMT-LIB's underlying logic
+ associates *total* functions to function symbols, we then consider as models
+ of this theory *any* interpretation conforming to the specifications above
+ (and defining bvudiv and bvurem arbitrarily when the second argument
+ evaluates to 0). Benchmarks using this theory should only include a
+ :status sat or :status unsat attribute if the status is independent of
+ the particular choice of model for the theory.
+
+ "
+
+)
Added: klee/trunk/docs/SMT-COMP/QF_AUFBV.smt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/docs/SMT-COMP/QF_AUFBV.smt?rev=72205&view=auto
==============================================================================
--- klee/trunk/docs/SMT-COMP/QF_AUFBV.smt (added)
+++ klee/trunk/docs/SMT-COMP/QF_AUFBV.smt Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+(logic QF_AUFBV
+
+ :written_by {Clark Barrett}
+ :date {May 7, 2007}
+
+ :theory BV_ArraysEx
+
+ :language
+ "Closed quantifier-free formulas built over an arbitrary expansion of the
+ BV_ArraysEx signature with free function and predicate symbols over
+ the sorts of BV_ArraysEx. Formulas in ite terms must satisfy the same
+ restriction as well, with the exception that they need not be closed (because
+ they may be in the scope of a let expression).
+ "
+ :extensions
+ "As in the logic QF_BV."
+)
+
+
Added: klee/trunk/docs/SMT-COMP/QF_BV.smt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/docs/SMT-COMP/QF_BV.smt?rev=72205&view=auto
==============================================================================
--- klee/trunk/docs/SMT-COMP/QF_BV.smt (added)
+++ klee/trunk/docs/SMT-COMP/QF_BV.smt Wed May 20 23:36:41 2009
@@ -0,0 +1,261 @@
+(logic QF_BV
+
+:written_by {Silvio Ranise, Cesare Tinelli, and Clark Barrett}
+:date {May 7, 2007}
+
+:theory Fixed_Size_BitVectors
+
+:language
+
+ "Closed quantifier-free formulas built over an arbitrary expansion of the
+ Fixed_Size_BitVectors signature with free constant symbols over the sorts
+ BitVec[m] for 0 < m. Formulas in ite terms must satisfy the same restriction
+ as well, with the exception that they need not be closed (because they may be
+ in the scope of a let expression).
+ "
+
+:notes
+ "For quick reference, the following is a brief and informal summary of the
+ legal symbols in this logic and their meaning (formal definitions are found
+ either in the Fixed_Size_Bitvectors theory, or in the extensions below).
+
+ Defined in theory Fixed_Size_Bitvectors:
+
+ Functions/Constants:
+
+ (bit0 BitVec[1])
+ - the constant consisting of a single bit with value 0
+ (bit1 BitVec[1])
+ - the constant consisting of a single bit with value 1
+ (concat BitVec[i] BitVec[j] BitVec[m])
+ - concatenation of bitvectors of size i and j to get a new bitvector of
+ size m, where m = i + j
+ (extract[i:j] BitVec[m] BitVec[n])
+ - extraction of bits i down to j from a bitvector of size m to yield a
+ new bitvector of size n, where n = i - j + 1
+ (bvnot BitVec[m] BitVec[m])
+ - bitwise negation
+ (bvand BitVec[m] BitVec[m] BitVec[m])
+ - bitwise and
+ (bvor BitVec[m] BitVec[m] BitVec[m])
+ - bitwise or
+ (bvneg BitVec[m] BitVec[m])
+ - 2's complement unary minus
+ (bvadd BitVec[m] BitVec[m] BitVec[m])
+ - addition modulo 2^m
+ (bvmul BitVec[m] BitVec[m] BitVec[m])
+ - multiplication modulo 2^m
+ (bvudiv BitVec[m] BitVec[m] BitVec[m])
+ - unsigned division, truncating towards 0 (undefined if divisor is 0)
+ (bvurem BitVec[m] BitVec[m] BitVec[m])
+ - unsigned remainder from truncating division (undefined if divisor is 0)
+ (bvshl BitVec[m] BitVec[m] BitVec[m])
+ - shift left (equivalent to multiplication by 2^x where x is the value of
+ the second argument)
+ (bvlshr BitVec[m] BitVec[m] BitVec[m])
+ - logical shift right (equivalent to unsigned division by 2^x where x is
+ the value of the second argument)
+
+ Predicates:
+
+ (bvult BitVec[m] BitVec[m])
+ - binary predicate for unsigned less than
+
+ Defined below:
+
+ Functions/Constants:
+
+ Bitvector constants:
+ - bvX[m] where X is a numeral in base 10 defines the bitvector constant
+ with numeric value X of size m.
+ - bvbinX where X is a binary numeral of length m defines the
+ bitvector constant with value X and size m.
+ - bvhexX where X is a hexadecimal numeral of length m defines the
+ bitvector constant with value X and size 4*m.
+ (bvnand BitVec[m] BitVec[m] BitVec[m])
+ - bitwise nand (negation of and)
+ (bvnor BitVec[m] BitVec[m] BitVec[m])
+ - bitwise nor (negation of or)
+ (bvxor BitVec[m] BitVec[m] BitVec[m])
+ - bitwise exclusive or
+ (bvxnor BitVec[m] BitVec[m] BitVec[m])
+ - bitwise equivalence (equivalently, negation of bitwise exclusive or)
+ (bvcomp BitVec[m] BitVec[m] BitVec[1])
+ - bit comparator: equals bit1 iff all bits are equal
+ (bvsub BitVec[m] BitVec[m] BitVec[m])
+ - 2's complement subtraction modulo 2^m
+ (bvsdiv BitVec[m] BitVec[m] BitVec[m])
+ - 2's complement signed division
+ (bvsrem BitVec[m] BitVec[m] BitVec[m])
+ - 2's complement signed remainder (sign follows dividend)
+ (bvsmod BitVec[m] BitVec[m] BitVec[m])
+ - 2's complement signed remainder (sign follows divisor)
+ (bvashr BitVec[m] BitVec[m] BitVec[m])
+ - Arithmetic shift right, like logical shift right except that the most
+ significant bits of the result always copy the most significant
+ bit of the first argument.
+
+ The following symbols are parameterized by the numeral i, where i >= 0.
+
+ (repeat[i] BitVec[m] BitVec[i*m])
+ - (repeat[i] x) means concatenate i copies of x
+ (zero_extend[i] BitVec[m] BitVec[m+i])
+ - (zero_extend[i] x) means extend x with zeroes to the (unsigned)
+ equivalent bitvector of size m+i
+ (sign_extend[i] BitVec[m] BitVec[m+i])
+ - (sign_extend[i] x) means extend x to the (signed) equivalent bitvector
+ of size m+i
+ (rotate_left[i] BitVec[m] BitVec[m])
+ - (rotate_left[i] x) means rotate bits of x to the left i times
+ (rotate_right[i] BitVec[m] BitVec[m])
+ - (rotate_right[i] x) means rotate bits of x to the right y times
+
+ Predicates:
+
+ (bvule BitVec[m] BitVec[m])
+ - binary predicate for unsigned less than or equal
+ (bvugt BitVec[m] BitVec[m])
+ - binary predicate for unsigned greater than
+ (bvuge BitVec[m] BitVec[m])
+ - binary predicate for unsigned greater than or equal
+ (bvslt BitVec[m] BitVec[m])
+ - binary predicate for signed less than
+ (bvsle BitVec[m] BitVec[m])
+ - binary predicate for signed less than or equal
+ (bvsgt BitVec[m] BitVec[m])
+ - binary predicate for signed greater than
+ (bvsge BitVec[m] BitVec[m])
+ - binary predicate for signed greater than or equal
+
+ "
+
+:extensions
+ "Below, let |exp| denote the integer resulting from the evaluation
+ of the arithmetic expression exp.
+
+ - Bitvector Constants:
+ The string bv followed by the numeral n and a size [m] (as in bv13[32])
+ abbreviates any term t of sort BitVec[m] built only out of the symbols in
+ {concat, bit0, bit1} such that
+
+ [[t]] = nat2bv[m](n) for n=0, ..., 2^m - 1.
+
+ See the specification of the theory's semantics for a definition
+ of the functions [[_]] and nat2bv. Note that this convention implicitly
+ considers the numeral n as a number written in base 10.
+
+ For backward compatibility, if the size [m] is omitted, then the size is
+ assumed to be 32.
+
+ The string bvbin followed by a sequence of 0's and 1's abbreviates the
+ concatenation of a similar sequence of bit0 and bit1 terms. Thus,
+ if n is the numeral represented in base 2 by the sequence of 0's and 1's
+ and m is the length of the sequence, then the term represents
+ nat2bv[m](n). For example bvbin0101 is equivalent to bv5[4].
+
+ The string bvhex followed by a sequence of digits and/or letters from A to
+ F is interpreted similarly as a concatenation of bit0 and bit1 as follows.
+ If n is the numeral represented in hexadecimal (base 16) by the sequence of
+ digits and letters from A to F and m is four times the length of the
+ sequence, then the term represents nat2bv[m](n). For example, bvbinFF is
+ equivalent to bv255[8]. Letters in the hexadecimal sequence may be in
+ either upper or lower case.
+
+ - Bitwise operators
+
+ For all terms s,t of sort BitVec[m], where 0 < m,
+
+ (bvnand s t) abbreviates (bvnot (bvand s t))
+ (bvnor s t) abbreviates (bvnot (bvor s t))
+ (bvxor s t) abbreviates (bvor (bvand s (bvnot t)) (bvand (bvnot s) t))
+ (bvxnor s t) abbreviates (bvor (bvand s t) (bvand (bvnot s) (bvnot t)))
+ (bvcomp s t) abbreviates (bvxnor s t) if m = 1, and
+ (bvand (bvxnor (extract[|m-1|:|m-1|] s) (extract[|m-1|:|m-1|] t))
+ (bvcomp (extract[|m-2|:0] s) (extract[|m-2|:0] t))) otherwise
+
+ - Arithmetic operators
+
+ For all terms s,t of sort BitVec[m], where 0 < m,
+
+ (bvsub s t) abbreviates (bvadd s (bvneg t))
+ (bvsdiv s t) abbreviates
+ (let (?msb_s (extract[|m-1|:|m-1|] s))
+ (let (?msb_t (extract[|m-1|:|m-1|] t))
+ (ite (and (= ?msb_s bit0) (= ?msb_t bit0))
+ (bvudiv s t)
+ (ite (and (= ?msb_s bit1) (= ?msb_t bit0))
+ (bvneg (bvudiv (bvneg s) t))
+ (ite (and (= ?msb_s bit0) (= ?msb_t bit1))
+ (bvneg (bvudiv s (bvneg t)))
+ (bvudiv (bvneg s) (bvneg t)))))))
+ (bvsrem s t) abbreviates
+ (let (?msb_s (extract[|m-1|:|m-1|] s))
+ (let (?msb_t (extract[|m-1|:|m-1|] t))
+ (ite (and (= ?msb_s bit0) (= ?msb_t bit0))
+ (bvurem s t)
+ (ite (and (= ?msb_s bit1) (= ?msb_t bit0))
+ (bvneg (bvurem (bvneg s) t))
+ (ite (and (= ?msb_s bit0) (= ?msb_t bit1))
+ (bvurem s (bvneg t)))
+ (bvneg (bvurem (bvneg s) (bvneg t)))))))
+ (bvsmod s t) abbreviates
+ (let (?msb_s (extract[|m-1|:|m-1|] s))
+ (let (?msb_t (extract[|m-1|:|m-1|] t))
+ (ite (and (= ?msb_s bit0) (= ?msb_t bit0))
+ (bvurem s t)
+ (ite (and (= ?msb_s bit1) (= ?msb_t bit0))
+ (bvadd (bvneg (bvurem (bvneg s) t)) t)
+ (ite (and (= ?msb_s bit0) (= ?msb_t bit1))
+ (bvadd (bvurem s (bvneg t)) t)
+ (bvneg (bvurem (bvneg s) (bvneg t)))))))
+ (bvule s t) abbreviates (or (bvult s t) (= s t))
+ (bvugt s t) abbreviates (bvult t s)
+ (bvuge s t) abbreviates (or (bvult t s) (= s t))
+ (bvslt s t) abbreviates:
+ (or (and (= (extract[|m-1|:|m-1|] s) bit1)
+ (= (extract[|m-1|:|m-1|] t) bit0))
+ (and (= (extract[|m-1|:|m-1|] s) (extract[|m-1|:|m-1|] t))
+ (bvult s t)))
+ (bvsle s t) abbreviates:
+ (or (and (= (extract[|m-1|:|m-1|] s) bit1)
+ (= (extract[|m-1|:|m-1|] t) bit0))
+ (and (= (extract[|m-1|:|m-1|] s) (extract[|m-1|:|m-1|] t))
+ (bvule s t)))
+ (bvsgt s t) abbreviates (bvslt t s)
+ (bvsge s t) abbreviates (bvsle t s)
+
+ - Other operations
+
+ For all numerals j > 1 and 0 < m, and all terms of s and t of
+ sort BitVec[m],
+
+ (bvashr s t) abbreviates
+ (ite (= (extract[|m-1|:|m-1|] s) bit0)
+ (bvlshr s t)
+ (bvnot (bvlshr (bvnot s) t)))
+
+ (repeat[1] t) stands for t
+ (repeat[j] t) abbreviates (concat t (repeat[|j-1|] t))
+
+ (zero_extend[0] t) stands for t
+ (zero_extend[j] t) abbreviates (concat (repeat[j] bit0) t)
+
+ (sign_extend[0] t) stands for t
+ (sign_extend[j] t) abbreviates
+ (concat (repeat[j] (extract[|m-1|:|m-1|] t)) t)
+
+ (rotate_left[0] t) stands for t
+ (rotate_left[j] t) abbreviates t if m = 1, and
+ (rotate_left[|j-1|]
+ (concat (extract[|m-2|:0] t) (extract[|m-1|:|m-1|] t))
+ otherwise
+
+ (rotate_right[0] t) stands for t
+ (rotate_right[j] t) abbreviates t if m = 1, and
+ (rotate_right[|j-1|]
+ (concat (extract[0:0] t) (extract[|m-1|:1] t)))
+ otherwise
+
+ "
+)
+
Added: klee/trunk/docs/doxygen.cfg
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/docs/doxygen.cfg?rev=72205&view=auto
==============================================================================
--- klee/trunk/docs/doxygen.cfg (added)
+++ klee/trunk/docs/doxygen.cfg Wed May 20 23:36:41 2009
@@ -0,0 +1,1291 @@
+# Doxyfile 1.5.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = klee
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = docs/doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be extracted
+# and appear in the documentation as a namespace called 'anonymous_namespace{file}',
+# where file will be replaced with the base name of the file that contains the anonymous
+# namespace. By default anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = tools/ \
+ lib/ \
+ include/klee \
+ docs/intro \
+ docs/overview
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = */.svn* */Debug*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH
+# then you must also enable this option. If you don't then doxygen will produce
+# a warning and turn it on anyway
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = YES
+
+# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the number
+# of direct children of the root node in a graph is already larger than
+# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = YES
Added: klee/trunk/docs/intro
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/docs/intro?rev=72205&view=auto
==============================================================================
--- klee/trunk/docs/intro (added)
+++ klee/trunk/docs/intro Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+/// @mainpage KLEE
+///
+/// @section main_intro Introduction
+/// Welcome to KLEE. KLEE is a symbolic execution engine that works on LLVM
+/// bitcode.
+///
+/// @section Documentation
+/// The documentation of KLEE is composed of the Doxygen documentation
+/// of the code as well as the following documents:
+/// - @subpage overview
Added: klee/trunk/docs/overview
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/docs/overview?rev=72205&view=auto
==============================================================================
--- klee/trunk/docs/overview (added)
+++ klee/trunk/docs/overview Wed May 20 23:36:41 2009
@@ -0,0 +1,104 @@
+/// @page overview High level overview of KLEE.
+/// This document contains a high level overview of the inner workings of KLEE.
+///
+/// KLEE implements symbolic execution by interpreting LLVM bitcode. Symbolic
+/// memory is defined by inserting special calls to KLEE (namely
+/// klee_make_symbolic)
+/// During execution, KLEE tracks all uses of symbolic memory. Constraints
+/// on symbolic memory usage are collected. Memory
+/// that is defined using previously declared symbolic memory become
+/// symbolic as well.
+/// Whenever a branch refering to symbolic memory is encountered, KLEE forks
+/// the entire states and explores each side of the branch for which a possible
+/// solution to the symbolic constraints can be found.
+/// KLEE makes queries to STP to solve symbolic constraints.
+///
+/// The rest of this document describes some of the important components of KLEE
+///
+/// @section executor Interpreter
+/// klee::Interpreter is the main abstract class defining the interface of the
+/// bitcode interpreter. klee::Executor is the main concrete instance of this
+/// class.
+/// Application states (i.e. memory, registers and PC) are stored in instances of
+/// class klee::ExecutionState. There is one such instance for each path beeing
+/// executed (except when some states are merged together).
+/// On a branch, if condition is symbolic, klee::Executor::fork returns a
+/// klee::ExecutionState::StatePair which is a pair of ExecutionState to be
+/// executed.
+///
+/// @section memory Memory model
+/// MemoryObject's represent allocation sites in the program (calls to malloc, stack
+/// objects, global variables)
+/// and, at least conceptually, can be thought of as the unique name for the object
+/// allocated at that site.
+/// ObjectState's are used to store the actual contents of a MemoryObject in a
+/// particular ExecutionState (but
+/// can be shared). I need better names for these two things.
+///
+/// Each ExecutionState stores a mapping of MemoryObjects -> ObjectState using the
+/// AddressSpace data
+/// structure (implemented as an immutable tree so that copying is cheap and the
+/// shared structure is exploited).
+/// Each AddressSpace may "own" some subset of the ObjectStates in the mapping. When
+/// an AddressSpace
+/// is duplicated it loses ownership of the ObjectState in the map. Any subsequent
+/// write to an ObjectState will
+/// create a copy of the object (AddressSpace::getWriteable). This is the COW
+/// mechanism (which gets used
+/// for all objects, not just globals).
+///
+/// From the point of view of the state and this mapping there is no distinction
+/// between stack, heap, and global
+/// objects. The only special handling for stack objects is that the MemoryObject is
+/// marked as isLocal and the
+/// MemoryObject is stored in the StackFrame alloca list. When the StackFrame is
+/// popped these objects are
+/// then unbound so that the state can no longer access the memory directly
+/// (references to the memory object
+/// may still remain in ReadExprs, but conceptually the actual memory is no longer
+/// addressable).
+///
+/// It is also important that the AddressSpace mapping is ordered. We use this when
+/// we need to resolve a symbolic
+/// address to an ObjectState by first getting a particular value for the symbolic
+/// address, and using that value to start
+/// looking for objects that the pointer can fall within.
+/// Difference betweens MemoryObjects and ObjectStates ?
+///
+/// @section expression Expressions
+/// The various Expr classes mostly model the llvm instruction set. ref<Expr> is
+/// used to maintain the reference count
+/// but also embeds any constant expressions. In fact in the current code base
+/// ConstantExprs should almost never be
+/// created. Most of the Expr's are straightforward. Some of the most important ones
+/// are Concat?Expr, which join
+/// some number of bytes into a larger type, ExtractExpr which extracts smaller
+/// types from larger ones, and ReadExpr
+/// which is a symbolic array access.
+///
+/// The way memory is implemented all accesses are broken down into byte level
+/// operations. This means that the
+/// memory system (by which I mean the ObjectState data structure) tends to use a
+/// lot of ExtractExpr and Concat?Expr,
+/// so it is very important that these expressions fold their operands when
+/// possible.
+///
+/// The ReadExpr is probably the most important one. Conceptually it is simply an
+/// index and a list of (index, value)
+/// updates (writes). The ReadExpr evaluates to all the values for which the two
+/// indices can be equal. The ObjectState
+/// structure uses a cache for concrete writes and for symbolic writes at concrete
+/// indices, but for writes at symbolic
+/// indices it must construct a list of such updates. These are stored in the
+/// UpdateList and UpdateNode structures
+/// which are again immutable data structures so that copy is cheap and the sharing
+/// is exploited.
+///
+/// @section searcher Searcher
+/// Base classe: klee::Searcher. The Executor uses a Searcher to select the next
+/// state (i.e. program instance following a single path) for which an
+/// instruction
+/// will be executed. There are multiple implementations of Searcher in klee,
+/// implementing different search policies. klee::RandomSearcher selects the next state randomly.
+/// klee::DFSSearcher uses a depth first approach. klee::MergingSearcher tries
+/// to merge states ?
Added: klee/trunk/examples/regexp/Regexp.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/examples/regexp/Regexp.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/examples/regexp/Regexp.c (added)
+++ klee/trunk/examples/regexp/Regexp.c Wed May 20 23:36:41 2009
@@ -0,0 +1,62 @@
+/*
+ * Simple regular expression matching.
+ *
+ * From:
+ * The Practice of Programming
+ * Brian W. Kernighan, Rob Pike
+ *
+ */
+
+#include <klee/klee.h>
+
+static int matchhere(char*,char*);
+
+static int matchstar(int c, char *re, char *text) {
+ do {
+ if (matchhere(re, text))
+ return 1;
+ } while (*text != '\0' && (*text++ == c || c== '.'));
+ return 0;
+}
+
+static int matchhere(char *re, char *text) {
+ if (re[0] == '\0')
+ return 0;
+ if (re[1] == '*')
+ return matchstar(re[0], re+2, text);
+ if (re[0] == '$' && re[1]=='\0')
+ return *text == '\0';
+ if (*text!='\0' && (re[0]=='.' || re[0]==*text))
+ return matchhere(re+1, text+1);
+ return 0;
+}
+
+int match(char *re, char *text) {
+ if (re[0] == '^')
+ return matchhere(re+1, text);
+ do {
+ if (matchhere(re, text))
+ return 1;
+ } while (*text++ != '\0');
+ return 0;
+}
+
+/*
+ * Harness for testing with KLEE.
+ */
+
+// The size of the buffer to test with.
+#define SIZE 7
+
+int main() {
+ // The input regular expression.
+ char re[SIZE];
+
+ // Make the input symbolic.
+ klee_make_symbolic_name(re, sizeof re, "re");
+
+ // Try to match against a constant string "hello".
+ match(re, "hello");
+
+ return 0;
+}
Added: klee/trunk/examples/regexp/notes.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/examples/regexp/notes.txt?rev=72205&view=auto
==============================================================================
--- klee/trunk/examples/regexp/notes.txt (added)
+++ klee/trunk/examples/regexp/notes.txt Wed May 20 23:36:41 2009
@@ -0,0 +1,26 @@
+clang -m32 -I ~/private/klee/include -c -emit-llvm Regexp.c
+
+klee Regexp.o
+klee --only-output-states-covering-new Regexp.o
+ls -l klee-out-0
+ls -l klee-out-1
+ls -l klee-last
+
+cd klee-last
+klee-bout-tool *.bout
+klee-bout-tool --trim-zeros *.bout
+
+Stuff to show:
+Adding klee_prefer_cex
+
+PrintStats.py klee-last
+
+PrintStats.py klee-last
+Why not 100% coverage?
+
+clang -g -m32 -I ~/private/klee/include -c -emit-llvm Regexp.c
+
+KCachegrind?
+
+Disable klee_assume, show coverage again (why is klee-check-div getting pulled
+in?)
Added: klee/trunk/examples/sort/sort.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/examples/sort/sort.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/examples/sort/sort.c (added)
+++ klee/trunk/examples/sort/sort.c Wed May 20 23:36:41 2009
@@ -0,0 +1,78 @@
+#include <klee/klee.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+static void insert_ordered(int *array, unsigned nelem, int item) {
+ unsigned i = 0;
+
+ for (; i != nelem; ++i) {
+ if (item < array[i]) {
+ memmove(&array[i+1], &array[i], sizeof(*array) * (nelem - i));
+ break;
+ }
+ }
+
+ array[i] = item;
+}
+
+void bubble_sort(int *array, unsigned nelem) {
+ for (;;) {
+ int done = 1;
+
+ for (unsigned i = 0; i + 1 < nelem; ++i) {
+ if (array[i+1] < array[i]) {
+ int t = array[i + 1];
+ array[i + 1] = array[i];
+ array[i] = t;
+ done = 0;
+ }
+ }
+
+ break;
+ }
+}
+
+void insertion_sort(int *array, unsigned nelem) {
+ int *temp = malloc(sizeof(*temp) * nelem);
+
+ for (unsigned i = 0; i != nelem; ++i)
+ insert_ordered(temp, i, array[i]);
+
+ memcpy(array, temp, sizeof(*array) * nelem);
+ free(temp);
+}
+
+void test(int *array, unsigned nelem) {
+ int *temp1 = malloc(sizeof(*array) * nelem);
+ int *temp2 = malloc(sizeof(*array) * nelem);
+
+ printf("input: [%d, %d, %d, %d]\n",
+ array[0], array[1], array[2], array[3]);
+
+ memcpy(temp1, array, sizeof(*array) * 4);
+ memcpy(temp2, array, sizeof(*array) * 4);
+
+ insertion_sort(temp1, 4);
+ bubble_sort(temp2, 4);
+
+ printf("insertion_sort: [%d, %d, %d, %d]\n",
+ temp1[0], temp1[1], temp1[2], temp1[3]);
+
+ printf("bubble_sort : [%d, %d, %d, %d]\n",
+ temp2[0], temp2[1], temp2[2], temp2[3]);
+
+ for (unsigned i = 0; i != nelem; ++i)
+ assert(temp1[i] == temp2[i]);
+}
+
+int main() {
+ int input[4] = { 4, 3, 2, 1};
+
+ klee_make_symbolic(&input, sizeof(input));
+ test(input, 4);
+
+ return 0;
+}
Added: klee/trunk/include/expr/Lexer.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/expr/Lexer.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/expr/Lexer.h (added)
+++ klee/trunk/include/expr/Lexer.h Wed May 20 23:36:41 2009
@@ -0,0 +1,114 @@
+//===-- Lexer.h -------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPR_LEXER_H
+#define KLEE_EXPR_LEXER_H
+
+#include <string>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace klee {
+namespace expr {
+ struct Token {
+ enum Kind {
+ At, /// '@'
+ Arrow, /// '->'
+ Colon, /// ':'
+ Comma, /// ','
+ Comment, /// #[^\n]+
+ EndOfFile, /// <end of file>
+ Equals, /// ' = '
+ Identifier, /// [a-zA-Z_][a-zA-Z0-9._]*
+ KWFalse, /// 'false'
+ KWQuery, /// 'query'
+ KWReserved, /// fp[0-9]+([.].*)?, i[0-9]+
+ KWTrue, /// 'true'
+ KWWidth, /// w[0-9]+
+ LBrace, /// '{'
+ LParen, /// '('
+ LSquare, /// '['
+ Number, /// [+-]?[0-9][a-zA-Z0-9_]+
+ RBrace, /// '}'
+ RParen, /// ')'
+ RSquare, /// ']'
+ Semicolon, /// ';'
+ Unknown /// <other>
+ };
+
+ Kind kind; /// The token kind.
+ const char *start; /// The beginning of the token string.
+ unsigned length; /// The length of the token.
+ unsigned line; /// The line number of the start of this token.
+ unsigned column; /// The column number at the start of
+ /// this token.
+
+ /// getKindName - The name of this token's kind.
+ const char *getKindName() const;
+
+ /// getString - The string spanned by this token. This is not
+ /// particularly efficient, use start and length when reasonable.
+ std::string getString() const { return std::string(start, length); }
+
+ /// isKeyword - True if this token is a keyword.
+ bool isKeyword() const {
+ return kind >= KWFalse && kind <= KWTrue;
+ }
+
+ // dump - Dump the token to stderr.
+ void dump();
+ };
+
+ /// Lexer - Interface for lexing tokens from a .pc language file.
+ class Lexer {
+ const char *BufferPos; /// The current lexer position.
+ const char *BufferEnd; /// The buffer end position.
+ unsigned LineNumber; /// The current line.
+ unsigned ColumnNumber; /// The current column.
+
+ /// GetNextChar - Eat a character or -1 from the stream.
+ int GetNextChar();
+
+ /// PeekNextChar - Return the next character without consuming it
+ /// from the stream. This does not perform newline
+ /// canonicalization.
+ int PeekNextChar();
+
+ /// SetTokenKind - Set the token kind and length (using the
+ /// token's start pointer, which must have been initialized).
+ Token &SetTokenKind(Token &Result, Token::Kind k);
+
+ /// SetTokenKind - Set an identifiers token kind. This has the
+ /// same requirements as SetTokenKind and additionally takes care
+ /// of keyword recognition.
+ Token &SetIdentifierTokenKind(Token &Result);
+
+ void SkipToEndOfLine();
+
+ /// LexNumber - Lex a number which does not have a base specifier.
+ Token &LexNumber(Token &Result);
+
+ /// LexIdentifier - Lex an identifier.
+ Token &LexIdentifier(Token &Result);
+
+ public:
+ explicit Lexer(const llvm::MemoryBuffer *_buf);
+ ~Lexer();
+
+ /// Lex - Return the next token from the file or EOF continually
+ /// when the end of the file is reached. The input argument is
+ /// used as the result, for convenience.
+ Token &Lex(Token &Result);
+ };
+}
+}
+
+#endif
Added: klee/trunk/include/expr/Parser.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/expr/Parser.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/expr/Parser.h (added)
+++ klee/trunk/include/expr/Parser.h Wed May 20 23:36:41 2009
@@ -0,0 +1,178 @@
+//===-- Parser.h ------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPR_PARSER_H
+#define KLEE_EXPR_PARSER_H
+
+#include "klee/Expr.h"
+
+#include <vector>
+#include <string>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace klee {
+namespace expr {
+ // These are the language types we manipulate.
+ typedef ref<Expr> ExprHandle;
+ typedef UpdateList VersionHandle;
+
+ /// Identifier - Wrapper for a uniqued string.
+ struct Identifier {
+ const std::string Name;
+
+ public:
+ Identifier(const std::string _Name) : Name(_Name) {}
+ };
+
+ // FIXME: Do we have a use for tracking source locations?
+
+ /// Decl - Base class for top level declarations.
+ class Decl {
+ public:
+ Decl();
+ virtual ~Decl() {}
+
+ /// dump - Dump the AST node to stderr.
+ virtual void dump() = 0;
+ };
+
+ /// ArrayDecl - Array declarations.
+ ///
+ /// For example:
+ /// array obj : 32 -> 8 = symbolic
+ /// array obj[32] : 32 -> 8 = { ... }
+ class ArrayDecl : public Decl {
+ public:
+ /// Name - The name of this array.
+ const Identifier *Name;
+
+ /// Size - The maximum array size (or 0 if unspecified). Concrete
+ /// arrays always are specified with a size.
+ const unsigned Size;
+
+ /// Domain - The width of indices.
+ const unsigned Domain;
+
+ /// Range - The width of array contents.
+ const unsigned Range;
+
+ /// Contents - The initial contents of the array. The array is
+ /// symbolic if no contents are specified. The contained
+ /// expressions are guaranteed to be constants.
+ const std::vector<ExprHandle> Contents;
+
+ public:
+ template<typename InputIterator>
+ ArrayDecl(const Identifier *_Name, unsigned _Size,
+ unsigned _Domain, unsigned _Range,
+ InputIterator ContentsBegin=InputIterator(),
+ InputIterator ContentsEnd=InputIterator())
+ : Name(_Name), Size(_Size), Domain(_Domain), Range(_Range),
+ Contents(ContentsBegin, ContentsEnd) {}
+ };
+
+ /// VarDecl - Variable declarations, used to associate names to
+ /// expressions or array versions outside of expressions.
+ ///
+ /// For example:
+ // FIXME: What syntax are we going to use for this? We need it.
+ class VarDecl : public Decl {
+ public:
+ const Identifier *Name;
+ };
+
+ /// ExprVarDecl - Expression variable declarations.
+ class ExprVarDecl : public VarDecl {
+ public:
+ ExprHandle Value;
+ };
+
+ /// VersionVarDecl - Array version variable declarations.
+ class VersionVarDecl : public VarDecl {
+ public:
+ VersionHandle Value;
+ };
+
+ /// CommandDecl - Base class for language commands.
+ class CommandDecl : public Decl {
+ public:
+ const Identifier *Name;
+ };
+
+ /// QueryCommand - Query commands.
+ ///
+ /// (query [ ... constraints ... ] expression)
+ /// (query [ ... constraints ... ] expression values)
+ /// (query [ ... constraints ... ] expression values objects)
+ class QueryCommand : public CommandDecl {
+ public:
+ // FIXME: One issue with STP... should we require the FE to
+ // guarantee that these are consistent? That is a cornerstone of
+ // being able to do independence. We may want this as a flag, if
+ // we are to interface with things like SMT.
+
+ /// Constraints - The list of constraints to assume for this
+ /// expression.
+ const std::vector<ExprHandle> Constraints;
+
+ /// Query - The expression being queried.
+ ExprHandle Query;
+
+ /// Values - The expressions for which counterexamples should be
+ /// given if the query is invalid.
+ const std::vector<ExprHandle> Values;
+
+ /// Objects - Symbolic arrays whose initial contents should be
+ /// given if the query is invalid.
+ const std::vector<ArrayDecl> Objects;
+
+ public:
+ template<typename InputIterator>
+ QueryCommand(InputIterator ConstraintsBegin,
+ InputIterator ConstraintsEnd,
+ ExprHandle _Query)
+ : Constraints(ConstraintsBegin, ConstraintsEnd),
+ Query(_Query) {}
+
+ virtual void dump();
+ };
+
+ /// Parser - Public interface for parsing a .pc language file.
+ class Parser {
+ protected:
+ Parser();
+ public:
+ virtual ~Parser();
+
+ /// SetMaxErrors - Suppress anything beyond the first N errors.
+ virtual void SetMaxErrors(unsigned N) = 0;
+
+ /// GetNumErrors - Return the number of encountered errors.
+ virtual unsigned GetNumErrors() const = 0;
+
+ /// ParseTopLevelDecl - Parse and return a top level declaration,
+ /// which the caller assumes ownership of.
+ ///
+ /// \return NULL indicates the end of the file has been reached.
+ virtual Decl *ParseTopLevelDecl() = 0;
+
+ /// CreateParser - Create a parser implementation for the given
+ /// MemoryBuffer.
+ ///
+ /// \arg Name - The name to use in diagnostic messages.
+ static Parser *Create(const std::string Name,
+ const llvm::MemoryBuffer *MB);
+ };
+}
+}
+
+#endif
Added: klee/trunk/include/klee/Config/config.h.in
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Config/config.h.in?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Config/config.h.in (added)
+++ klee/trunk/include/klee/Config/config.h.in Wed May 20 23:36:41 2009
@@ -0,0 +1,64 @@
+/* include/klee/Config/config.h.in. Generated from autoconf/configure.tmp.ac by autoheader. */
+
+/* Define if stplog enabled */
+#undef ENABLE_STPLOG
+
+/* Does the platform use __ctype_b_loc, etc. */
+#undef HAVE_CTYPE_EXTERNALS
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <selinux/selinux.h> header file. */
+#undef HAVE_SELINUX_SELINUX_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/acl.h> header file. */
+#undef HAVE_SYS_ACL_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Path to KLEE's uClibc */
+#undef KLEE_UCLIBC
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Configuration for runtime libraries */
+#undef RUNTIME_CONFIGURATION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
Added: klee/trunk/include/klee/Constraints.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Constraints.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Constraints.h (added)
+++ klee/trunk/include/klee/Constraints.h Wed May 20 23:36:41 2009
@@ -0,0 +1,79 @@
+//===-- Constraints.h -------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_CONSTRAINTS_H
+#define KLEE_CONSTRAINTS_H
+
+#include "klee/Expr.h"
+
+// FIXME: Currently we use ConstraintManager for two things: to pass
+// sets of constraints around, and to optimize constraints. We should
+// move the first usage into a separate data structure
+// (ConstraintSet?) which ConstraintManager could embed if it likes.
+namespace klee {
+
+class ExprVisitor;
+
+class ConstraintManager {
+public:
+ typedef std::vector< ref<Expr> > constraints_ty;
+ typedef constraints_ty::iterator iterator;
+ typedef constraints_ty::const_iterator const_iterator;
+
+ ConstraintManager() {}
+
+ // create from constraints with no optimization
+ explicit
+ ConstraintManager(const std::vector< ref<Expr> > &_constraints) :
+ constraints(_constraints) {}
+
+ ConstraintManager(const ConstraintManager &cs) : constraints(cs.constraints) {}
+
+ typedef std::vector< ref<Expr> >::const_iterator constraint_iterator;
+
+ // given a constraint which is known to be valid, attempt to
+ // simplify the existing constraint set
+ void simplifyForValidConstraint(ref<Expr> e);
+
+ ref<Expr> simplifyExpr(ref<Expr> e) const;
+
+ void addConstraint(ref<Expr> e);
+
+ bool empty() const {
+ return constraints.empty();
+ }
+ ref<Expr> back() const {
+ return constraints.back();
+ }
+ constraint_iterator begin() const {
+ return constraints.begin();
+ }
+ constraint_iterator end() const {
+ return constraints.end();
+ }
+ size_t size() const {
+ return constraints.size();
+ }
+
+ bool operator==(const ConstraintManager &other) const {
+ return constraints == other.constraints;
+ }
+
+private:
+ std::vector< ref<Expr> > constraints;
+
+ // returns true iff the constraints were modified
+ bool rewriteConstraints(ExprVisitor &visitor);
+
+ void addConstraintInternal(ref<Expr> e);
+};
+
+}
+
+#endif /* KLEE_CONSTRAINTS_H */
Added: klee/trunk/include/klee/ExecutionState.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/ExecutionState.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/ExecutionState.h (added)
+++ klee/trunk/include/klee/ExecutionState.h Wed May 20 23:36:41 2009
@@ -0,0 +1,250 @@
+//===-- ExecutionState.h ----------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXECUTIONSTATE_H
+#define KLEE_EXECUTIONSTATE_H
+
+#include "klee/Constraints.h"
+#include "klee/Expr.h"
+#include "klee/Internal/ADT/TreeStream.h"
+
+// FIXME: We do not want to be exposing these? :(
+#include "../../lib/Core/AddressSpace.h"
+#include "klee/Internal/Module/KInstIterator.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+namespace klee {
+ class CallPathNode;
+ class Cell;
+ class KFunction;
+ class KInstruction;
+ class MemoryObject;
+ class PTreeNode;
+ class InstructionInfo;
+ class ExecutionTraceEvent;
+
+std::ostream &operator<<(std::ostream &os, const MemoryMap &mm);
+
+struct StackFrame {
+ KInstIterator caller;
+ KFunction *kf;
+ CallPathNode *callPathNode;
+
+ std::vector<const MemoryObject*> allocas;
+ Cell *locals;
+
+ /// Minimum distance to an uncovered instruction once the function
+ /// returns. This is not a good place for this but is used to
+ /// quickly compute the context sensitive minimum distance to an
+ /// uncovered instruction. This value is updated by the StatsTracker
+ /// periodically.
+ unsigned minDistToUncoveredOnReturn;
+
+ // For vararg functions: arguments not passed via parameter are
+ // stored (packed tightly) in a local (alloca) memory object. This
+ // is setup to match the way the front-end generates vaarg code (it
+ // does not pass vaarg through as expected). VACopy is lowered inside
+ // of intrinsic lowering.
+ MemoryObject *varargs;
+
+ StackFrame(KInstIterator caller, KFunction *kf);
+ StackFrame(const StackFrame &s);
+ ~StackFrame();
+};
+
+// FIXME: Redo execution trace stuff to use a TreeStream, there is no
+// need to keep this stuff in memory as far as I can tell.
+
+// each state should have only one of these guys ...
+class ExecutionTraceManager {
+public:
+ ExecutionTraceManager() : hasSeenUserMain(false) {}
+
+ void addEvent(ExecutionTraceEvent* evt);
+ void printAllEvents(std::ostream &os) const;
+
+private:
+ // have we seen a call to __user_main() yet?
+ // don't bother tracing anything until we see this,
+ // or else we'll get junky prologue shit
+ bool hasSeenUserMain;
+
+ // ugh C++ only supports polymorphic calls thru pointers
+ //
+ // WARNING: these are NEVER FREED, because they are shared
+ // across different states (when states fork), so we have
+ // an *intentional* memory leak, but oh wellz ;)
+ std::vector<ExecutionTraceEvent*> events;
+};
+
+
+class ExecutionState {
+public:
+ typedef std::vector<StackFrame> stack_ty;
+
+private:
+ // unsupported, use copy constructor
+ ExecutionState &operator=(const ExecutionState&);
+ std::map< std::string, std::string > fnAliases;
+
+public:
+ bool fakeState;
+ // Are we currently underconstrained? Hack: value is size to make fake
+ // objects.
+ unsigned underConstrained;
+ unsigned depth;
+
+ // pc - pointer to current instruction stream
+ KInstIterator pc, prevPC;
+ stack_ty stack;
+ ConstraintManager constraints;
+ mutable double queryCost;
+ double weight;
+ AddressSpace addressSpace;
+ TreeOStream pathOS, symPathOS;
+ unsigned instsSinceCovNew;
+ bool coveredNew;
+
+ // for printing execution traces when this state terminates
+ ExecutionTraceManager exeTraceMgr;
+
+ /// Disables forking, set by user code.
+ bool forkDisabled;
+
+ std::map<const std::string*, std::set<unsigned> > coveredLines;
+ PTreeNode *ptreeNode;
+
+ /// ordered list of symbolics: used to generate test cases.
+ //
+ // FIXME: Move to a shared list structure (not critical).
+ std::vector<const MemoryObject*> symbolics;
+
+ // Used by the checkpoint/rollback methods for fake objects.
+ // FIXME: not freeing things on branch deletion.
+ MemoryMap shadowObjects;
+
+ unsigned incomingBBIndex;
+
+ std::string getFnAlias(std::string fn);
+ void addFnAlias(std::string old_fn, std::string new_fn);
+ void removeFnAlias(std::string fn);
+
+private:
+ ExecutionState() : fakeState(false), underConstrained(0), ptreeNode(0) {};
+
+public:
+ ExecutionState(KFunction *kf);
+
+ // XXX total hack, just used to make a state so solver can
+ // use on structure
+ ExecutionState(const std::vector<ref<Expr> > &assumptions);
+
+ ~ExecutionState();
+
+ ExecutionState *branch();
+
+ void pushFrame(KInstIterator caller, KFunction *kf);
+ void popFrame();
+
+ void addSymbolic(const MemoryObject *mo) {
+ symbolics.push_back(mo);
+ }
+ void addConstraint(ref<Expr> e) {
+ constraints.addConstraint(e);
+ }
+
+ // Used for checkpoint/rollback of fake objects created during tainting.
+ ObjectState *cloneObject(ObjectState *os, MemoryObject *mo);
+
+ //
+
+ bool merge(const ExecutionState &b);
+};
+
+
+// for producing abbreviated execution traces to help visualize
+// paths and diagnose bugs
+
+class ExecutionTraceEvent {
+public:
+ // the location of the instruction:
+ std::string file;
+ unsigned line;
+ std::string funcName;
+ unsigned stackDepth;
+
+ unsigned consecutiveCount; // init to 1, increase for CONSECUTIVE
+ // repetitions of the SAME event
+
+ ExecutionTraceEvent()
+ : file("global"), line(0), funcName("global_def"),
+ consecutiveCount(1) {}
+
+ ExecutionTraceEvent(ExecutionState& state, KInstruction* ki);
+
+ virtual ~ExecutionTraceEvent() {}
+
+ void print(std::ostream &os) const;
+
+ // return true if it shouldn't be added to ExecutionTraceManager
+ //
+ virtual bool ignoreMe() const;
+
+private:
+ virtual void printDetails(std::ostream &os) const = 0;
+};
+
+
+class FunctionCallTraceEvent : public ExecutionTraceEvent {
+public:
+ std::string calleeFuncName;
+
+ FunctionCallTraceEvent(ExecutionState& state, KInstruction* ki,
+ const std::string& _calleeFuncName)
+ : ExecutionTraceEvent(state, ki), calleeFuncName(_calleeFuncName) {}
+
+private:
+ virtual void printDetails(std::ostream &os) const {
+ os << "CALL " << calleeFuncName;
+ }
+
+};
+
+class FunctionReturnTraceEvent : public ExecutionTraceEvent {
+public:
+ FunctionReturnTraceEvent(ExecutionState& state, KInstruction* ki)
+ : ExecutionTraceEvent(state, ki) {}
+
+private:
+ virtual void printDetails(std::ostream &os) const {
+ os << "RETURN";
+ }
+};
+
+class BranchTraceEvent : public ExecutionTraceEvent {
+public:
+ bool trueTaken; // which side taken?
+ bool canForkGoBothWays;
+
+ BranchTraceEvent(ExecutionState& state, KInstruction* ki,
+ bool _trueTaken, bool _isTwoWay)
+ : ExecutionTraceEvent(state, ki),
+ trueTaken(_trueTaken),
+ canForkGoBothWays(_isTwoWay) {}
+
+private:
+ virtual void printDetails(std::ostream &os) const;
+};
+
+}
+
+#endif
Added: klee/trunk/include/klee/Expr.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Expr.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Expr.h (added)
+++ klee/trunk/include/klee/Expr.h Wed May 20 23:36:41 2009
@@ -0,0 +1,808 @@
+//===-- Expr.h --------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPR_H
+#define KLEE_EXPR_H
+
+#include "Machine.h"
+#include "klee/util/Bits.h"
+
+#include "llvm/Support/Streams.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include <set>
+#include <vector>
+
+namespace llvm {
+ class Type;
+}
+
+namespace klee {
+
+class Array;
+class ConstantExpr;
+class ObjectState;
+class MemoryObject;
+
+template<class T> class ref;
+
+
+/// Class representing symbolic expressions.
+/**
+
+<b>Expression canonicalization</b>: we define certain rules for
+canonicalization rules for Exprs in order to simplify code that
+pattern matches Exprs (since the number of forms are reduced), to open
+up further chances for optimization, and to increase similarity for
+caching and other purposes.
+
+The general rules are:
+<ol>
+<li> No Expr has all constant arguments.</li>
+
+<li> Booleans:
+ <ol type="a">
+ <li> Boolean not is written as <tt>(false == ?)</tt> </li>
+ <li> \c Ne, \c Ugt, \c Uge, \c Sgt, \c Sge are not used </li>
+ <li> The only acceptable operations with boolean arguments are \c And,
+ \c Or, \c Xor, \c Eq, as well as \c SExt, \c ZExt,
+ \c Select and \c NotOptimized. </li>
+ <li> The only boolean operation which may involve a constant is boolean not (<tt>== false</tt>). </li>
+ </ol>
+</li>
+
+<li> Linear Formulas:
+ <ol type="a">
+ <li> For any subtree representing a linear formula, a constant
+ term must be on the LHS of the root node of the subtree. In particular,
+ in a BinaryExpr a constant must always be on the LHS. For example, subtraction
+ by a constant c is written as <tt>add(-c, ?)</tt>. </li>
+ </ol>
+</li>
+
+
+<li> Chains are unbalanced to the right </li>
+
+</ol>
+
+
+<b>Steps required for adding an expr</b>:
+ -# Add case to printKind
+ -# Add to ExprVisitor
+ -# Add to IVC (implied value concretization) if possible
+
+Todo: Shouldn't bool \c Xor just be written as not equal?
+
+*/
+
+class Expr {
+public:
+ static unsigned count;
+ static const unsigned MAGIC_HASH_CONSTANT = 39;
+
+ /// The type of an expression is simply its width, in bits.
+ typedef unsigned Width;
+
+ static const Width InvalidWidth = 0;
+ static const Width Bool = 1;
+ static const Width Int8 = 8;
+ static const Width Int16 = 16;
+ static const Width Int32 = 32;
+ static const Width Int64 = 64;
+
+
+ enum Kind {
+ InvalidKind = -1,
+
+ // Primitive
+
+ Constant = 0,
+
+ // Special
+
+ /// Prevents optimization below the given expression. Used for
+ /// testing: make equality constraints that KLEE will not use to
+ /// optimize to concretes.
+ NotOptimized,
+
+ //// Skip old varexpr, just for deserialization, purge at some point
+ Read=NotOptimized+2,
+ Select,
+ Concat,
+ Extract,
+
+ // Casting,
+
+ ZExt,
+ SExt,
+
+ // Arithmetic
+ Add,
+ Sub,
+ Mul,
+ UDiv,
+ SDiv,
+ URem,
+ SRem,
+
+ // Bit
+ And,
+ Or,
+ Xor,
+ Shl,
+ LShr,
+ AShr,
+
+ // Compare
+ Eq,
+ Ne, /// Not used in canonical form
+ Ult,
+ Ule,
+ Ugt, /// Not used in canonical form
+ Uge, /// Not used in canonical form
+ Slt,
+ Sle,
+ Sgt, /// Not used in canonical form
+ Sge, /// Not used in canonical form
+
+ LastKind=Sge
+ };
+
+ unsigned refCount;
+
+protected:
+ unsigned hashValue;
+
+public:
+ Expr() : refCount(0) { Expr::count++; }
+ virtual ~Expr() { Expr::count--; }
+
+ virtual Kind getKind() const = 0;
+ virtual Width getWidth() const = 0;
+
+ virtual unsigned getNumKids() const = 0;
+ virtual ref<Expr> getKid(unsigned i) const = 0;
+
+ virtual void print(std::ostream &os) const;
+
+ /// Returns the pre-computed hash of the current expression
+ virtual unsigned hash() const { return hashValue; }
+
+ /// (Re)computes the hash of the current expression.
+ /// Returns the hash value.
+ virtual unsigned computeHash();
+
+ static unsigned hashConstant(uint64_t val, Width w) {
+ return val ^ (w * MAGIC_HASH_CONSTANT);
+ }
+
+ /// Returns 0 iff b is structuraly equivalent to *this
+ int compare(const Expr &b) const;
+ virtual int compareContents(const Expr &b) const { return 0; }
+
+ // Given an array of new kids return a copy of the expression
+ // but using those children.
+ virtual ref<Expr> rebuild(ref<Expr> kids[/* getNumKids() */]) const = 0;
+
+ ///
+
+ uint64_t getConstantValue() const;
+
+ /* Static utility methods */
+
+ static void printKind(std::ostream &os, Kind k);
+ static void printWidth(std::ostream &os, Expr::Width w);
+ static Width getWidthForLLVMType(const llvm::Type *type);
+
+ /// returns the smallest number of bytes in which the given width fits
+ static inline unsigned getMinBytesForWidth(Width w) {
+ return (w + 7) / 8;
+ }
+
+ /* Kind utilities */
+
+ /* Utility creation functions */
+ static ref<Expr> createCoerceToPointerType(ref<Expr> e);
+ static ref<Expr> createNot(ref<Expr> e);
+ static ref<Expr> createImplies(ref<Expr> hyp, ref<Expr> conc);
+ static ref<Expr> createIsZero(ref<Expr> e);
+
+ /// Create a little endian read of the given type at offset 0 of the
+ /// given object.
+ static ref<Expr> createTempRead(const Array *array, Expr::Width w);
+
+ static ref<Expr> createPointer(uint64_t v);
+
+ // do not use
+ static Expr *createConstant(uint64_t val, Width w);
+
+ struct CreateArg;
+ static ref<Expr> createFromKind(Kind k, std::vector<CreateArg> args);
+
+ static bool isValidKidWidth(unsigned kid, Width w) { return true; }
+ static bool needsResultType() { return false; }
+};
+// END class Expr
+
+
+
+#include "klee/util/Ref.h"
+
+struct Expr::CreateArg {
+ ref<Expr> expr;
+ Width width;
+
+ CreateArg(Width w = Bool) : expr(0, Expr::Bool), width(w) {}
+ CreateArg(ref<Expr> e) : expr(e), width(Expr::InvalidWidth) {}
+
+ bool isExpr() { return !isWidth(); }
+ bool isWidth() { return width != Expr::InvalidWidth; }
+};
+
+// Comparison operators
+
+inline bool operator==(const Expr &lhs, const Expr &rhs) {
+ return lhs.compare(rhs) == 0;
+}
+
+inline bool operator<(const Expr &lhs, const Expr &rhs) {
+ return lhs.compare(rhs) < 0;
+}
+
+inline bool operator!=(const Expr &lhs, const Expr &rhs) {
+ return !(lhs == rhs);
+}
+
+inline bool operator>(const Expr &lhs, const Expr &rhs) {
+ return rhs < lhs;
+}
+
+inline bool operator<=(const Expr &lhs, const Expr &rhs) {
+ return !(lhs > rhs);
+}
+
+inline bool operator>=(const Expr &lhs, const Expr &rhs) {
+ return !(lhs < rhs);
+}
+
+// Printing operators
+
+inline std::ostream &operator<<(std::ostream &os, const Expr &e) {
+ e.print(os);
+ return os;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const Expr::Kind kind) {
+ Expr::printKind(os, kind);
+ return os;
+}
+
+// Terminal Exprs
+
+class ConstantExpr : public Expr {
+public:
+ static const Kind kind = Constant;
+ static const unsigned numKids = 0;
+
+public:
+ union {
+ uint64_t asUInt64;
+ };
+ Width width;
+
+public:
+ ~ConstantExpr() {};
+ // should change the code to make this private
+ ConstantExpr(uint64_t v, Width w) : asUInt64(v), width(w) {}
+
+ Width getWidth() const { return width; }
+ Kind getKind() const { return Constant; }
+
+ unsigned getNumKids() const { return 0; }
+ ref<Expr> getKid(unsigned i) const { return 0; }
+
+ int compareContents(const Expr &b) const {
+ const ConstantExpr &cb = static_cast<const ConstantExpr&>(b);
+ if (width != cb.width) return width < cb.width ? -1 : 1;
+ if (asUInt64 < cb.asUInt64) {
+ return -1;
+ } else if (asUInt64 > cb.asUInt64) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const {
+ assert(0 && "rebuild() on ConstantExpr");
+ }
+
+ virtual unsigned computeHash();
+
+ static ref<ConstantExpr> fromMemory(void *address, Width w);
+ void toMemory(void *address);
+
+ static ref<ConstantExpr> alloc(uint64_t v, Width w) {
+ // constructs an "optimized" ConstantExpr
+ return ref<ConstantExpr>(v, w);
+ }
+
+ static ref<ConstantExpr> create(uint64_t v, Width w) {
+ assert(v == bits64::truncateToNBits(v, w) &&
+ "invalid constant");
+ return alloc(v, w);
+ }
+};
+
+
+// Utility classes
+
+class BinaryExpr : public Expr {
+public:
+ ref<Expr> left, right;
+
+public:
+ unsigned getNumKids() const { return 2; }
+ ref<Expr> getKid(unsigned i) const {
+ if(i == 0)
+ return left;
+ if(i == 1)
+ return right;
+ return 0;
+ }
+
+protected:
+ BinaryExpr(const ref<Expr> &l, const ref<Expr> &r) : left(l), right(r) {}
+};
+
+
+class CmpExpr : public BinaryExpr {
+
+protected:
+ CmpExpr(ref<Expr> l, ref<Expr> r) : BinaryExpr(l,r) {}
+
+public:
+ Width getWidth() const { return Bool; }
+};
+
+// Special
+
+class NotOptimizedExpr : public Expr {
+public:
+ static const Kind kind = NotOptimized;
+ static const unsigned numKids = 1;
+ ref<Expr> src;
+
+ static ref<Expr> alloc(const ref<Expr> &src) {
+ ref<Expr> r(new NotOptimizedExpr(src));
+ r.computeHash();
+ return r;
+ }
+
+ static ref<Expr> create(ref<Expr> src);
+
+ Width getWidth() const { return src.getWidth(); }
+ Kind getKind() const { return NotOptimized; }
+
+ unsigned getNumKids() const { return 1; }
+ ref<Expr> getKid(unsigned i) const { return src; }
+
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const { return create(kids[0]); }
+
+private:
+ NotOptimizedExpr(const ref<Expr> &_src) : src(_src) {}
+};
+
+
+/// Class representing a byte update of an array.
+class UpdateNode {
+ friend class UpdateList;
+ friend class STPBuilder; // for setting STPArray
+
+ mutable unsigned refCount;
+ // gross
+ mutable void *stpArray;
+ // cache instead of recalc
+ unsigned hashValue;
+
+public:
+ const UpdateNode *next;
+ ref<Expr> index, value;
+
+private:
+ /// size of this update sequence, including this update
+ unsigned size;
+
+public:
+ UpdateNode(const UpdateNode *_next,
+ const ref<Expr> &_index,
+ const ref<Expr> &_value);
+
+ unsigned getSize() const { return size; }
+
+ int compare(const UpdateNode &b) const;
+ unsigned hash() const { return hashValue; }
+
+private:
+ UpdateNode() : refCount(0), stpArray(0) {}
+ ~UpdateNode();
+
+ unsigned computeHash();
+};
+
+class Array {
+public:
+ const MemoryObject *object;
+ unsigned id;
+ unsigned size;
+
+ // FIXME: This does not belong here.
+ mutable void *stpInitialArray;
+
+public:
+ // NOTE: id's ***MUST*** be unique to ensure sanity w.r.t. STP,
+ // which hashes different arrays with the same id to the same
+ // object! We should probably use the pointer for talking to STP, as
+ // long as we can guarantee that it won't be a "stale" reference
+ // once we have freed it.
+ Array(const MemoryObject *_object, unsigned _id, uint64_t _size)
+ : object(_object), id(_id), size(_size), stpInitialArray(0) {}
+ ~Array() {
+ // FIXME: This relies on caller to delete the STP array.
+ assert(!stpInitialArray && "Array must be deleted by caller!");
+ }
+};
+
+/// Class representing a complete list of updates into an array.
+/** The main trick is the isRooted bit, which enables important optimizations.
+ ...
+ */
+class UpdateList {
+ friend class ReadExpr; // for default constructor
+
+public:
+ const Array *root;
+
+ /// pointer to the most recent update node
+ const UpdateNode *head;
+
+ // shouldn't this be part of the ReadExpr?
+ bool isRooted;
+
+public:
+ UpdateList(const Array *_root, bool isRooted, const UpdateNode *_head);
+ UpdateList(const UpdateList &b);
+ ~UpdateList();
+
+ UpdateList &operator=(const UpdateList &b);
+
+ /// size of this update list
+ unsigned getSize() const { return (head ? head->getSize() : 0); }
+
+ void extend(const ref<Expr> &index, const ref<Expr> &value);
+
+ int compare(const UpdateList &b) const;
+ unsigned hash() const;
+};
+
+/// Class representing a one byte read from an array.
+class ReadExpr : public Expr {
+public:
+ static const Kind kind = Read;
+ static const unsigned numKids = 1;
+
+public:
+ UpdateList updates;
+ ref<Expr> index;
+
+public:
+ static ref<Expr> alloc(const UpdateList &updates, const ref<Expr> &index) {
+ ref<Expr> r(new ReadExpr(updates, index));
+ r.computeHash();
+ return r;
+ }
+
+ static ref<Expr> create(const UpdateList &updates, ref<Expr> i);
+
+ Width getWidth() const { return Expr::Int8; }
+ Kind getKind() const { return Read; }
+
+ unsigned getNumKids() const { return numKids; }
+ ref<Expr> getKid(unsigned i) const { return !i ? index : 0; }
+
+ int compareContents(const Expr &b) const;
+
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const {
+ return create(updates, kids[0]);
+ }
+
+ virtual unsigned computeHash();
+
+private:
+ ReadExpr(const UpdateList &_updates, const ref<Expr> &_index) :
+ updates(_updates), index(_index) {}
+};
+
+
+/// Class representing an if-then-else expression.
+class SelectExpr : public Expr {
+public:
+ static const Kind kind = Select;
+ static const unsigned numKids = 3;
+
+public:
+ ref<Expr> cond, trueExpr, falseExpr;
+
+public:
+ static ref<Expr> alloc(const ref<Expr> &c, const ref<Expr> &t, const ref<Expr> &f) {
+ ref<Expr> r(new SelectExpr(c, t, f));
+ r.computeHash();
+ return r;
+ }
+
+ static ref<Expr> create(ref<Expr> c, ref<Expr> t, ref<Expr> f);
+
+ Width getWidth() const { return trueExpr.getWidth(); }
+ Kind getKind() const { return Select; }
+
+ unsigned getNumKids() const { return numKids; }
+ ref<Expr> getKid(unsigned i) const {
+ switch(i) {
+ case 0: return cond;
+ case 1: return trueExpr;
+ case 2: return falseExpr;
+ default: return 0;
+ }
+ }
+
+ static bool isValidKidWidth(unsigned kid, Width w) {
+ if (kid == 0)
+ return w == Bool;
+ else
+ return true;
+ }
+
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const {
+ return create(kids[0], kids[1], kids[2]);
+ }
+
+private:
+ SelectExpr(const ref<Expr> &c, const ref<Expr> &t, const ref<Expr> &f)
+ : cond(c), trueExpr(t), falseExpr(f) {}
+};
+
+
+/** Children of a concat expression can have arbitrary widths.
+ Kid 0 is the left kid, kid 1 is the right kid.
+*/
+class ConcatExpr : public Expr {
+public:
+ static const Kind kind = Concat;
+ static const unsigned numKids = 2;
+
+private:
+ Width width;
+ ref<Expr> left, right;
+
+public:
+ static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) {
+ ref<Expr> c(new ConcatExpr(l, r));
+ c.computeHash();
+ return c;
+ }
+
+ static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r);
+
+ Width getWidth() const { return width; }
+ Kind getKind() const { return kind; }
+ ref<Expr> getLeft() const { return left; }
+ ref<Expr> getRight() const { return right; }
+
+ unsigned getNumKids() const { return numKids; }
+ ref<Expr> getKid(unsigned i) const {
+ if (i == 0) return left;
+ else if (i == 1) return right;
+ else return NULL;
+ }
+
+ /// Shortcuts to create larger concats. The chain returned is unbalanced to the right
+ static ref<Expr> createN(unsigned nKids, const ref<Expr> kids[]);
+ static ref<Expr> create4(const ref<Expr> &kid1, const ref<Expr> &kid2,
+ const ref<Expr> &kid3, const ref<Expr> &kid4);
+ static ref<Expr> create8(const ref<Expr> &kid1, const ref<Expr> &kid2,
+ const ref<Expr> &kid3, const ref<Expr> &kid4,
+ const ref<Expr> &kid5, const ref<Expr> &kid6,
+ const ref<Expr> &kid7, const ref<Expr> &kid8);
+
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const { return create(kids[0], kids[1]); }
+
+
+ /* These will be eliminated */
+ bool is2ByteConcat() const { return false; }
+ bool is4ByteConcat() const { return false; }
+ bool is8ByteConcat() const { return false; }
+
+private:
+ ConcatExpr(const ref<Expr> &l, const ref<Expr> &r) : left(l), right(r) {
+ width = l.getWidth() + r.getWidth();
+ }
+};
+
+
+/** This class represents an extract from expression {\tt expr}, at
+ bit offset {\tt offset} of width {\tt width}. Bit 0 is the right most
+ bit of the expression.
+ */
+class ExtractExpr : public Expr {
+public:
+ static const Kind kind = Extract;
+ static const unsigned numKids = 1;
+
+public:
+ ref<Expr> expr;
+ unsigned offset;
+ Width width;
+
+public:
+ static ref<Expr> alloc(const ref<Expr> &e, unsigned o, Width w) {
+ ref<Expr> r(new ExtractExpr(e, o, w));
+ r.computeHash();
+ return r;
+ }
+
+ /// Creates an ExtractExpr with the given bit offset and width
+ static ref<Expr> create(ref<Expr> e, unsigned bitOff, Width w);
+
+ /// Creates an ExtractExpr with the given byte offset and width
+ static ref<Expr> createByteOff(ref<Expr> e, unsigned byteOff, Width w=Expr::Int8);
+
+ Width getWidth() const { return width; }
+ Kind getKind() const { return Extract; }
+
+ unsigned getNumKids() const { return numKids; }
+ ref<Expr> getKid(unsigned i) const { return expr; }
+
+ int compareContents(const Expr &b) const {
+ const ExtractExpr &eb = static_cast<const ExtractExpr&>(b);
+ if (offset != eb.offset) return offset < eb.offset ? -1 : 1;
+ if (width != eb.width) return width < eb.width ? -1 : 1;
+ return 0;
+ }
+
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const {
+ return create(kids[0], offset, width);
+ }
+
+ virtual unsigned computeHash();
+
+private:
+ ExtractExpr(const ref<Expr> &e, unsigned b, Width w)
+ : expr(e),offset(b),width(w) {}
+};
+
+
+// Casting
+
+class CastExpr : public Expr {
+public:
+ ref<Expr> src;
+ Width width;
+
+public:
+ CastExpr(const ref<Expr> &e, Width w) : src(e), width(w) {}
+
+ Width getWidth() const { return width; }
+
+ unsigned getNumKids() const { return 1; }
+ ref<Expr> getKid(unsigned i) const { return (i==0) ? src : 0; }
+
+ static bool needsResultType() { return true; }
+
+ int compareContents(const Expr &b) const {
+ const CastExpr &eb = static_cast<const CastExpr&>(b);
+ if (width != eb.width) return width < eb.width ? -1 : 1;
+ return 0;
+ }
+
+ virtual unsigned computeHash();
+};
+
+#define CAST_EXPR_CLASS(_class_kind) \
+class _class_kind ## Expr : public CastExpr { \
+public: \
+ static const Kind kind = _class_kind; \
+ static const unsigned numKids = 1; \
+public: \
+ _class_kind ## Expr(ref<Expr> e, Width w) : CastExpr(e,w) {} \
+ static ref<Expr> alloc(const ref<Expr> &e, Width w) { \
+ ref<Expr> r(new _class_kind ## Expr(e, w)); \
+ r.computeHash(); \
+ return r; \
+ } \
+ static ref<Expr> create(const ref<Expr> &e, Width w); \
+ Kind getKind() const { return _class_kind; } \
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const { \
+ return create(kids[0], width); \
+ } \
+}; \
+
+CAST_EXPR_CLASS(SExt)
+CAST_EXPR_CLASS(ZExt)
+
+// Arithmetic/Bit Exprs
+
+#define ARITHMETIC_EXPR_CLASS(_class_kind) \
+class _class_kind ## Expr : public BinaryExpr { \
+public: \
+ static const Kind kind = _class_kind; \
+ static const unsigned numKids = 2; \
+public: \
+ _class_kind ## Expr(const ref<Expr> &l, const ref<Expr> &r) : BinaryExpr(l,r) {} \
+ static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
+ ref<Expr> res(new _class_kind ## Expr (l, r)); \
+ res.computeHash(); \
+ return res; \
+ } \
+ static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
+ Width getWidth() const { return left.getWidth(); } \
+ Kind getKind() const { return _class_kind; } \
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const { \
+ return create(kids[0], kids[1]); \
+ } \
+}; \
+
+ARITHMETIC_EXPR_CLASS(Add)
+ARITHMETIC_EXPR_CLASS(Sub)
+ARITHMETIC_EXPR_CLASS(Mul)
+ARITHMETIC_EXPR_CLASS(UDiv)
+ARITHMETIC_EXPR_CLASS(SDiv)
+ARITHMETIC_EXPR_CLASS(URem)
+ARITHMETIC_EXPR_CLASS(SRem)
+ARITHMETIC_EXPR_CLASS(And)
+ARITHMETIC_EXPR_CLASS(Or)
+ARITHMETIC_EXPR_CLASS(Xor)
+ARITHMETIC_EXPR_CLASS(Shl)
+ARITHMETIC_EXPR_CLASS(LShr)
+ARITHMETIC_EXPR_CLASS(AShr)
+
+// Comparison Exprs
+
+#define COMPARISON_EXPR_CLASS(_class_kind) \
+class _class_kind ## Expr : public CmpExpr { \
+public: \
+ static const Kind kind = _class_kind; \
+ static const unsigned numKids = 2; \
+public: \
+ _class_kind ## Expr(const ref<Expr> &l, const ref<Expr> &r) : CmpExpr(l,r) {} \
+ static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
+ ref<Expr> res(new _class_kind ## Expr (l, r)); \
+ res.computeHash(); \
+ return res; \
+ } \
+ static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
+ Kind getKind() const { return _class_kind; } \
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const { \
+ return create(kids[0], kids[1]); \
+ } \
+}; \
+
+COMPARISON_EXPR_CLASS(Eq)
+COMPARISON_EXPR_CLASS(Ne)
+COMPARISON_EXPR_CLASS(Ult)
+COMPARISON_EXPR_CLASS(Ule)
+COMPARISON_EXPR_CLASS(Ugt)
+COMPARISON_EXPR_CLASS(Uge)
+COMPARISON_EXPR_CLASS(Slt)
+COMPARISON_EXPR_CLASS(Sle)
+COMPARISON_EXPR_CLASS(Sgt)
+COMPARISON_EXPR_CLASS(Sge)
+
+} // End klee namespace
+
+#endif
Added: klee/trunk/include/klee/IncompleteSolver.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/IncompleteSolver.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/IncompleteSolver.h (added)
+++ klee/trunk/include/klee/IncompleteSolver.h Wed May 20 23:36:41 2009
@@ -0,0 +1,108 @@
+//===-- IncompleteSolver.h --------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_INCOMPLETESOLVER_H
+#define KLEE_INCOMPLETESOLVER_H
+
+#include "klee/Solver.h"
+#include "klee/SolverImpl.h"
+
+namespace klee {
+
+/// IncompleteSolver - Base class for incomplete solver
+/// implementations.
+///
+/// Incomplete solvers are useful for implementing optimizations which
+/// may quickly compute an answer, but cannot always compute the
+/// correct answer. They can be used with the StagedSolver to provide
+/// a complete Solver implementation.
+class IncompleteSolver {
+public:
+ /// PartialValidity - Represent a possibility incomplete query
+ /// validity.
+ enum PartialValidity {
+ /// The query is provably true.
+ MustBeTrue = 1,
+
+ /// The query is provably false.
+ MustBeFalse = -1,
+
+ /// The query is not provably false (a true assignment is known to
+ /// exist).
+ MayBeTrue = 2,
+
+ /// The query is not provably true (a false assignment is known to
+ /// exist).
+ MayBeFalse = -2,
+
+ /// The query is known to have both true and false assignments.
+ TrueOrFalse = 0,
+
+ /// The validity of the query is unknown.
+ None = 3
+ };
+
+ static PartialValidity negatePartialValidity(PartialValidity pv);
+
+public:
+ IncompleteSolver() {};
+ virtual ~IncompleteSolver() {};
+
+ /// computeValidity - Compute a partial validity for the given query.
+ ///
+ /// The passed expression is non-constant with bool type.
+ ///
+ /// The IncompleteSolver class provides an implementation of
+ /// computeValidity using computeTruth. Sub-classes may override
+ /// this if a more efficient implementation is available.
+ virtual IncompleteSolver::PartialValidity computeValidity(const Query&);
+
+ /// computeValidity - Compute a partial validity for the given query.
+ ///
+ /// The passed expression is non-constant with bool type.
+ virtual IncompleteSolver::PartialValidity computeTruth(const Query&) = 0;
+
+ /// computeValue - Attempt to compute a value for the given expression.
+ virtual bool computeValue(const Query&, ref<Expr> &result) = 0;
+
+ /// computeInitialValues - Attempt to compute the constant values
+ /// for the initial state of each given object. If a correct result
+ /// is not found, then the values array must be unmodified.
+ virtual bool computeInitialValues(const Query&,
+ const std::vector<const Array*>
+ &objects,
+ std::vector< std::vector<unsigned char> >
+ &values,
+ bool &hasSolution) = 0;
+};
+
+/// StagedSolver - Adapter class for staging an incomplete solver with
+/// a complete secondary solver, to form an (optimized) complete
+/// solver.
+class StagedSolverImpl : public SolverImpl {
+private:
+ IncompleteSolver *primary;
+ Solver *secondary;
+
+public:
+ StagedSolverImpl(IncompleteSolver *_primary, Solver *_secondary);
+ ~StagedSolverImpl();
+
+ bool computeTruth(const Query&, bool &isValid);
+ bool computeValidity(const Query&, Solver::Validity &result);
+ bool computeValue(const Query&, ref<Expr> &result);
+ bool computeInitialValues(const Query&,
+ const std::vector<const Array*> &objects,
+ std::vector< std::vector<unsigned char> > &values,
+ bool &hasSolution);
+};
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/ADT/BOut.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/BOut.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/BOut.h (added)
+++ klee/trunk/include/klee/Internal/ADT/BOut.h Wed May 20 23:36:41 2009
@@ -0,0 +1,62 @@
+//===-- BOut.h --------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __COMMON_BOUT_H__
+#define __COMMON_BOUT_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct BOutObject BOutObject;
+ struct BOutObject {
+ char *name;
+ unsigned numBytes;
+ unsigned char *bytes;
+ };
+
+ typedef struct BOut BOut;
+ struct BOut {
+ /* file format version */
+ unsigned version;
+
+ unsigned numArgs;
+ char **args;
+
+ unsigned symArgvs;
+ unsigned symArgvLen;
+
+ unsigned numObjects;
+ BOutObject *objects;
+ };
+
+
+ /* returns the current .bout file format version */
+ unsigned bOut_getCurrentVersion();
+
+ /* return true iff file at path matches BOut header */
+ int bOut_isBOutFile(const char *path);
+
+ /* returns NULL on (unspecified) error */
+ BOut* bOut_fromFile(const char *path);
+
+ /* returns 1 on success, 0 on (unspecified) error */
+ int bOut_toFile(BOut *, const char *path);
+
+ /* returns total number of object bytes */
+ unsigned bOut_numBytes(BOut *);
+
+ void bOut_free(BOut *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Added: klee/trunk/include/klee/Internal/ADT/DiscretePDF.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/DiscretePDF.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/DiscretePDF.h (added)
+++ klee/trunk/include/klee/Internal/ADT/DiscretePDF.h Wed May 20 23:36:41 2009
@@ -0,0 +1,47 @@
+//===-- DiscretePDF.h -------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+namespace klee {
+ template <class T>
+ class DiscretePDF {
+ // not perfectly parameterized, but float/double/int should work ok,
+ // although it would be better to have choose argument range from 0
+ // to queryable max.
+ typedef double weight_type;
+
+ public:
+ DiscretePDF();
+ ~DiscretePDF();
+
+ bool empty() const;
+ void insert(T item, weight_type weight);
+ void update(T item, weight_type newWeight);
+ void remove(T item);
+ bool inTree(T item);
+ weight_type getWeight(T item);
+
+ /* pick a tree element according to its
+ * weight. p should be in [0,1).
+ */
+ T choose(double p);
+
+ private:
+ class Node;
+ Node *m_root;
+
+ Node **lookup(T item, Node **parent_out);
+ void split(Node *node);
+ void rotate(Node *node);
+ void lengthen(Node *node);
+ void propogateSumsUp(Node *n);
+ };
+
+}
+
+#include "DiscretePDF.inc"
Added: klee/trunk/include/klee/Internal/ADT/DiscretePDF.inc
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/DiscretePDF.inc?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/DiscretePDF.inc (added)
+++ klee/trunk/include/klee/Internal/ADT/DiscretePDF.inc Wed May 20 23:36:41 2009
@@ -0,0 +1,342 @@
+//===- DiscretePDF.inc - --*- C++ -*-===//
+
+//
+
+namespace klee {
+
+template <class T>
+class DiscretePDF<T>::Node
+{
+private:
+ bool m_mark;
+
+public:
+ Node *parent, *left, *right;
+ T key;
+ weight_type weight, sumWeights;
+
+public:
+ Node(T key_, weight_type weight_, Node *parent_);
+ ~Node();
+
+ Node *sibling() { return this==parent->left?parent->right:parent->left; }
+
+ void markRed() { m_mark = true; }
+ void markBlack() { m_mark = false; }
+ bool isBlack() { return !m_mark; }
+ bool leftIsBlack() { return !left || left->isBlack(); }
+ bool rightIsBlack() { return !right || right->isBlack(); }
+ void setSum() {
+ sumWeights = weight;
+ if (left) sumWeights += left->sumWeights;
+ if (right) sumWeights += right->sumWeights;
+ }
+};
+
+ ///
+
+template <class T>
+DiscretePDF<T>::Node::Node(T key_, weight_type weight_, Node *parent_) {
+ m_mark = false;
+
+ key = key_;
+ weight = weight_;
+ sumWeights = 0;
+ left = right = 0;
+ parent = parent_;
+}
+
+template <class T>
+DiscretePDF<T>::Node::~Node() {
+ if (left) delete left;
+ if (right) delete right;
+}
+
+//
+
+template <class T>
+DiscretePDF<T>::DiscretePDF() {
+ m_root = 0;
+}
+
+template <class T>
+DiscretePDF<T>::~DiscretePDF() {
+ if (m_root) delete m_root;
+}
+
+template <class T>
+bool DiscretePDF<T>::empty() const {
+ return m_root == 0;
+}
+
+template <class T>
+void DiscretePDF<T>::insert(T item, weight_type weight) {
+ Node *p=0, *n=m_root;
+
+ while (n) {
+ if (!n->leftIsBlack() && !n->rightIsBlack())
+ split(n);
+
+ p = n;
+ if (n->key==item) {
+ assert(0 && "insert: argument(item) already in tree");
+ } else {
+ n = (item<n->key)?n->left:n->right;
+ }
+ }
+
+ n = new Node(item, weight, p);
+
+ if (!p) {
+ m_root = n;
+ } else {
+ if (item<p->key) {
+ p->left = n;
+ } else {
+ p->right = n;
+ }
+
+ split(n);
+ }
+
+ propogateSumsUp(n);
+}
+
+template <class T>
+void DiscretePDF<T>::remove(T item) {
+ Node **np = lookup(item, 0);
+ Node *child, *n = *np;
+
+ if (!n) {
+ assert(0 && "remove: argument(item) not in tree");
+ } else {
+ if (n->left) {
+ Node **leftMaxp = &n->left;
+
+ while ((*leftMaxp)->right)
+ leftMaxp = &(*leftMaxp)->right;
+
+ n->key = (*leftMaxp)->key;
+ n->weight = (*leftMaxp)->weight;
+
+ np = leftMaxp;
+ n = *np;
+ }
+
+ // node now has at most one child
+
+ child = n->left?n->left:n->right;
+ *np = child;
+
+ if (child) {
+ child->parent = n->parent;
+
+ if (n->isBlack()) {
+ lengthen(child);
+ }
+ }
+
+ propogateSumsUp(n->parent);
+
+ n->left = n->right = 0;
+ delete n;
+ }
+}
+
+template <class T>
+void DiscretePDF<T>::update(T item, weight_type weight) {
+ Node *n = *lookup(item, 0);
+
+ if (!n) {
+ assert(0 && "update: argument(item) not in tree");
+ } else {
+ n->weight = weight;
+ propogateSumsUp(n);
+ }
+}
+
+template <class T>
+T DiscretePDF<T>::choose(double p) {
+ if (p<0.0 || p>=1.0) {
+ assert(0 && "choose: argument(p) outside valid range");
+ } else if (!m_root) {
+ assert(0 && "choose: choose() called on empty tree");
+ } else {
+ weight_type w = (weight_type) (m_root->sumWeights * p);
+ Node *n = m_root;
+
+ while (1) {
+ if (n->left) {
+ if (w<n->left->sumWeights) {
+ n = n->left;
+ continue;
+ } else {
+ w -= n->left->sumWeights;
+ }
+ }
+ if (w<n->weight || !n->right) {
+ break; // !n->right condition shouldn't be necessary, just sanity check
+ }
+ w -= n->weight;
+ n = n->right;
+ }
+
+ return n->key;
+ }
+}
+
+template <class T>
+bool DiscretePDF<T>::inTree(T item) {
+ Node *n = *lookup(item, 0);
+
+ return !!n;
+}
+
+template <class T>
+typename DiscretePDF<T>::weight_type DiscretePDF<T>::getWeight(T item) {
+ Node *n = *lookup(item, 0);
+ assert(n);
+ return n->weight;
+}
+
+//
+
+template <class T>
+typename DiscretePDF<T>::Node **
+DiscretePDF<T>::lookup(T item, Node **parent_out) {
+ Node *n, *p=0, **np=&m_root;
+
+ while ((n = *np)) {
+ if (n->key==item) {
+ break;
+ } else {
+ p = n;
+ if (item<n->key) {
+ np = &n->left;
+ } else {
+ np = &n->right;
+ }
+ }
+ }
+
+ if (parent_out)
+ *parent_out = p;
+ return np;
+}
+
+template <class T>
+void DiscretePDF<T>::split(Node *n) {
+ if (n->left) n->left->markBlack();
+ if (n->right) n->right->markBlack();
+
+ if (n->parent) {
+ Node *p = n->parent;
+
+ n->markRed();
+
+ if (!p->isBlack()) {
+ p->parent->markRed();
+
+ // not same direction
+ if (!((n==p->left && p==p->parent->left) ||
+ (n==p->right && p==p->parent->right))) {
+ rotate(n);
+ p = n;
+ }
+
+ rotate(p);
+ p->markBlack();
+ }
+ }
+}
+
+template <class T>
+void DiscretePDF<T>::rotate(Node *n) {
+ Node *p=n->parent, *pp=p->parent;
+
+ n->parent = pp;
+ p->parent = n;
+
+ if (n==p->left) {
+ p->left = n->right;
+ n->right = p;
+ if (p->left) p->left->parent = p;
+ } else {
+ p->right = n->left;
+ n->left = p;
+ if (p->right) p->right->parent = p;
+ }
+
+ n->setSum();
+ p->setSum();
+
+ if (!pp) {
+ m_root = n;
+ } else {
+ if (p==pp->left) {
+ pp->left = n;
+ } else {
+ pp->right = n;
+ }
+ }
+}
+
+template <class T>
+void DiscretePDF<T>::lengthen(Node *n) {
+ if (!n->isBlack()) {
+ n->markBlack();
+ } else if (n->parent) {
+ Node *sibling = n->sibling();
+
+ if (sibling && !sibling->isBlack()) {
+ n->parent->markRed();
+ sibling->markBlack();
+
+ rotate(sibling); // node sibling is now old sibling child, must be black
+ sibling = n->sibling();
+ }
+
+ // sibling is black
+
+ if (!sibling) {
+ lengthen(n->parent);
+ } else if (sibling->leftIsBlack() && sibling->rightIsBlack()) {
+ if (n->parent->isBlack()) {
+ sibling->markRed();
+ lengthen(n->parent);
+ } else {
+ sibling->markRed();
+ n->parent->markBlack();
+ }
+ } else {
+ if (n==n->parent->left && sibling->rightIsBlack()) {
+ rotate(sibling->left); // sibling->left must be red
+ sibling->markRed();
+ sibling->parent->markBlack();
+ sibling = sibling->parent;
+ } else if (n==n->parent->right && sibling->leftIsBlack()) {
+ rotate(sibling->right); // sibling->right must be red
+ sibling->markRed();
+ sibling->parent->markBlack();
+ sibling = sibling->parent;
+ }
+
+ // sibling is black, and sibling's far child is red
+
+ rotate(sibling);
+ if (!n->parent->isBlack())
+ sibling->markRed();
+ sibling->left->markBlack();
+ sibling->right->markBlack();
+ }
+ }
+}
+
+template <class T>
+void DiscretePDF<T>::propogateSumsUp(Node *n) {
+ for (; n; n=n->parent)
+ n->setSum();
+}
+
+}
+
Added: klee/trunk/include/klee/Internal/ADT/ImmutableMap.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/ImmutableMap.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/ImmutableMap.h (added)
+++ klee/trunk/include/klee/Internal/ADT/ImmutableMap.h Wed May 20 23:36:41 2009
@@ -0,0 +1,104 @@
+//===-- ImmutableMap.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UTIL_IMMUTABLEMAP_H__
+#define __UTIL_IMMUTABLEMAP_H__
+
+#include <functional>
+
+#include "ImmutableTree.h"
+
+namespace klee {
+ template<class V, class D>
+ struct _Select1st {
+ D &operator()(V &a) const { return a.first; }
+ const D &operator()(const V &a) const { return a.first; }
+ };
+
+ template<class K, class D, class CMP=std::less<K> >
+ class ImmutableMap {
+ public:
+ typedef K key_type;
+ typedef std::pair<K,D> value_type;
+
+ typedef ImmutableTree<K, value_type, _Select1st<value_type,key_type>, CMP> Tree;
+ typedef typename Tree::iterator iterator;
+
+ private:
+ Tree elts;
+
+ ImmutableMap(const Tree &b): elts(b) {}
+
+ public:
+ ImmutableMap() {}
+ ImmutableMap(const ImmutableMap &b) : elts(b.elts) {}
+ ~ImmutableMap() {}
+
+ ImmutableMap &operator=(const ImmutableMap &b) { elts = b.elts; return *this; }
+
+ bool empty() const {
+ return elts.empty();
+ }
+ unsigned count(const key_type &key) const {
+ return elts.count(key);
+ }
+ const value_type *lookup(const key_type &key) const {
+ return elts.lookup(key);
+ }
+ const value_type *lookup_previous(const key_type &key) const {
+ return elts.lookup_previous(key);
+ }
+ const value_type &min() const {
+ return elts.min();
+ }
+ const value_type &max() const {
+ return elts.max();
+ }
+ unsigned size() const {
+ return elts.size();
+ }
+
+ ImmutableMap insert(const value_type &value) const {
+ return elts.insert(value);
+ }
+ ImmutableMap replace(const value_type &value) const {
+ return elts.replace(value);
+ }
+ ImmutableMap remove(const key_type &key) const {
+ return elts.remove(key);
+ }
+ ImmutableMap popMin(const value_type &valueOut) const {
+ return elts.popMin(valueOut);
+ }
+ ImmutableMap popMax(const value_type &valueOut) const {
+ return elts.popMax(valueOut);
+ }
+
+ iterator begin() const {
+ return elts.begin();
+ }
+ iterator end() const {
+ return elts.end();
+ }
+ iterator find(const key_type &key) const {
+ return elts.find(key);
+ }
+ iterator lower_bound(const key_type &key) const {
+ return elts.lower_bound(key);
+ }
+ iterator upper_bound(const key_type &key) const {
+ return elts.upper_bound(key);
+ }
+
+ static unsigned getAllocated() { return Tree::allocated; }
+ };
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/ADT/ImmutableSet.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/ImmutableSet.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/ImmutableSet.h (added)
+++ klee/trunk/include/klee/Internal/ADT/ImmutableSet.h Wed May 20 23:36:41 2009
@@ -0,0 +1,101 @@
+//===-- ImmutableSet.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UTIL_IMMUTABLESET_H__
+#define __UTIL_IMMUTABLESET_H__
+
+#include <functional>
+
+#include "ImmutableTree.h"
+
+namespace klee {
+ template<class T>
+ struct _Identity {
+ T &operator()(T &a) const { return a; }
+ const T &operator()(const T &a) const { return a; }
+ };
+
+ template<class T, class CMP=std::less<T> >
+ class ImmutableSet {
+ public:
+ typedef T key_type;
+ typedef T value_type;
+
+ typedef ImmutableTree<T, T, _Identity<T>, CMP> Tree;
+ typedef typename Tree::iterator iterator;
+
+ private:
+ Tree elts;
+
+ ImmutableSet(const Tree &b): elts(b) {}
+
+ public:
+ ImmutableSet() {}
+ ImmutableSet(const ImmutableSet &b) : elts(b.elts) {}
+ ~ImmutableSet() {}
+
+ ImmutableSet &operator=(const ImmutableSet &b) { elts = b.elts; return *this; }
+
+ bool empty() const {
+ return elts.empty();
+ }
+ unsigned count(const key_type &key) const {
+ return elts.count(key);
+ }
+ const value_type *lookup(const key_type &key) const {
+ return elts.lookup(key);
+ }
+ const value_type &min() const {
+ return elts.min();
+ }
+ const value_type &max() const {
+ return elts.max();
+ }
+ unsigned size() {
+ return elts.size();
+ }
+
+ ImmutableSet insert(const value_type &value) const {
+ return elts.insert(value);
+ }
+ ImmutableSet replace(const value_type &value) const {
+ return elts.replace(value);
+ }
+ ImmutableSet remove(const key_type &key) const {
+ return elts.remove(key);
+ }
+ ImmutableSet popMin(const value_type &valueOut) const {
+ return elts.popMin(valueOut);
+ }
+ ImmutableSet popMax(const value_type &valueOut) const {
+ return elts.popMax(valueOut);
+ }
+
+ iterator begin() const {
+ return elts.begin();
+ }
+ iterator end() const {
+ return elts.end();
+ }
+ iterator find(const key_type &key) const {
+ return elts.find(key);
+ }
+ iterator lower_bound(const key_type &key) const {
+ return elts.lower_bound(key);
+ }
+ iterator upper_bound(const key_type &key) const {
+ return elts.upper_bound(key);
+ }
+
+ static unsigned getAllocated() { return Tree::allocated; }
+ };
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/ADT/ImmutableTree.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/ImmutableTree.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/ImmutableTree.h (added)
+++ klee/trunk/include/klee/Internal/ADT/ImmutableTree.h Wed May 20 23:36:41 2009
@@ -0,0 +1,619 @@
+//===-- ImmutableTree.h -----------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UTIL_IMMUTABLETREE_H__
+#define __UTIL_IMMUTABLETREE_H__
+
+#include <cassert>
+#include <vector>
+
+namespace klee {
+ template<class K, class V, class KOV, class CMP>
+ class ImmutableTree {
+ public:
+ static unsigned allocated;
+ class iterator;
+
+ typedef K key_type;
+ typedef V value_type;
+ typedef KOV key_of_value;
+ typedef CMP key_compare;
+
+ public:
+ ImmutableTree();
+ ImmutableTree(const ImmutableTree &s);
+ ~ImmutableTree();
+
+ ImmutableTree &operator=(const ImmutableTree &s);
+
+ bool empty() const;
+
+ unsigned count(const key_type &key) const; // always 0 or 1
+ const value_type *lookup(const key_type &key) const;
+
+ // find the last value less than or equal to key, or null if
+ // no such value exists
+ const value_type *lookup_previous(const key_type &key) const;
+
+ const value_type &min() const;
+ const value_type &max() const;
+ unsigned size() const;
+
+ ImmutableTree insert(const value_type &value) const;
+ ImmutableTree replace(const value_type &value) const;
+ ImmutableTree remove(const key_type &key) const;
+ ImmutableTree popMin(value_type &valueOut) const;
+ ImmutableTree popMax(value_type &valueOut) const;
+
+ iterator begin() const;
+ iterator end() const;
+ iterator find(const key_type &key) const;
+ iterator lower_bound(const key_type &key) const;
+ iterator upper_bound(const key_type &key) const;
+
+ static unsigned getAllocated() { return allocated; }
+
+ private:
+ class Node;
+
+ Node *node;
+ ImmutableTree(Node *_node);
+ };
+
+ /***/
+
+ template<class K, class V, class KOV, class CMP>
+ class ImmutableTree<K,V,KOV,CMP>::Node {
+ public:
+ static Node terminator;
+ Node *left, *right;
+ value_type value;
+ unsigned height, references;
+
+ protected:
+ Node(); // solely for creating the terminator node
+ static Node *balance(Node *left, const value_type &value, Node *right);
+
+ public:
+
+ Node(Node *_left, Node *_right, const value_type &_value);
+ ~Node();
+
+ void decref();
+ Node *incref();
+
+ bool isTerminator();
+
+ unsigned size();
+ Node *popMin(value_type &valueOut);
+ Node *popMax(value_type &valueOut);
+ Node *insert(const value_type &v);
+ Node *replace(const value_type &v);
+ Node *remove(const key_type &k);
+ };
+
+ // Should live somewhere else, this is a simple stack with maximum size.
+ template<typename T>
+ class FixedStack {
+ unsigned pos, max;
+ T *elts;
+
+ public:
+ FixedStack(unsigned _max) : pos(0),
+ max(_max),
+ elts(new T[max]) {}
+ FixedStack(const FixedStack &b) : pos(b.pos),
+ max(b.max),
+ elts(new T[b.max]) {
+ std::copy(b.elts, b.elts+pos, elts);
+ }
+ ~FixedStack() { delete[] elts; }
+
+ void push_back(const T &elt) { elts[pos++] = elt; }
+ void pop_back() { --pos; }
+ bool empty() { return pos==0; }
+ T &back() { return elts[pos-1]; }
+
+
+ FixedStack &operator=(const FixedStack &b) {
+ assert(max == b.max);
+ pos = b.pos;
+ std::copy(b.elts, b.elts+pos, elts);
+ return *this;
+ }
+
+ bool operator==(const FixedStack &b) {
+ return (pos == b.pos &&
+ std::equal(elts, elts+pos, b.elts));
+ }
+ bool operator!=(const FixedStack &b) { return !(*this==b); }
+ };
+
+ template<class K, class V, class KOV, class CMP>
+ class ImmutableTree<K,V,KOV,CMP>::iterator {
+ friend class ImmutableTree<K,V,KOV,CMP>;
+ private:
+ Node *root; // so can back up from end
+ FixedStack<Node*> stack;
+
+ public:
+ iterator(Node *_root, bool atBeginning) : root(_root->incref()),
+ stack(root->height) {
+ if (atBeginning) {
+ for (Node *n=root; !n->isTerminator(); n=n->left)
+ stack.push_back(n);
+ }
+ }
+ iterator(const iterator &i) : root(i.root->incref()),
+ stack(i.stack) {
+ }
+ ~iterator() {
+ root->decref();
+ }
+
+ iterator &operator=(const iterator &b) {
+ b.root->incref();
+ root->decref();
+ root = b.root;
+ stack = b.stack;
+ return *this;
+ }
+
+ const value_type &operator*() {
+ Node *n = stack.back();
+ return n->value;
+ }
+
+ const value_type *operator->() {
+ Node *n = stack.back();
+ return &n->value;
+ }
+
+ bool operator==(const iterator &b) {
+ return stack==b.stack;
+ }
+ bool operator!=(const iterator &b) {
+ return stack!=b.stack;
+ }
+
+ iterator &operator--() {
+ if (stack.empty()) {
+ for (Node *n=root; !n->isTerminator(); n=n->right)
+ stack.push_back(n);
+ } else {
+ Node *n = stack.back();
+ if (n->left->isTerminator()) {
+ for (;;) {
+ Node *prev = n;
+ stack.pop_back();
+ if (stack.empty()) {
+ break;
+ } else {
+ n = stack.back();
+ if (prev==n->right)
+ break;
+ }
+ }
+ } else {
+ stack.push_back(n->left);
+ for (n=n->left->right; !n->isTerminator(); n=n->right)
+ stack.push_back(n);
+ }
+ }
+ return *this;
+ }
+
+ iterator &operator++() {
+ assert(!stack.empty());
+ Node *n = stack.back();
+ if (n->right->isTerminator()) {
+ for (;;) {
+ Node *prev = n;
+ stack.pop_back();
+ if (stack.empty()) {
+ break;
+ } else {
+ n = stack.back();
+ if (prev==n->left)
+ break;
+ }
+ }
+ } else {
+ stack.push_back(n->right);
+ for (n=n->right->left; !n->isTerminator(); n=n->left)
+ stack.push_back(n);
+ }
+ return *this;
+ }
+ };
+
+ /***/
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::Node
+ ImmutableTree<K,V,KOV,CMP>::Node::terminator;
+
+ template<class K, class V, class KOV, class CMP>
+ unsigned ImmutableTree<K,V,KOV,CMP>::allocated = 0;
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>::Node::Node()
+ : left(&terminator),
+ right(&terminator),
+ height(0),
+ references(3) {
+ assert(this==&terminator);
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>::Node::Node(Node *_left, Node *_right, const value_type &_value)
+ : left(_left),
+ right(_right),
+ value(_value),
+ height(std::max(left->height, right->height) + 1),
+ references(1)
+ {
+ ++allocated;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>::Node::~Node() {
+ left->decref();
+ right->decref();
+ --allocated;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ inline void ImmutableTree<K,V,KOV,CMP>::Node::decref() {
+ --references;
+ if (references==0) delete this;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ inline typename ImmutableTree<K,V,KOV,CMP>::Node *ImmutableTree<K,V,KOV,CMP>::Node::incref() {
+ ++references;
+ return this;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ inline bool ImmutableTree<K,V,KOV,CMP>::Node::isTerminator() {
+ return this==&terminator;
+ }
+
+ /***/
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::Node *
+ ImmutableTree<K,V,KOV,CMP>::Node::balance(Node *left, const value_type &value, Node *right) {
+ if (left->height > right->height + 2) {
+ Node *ll = left->left;
+ Node *lr = left->right;
+ if (ll->height >= lr->height) {
+ Node *nlr = new Node(lr->incref(), right, value);
+ Node *res = new Node(ll->incref(), nlr, left->value);
+ left->decref();
+ return res;
+ } else {
+ Node *lrl = lr->left;
+ Node *lrr = lr->right;
+ Node *nll = new Node(ll->incref(), lrl->incref(), left->value);
+ Node *nlr = new Node(lrr->incref(), right, value);
+ Node *res = new Node(nll, nlr, lr->value);
+ left->decref();
+ return res;
+ }
+ } else if (right->height > left->height + 2) {
+ Node *rl = right->left;
+ Node *rr = right->right;
+ if (rr->height >= rl->height) {
+ Node *nrl = new Node(left, rl->incref(), value);
+ Node *res = new Node(nrl, rr->incref(), right->value);
+ right->decref();
+ return res;
+ } else {
+ Node *rll = rl->left;
+ Node *rlr = rl->right;
+ Node *nrl = new Node(left, rll->incref(), value);
+ Node *nrr = new Node(rlr->incref(), rr->incref(), right->value);
+ Node *res = new Node(nrl, nrr, rl->value);
+ right->decref();
+ return res;
+ }
+ } else {
+ return new Node(left, right, value);
+ }
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ unsigned ImmutableTree<K,V,KOV,CMP>::Node::size() {
+ if (isTerminator()) {
+ return 0;
+ } else {
+ return left->size() + 1 + right->size();
+ }
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::Node *
+ ImmutableTree<K,V,KOV,CMP>::Node::popMin(value_type &valueOut) {
+ if (left->isTerminator()) {
+ valueOut = value;
+ return right->incref();
+ } else {
+ return balance(left->popMin(valueOut), value, right->incref());
+ }
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::Node *
+ ImmutableTree<K,V,KOV,CMP>::Node::popMax(value_type &valueOut) {
+ if (right->isTerminator()) {
+ valueOut = value;
+ return left->incref();
+ } else {
+ return balance(left->incref(), value, right->popMax(valueOut));
+ }
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::Node *
+ ImmutableTree<K,V,KOV,CMP>::Node::insert(const value_type &v) {
+ if (isTerminator()) {
+ return new Node(terminator.incref(), terminator.incref(), v);
+ } else {
+ if (key_compare()(key_of_value()(v), key_of_value()(value))) {
+ return balance(left->insert(v), value, right->incref());
+ } else if (key_compare()(key_of_value()(value), key_of_value()(v))) {
+ return balance(left->incref(), value, right->insert(v));
+ } else {
+ return incref();
+ }
+ }
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::Node *
+ ImmutableTree<K,V,KOV,CMP>::Node::replace(const value_type &v) {
+ if (isTerminator()) {
+ return new Node(terminator.incref(), terminator.incref(), v);
+ } else {
+ if (key_compare()(key_of_value()(v), key_of_value()(value))) {
+ return balance(left->replace(v), value, right->incref());
+ } else if (key_compare()(key_of_value()(value), key_of_value()(v))) {
+ return balance(left->incref(), value, right->replace(v));
+ } else {
+ return new Node(left->incref(), right->incref(), v);
+ }
+ }
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::Node *
+ ImmutableTree<K,V,KOV,CMP>::Node::remove(const key_type &k) {
+ if (isTerminator()) {
+ return incref();
+ } else {
+ if (key_compare()(k, key_of_value()(value))) {
+ return balance(left->remove(k), value, right->incref());
+ } else if (key_compare()(key_of_value()(value), k)) {
+ return balance(left->incref(), value, right->remove(k));
+ } else {
+ if (left->isTerminator()) {
+ return right->incref();
+ } else if (right->isTerminator()) {
+ return left->incref();
+ } else {
+ value_type min;
+ Node *nr = right->popMin(min);
+ return balance(left->incref(), min, nr);
+ }
+ }
+ }
+ }
+
+ /***/
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>::ImmutableTree()
+ : node(Node::terminator.incref()) {
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>::ImmutableTree(Node *_node)
+ : node(_node) {
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>::ImmutableTree(const ImmutableTree &s)
+ : node(s.node->incref()) {
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>::~ImmutableTree() {
+ node->decref();
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP> &ImmutableTree<K,V,KOV,CMP>::operator=(const ImmutableTree &s) {
+ Node *n = s.node->incref();
+ node->decref();
+ node = n;
+ return *this;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ bool ImmutableTree<K,V,KOV,CMP>::empty() const {
+ return node->isTerminator();
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ unsigned ImmutableTree<K,V,KOV,CMP>::count(const key_type &k) const {
+ Node *n = node;
+ while (!n->isTerminator()) {
+ key_type key = key_of_value()(n->value);
+ if (key_compare()(k, key)) {
+ n = n->left;
+ } else if (key_compare()(key, k)) {
+ n = n->right;
+ } else {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ const typename ImmutableTree<K,V,KOV,CMP>::value_type *
+ ImmutableTree<K,V,KOV,CMP>::lookup(const key_type &k) const {
+ Node *n = node;
+ while (!n->isTerminator()) {
+ key_type key = key_of_value()(n->value);
+ if (key_compare()(k, key)) {
+ n = n->left;
+ } else if (key_compare()(key, k)) {
+ n = n->right;
+ } else {
+ return &n->value;
+ }
+ }
+ return 0;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ const typename ImmutableTree<K,V,KOV,CMP>::value_type *
+ ImmutableTree<K,V,KOV,CMP>::lookup_previous(const key_type &k) const {
+ Node *n = node;
+ Node *result = 0;
+ while (!n->isTerminator()) {
+ key_type key = key_of_value()(n->value);
+ if (key_compare()(k, key)) {
+ n = n->left;
+ } else if (key_compare()(key, k)) {
+ result = n;
+ n = n->right;
+ } else {
+ return &n->value;
+ }
+ }
+ return result ? &result->value : 0;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ const typename ImmutableTree<K,V,KOV,CMP>::value_type &
+ ImmutableTree<K,V,KOV,CMP>::min() const {
+ Node *n = node;
+ assert(!n->isTerminator());
+ while (!n->left->isTerminator()) n = n->left;
+ return n->value;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ const typename ImmutableTree<K,V,KOV,CMP>::value_type &
+ ImmutableTree<K,V,KOV,CMP>::max() const {
+ Node *n = node;
+ assert(!n->isTerminator());
+ while (!n->right->isTerminator()) n = n->right;
+ return n->value;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ unsigned ImmutableTree<K,V,KOV,CMP>::size() const {
+ return node->size();
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>
+ ImmutableTree<K,V,KOV,CMP>::insert(const value_type &value) const {
+ return ImmutableTree(node->insert(value));
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>
+ ImmutableTree<K,V,KOV,CMP>::replace(const value_type &value) const {
+ return ImmutableTree(node->replace(value));
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>
+ ImmutableTree<K,V,KOV,CMP>::remove(const key_type &key) const {
+ return ImmutableTree(node->remove(key));
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>
+ ImmutableTree<K,V,KOV,CMP>::popMin(value_type &valueOut) const {
+ return ImmutableTree(node->popMin(valueOut));
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ ImmutableTree<K,V,KOV,CMP>
+ ImmutableTree<K,V,KOV,CMP>::popMax(value_type &valueOut) const {
+ return ImmutableTree(node->popMax(valueOut));
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ inline typename ImmutableTree<K,V,KOV,CMP>::iterator
+ ImmutableTree<K,V,KOV,CMP>::begin() const {
+ return iterator(node, true);
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ inline typename ImmutableTree<K,V,KOV,CMP>::iterator
+ ImmutableTree<K,V,KOV,CMP>::end() const {
+ return iterator(node, false);
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ inline typename ImmutableTree<K,V,KOV,CMP>::iterator
+ ImmutableTree<K,V,KOV,CMP>::find(const key_type &key) const {
+ iterator end(node,false), it = lower_bound(key);
+ if (it==end || key_compare()(key,key_of_value()(*it))) {
+ return end;
+ } else {
+ return it;
+ }
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ inline typename ImmutableTree<K,V,KOV,CMP>::iterator
+ ImmutableTree<K,V,KOV,CMP>::lower_bound(const key_type &k) const {
+ // XXX ugh this doesn't have to be so ugly does it?
+ iterator it(node,false);
+ for (Node *root=node; !root->isTerminator();) {
+ it.stack.push_back(root);
+ if (key_compare()(k, key_of_value()(root->value))) {
+ root = root->left;
+ } else if (key_compare()(key_of_value()(root->value), k)) {
+ root = root->right;
+ } else {
+ return it;
+ }
+ }
+ // it is now beginning or first element < k
+ if (!it.stack.empty()) {
+ Node *last = it.stack.back();
+ if (key_compare()(key_of_value()(last->value), k))
+ ++it;
+ }
+ return it;
+ }
+
+ template<class K, class V, class KOV, class CMP>
+ typename ImmutableTree<K,V,KOV,CMP>::iterator
+ ImmutableTree<K,V,KOV,CMP>::upper_bound(const key_type &key) const {
+ iterator end(node,false),it = lower_bound(key);
+ if (it!=end &&
+ !key_compare()(key,key_of_value()(*it))) // no need to loop, no duplicates
+ ++it;
+ return it;
+ }
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/ADT/MapOfSets.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/MapOfSets.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/MapOfSets.h (added)
+++ klee/trunk/include/klee/Internal/ADT/MapOfSets.h Wed May 20 23:36:41 2009
@@ -0,0 +1,385 @@
+//===-- MapOfSets.h ---------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UTIL_MAPOFSETS_H__
+#define __UTIL_MAPOFSETS_H__
+
+#include <cassert>
+#include <vector>
+#include <set>
+#include <map>
+
+// This should really be broken down into TreeOfSets on top of which
+// SetOfSets and MapOfSets are easily implemeted. It should also be
+// parameterized on the underlying set type. Neither are hard to do,
+// just not worth it at the moment.
+//
+// I also broke some STLish conventions because I was bored.
+
+namespace klee {
+
+ /** This implements the UBTree data structure (see Hoffmann and
+ Koehler, "A New Method to Index and Query Sets", IJCAI 1999) */
+ template<class K, class V>
+ class MapOfSets {
+ public:
+ class iterator;
+
+ public:
+ MapOfSets();
+
+ void clear();
+
+ void insert(const std::set<K> &set, const V &value);
+
+ V *lookup(const std::set<K> &set);
+
+ iterator begin();
+ iterator end();
+
+ void subsets(const std::set<K> &set,
+ std::vector< std::pair<std::set<K>, V> > &resultOut);
+ void supersets(const std::set<K> &set,
+ std::vector< std::pair<std::set<K>, V> > &resultOut);
+
+ template<class Predicate>
+ V *findSuperset(const std::set<K> &set, const Predicate &p);
+ template<class Predicate>
+ V *findSubset(const std::set<K> &set, const Predicate &p);
+
+ private:
+ class Node;
+
+ Node root;
+
+ template<class Iterator, class Vector>
+ void findSubsets(Node *n,
+ const std::set<K> &accum,
+ Iterator begin,
+ Iterator end,
+ Vector &resultsOut);
+ template<class Iterator, class Vector>
+ void findSupersets(Node *n,
+ const std::set<K> &accum,
+ Iterator begin,
+ Iterator end,
+ Vector &resultsOut);
+ template<class Predicate>
+ V *findSuperset(Node *n,
+ typename std::set<K>::iterator begin,
+ typename std::set<K>::iterator end,
+ const Predicate &p);
+ template<class Predicate>
+ V *findSubset(Node *n,
+ typename std::set<K>::iterator begin,
+ typename std::set<K>::iterator end,
+ const Predicate &p);
+ };
+
+ /***/
+
+ template<class K, class V>
+ class MapOfSets<K,V>::Node {
+ friend class MapOfSets<K,V>;
+ friend class MapOfSets<K,V>::iterator;
+
+ public:
+ typedef std::map<K, Node> children_ty;
+
+ V value;
+
+ private:
+ bool isEndOfSet;
+ std::map<K, Node> children;
+
+ public:
+ Node() : isEndOfSet(false) {}
+ };
+
+ template<class K, class V>
+ class MapOfSets<K,V>::iterator {
+ typedef std::vector< typename std::map<K, Node>::iterator > stack_ty;
+ friend class MapOfSets<K,V>;
+ private:
+ Node *root;
+ bool onEntry;
+ stack_ty stack;
+
+ void step() {
+ if (onEntry) {
+ onEntry = false;
+ Node *n = stack.empty() ? root : &stack.back()->second;
+ while (!n->children.empty()) {
+ stack.push_back(n->children.begin());
+ n = &stack.back()->second;
+ if (n->isEndOfSet) {
+ onEntry = true;
+ return;
+ }
+ }
+ }
+
+ while (!stack.empty()) {
+ unsigned size = stack.size();
+ Node *at = size==1 ? root : &stack[size-2]->second;
+ typename std::map<K,Node>::iterator &cur = stack.back();
+ ++cur;
+ if (cur==at->children.end()) {
+ stack.pop_back();
+ } else {
+ Node *n = &cur->second;
+
+ while (!n->isEndOfSet) {
+ assert(!n->children.empty());
+ stack.push_back(n->children.begin());
+ n = &stack.back()->second;
+ }
+
+ onEntry = true;
+ break;
+ }
+ }
+ }
+
+ public:
+ // end()
+ iterator() : onEntry(false) {}
+ // begin()
+ iterator(Node *_n) : root(_n), onEntry(true) {
+ if (!root->isEndOfSet)
+ step();
+ }
+
+ const std::pair<const std::set<K>, const V> operator*() {
+ assert(onEntry || !stack.empty());
+ std::set<K> s;
+ for (typename stack_ty::iterator it = stack.begin(), ie = stack.end();
+ it != ie; ++it)
+ s.insert((*it)->first);
+ Node *n = stack.empty() ? root : &stack.back()->second;
+ return std::make_pair(s, n->value);
+ }
+
+ bool operator==(const iterator &b) {
+ return onEntry==b.onEntry && stack==b.stack;
+ }
+ bool operator!=(const iterator &b) {
+ return !(*this==b);
+ }
+
+ iterator &operator++() {
+ step();
+ return *this;
+ }
+ };
+
+ /***/
+
+ template<class K, class V>
+ MapOfSets<K,V>::MapOfSets() {}
+
+ template<class K, class V>
+ void MapOfSets<K,V>::insert(const std::set<K> &set, const V &value) {
+ Node *n = &root;
+ for (typename std::set<K>::const_iterator it = set.begin(), ie = set.end();
+ it != ie; ++it)
+ n = &n->children.insert(std::make_pair(*it, Node())).first->second;
+ n->isEndOfSet = true;
+ n->value = value;
+ }
+
+ template<class K, class V>
+ V *MapOfSets<K,V>::lookup(const std::set<K> &set) {
+ Node *n = &root;
+ for (typename std::set<K>::const_iterator it = set.begin(), ie = set.end();
+ it != ie; ++it) {
+ typename Node::children_ty::iterator kit = n->children.find(*it);
+ if (kit==n->children.end()) {
+ return 0;
+ } else {
+ n = &kit->second;
+ }
+ }
+ if (n->isEndOfSet) {
+ return &n->value;
+ } else {
+ return 0;
+ }
+ }
+
+ template<class K, class V>
+ typename MapOfSets<K,V>::iterator
+ MapOfSets<K,V>::begin() { return iterator(&root); }
+
+ template<class K, class V>
+ typename MapOfSets<K,V>::iterator
+ MapOfSets<K,V>::end() { return iterator(); }
+
+ template<class K, class V>
+ template<class Iterator, class Vector>
+ void MapOfSets<K,V>::findSubsets(Node *n,
+ const std::set<K> &accum,
+ Iterator begin,
+ Iterator end,
+ Vector &resultsOut) {
+ if (n->isEndOfSet) {
+ resultsOut.push_back(std::make_pair(accum, n->value));
+ }
+
+ for (Iterator it=begin; it!=end;) {
+ K elt = *it;
+ typename Node::children_ty::iterator kit = n->children.find(elt);
+ it++;
+ if (kit!=n->children.end()) {
+ std::set<K> nacc = accum;
+ nacc.insert(elt);
+ findSubsets(&kit->second, nacc, it, end, resultsOut);
+ }
+ }
+ }
+
+ template<class K, class V>
+ void MapOfSets<K,V>::subsets(const std::set<K> &set,
+ std::vector< std::pair<std::set<K>,
+ V> > &resultOut) {
+ findSubsets(&root, std::set<K>(), set.begin(), set.end(), resultOut);
+ }
+
+ template<class K, class V>
+ template<class Iterator, class Vector>
+ void MapOfSets<K,V>::findSupersets(Node *n,
+ const std::set<K> &accum,
+ Iterator begin,
+ Iterator end,
+ Vector &resultsOut) {
+ if (begin==end) {
+ if (n->isEndOfSet)
+ resultsOut.push_back(std::make_pair(accum, n->value));
+ for (typename Node::children_ty::iterator it = n->children.begin(),
+ ie = n->children.end(); it != ie; ++it) {
+ std::set<K> nacc = accum;
+ nacc.insert(it->first);
+ findSupersets(&it->second, nacc, begin, end, resultsOut);
+ }
+ } else {
+ K elt = *begin;
+ Iterator next = begin;
+ ++next;
+ for (typename Node::children_ty::iterator it = n->children.begin(),
+ ie = n->children.end(); it != ie; ++it) {
+ std::set<K> nacc = accum;
+ nacc.insert(it->first);
+ if (elt==it->first) {
+ findSupersets(&it->second, nacc, next, end, resultsOut);
+ } else if (it->first<elt) {
+ findSupersets(&it->second, nacc, begin, end, resultsOut);
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ template<class K, class V>
+ void MapOfSets<K,V>::supersets(const std::set<K> &set,
+ std::vector< std::pair<std::set<K>, V> > &resultOut) {
+ findSupersets(&root, std::set<K>(), set.begin(), set.end(), resultOut);
+ }
+
+ template<class K, class V>
+ template<class Predicate>
+ V *MapOfSets<K,V>::findSubset(Node *n,
+ typename std::set<K>::iterator begin,
+ typename std::set<K>::iterator end,
+ const Predicate &p) {
+ if (n->isEndOfSet && p(n->value)) {
+ return &n->value;
+ } else if (begin==end) {
+ return 0;
+ } else {
+ typename Node::children_ty::iterator kend = n->children.end();
+ typename Node::children_ty::iterator
+ kbegin = n->children.lower_bound(*begin);
+ typename std::set<K>::iterator it = begin;
+ if (kbegin==kend)
+ return 0;
+ for (;;) { // kbegin!=kend && *it <= kbegin->first
+ while (*it < kbegin->first) {
+ ++it;
+ if (it==end)
+ return 0;
+ }
+ if (*it == kbegin->first) {
+ ++it;
+ V *res = findSubset(&kbegin->second, it, end, p);
+ if (res || it==end)
+ return res;
+ }
+ while (kbegin->first < *it) {
+ ++kbegin;
+ if (kbegin==kend)
+ return 0;
+ }
+ }
+ }
+ }
+
+ template<class K, class V>
+ template<class Predicate>
+ V *MapOfSets<K,V>::findSuperset(Node *n,
+ typename std::set<K>::iterator begin,
+ typename std::set<K>::iterator end,
+ const Predicate &p) {
+ if (begin==end) {
+ if (n->isEndOfSet && p(n->value))
+ return &n->value;
+ for (typename Node::children_ty::iterator it = n->children.begin(),
+ ie = n->children.end(); it != ie; ++it) {
+ V *res = findSuperset(&it->second, begin, end, p);
+ if (res) return res;
+ }
+ } else {
+ typename Node::children_ty::iterator kbegin = n->children.begin();
+ typename Node::children_ty::iterator kmid =
+ n->children.lower_bound(*begin);
+ for (typename Node::children_ty::iterator it = n->children.begin(),
+ ie = n->children.end(); it != ie; ++it) {
+ V *res = findSuperset(&it->second, begin, end, p);
+ if (res) return res;
+ }
+ if (kmid!=n->children.end() && *begin==kmid->first) {
+ V *res = findSuperset(&kmid->second, ++begin, end, p);
+ if (res) return res;
+ }
+ }
+ return 0;
+ }
+
+ template<class K, class V>
+ template<class Predicate>
+ V *MapOfSets<K,V>::findSuperset(const std::set<K> &set, const Predicate &p) {
+ return findSuperset(&root, set.begin(), set.end(), p);
+ }
+
+ template<class K, class V>
+ template<class Predicate>
+ V *MapOfSets<K,V>::findSubset(const std::set<K> &set, const Predicate &p) {
+ return findSubset(&root, set.begin(), set.end(), p);
+ }
+
+ template<class K, class V>
+ void MapOfSets<K,V>::clear() {
+ root.isEndOfSet = false;
+ root.value = V();
+ root.children.clear();
+ }
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/ADT/RNG.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/RNG.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/RNG.h (added)
+++ klee/trunk/include/klee/Internal/ADT/RNG.h Wed May 20 23:36:41 2009
@@ -0,0 +1,50 @@
+//===-- RNG.h ---------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_UTIL_RNG_H
+#define KLEE_UTIL_RNG_H
+
+namespace klee {
+ class RNG {
+ private:
+ /* Period parameters */
+ static const int N = 624;
+ static const int M = 397;
+ static const unsigned int MATRIX_A = 0x9908b0dfUL; /* constant vector a */
+ static const unsigned int UPPER_MASK = 0x80000000UL; /* most significant w-r bits */
+ static const unsigned int LOWER_MASK = 0x7fffffffUL; /* least significant r bits */
+
+ private:
+ unsigned int mt[N]; /* the array for the state vector */
+ int mti;
+
+ public:
+ RNG(unsigned int seed=5489UL);
+
+ void seed(unsigned int seed);
+
+ /* generates a random number on [0,0xffffffff]-interval */
+ unsigned int getInt32();
+ /* generates a random number on [0,0x7fffffff]-interval */
+ int getInt31();
+ /* generates a random number on [0,1]-real-interval */
+ double getDoubleLR();
+ float getFloatLR();
+ /* generates a random number on [0,1)-real-interval */
+ double getDoubleL();
+ float getFloatL();
+ /* generates a random number on (0,1)-real-interval */
+ double getDouble();
+ float getFloat();
+ /* generators a random flop */
+ bool getBool();
+ };
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/ADT/TreeStream.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/ADT/TreeStream.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/ADT/TreeStream.h (added)
+++ klee/trunk/include/klee/Internal/ADT/TreeStream.h Wed May 20 23:36:41 2009
@@ -0,0 +1,77 @@
+//===-- TreeStream.h --------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UTIL_TREESTREAM_H__
+#define __UTIL_TREESTREAM_H__
+
+#include <string>
+#include <iostream>
+#include <vector>
+
+namespace klee {
+
+ typedef unsigned TreeStreamID;
+ class TreeOStream;
+
+ class TreeStreamWriter {
+ static const unsigned bufferSize = 4*4096;
+
+ friend class TreeOStream;
+
+ private:
+ char buffer[bufferSize];
+ unsigned lastID, bufferCount;
+
+ std::string path;
+ std::ofstream *output;
+ unsigned ids;
+
+ void write(TreeOStream &os, const char *s, unsigned size);
+ void flushBuffer();
+
+ public:
+ TreeStreamWriter(const std::string &_path);
+ ~TreeStreamWriter();
+
+ bool good();
+
+ TreeOStream open();
+ TreeOStream open(const TreeOStream &node);
+
+ void flush();
+
+ // hack, to be replace by proper stream capabilities
+ void readStream(TreeStreamID id,
+ std::vector<unsigned char> &out);
+ };
+
+ class TreeOStream {
+ friend class TreeStreamWriter;
+
+ private:
+ TreeStreamWriter *writer;
+ unsigned id;
+
+ TreeOStream(TreeStreamWriter &_writer, unsigned _id);
+
+ public:
+ TreeOStream();
+ ~TreeOStream();
+
+ unsigned getID() const;
+
+ void write(const char *buffer, unsigned size);
+
+ TreeOStream &operator<<(const std::string &s);
+
+ void flush();
+ };
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/Module/Cell.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Module/Cell.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Module/Cell.h (added)
+++ klee/trunk/include/klee/Internal/Module/Cell.h Wed May 20 23:36:41 2009
@@ -0,0 +1,23 @@
+//===-- Cell.h --------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_CELL_H
+#define KLEE_CELL_H
+
+#include <klee/Expr.h>
+
+namespace klee {
+ class MemoryObject;
+
+ struct Cell {
+ ref<Expr> value;
+ };
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/Module/InstructionInfoTable.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Module/InstructionInfoTable.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Module/InstructionInfoTable.h (added)
+++ klee/trunk/include/klee/Internal/Module/InstructionInfoTable.h Wed May 20 23:36:41 2009
@@ -0,0 +1,70 @@
+//===-- InstructionInfoTable.h ----------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_LIB_INSTRUCTIONINFOTABLE_H
+#define KLEE_LIB_INSTRUCTIONINFOTABLE_H
+
+#include <map>
+#include <string>
+#include <set>
+
+namespace llvm {
+ class Function;
+ class Instruction;
+ class Module;
+}
+
+namespace klee {
+
+ /* Stores debug information for a KInstruction */
+ struct InstructionInfo {
+ unsigned id;
+ const std::string &file;
+ unsigned line;
+ unsigned assemblyLine;
+
+ public:
+ InstructionInfo(unsigned _id,
+ const std::string &_file,
+ unsigned _line,
+ unsigned _assemblyLine)
+ : id(_id),
+ file(_file),
+ line(_line),
+ assemblyLine(_assemblyLine) {
+ }
+ };
+
+ class InstructionInfoTable {
+ struct ltstr {
+ bool operator()(const std::string *a, const std::string *b) const {
+ return *a<*b;
+ }
+ };
+
+ std::string dummyString;
+ InstructionInfo dummyInfo;
+ std::map<const llvm::Instruction*, InstructionInfo> infos;
+ std::set<const std::string *, ltstr> internedStrings;
+
+ private:
+ const std::string *internString(std::string s);
+
+ public:
+ InstructionInfoTable(llvm::Module *m);
+ ~InstructionInfoTable();
+
+ unsigned getMaxID() const;
+ const InstructionInfo &getInfo(const llvm::Instruction*) const;
+ const InstructionInfo &getFunctionInfo(const llvm::Function*) const;
+ };
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/Module/KInstIterator.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Module/KInstIterator.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Module/KInstIterator.h (added)
+++ klee/trunk/include/klee/Internal/Module/KInstIterator.h Wed May 20 23:36:41 2009
@@ -0,0 +1,49 @@
+//===-- KInstIterator.h -----------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_KINSTITERATOR_H
+#define KLEE_KINSTITERATOR_H
+
+namespace klee {
+ class KInstruction;
+
+ class KInstIterator {
+ KInstruction **it;
+
+ public:
+ KInstIterator() : it(0) {}
+ KInstIterator(KInstruction **_it) : it(_it) {}
+ KInstIterator(const KInstIterator &b) : it(b.it) {}
+ ~KInstIterator() {}
+
+ KInstIterator &operator=(const KInstIterator &b) {
+ it = b.it;
+ return *this;
+ }
+
+ bool operator==(const KInstIterator &b) const {
+ return it==b.it;
+ }
+ bool operator!=(const KInstIterator &b) const {
+ return !(*this == b);
+ }
+
+ KInstIterator &operator++() {
+ ++it;
+ return *this;
+ }
+
+ operator KInstruction*() const { return it ? *it : 0;}
+ operator bool() const { return it != 0; }
+
+ KInstruction *operator ->() const { return *it; }
+ };
+} // End klee namespace
+
+#endif
Added: klee/trunk/include/klee/Internal/Module/KInstruction.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Module/KInstruction.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Module/KInstruction.h (added)
+++ klee/trunk/include/klee/Internal/Module/KInstruction.h Wed May 20 23:36:41 2009
@@ -0,0 +1,50 @@
+//===-- KInstruction.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_KINSTRUCTION_H
+#define KLEE_KINSTRUCTION_H
+
+#include <vector>
+
+namespace llvm {
+ class Instruction;
+}
+
+namespace klee {
+ class Executor;
+ struct InstructionInfo;
+ class KModule;
+
+
+ /// KInstruction - Intermediate instruction representation used
+ /// during execution.
+ struct KInstruction {
+ llvm::Instruction *inst;
+ const InstructionInfo *info;
+
+ /// Value numbers for each operand. -1 is an invalid value,
+ /// otherwise negative numbers are indices (negated and offset by
+ /// 2) into the module constant table and positive numbers are
+ /// register indices.
+ int *operands;
+ /// Destination register index.
+ unsigned dest;
+
+ public:
+ virtual ~KInstruction();
+ };
+
+ struct KGEPInstruction : KInstruction {
+ std::vector< std::pair<unsigned, unsigned> > indices;
+ unsigned offset;
+ };
+}
+
+#endif
+
Added: klee/trunk/include/klee/Internal/Module/KModule.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Module/KModule.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Module/KModule.h (added)
+++ klee/trunk/include/klee/Internal/Module/KModule.h Wed May 20 23:36:41 2009
@@ -0,0 +1,119 @@
+//===-- KModule.h -----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_KMODULE_H
+#define KLEE_KMODULE_H
+
+#include "klee/Interpreter.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+namespace llvm {
+ class BasicBlock;
+ class Constant;
+ class Function;
+ class Instruction;
+ class Module;
+ class TargetData;
+}
+
+namespace klee {
+ class Cell;
+ class Executor;
+ class Expr;
+ class InterpreterHandler;
+ class InstructionInfoTable;
+ class KInstruction;
+ class KModule;
+ template<class T> class ref;
+
+ struct KFunction {
+ llvm::Function *function;
+
+ unsigned numArgs, numRegisters;
+
+ unsigned numInstructions;
+ KInstruction **instructions;
+
+ std::map<llvm::BasicBlock*, unsigned> basicBlockEntry;
+
+ /// Whether instructions in this function should count as
+ /// "coverable" for statistics and search heuristics.
+ bool trackCoverage;
+
+ private:
+ KFunction(const KFunction&);
+ KFunction &operator=(const KFunction&);
+
+ public:
+ explicit KFunction(llvm::Function*, KModule *);
+ ~KFunction();
+
+ unsigned getArgRegister(unsigned index) { return index; }
+ };
+
+
+ class KConstant {
+ public:
+ /// Actual LLVM constant this represents.
+ llvm::Constant* ct;
+
+ /// The constant ID.
+ unsigned id;
+
+ /// First instruction where this constant was encountered, or NULL
+ /// if not applicable/unavailable.
+ KInstruction *ki;
+
+ KConstant(llvm::Constant*, unsigned, KInstruction*);
+ };
+
+
+ class KModule {
+ public:
+ llvm::Module *module;
+ llvm::TargetData *targetData;
+
+ // Some useful functions to know the address of
+ llvm::Function *dbgStopPointFn, *kleeMergeFn;
+
+ // Our shadow versions of LLVM structures.
+ std::vector<KFunction*> functions;
+ std::map<llvm::Function*, KFunction*> functionMap;
+
+ // Functions which escape (may be called indirectly)
+ // XXX change to KFunction
+ std::set<llvm::Function*> escapingFunctions;
+
+ InstructionInfoTable *infos;
+
+ std::vector<llvm::Constant*> constants;
+ std::map<llvm::Constant*, KConstant*> constantMap;
+ KConstant* getKConstant(llvm::Constant *c);
+
+ Cell *constantTable;
+
+ public:
+ KModule(llvm::Module *_module);
+ ~KModule();
+
+ /// Initialize local data structures.
+ //
+ // FIXME: ihandler should not be here
+ void prepare(const Interpreter::ModuleOptions &opts,
+ InterpreterHandler *ihandler);
+
+ /// Return an id for the given constant, creating a new one if necessary.
+ unsigned getConstantID(llvm::Constant *c, KInstruction* ki);
+ };
+} // End klee namespace
+
+#endif
Added: klee/trunk/include/klee/Internal/README.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/README.txt?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/README.txt (added)
+++ klee/trunk/include/klee/Internal/README.txt Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+This directory holds header files for things which are exposed as part
+of the internal API of a library, but shouldn't be exposed to
+externally.
Added: klee/trunk/include/klee/Internal/Support/FloatEvaluation.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Support/FloatEvaluation.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Support/FloatEvaluation.h (added)
+++ klee/trunk/include/klee/Internal/Support/FloatEvaluation.h Wed May 20 23:36:41 2009
@@ -0,0 +1,258 @@
+//===-- FloatEvaluation.h ---------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: Ditch this and use APFloat.
+
+#ifndef KLEE_UTIL_FLOATS_H
+#define KLEE_UTIL_FLOATS_H
+
+#include "klee/util/Bits.h" //bits64::truncateToNBits
+#include "IntEvaluation.h" //ints::sext
+
+#include "llvm/Support/MathExtras.h"
+
+namespace klee {
+namespace floats {
+
+// ********************************** //
+// *** Pack uint64_t into FP types ** //
+// ********************************** //
+
+// interpret the 64 bits as a double instead of a uint64_t
+inline double UInt64AsDouble( uint64_t bits ) {
+ double ret;
+ assert( sizeof(bits) == sizeof(ret) );
+ memcpy( &ret, &bits, sizeof bits );
+ return ret;
+}
+
+// interpret the first 32 bits as a float instead of a uint64_t
+inline float UInt64AsFloat( uint64_t bits ) {
+ uint32_t tmp = bits; // ensure that we read correct bytes
+ float ret;
+ assert( sizeof(tmp) == sizeof(ret) );
+ memcpy( &ret, &tmp, sizeof tmp );
+ return ret;
+}
+
+
+// ********************************** //
+// *** Pack FP types into uint64_t ** //
+// ********************************** //
+
+// interpret the 64 bits as a uint64_t instead of a double
+inline uint64_t DoubleAsUInt64( double d ) {
+ uint64_t ret;
+ assert( sizeof(d) == sizeof(ret) );
+ memcpy( &ret, &d, sizeof d );
+ return ret;
+}
+
+// interpret the 32 bits as a uint64_t instead of as a float (add 32 0s)
+inline uint64_t FloatAsUInt64( float f ) {
+ uint32_t tmp;
+ assert( sizeof(tmp) == sizeof(f) );
+ memcpy( &tmp, &f, sizeof f );
+ return (uint64_t)tmp;
+}
+
+
+// ********************************** //
+// ************ Constants *********** //
+// ********************************** //
+
+const unsigned FLT_BITS = 32;
+const unsigned DBL_BITS = 64;
+
+
+
+// ********************************** //
+// ***** LLVM Binary Operations ***** //
+// ********************************** //
+
+// add of l and r
+inline uint64_t add(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) + UInt64AsFloat(r)), FLT_BITS);
+ case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) + UInt64AsDouble(r)), DBL_BITS);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+// difference of l and r
+inline uint64_t sub(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) - UInt64AsFloat(r)), FLT_BITS);
+ case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) - UInt64AsDouble(r)), DBL_BITS);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+// product of l and r
+inline uint64_t mul(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) * UInt64AsFloat(r)), FLT_BITS);
+ case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) * UInt64AsDouble(r)), DBL_BITS);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+// signed divide of l by r
+inline uint64_t div(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) / UInt64AsFloat(r)), FLT_BITS);
+ case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) / UInt64AsDouble(r)), DBL_BITS);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+// signed modulo of l by r
+inline uint64_t mod(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64( fmod(UInt64AsFloat(l), UInt64AsFloat(r)) ), FLT_BITS);
+ case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64( fmod(UInt64AsDouble(l), UInt64AsDouble(r)) ), DBL_BITS);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+
+// ********************************** //
+// *** LLVM Comparison Operations *** //
+// ********************************** //
+
+// determine if l represents NaN
+inline bool isNaN(uint64_t l, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return llvm::IsNAN( UInt64AsFloat(l) );
+ case DBL_BITS: return llvm::IsNAN( UInt64AsDouble(l) );
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+inline uint64_t eq(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return UInt64AsFloat(l) == UInt64AsFloat(r);
+ case DBL_BITS: return UInt64AsDouble(l) == UInt64AsDouble(r);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+inline uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return UInt64AsFloat(l) != UInt64AsFloat(r);
+ case DBL_BITS: return UInt64AsDouble(l) != UInt64AsDouble(r);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+inline uint64_t lt(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return UInt64AsFloat(l) < UInt64AsFloat(r);
+ case DBL_BITS: return UInt64AsDouble(l) < UInt64AsDouble(r);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+inline uint64_t le(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return UInt64AsFloat(l) <= UInt64AsFloat(r);
+ case DBL_BITS: return UInt64AsDouble(l) <= UInt64AsDouble(r);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+inline uint64_t gt(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return UInt64AsFloat(l) > UInt64AsFloat(r);
+ case DBL_BITS: return UInt64AsDouble(l) > UInt64AsDouble(r);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+inline uint64_t ge(uint64_t l, uint64_t r, unsigned inWidth) {
+ switch( inWidth ) {
+ case FLT_BITS: return UInt64AsFloat(l) >= UInt64AsFloat(r);
+ case DBL_BITS: return UInt64AsDouble(l) >= UInt64AsDouble(r);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+
+// ********************************** //
+// *** LLVM Conversion Operations *** //
+// ********************************** //
+
+// truncation of l (which must be a double) to float (casts a double to a float)
+inline uint64_t trunc(uint64_t l, unsigned outWidth, unsigned inWidth) {
+ // FIXME: Investigate this, should this not happen? Was a quick
+ // patch for busybox.
+ if (inWidth==64 && outWidth==64) {
+ return l;
+ } else {
+ assert(inWidth==64 && "can only truncate from a 64-bit double");
+ assert(outWidth==32 && "can only truncate to a 32-bit float");
+ float trunc = (float)UInt64AsDouble(l);
+ return bits64::truncateToNBits(FloatAsUInt64(trunc), outWidth);
+ }
+}
+
+// extension of l (which must be a float) to double (casts a float to a double)
+inline uint64_t ext(uint64_t l, unsigned outWidth, unsigned inWidth) {
+ // FIXME: Investigate this, should this not happen? Was a quick
+ // patch for busybox.
+ if (inWidth==64 && outWidth==64) {
+ return l;
+ } else {
+ assert(inWidth==32 && "can only extend from a 32-bit float");
+ assert(outWidth==64 && "can only extend to a 64-bit double");
+ double ext = (double)UInt64AsFloat(l);
+ return bits64::truncateToNBits(DoubleAsUInt64(ext), outWidth);
+ }
+}
+
+// conversion of l to an unsigned integer, rounding towards zero
+inline uint64_t toUnsignedInt( uint64_t l, unsigned outWidth, unsigned inWidth ) {
+ switch( inWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits((uint64_t)UInt64AsFloat(l), outWidth );
+ case DBL_BITS: return bits64::truncateToNBits((uint64_t)UInt64AsDouble(l), outWidth );
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+// conversion of l to a signed integer, rounding towards zero
+inline uint64_t toSignedInt( uint64_t l, unsigned outWidth, unsigned inWidth ) {
+ switch( inWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits((int64_t)UInt64AsFloat(l), outWidth);
+ case DBL_BITS: return bits64::truncateToNBits((int64_t)UInt64AsDouble(l), outWidth);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+// conversion of l, interpreted as an unsigned int, to a floating point number
+inline uint64_t UnsignedIntToFP( uint64_t l, unsigned outWidth ) {
+ switch( outWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64((float)l), outWidth);
+ case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64((double)l), outWidth);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+// conversion of l, interpreted as a signed int, to a floating point number
+inline uint64_t SignedIntToFP( uint64_t l, unsigned outWidth, unsigned inWidth ) {
+ switch( outWidth ) {
+ case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64((float)(int64_t)ints::sext(l, 64, inWidth)), outWidth);
+ case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64((double)(int64_t)ints::sext(l,64, inWidth)), outWidth);
+ default: assert(0 && "invalid floating point width");
+ }
+}
+
+} // end namespace ints
+} // end namespace klee
+
+#endif //KLEE_UTIL_FLOATS_H
Added: klee/trunk/include/klee/Internal/Support/IntEvaluation.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Support/IntEvaluation.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Support/IntEvaluation.h (added)
+++ klee/trunk/include/klee/Internal/Support/IntEvaluation.h Wed May 20 23:36:41 2009
@@ -0,0 +1,164 @@
+//===-- IntEvaluation.h -----------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_UTIL_INTEVALUATION_H
+#define KLEE_UTIL_INTEVALUATION_H
+
+#include "klee/util/Bits.h"
+
+#define MAX_BITS (sizeof(uint64_t) * 8)
+
+// ASSUMPTION: invalid bits in each uint64_t are 0. the trade-off here is
+// between making trunc/zext/sext fast and making operations that depend
+// on the invalid bits being 0 fast.
+
+namespace klee {
+namespace ints {
+
+// add of l and r
+inline uint64_t add(uint64_t l, uint64_t r, unsigned inWidth) {
+ return bits64::truncateToNBits(l + r, inWidth);
+}
+
+// difference of l and r
+inline uint64_t sub(uint64_t l, uint64_t r, unsigned inWidth) {
+ return bits64::truncateToNBits(l - r, inWidth);
+}
+
+// product of l and r
+inline uint64_t mul(uint64_t l, uint64_t r, unsigned inWidth) {
+ return bits64::truncateToNBits(l * r, inWidth);
+}
+
+// truncation of l to outWidth bits
+inline uint64_t trunc(uint64_t l, unsigned outWidth, unsigned inWidth) {
+ return bits64::truncateToNBits(l, outWidth);
+}
+
+// zero-extension of l from inWidth to outWidth bits
+inline uint64_t zext(uint64_t l, unsigned outWidth, unsigned inWidth) {
+ return l;
+}
+
+// sign-extension of l from inWidth to outWidth bits
+inline uint64_t sext(uint64_t l, unsigned outWidth, unsigned inWidth) {
+ uint32_t numInvalidBits = MAX_BITS - inWidth;
+ return bits64::truncateToNBits(((int64_t)(l << numInvalidBits)) >> numInvalidBits, outWidth);
+}
+
+// unsigned divide of l by r
+inline uint64_t udiv(uint64_t l, uint64_t r, unsigned inWidth) {
+ return bits64::truncateToNBits(l / r, inWidth);
+}
+
+// unsigned mod of l by r
+inline uint64_t urem(uint64_t l, uint64_t r, unsigned inWidth) {
+ return bits64::truncateToNBits(l % r, inWidth);
+}
+
+// signed divide of l by r
+inline uint64_t sdiv(uint64_t l, uint64_t r, unsigned inWidth) {
+ // sign extend operands so that signed operation on 64-bits works correctly
+ int64_t sl = sext(l, MAX_BITS, inWidth);
+ int64_t sr = sext(r, MAX_BITS, inWidth);
+ return bits64::truncateToNBits(sl / sr, inWidth);
+}
+
+// signed mod of l by r
+inline uint64_t srem(uint64_t l, uint64_t r, unsigned inWidth) {
+ // sign extend operands so that signed operation on 64-bits works correctly
+ int64_t sl = sext(l, MAX_BITS, inWidth);
+ int64_t sr = sext(r, MAX_BITS, inWidth);
+ return bits64::truncateToNBits(sl % sr, inWidth);
+}
+
+// arithmetic shift right of l by r bits
+inline uint64_t ashr(uint64_t l, uint64_t shift, unsigned inWidth) {
+ int64_t sl = sext(l, MAX_BITS, inWidth);
+ return bits64::truncateToNBits(sl >> shift, inWidth);
+}
+
+// logical shift right of l by r bits
+inline uint64_t lshr(uint64_t l, uint64_t shift, unsigned inWidth) {
+ return l >> shift;
+}
+
+// shift left of l by r bits
+inline uint64_t shl(uint64_t l, uint64_t shift, unsigned inWidth) {
+ return bits64::truncateToNBits(l << shift, inWidth);
+}
+
+// logical AND of l and r
+inline uint64_t land(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l & r;
+}
+
+// logical OR of l and r
+inline uint64_t lor(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l | r;
+}
+
+// logical XOR of l and r
+inline uint64_t lxor(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l ^ r;
+}
+
+// comparison operations
+inline uint64_t eq(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l == r;
+}
+
+inline uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l != r;
+}
+
+inline uint64_t ult(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l < r;
+}
+
+inline uint64_t ule(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l <= r;
+}
+
+inline uint64_t ugt(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l > r;
+}
+
+inline uint64_t uge(uint64_t l, uint64_t r, unsigned inWidth) {
+ return l >= r;
+}
+
+inline uint64_t slt(uint64_t l, uint64_t r, unsigned inWidth) {
+ int64_t sl = sext(l, MAX_BITS, inWidth);
+ int64_t sr = sext(r, MAX_BITS, inWidth);
+ return sl < sr;
+}
+
+inline uint64_t sle(uint64_t l, uint64_t r, unsigned inWidth) {
+ int64_t sl = sext(l, MAX_BITS, inWidth);
+ int64_t sr = sext(r, MAX_BITS, inWidth);
+ return sl <= sr;
+}
+
+inline uint64_t sgt(uint64_t l, uint64_t r, unsigned inWidth) {
+ int64_t sl = sext(l, MAX_BITS, inWidth);
+ int64_t sr = sext(r, MAX_BITS, inWidth);
+ return sl > sr;
+}
+
+inline uint64_t sge(uint64_t l, uint64_t r, unsigned inWidth) {
+ int64_t sl = sext(l, MAX_BITS, inWidth);
+ int64_t sr = sext(r, MAX_BITS, inWidth);
+ return sl >= sr;
+}
+
+} // end namespace ints
+} // end namespace klee
+
+#endif
Added: klee/trunk/include/klee/Internal/Support/ModuleUtil.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Support/ModuleUtil.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Support/ModuleUtil.h (added)
+++ klee/trunk/include/klee/Internal/Support/ModuleUtil.h Wed May 20 23:36:41 2009
@@ -0,0 +1,40 @@
+//===-- ModuleUtil.h --------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_TRANSFORM_UTIL_H
+#define KLEE_TRANSFORM_UTIL_H
+
+#include <string>
+
+namespace llvm {
+ class Function;
+ class Instruction;
+ class Module;
+}
+
+namespace klee {
+
+ /// Link a module with a specified bitcode archive.
+ llvm::Module *linkWithLibrary(llvm::Module *module,
+ const std::string &libraryName);
+
+ /// Return the Function* target of a Call or Invoke instruction, or
+ /// null if it cannot be determined (should be only for indirect
+ /// calls, although complicated constant expressions might be
+ /// another possibility).
+ llvm::Function *getDirectCallTarget(const llvm::Instruction*);
+
+ /// Return true iff the given Function value is used in something
+ /// other than a direct call (or a constant expression that
+ /// terminates in a direct call).
+ bool functionEscapes(const llvm::Function *f);
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/Support/QueryLog.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Support/QueryLog.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Support/QueryLog.h (added)
+++ klee/trunk/include/klee/Internal/Support/QueryLog.h Wed May 20 23:36:41 2009
@@ -0,0 +1,63 @@
+//===-- QueryLog.h ----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_OPT_LOGGINGSOLVER_H
+#define KLEE_OPT_LOGGINGSOLVER_H
+
+#include "klee/Expr.h"
+
+#include <vector>
+
+namespace klee {
+ struct Query;
+
+ class QueryLogEntry {
+ public:
+ enum Type {
+ Validity,
+ Truth,
+ Value,
+ Cex
+ };
+
+ typedef std::vector< ref<Expr> > exprs_ty;
+ exprs_ty exprs;
+
+ Type type;
+ ref<Expr> query;
+ unsigned instruction;
+ std::vector<const Array*> objects;
+
+ public:
+ QueryLogEntry() : query(0,Expr::Bool) {}
+ QueryLogEntry(const QueryLogEntry &b);
+ QueryLogEntry(const Query &_query,
+ Type _type,
+ const std::vector<const Array*> *objects = 0);
+ };
+
+ class QueryLogResult {
+ public:
+ uint64_t result;
+ double time;
+
+ public:
+ QueryLogResult() {}
+ QueryLogResult(bool _success, uint64_t _result, double _time)
+ : result(_result), time(_time) {
+ if (!_success) { // la la la
+ result = 0;
+ time = -1;
+ }
+ }
+ };
+
+}
+
+#endif
Added: klee/trunk/include/klee/Internal/Support/Timer.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/Support/Timer.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/Support/Timer.h (added)
+++ klee/trunk/include/klee/Internal/Support/Timer.h Wed May 20 23:36:41 2009
@@ -0,0 +1,28 @@
+//===-- Timer.h -------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_TIMER_H
+#define KLEE_TIMER_H
+
+#include <stdint.h>
+
+namespace klee {
+ class WallTimer {
+ uint64_t startMicroseconds;
+
+ public:
+ WallTimer();
+
+ /// check - Return the delta since the timer was created, in microseconds.
+ uint64_t check();
+ };
+}
+
+#endif
+
Added: klee/trunk/include/klee/Internal/System/Time.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Internal/System/Time.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Internal/System/Time.h (added)
+++ klee/trunk/include/klee/Internal/System/Time.h Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+//===-- Time.h --------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_UTIL_TIME_H
+#define KLEE_UTIL_TIME_H
+
+namespace klee {
+ namespace util {
+ double getUserTime();
+ double getWallTime();
+ }
+}
+
+#endif
Added: klee/trunk/include/klee/Interpreter.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Interpreter.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Interpreter.h (added)
+++ klee/trunk/include/klee/Interpreter.h Wed May 20 23:36:41 2009
@@ -0,0 +1,149 @@
+//===-- Interpreter.h - Abstract Execution Engine Interface -----*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_INTERPRETER_H
+#define KLEE_INTERPRETER_H
+
+#include <vector>
+#include <string>
+#include <map>
+#include <set>
+
+struct BOut;
+
+namespace llvm {
+class Function;
+class Module;
+}
+
+namespace klee {
+class ExecutionState;
+class Interpreter;
+class TreeStreamWriter;
+
+class InterpreterHandler {
+public:
+ InterpreterHandler() {}
+ virtual ~InterpreterHandler() {};
+
+ virtual std::ostream &getInfoStream() const = 0;
+
+ virtual std::string getOutputFilename(const std::string &filename) = 0;
+ virtual std::ostream *openOutputFile(const std::string &filename) = 0;
+
+ virtual void incPathsExplored() = 0;
+
+ virtual void processTestCase(const ExecutionState &state,
+ const char *err,
+ const char *suffix) = 0;
+};
+
+class Interpreter {
+public:
+ /// ModuleOptions - Module level options which can be set when
+ /// registering a module with the interpreter.
+ struct ModuleOptions {
+ std::string LibraryDir;
+ bool Optimize;
+ bool CheckDivZero;
+
+ ModuleOptions(const std::string& _LibraryDir,
+ bool _Optimize, bool _CheckDivZero)
+ : LibraryDir(_LibraryDir), Optimize(_Optimize),
+ CheckDivZero(_CheckDivZero) {}
+ };
+
+ /// InterpreterOptions - Options varying the runtime behavior during
+ /// interpretation.
+ struct InterpreterOptions {
+ /// A frequency at which to make concrete reads return constrained
+ /// symbolic values. This is used to test the correctness of the
+ /// symbolic execution on concrete programs.
+ unsigned MakeConcreteSymbolic;
+
+ InterpreterOptions()
+ : MakeConcreteSymbolic(false)
+ {}
+ };
+
+protected:
+ const InterpreterOptions interpreterOpts;
+
+ Interpreter(const InterpreterOptions &_interpreterOpts)
+ : interpreterOpts(_interpreterOpts)
+ {};
+
+public:
+ virtual ~Interpreter() {};
+
+ static Interpreter *create(const InterpreterOptions &_interpreterOpts,
+ InterpreterHandler *ih);
+
+ /// Register the module to be executed.
+ ///
+ /// \return The final module after it has been optimized, checks
+ /// inserted, and modified for interpretation.
+ virtual const llvm::Module *
+ setModule(llvm::Module *module,
+ const ModuleOptions &opts) = 0;
+
+ // supply a tree stream writer which the interpreter will use
+ // to record the concrete path (as a stream of '0' and '1' bytes).
+ virtual void setPathWriter(TreeStreamWriter *tsw) = 0;
+
+ // supply a tree stream writer which the interpreter will use
+ // to record the symbolic path (as a stream of '0' and '1' bytes).
+ virtual void setSymbolicPathWriter(TreeStreamWriter *tsw) = 0;
+
+ // supply a test case to replay from. this can be used to drive the
+ // interpretation down a user specified path. use null to reset.
+ virtual void setReplayOut(const struct BOut *out) = 0;
+
+ // supply a list of branch decisions specifying which direction to
+ // take on forks. this can be used to drive the interpretation down
+ // a user specified path. use null to reset.
+ virtual void setReplayPath(const std::vector<bool> *path) = 0;
+
+ // supply a set of symbolic bindings that will be used as "seeds"
+ // for the search. use null to reset.
+ virtual void useSeeds(const std::vector<struct BOut *> *seeds) = 0;
+
+ virtual void runFunctionAsMain(llvm::Function *f,
+ int argc,
+ char **argv,
+ char **envp) = 0;
+
+ /*** Runtime options ***/
+
+ virtual void setHaltExecution(bool value) = 0;
+
+ virtual void setInhibitForking(bool value) = 0;
+
+ /*** State accessor methods ***/
+
+ virtual unsigned getPathStreamID(const ExecutionState &state) = 0;
+
+ virtual unsigned getSymbolicPathStreamID(const ExecutionState &state) = 0;
+
+ virtual void getConstraintLog(const ExecutionState &state,
+ std::string &res,
+ bool asCVC = false) = 0;
+
+ virtual bool getSymbolicSolution(const ExecutionState &state,
+ std::vector<
+ std::pair<std::string,
+ std::vector<unsigned char> > >
+ &res) = 0;
+
+ virtual void getCoveredLines(const ExecutionState &state,
+ std::map<const std::string*, std::set<unsigned> > &res) = 0;
+};
+
+} // End klee namespace
+
+#endif
Added: klee/trunk/include/klee/Machine.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Machine.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Machine.h (added)
+++ klee/trunk/include/klee/Machine.h Wed May 20 23:36:41 2009
@@ -0,0 +1,28 @@
+//===-- Machine.h -----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __KLEE_MACHINE_H__
+#define __KLEE_MACHINE_H__
+
+#include "klee/Expr.h"
+
+namespace klee {
+ namespace machine {
+ enum ByteOrder {
+ LSB = 0,
+ MSB = 1
+ };
+ }
+}
+
+#define kMachineByteOrder klee::machine::LSB
+#define kMachinePointerType Expr::Int32
+#define kMachinePointerSize 4
+
+#endif /* __KLEE_MACHINE_H__ */
Added: klee/trunk/include/klee/Solver.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Solver.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Solver.h (added)
+++ klee/trunk/include/klee/Solver.h Wed May 20 23:36:41 2009
@@ -0,0 +1,216 @@
+//===-- Solver.h ------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_SOLVER_H
+#define KLEE_SOLVER_H
+
+#include "klee/Expr.h"
+
+#include <vector>
+
+namespace klee {
+ class ConstraintManager;
+ class Expr;
+ class SolverImpl;
+
+ struct Query {
+ public:
+ const ConstraintManager &constraints;
+ ref<Expr> expr;
+
+ Query(const ConstraintManager& _constraints, ref<Expr> _expr)
+ : constraints(_constraints), expr(_expr) {
+ }
+
+ /// withExpr - Return a copy of the query with the given expression.
+ Query withExpr(ref<Expr> _expr) const {
+ return Query(constraints, _expr);
+ }
+
+ /// withFalse - Return a copy of the query with a false expression.
+ Query withFalse() const {
+ return Query(constraints, ref<Expr>(0, Expr::Bool));
+ }
+
+ /// negateExpr - Return a copy of the query with the expression negated.
+ Query negateExpr() const {
+ return withExpr(Expr::createNot(expr));
+ }
+ };
+
+ class Solver {
+ // DO NOT IMPLEMENT.
+ Solver(const Solver&);
+ void operator=(const Solver&);
+
+ public:
+ enum Validity {
+ True = 1,
+ False = -1,
+ Unknown = 0
+ };
+
+ public:
+ /// validity_to_str - Return the name of given Validity enum value.
+ static const char *validity_to_str(Validity v);
+
+ public:
+ SolverImpl *impl;
+
+ public:
+ Solver(SolverImpl *_impl) : impl(_impl) {};
+ ~Solver();
+
+ /// evaluate - Determine the full validity of an expression in particular
+ /// state.
+ ////
+ /// \param [out] result - The validity of the given expression (provably
+ /// true, provably false, or neither).
+ ///
+ /// \return True on success.
+ bool evaluate(const Query&, Validity &result);
+
+ /// mustBeTrue - Determine if the expression is provably true.
+ ///
+ /// \param [out] result - On success, true iff the expresssion is provably
+ /// false.
+ ///
+ /// \return True on success.
+ bool mustBeTrue(const Query&, bool &result);
+
+ /// mustBeFalse - Determine if the expression is provably false.
+ ///
+ /// \param [out] result - On success, true iff the expresssion is provably
+ /// false.
+ ///
+ /// \return True on success.
+ bool mustBeFalse(const Query&, bool &result);
+
+ /// mayBeTrue - Determine if there is a valid assignment for the given state
+ /// in which the expression evaluates to false.
+ ///
+ /// \param [out] result - On success, true iff the expresssion is true for
+ /// some satisfying assignment.
+ ///
+ /// \return True on success.
+ bool mayBeTrue(const Query&, bool &result);
+
+ /// mayBeFalse - Determine if there is a valid assignment for the given
+ /// state in which the expression evaluates to false.
+ ///
+ /// \param [out] result - On success, true iff the expresssion is false for
+ /// some satisfying assignment.
+ ///
+ /// \return True on success.
+ bool mayBeFalse(const Query&, bool &result);
+
+ /// getValue - Compute one possible value for the given expression.
+ ///
+ /// \param [out] result - On success, a value for the expression in some
+ /// satisying assignment.
+ ///
+ /// \return True on success.
+ bool getValue(const Query&, ref<Expr> &result);
+
+ /// getInitialValues - Compute the initial values for a list of objects.
+ ///
+ /// \param [out] result - On success, this vector will be filled in with an
+ /// array of bytes for each given object (with length matching the object
+ /// size). The bytes correspond to the initial values for the objects for
+ /// some satisying assignment.
+ ///
+ /// \return True on success.
+ ///
+ /// NOTE: This function returns failure if there is no satisfying
+ /// assignment.
+ //
+ // FIXME: This API is lame. We should probably just provide an API which
+ // returns an Assignment object, then clients can get out whatever values
+ // they want. This also allows us to optimize the representation.
+ bool getInitialValues(const Query&,
+ const std::vector<const Array*> &objects,
+ std::vector< std::vector<unsigned char> > &result);
+
+ /// getRange - Compute a tight range of possible values for a given
+ /// expression.
+ ///
+ /// \return - A pair with (min, max) values for the expression.
+ ///
+ /// \post(mustBeTrue(min <= e <= max) &&
+ /// mayBeTrue(min == e) &&
+ /// mayBeTrue(max == e))
+ //
+ // FIXME: This should go into a helper class, and should handle failure.
+ virtual std::pair< ref<Expr>, ref<Expr> > getRange(const Query&);
+ };
+
+ /// STPSolver - A complete solver based on STP.
+ class STPSolver : public Solver {
+ public:
+ /// STPSolver - Construct a new STPSolver.
+ ///
+ /// \param useForkedSTP - Whether STP should be run in a separate process
+ /// (required for using timeouts).
+ STPSolver(bool useForkedSTP);
+
+ /// getConstraintLog - Return the constraint log for the given state in CVC
+ /// format.
+ char *getConstraintLog(const Query&);
+
+ /// setTimeout - Set constraint solver timeout delay to the given value; 0
+ /// is off.
+ void setTimeout(double timeout);
+ };
+
+ /* *** */
+
+ /// createValidatingSolver - Create a solver which will validate all query
+ /// results against an oracle, used for testing that an optimized solver has
+ /// the same results as an unoptimized one. This solver will assert on any
+ /// mismatches.
+ ///
+ /// \param s - The primary underlying solver to use.
+ /// \param oracle - The solver to check query results against.
+ Solver *createValidatingSolver(Solver *s, Solver *oracle);
+
+ /// createCachingSolver - Create a solver which will cache the queries in
+ /// memory (without eviction).
+ ///
+ /// \param s - The underlying solver to use.
+ Solver *createCachingSolver(Solver *s);
+
+ /// createCexCachingSolver - Create a counterexample caching solver. This is a
+ /// more sophisticated cache which records counterexamples for a constraint
+ /// set and uses subset/superset relations among constraints to try and
+ /// quickly find satisfying assignments.
+ ///
+ /// \param s - The underlying solver to use.
+ Solver *createCexCachingSolver(Solver *s);
+
+ /// createFastCexSolver - Create a "fast counterexample solver", which tries
+ /// to quickly compute a satisfying assignment for a constraint set using
+ /// value propogation and range analysis.
+ ///
+ /// \param s - The underlying solver to use.
+ Solver *createFastCexSolver(Solver *s);
+
+ /// createIndependentSolver - Create a solver which will eliminate any
+ /// unnecessary constraints before propogating the query to the underlying
+ /// solver.
+ ///
+ /// \param s - The underlying solver to use.
+ Solver *createIndependentSolver(Solver *s);
+
+ /// createPCLoggingSolver - Create a solver which will forward all queries
+ /// after writing them to the given path in .pc format.
+ Solver *createPCLoggingSolver(Solver *s, std::string path);
+
+}
+
+#endif
Added: klee/trunk/include/klee/SolverImpl.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/SolverImpl.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/SolverImpl.h (added)
+++ klee/trunk/include/klee/SolverImpl.h Wed May 20 23:36:41 2009
@@ -0,0 +1,63 @@
+//===-- SolverImpl.h --------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_SOLVERIMPL_H
+#define KLEE_SOLVERIMPL_H
+
+#include <vector>
+
+namespace klee {
+ class Array;
+ class ExecutionState;
+ class Expr;
+ struct Query;
+
+ /// SolverImpl - Abstract base clase for solver implementations.
+ class SolverImpl {
+ // DO NOT IMPLEMENT.
+ SolverImpl(const SolverImpl&);
+ void operator=(const SolverImpl&);
+
+ public:
+ SolverImpl() {}
+ virtual ~SolverImpl();
+
+ /// computeValidity - Compute a full validity result for the
+ /// query.
+ ///
+ /// The query expression is guaranteed to be non-constant and have
+ /// bool type.
+ ///
+ /// SolverImpl provides a default implementation which uses
+ /// computeTruth. Clients should override this if a more efficient
+ /// implementation is available.
+ virtual bool computeValidity(const Query& query, Solver::Validity &result);
+
+ /// computeTruth - Determine whether the given query is provable.
+ ///
+ /// The query expression is guaranteed to be non-constant and have
+ /// bool type.
+ virtual bool computeTruth(const Query& query, bool &isValid) = 0;
+
+ /// computeValue - Compute a feasible value for the expression.
+ ///
+ /// The query expression is guaranteed to be non-constant.
+ virtual bool computeValue(const Query& query, ref<Expr> &result) = 0;
+
+ virtual bool computeInitialValues(const Query& query,
+ const std::vector<const Array*>
+ &objects,
+ std::vector< std::vector<unsigned char> >
+ &values,
+ bool &hasSolution) = 0;
+};
+
+}
+
+#endif
Added: klee/trunk/include/klee/Statistic.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Statistic.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Statistic.h (added)
+++ klee/trunk/include/klee/Statistic.h Wed May 20 23:36:41 2009
@@ -0,0 +1,65 @@
+//===-- Statistic.h ---------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_STATISTIC_H
+#define KLEE_STATISTIC_H
+
+#include <string>
+
+namespace klee {
+ class Statistic;
+ class StatisticManager;
+ class StatisticRecord;
+
+ /// Statistic - A named statistic instance.
+ ///
+ /// The Statistic class holds information about the statistic, but
+ /// not the actual values. Values are managed by the global
+ /// StatisticManager to enable transparent support for instruction
+ /// level and call path level statistics.
+ class Statistic {
+ friend class StatisticManager;
+ friend class StatisticRecord;
+
+ private:
+ unsigned id;
+ const std::string name;
+ const std::string shortName;
+
+ public:
+ Statistic(const std::string &_name,
+ const std::string &_shortName);
+ ~Statistic();
+
+ /// getID - Get the unique statistic ID.
+ unsigned getID() { return id; }
+
+ /// getName - Get the statistic name.
+ const std::string &getName() const { return name; }
+
+ /// getShortName - Get the "short" statistic name, used in
+ /// callgrind output for example.
+ const std::string &getShortName() const { return shortName; }
+
+ /// getValue - Get the current primary statistic value.
+ uint64_t getValue() const;
+
+ /// operator uint64_t - Get the current primary statistic value.
+ operator uint64_t () const { return getValue(); }
+
+ /// operator++ - Increment the statistic by 1.
+ Statistic &operator ++() { return (*this += 1); }
+
+ /// operator+= - Increment the statistic by \arg addend.
+ Statistic &operator +=(const uint64_t addend);
+ };
+}
+
+#endif
+
Added: klee/trunk/include/klee/Statistics.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/Statistics.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/Statistics.h (added)
+++ klee/trunk/include/klee/Statistics.h Wed May 20 23:36:41 2009
@@ -0,0 +1,154 @@
+//===-- Statistics.h --------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_STATISTICS_H
+#define KLEE_STATISTICS_H
+
+#include "Statistic.h"
+
+#include <vector>
+#include <string>
+#include <string.h>
+
+namespace klee {
+ class Statistic;
+ class StatisticRecord {
+ friend class StatisticManager;
+
+ private:
+ uint64_t *data;
+
+ public:
+ StatisticRecord();
+ StatisticRecord(const StatisticRecord &s);
+ ~StatisticRecord() { delete[] data; }
+
+ void zero();
+
+ uint64_t getValue(const Statistic &s) const;
+ void incrementValue(const Statistic &s, uint64_t addend) const;
+ StatisticRecord &operator =(const StatisticRecord &s);
+ StatisticRecord &operator +=(const StatisticRecord &sr);
+ };
+
+ class StatisticManager {
+ private:
+ bool enabled;
+ std::vector<Statistic*> stats;
+ uint64_t *globalStats;
+ uint64_t *indexedStats;
+ StatisticRecord *contextStats;
+ unsigned index;
+
+ public:
+ StatisticManager();
+ ~StatisticManager();
+
+ void useIndexedStats(unsigned totalIndices);
+
+ StatisticRecord *getContext();
+ void setContext(StatisticRecord *sr); /* null to reset */
+
+ void setIndex(unsigned i) { index = i; }
+ unsigned getIndex() { return index; }
+ unsigned getNumStatistics() { return stats.size(); }
+ Statistic &getStatistic(unsigned i) { return *stats[i]; }
+
+ void registerStatistic(Statistic &s);
+ void incrementStatistic(Statistic &s, uint64_t addend);
+ uint64_t getValue(const Statistic &s) const;
+ void incrementIndexedValue(const Statistic &s, unsigned index,
+ uint64_t addend) const;
+ uint64_t getIndexedValue(const Statistic &s, unsigned index) const;
+ void setIndexedValue(const Statistic &s, unsigned index, uint64_t value);
+ int getStatisticID(const std::string &name) const;
+ Statistic *getStatisticByName(const std::string &name) const;
+ };
+
+ extern StatisticManager *theStatisticManager;
+
+ inline void StatisticManager::incrementStatistic(Statistic &s,
+ uint64_t addend) {
+ if (enabled) {
+ globalStats[s.id] += addend;
+ if (indexedStats) {
+ indexedStats[index*stats.size() + s.id] += addend;
+ if (contextStats)
+ contextStats->data[s.id] += addend;
+ }
+ }
+ }
+
+ inline StatisticRecord *StatisticManager::getContext() {
+ return contextStats;
+ }
+ inline void StatisticManager::setContext(StatisticRecord *sr) {
+ contextStats = sr;
+ }
+
+ inline void StatisticRecord::zero() {
+ ::memset(data, 0, sizeof(*data)*theStatisticManager->getNumStatistics());
+ }
+
+ inline StatisticRecord::StatisticRecord()
+ : data(new uint64_t[theStatisticManager->getNumStatistics()]) {
+ zero();
+ }
+
+ inline StatisticRecord::StatisticRecord(const StatisticRecord &s)
+ : data(new uint64_t[theStatisticManager->getNumStatistics()]) {
+ ::memcpy(data, s.data,
+ sizeof(*data)*theStatisticManager->getNumStatistics());
+ }
+
+ inline StatisticRecord &StatisticRecord::operator=(const StatisticRecord &s) {
+ ::memcpy(data, s.data,
+ sizeof(*data)*theStatisticManager->getNumStatistics());
+ return *this;
+ }
+
+ inline void StatisticRecord::incrementValue(const Statistic &s,
+ uint64_t addend) const {
+ data[s.id] += addend;
+ }
+ inline uint64_t StatisticRecord::getValue(const Statistic &s) const {
+ return data[s.id];
+ }
+
+ inline StatisticRecord &
+ StatisticRecord::operator +=(const StatisticRecord &sr) {
+ unsigned nStats = theStatisticManager->getNumStatistics();
+ for (unsigned i=0; i<nStats; i++)
+ data[i] += sr.data[i];
+ return *this;
+ }
+
+ inline uint64_t StatisticManager::getValue(const Statistic &s) const {
+ return globalStats[s.id];
+ }
+
+ inline void StatisticManager::incrementIndexedValue(const Statistic &s,
+ unsigned index,
+ uint64_t addend) const {
+ indexedStats[index*stats.size() + s.id] += addend;
+ }
+
+ inline uint64_t StatisticManager::getIndexedValue(const Statistic &s,
+ unsigned index) const {
+ return indexedStats[index*stats.size() + s.id];
+ }
+
+ inline void StatisticManager::setIndexedValue(const Statistic &s,
+ unsigned index,
+ uint64_t value) {
+ indexedStats[index*stats.size() + s.id] = value;
+ }
+}
+
+#endif
Added: klee/trunk/include/klee/TimerStatIncrementer.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/TimerStatIncrementer.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/TimerStatIncrementer.h (added)
+++ klee/trunk/include/klee/TimerStatIncrementer.h Wed May 20 23:36:41 2009
@@ -0,0 +1,32 @@
+//===-- TimerStatIncrementer.h ----------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_TIMERSTATINCREMENTER_H
+#define KLEE_TIMERSTATINCREMENTER_H
+
+#include "klee/Statistics.h"
+#include "klee/Internal/Support/Timer.h"
+
+namespace klee {
+ class TimerStatIncrementer {
+ private:
+ WallTimer timer;
+ Statistic &statistic;
+
+ public:
+ TimerStatIncrementer(Statistic &_statistic) : statistic(_statistic) {}
+ ~TimerStatIncrementer() {
+ statistic += timer.check();
+ };
+
+ uint64_t check() { return timer.check(); }
+ };
+}
+
+#endif
Added: klee/trunk/include/klee/klee.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/klee.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/klee.h (added)
+++ klee/trunk/include/klee/klee.h Wed May 20 23:36:41 2009
@@ -0,0 +1,120 @@
+//===-- klee.h --------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __KLEE_H__
+#define __KLEE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Add an accesible memory object at a user specified location. It
+ is the users responsibility to make sure that these memory
+ objects do not overlap. These memory objects will also
+ (obviously) not correctly interact with external function
+ calls. */
+ void klee_define_fixed_object(void *addr, unsigned nbytes);
+
+ /* make the contents of the object pointed to by addr symbolic. addr
+ * should always be the start of the object and nbytes must be its
+ * entire size. name is an optional name (can be the empty string)
+ */
+ void klee_make_symbolic_name(void *addr, unsigned nbytes,
+ const char *name);
+
+ void klee_make_symbolic(void *addr, unsigned nbytes);
+
+ /* Return symbolic value in the (signed) interval [begin,end) */
+ int klee_range(int begin, int end, const char *name);
+
+ /* Return a symbolic integer */
+ int klee_int(const char *name);
+
+ void *klee_malloc_n(unsigned nelems, unsigned size, unsigned alignment);
+
+ /* terminate the state without generating a test file */
+ __attribute__((noreturn))
+ void klee_silent_exit(int status);
+
+ __attribute__((noreturn))
+ void klee_abort(void);
+
+ /** Report an error and terminate the state. */
+ __attribute__((noreturn))
+ void klee_report_error(const char *file,
+ int line,
+ const char *message,
+ const char *suffix);
+
+ /* called by checking code to get size of memory. */
+ unsigned klee_get_obj_size(void *ptr);
+
+ /* print the tree associated w/ a given expression. */
+ void klee_print_expr(const char *msg, ...);
+
+ /* NB: this *does not* fork n times and return [0,n) in children.
+ * It makes n be symbolic and returns: caller must compare N times.
+ */
+ unsigned klee_choose(unsigned n);
+
+ /* special klee assert macro. this assert should be used when path consistency
+ * across platforms is desired (e.g., in tests).
+ * NB: __assert_fail is a klee "special" function
+ */
+# define klee_assert(expr) \
+ ((expr) \
+ ? (void) (0) \
+ : __assert_fail (#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__)) \
+
+ /* Return true if the given value is symbolic (represented by an
+ * expression) in the current state. This is primarily for debugging
+ * and writing tests but can also be used to enable prints in replay
+ * mode.
+ */
+ unsigned klee_is_symbolic(unsigned n);
+
+
+ /* The following intrinsics are primarily intended for internal use
+ and may have peculiar semantics. */
+
+ void klee_assume(unsigned condition);
+ void klee_warning(const char *message);
+ void klee_warning_once(const char *message);
+ void klee_prefer_cex(void *object, unsigned condition);
+ void klee_mark_global(void *object);
+
+ /* Return a possible constant value for the input expression. This
+ allows programs to forcibly concretize values on their own. */
+ unsigned klee_get_value(unsigned expr);
+
+ /* Ensure that memory in the range [address, address+size) is
+ accessible to the program. If some byte in the range is not
+ accessible an error will be generated and the state
+ terminated.
+
+ The current implementation requires both address and size to be
+ constants and that the range lie within a single object. */
+ void klee_check_memory_access(const void *address, unsigned size);
+
+ /* Enable/disable forking. */
+ void klee_set_forking(unsigned enable);
+
+ /* klee_alias_function("foo", "bar") will replace, at runtime (on
+ the current path and all paths spawned on the current path), all
+ calls to foo() by calls to bar(). foo() and bar() have to exist
+ and have identical types. Use klee_alias_function("foo", "foo")
+ to undo. Be aware that some special functions, such as exit(),
+ may not always work. */
+ void klee_alias_function(const char* fn_name, const char* new_fn_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __KLEE_H__ */
Added: klee/trunk/include/klee/util/Assignment.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/Assignment.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/Assignment.h (added)
+++ klee/trunk/include/klee/util/Assignment.h Wed May 20 23:36:41 2009
@@ -0,0 +1,100 @@
+//===-- Assignment.h --------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_UTIL_ASSIGNMENT_H
+#define KLEE_UTIL_ASSIGNMENT_H
+
+#include <map>
+
+#include "klee/util/ExprEvaluator.h"
+
+// FIXME: Rename?
+
+namespace klee {
+ class Array;
+
+ class Assignment {
+ public:
+ typedef std::map<const Array*, std::vector<unsigned char> > bindings_ty;
+
+ bool allowFreeValues;
+ bindings_ty bindings;
+
+ public:
+ Assignment(bool _allowFreeValues=false)
+ : allowFreeValues(_allowFreeValues) {}
+ Assignment(std::vector<const Array*> &objects,
+ std::vector< std::vector<unsigned char> > &values,
+ bool _allowFreeValues=false)
+ : allowFreeValues(_allowFreeValues){
+ std::vector< std::vector<unsigned char> >::iterator valIt =
+ values.begin();
+ for (std::vector<const Array*>::iterator it = objects.begin(),
+ ie = objects.end(); it != ie; ++it) {
+ const Array *os = *it;
+ std::vector<unsigned char> &arr = *valIt;
+ bindings.insert(std::make_pair(os, arr));
+ ++valIt;
+ }
+ }
+
+ ref<Expr> evaluate(const Array *mo, unsigned index) const;
+ ref<Expr> evaluate(ref<Expr> e);
+
+ template<typename InputIterator>
+ bool satisfies(InputIterator begin, InputIterator end);
+ };
+
+ class AssignmentEvaluator : public ExprEvaluator {
+ const Assignment &a;
+
+ protected:
+ ref<Expr> getInitialValue(const Array &mo, unsigned index) {
+ return a.evaluate(&mo, index);
+ }
+
+ public:
+ AssignmentEvaluator(const Assignment &_a) : a(_a) {}
+ };
+
+ /***/
+
+ inline ref<Expr> Assignment::evaluate(const Array *array,
+ unsigned index) const {
+ bindings_ty::const_iterator it = bindings.find(array);
+ if (it!=bindings.end() && index<it->second.size()) {
+ return ref<Expr>(it->second[index], Expr::Int8);
+ } else {
+ if (allowFreeValues) {
+ return ReadExpr::create(UpdateList(array, true, 0),
+ ref<Expr>(index, Expr::Int32));
+ } else {
+ return ref<Expr>(0, Expr::Int8);
+ }
+ }
+ }
+
+ inline ref<Expr> Assignment::evaluate(ref<Expr> e) {
+ AssignmentEvaluator v(*this);
+ return v.visit(e);
+ }
+
+ template<typename InputIterator>
+ inline bool Assignment::satisfies(InputIterator begin, InputIterator end) {
+ AssignmentEvaluator v(*this);
+ for (; begin!=end; ++begin) {
+ ref<Expr> res = v.visit(*begin);
+ if (!res.isConstant() || !res.getConstantValue())
+ return false;
+ }
+ return true;
+ }
+}
+
+#endif
Added: klee/trunk/include/klee/util/BitArray.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/BitArray.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/BitArray.h (added)
+++ klee/trunk/include/klee/util/BitArray.h Wed May 20 23:36:41 2009
@@ -0,0 +1,42 @@
+//===-- BitArray.h ----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_UTIL_BITARRAY_H
+#define KLEE_UTIL_BITARRAY_H
+
+namespace klee {
+
+ // XXX would be nice not to have
+ // two allocations here for allocated
+ // BitArrays
+class BitArray {
+private:
+ uint32_t *bits;
+
+protected:
+ static uint32_t length(unsigned size) { return (size+31)/32; }
+
+public:
+ BitArray(unsigned size, bool value = false) : bits(new uint32_t[length(size)]) {
+ memset(bits, value?0xFF:0, sizeof(*bits)*length(size));
+ }
+ BitArray(const BitArray &b, unsigned size) : bits(new uint32_t[length(size)]) {
+ memcpy(bits, b.bits, sizeof(*bits)*length(size));
+ }
+ ~BitArray() { delete[] bits; }
+
+ bool get(unsigned idx) { return (bool) ((bits[idx/32]>>(idx&0x1F))&1); }
+ void set(unsigned idx) { bits[idx/32] |= 1<<(idx&0x1F); }
+ void unset(unsigned idx) { bits[idx/32] &= ~(1<<(idx&0x1F)); }
+ void set(unsigned idx, bool value) { if (value) set(idx); else unset(idx); }
+};
+
+} // End klee namespace
+
+#endif
Added: klee/trunk/include/klee/util/Bits.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/Bits.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/Bits.h (added)
+++ klee/trunk/include/klee/util/Bits.h Wed May 20 23:36:41 2009
@@ -0,0 +1,102 @@
+//===-- Bits.h --------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_UTIL_BITS_H
+#define KLEE_UTIL_BITS_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace klee {
+ namespace bits32 {
+ // @pre(0 <= N <= 32)
+ // @post(retval = max([truncateToNBits(i,N) for i in naturals()]))
+ inline unsigned maxValueOfNBits(unsigned N) {
+ if (N==0)
+ return 0;
+ return ((unsigned) -1) >> (32 - N);
+ }
+
+ // @pre(0 < N <= 32)
+ inline unsigned truncateToNBits(unsigned x, unsigned N) {
+ return x&(((unsigned) -1) >> (32 - N));
+ }
+
+ inline unsigned withoutRightmostBit(unsigned x) {
+ return x&(x-1);
+ }
+
+ inline unsigned isolateRightmostBit(unsigned x) {
+ return x&-x;
+ }
+
+ inline unsigned isPowerOfTwo(unsigned x) {
+ if (x==0) return 0;
+ return !(x&(x-1));
+ }
+
+ // @pre(withoutRightmostBit(x) == 0)
+ // @post((1 << retval) == x)
+ inline unsigned indexOfSingleBit(unsigned x) {
+ unsigned res = 0;
+ if (x&0xFFFF0000) res += 16;
+ if (x&0xFF00FF00) res += 8;
+ if (x&0xF0F0F0F0) res += 4;
+ if (x&0xCCCCCCCC) res += 2;
+ if (x&0xAAAAAAAA) res += 1;
+ return res;
+ }
+
+ inline unsigned indexOfRightmostBit(unsigned x) {
+ return indexOfSingleBit(isolateRightmostBit(x));
+ }
+ }
+
+ namespace bits64 {
+ // @pre(0 <= N <= 32)
+ // @post(retval = max([truncateToNBits(i,N) for i in naturals()]))
+ inline uint64_t maxValueOfNBits(unsigned N) {
+ if (N==0)
+ return 0;
+ return ((uint64_t) (int64_t) -1) >> (64 - N);
+ }
+
+ // @pre(0 < N <= 64)
+ inline uint64_t truncateToNBits(uint64_t x, unsigned N) {
+ return x&(((uint64_t) (int64_t) -1) >> (64 - N));
+ }
+
+ inline uint64_t withoutRightmostBit(uint64_t x) {
+ return x&(x-1);
+ }
+
+ inline uint64_t isolateRightmostBit(uint64_t x) {
+ return x&-x;
+ }
+
+ inline uint64_t isPowerOfTwo(uint64_t x) {
+ if (x==0) return 0;
+ return !(x&(x-1));
+ }
+
+ // @pre((x&(x-1)) == 0)
+ // @post((1 << retval) == x)
+ inline unsigned indexOfSingleBit(uint64_t x) {
+ unsigned res = bits32::indexOfSingleBit((unsigned) (x | (x>>32)));
+ if (x&((uint64_t) 0xFFFFFFFF << 32))
+ res += 32;
+ return res;
+ }
+
+ inline uint64_t indexOfRightmostBit(uint64_t x) {
+ return indexOfSingleBit(isolateRightmostBit(x));
+ }
+ }
+} // End klee namespace
+
+#endif
Added: klee/trunk/include/klee/util/ExprEvaluator.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/ExprEvaluator.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/ExprEvaluator.h (added)
+++ klee/trunk/include/klee/util/ExprEvaluator.h Wed May 20 23:36:41 2009
@@ -0,0 +1,39 @@
+//===-- ExprEvaluator.h -----------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPREVALUATOR_H
+#define KLEE_EXPREVALUATOR_H
+
+#include "klee/Expr.h"
+#include "klee/util/ExprVisitor.h"
+
+namespace klee {
+ class ExprEvaluator : public ExprVisitor {
+ protected:
+ Action evalRead(const UpdateList &ul, unsigned index);
+ Action visitRead(const ReadExpr &re);
+
+ Action protectedDivOperation(const BinaryExpr &e);
+ Action visitUDiv(const UDivExpr &e);
+ Action visitSDiv(const SDivExpr &e);
+ Action visitURem(const URemExpr &e);
+ Action visitSRem(const SRemExpr &e);
+
+ public:
+ ExprEvaluator() {}
+
+ // override to implement evaluation, this function is called to
+ // get the initial value for a symbolic byte. if the value is
+ // unknown then the user can simply return a ReadExpr at version 0
+ // of this MemoryObject.
+ virtual ref<Expr> getInitialValue(const Array& os, unsigned index) = 0;
+ };
+}
+
+#endif
Added: klee/trunk/include/klee/util/ExprHashMap.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/ExprHashMap.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/ExprHashMap.h (added)
+++ klee/trunk/include/klee/util/ExprHashMap.h Wed May 20 23:36:41 2009
@@ -0,0 +1,48 @@
+//===-- ExprHashMap.h -------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPRHASHMAP_H
+#define KLEE_EXPRHASHMAP_H
+
+#include "klee/Expr.h"
+#include <tr1/unordered_map>
+#include <tr1/unordered_set>
+
+namespace klee {
+
+ namespace util {
+ struct ExprHash {
+ unsigned operator()(const ref<Expr> e) const {
+ return e.hash();
+ }
+ };
+
+ struct ExprCmp {
+ bool operator()(const ref<Expr> &a, const ref<Expr> &b) const {
+ return a==b;
+ }
+ };
+ }
+
+ template<class T>
+ class ExprHashMap :
+
+ public std::tr1::unordered_map<ref<Expr>,
+ T,
+ klee::util::ExprHash,
+ klee::util::ExprCmp> {
+ };
+
+ typedef std::tr1::unordered_set<ref<Expr>,
+ klee::util::ExprHash,
+ klee::util::ExprCmp> ExprHashSet;
+
+}
+
+#endif
Added: klee/trunk/include/klee/util/ExprPPrinter.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/ExprPPrinter.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/ExprPPrinter.h (added)
+++ klee/trunk/include/klee/util/ExprPPrinter.h Wed May 20 23:36:41 2009
@@ -0,0 +1,58 @@
+//===-- ExprPPrinter.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPRPPRINTER_H
+#define KLEE_EXPRPPRINTER_H
+
+#include "klee/Expr.h"
+
+namespace klee {
+ class ConstraintManager;
+
+ class ExprPPrinter {
+ protected:
+ ExprPPrinter() {}
+
+ public:
+ static ExprPPrinter *create(std::ostream &os);
+
+ virtual ~ExprPPrinter() {}
+
+ virtual void setNewline(const std::string &newline) = 0;
+ virtual void reset() = 0;
+ virtual void scan(const ref<Expr> &e) = 0;
+ virtual void print(const ref<Expr> &e, unsigned indent=0) = 0;
+
+ // utility methods
+
+ template<class Container>
+ void scan(Container c) {
+ scan(c.begin(), c.end());
+ }
+
+ template<class InputIterator>
+ void scan(InputIterator it, InputIterator end) {
+ for (; it!=end; ++it)
+ scan(*it);
+ }
+
+ static void printOne(std::ostream &os, const char *message,
+ const ref<Expr> &e);
+
+ static void printConstraints(std::ostream &os,
+ const ConstraintManager &constraints);
+
+ static void printQuery(std::ostream &os,
+ const ConstraintManager &constraints,
+ const ref<Expr> &q);
+ };
+
+}
+
+#endif
Added: klee/trunk/include/klee/util/ExprRangeEvaluator.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/ExprRangeEvaluator.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/ExprRangeEvaluator.h (added)
+++ klee/trunk/include/klee/util/ExprRangeEvaluator.h Wed May 20 23:36:41 2009
@@ -0,0 +1,283 @@
+//===-- ExprRangeEvaluator.h ------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPRRANGEEVALUATOR_H
+#define KLEE_EXPRRANGEEVALUATOR_H
+
+#include "klee/Expr.h"
+#include "klee/util/Bits.h"
+
+namespace klee {
+
+/*
+class ValueType {
+public:
+ ValueType(); // empty range
+ ValueType(uint64_t value);
+ ValueType(uint64_t min, uint64_t max);
+
+ bool mustEqual(const uint64_t b);
+ bool mustEqual(const ValueType &b);
+ bool mayEqual(const uint64_t b);
+ bool mayEqual(const ValueType &b);
+
+ bool isFullRange(unsigned width);
+
+ ValueType set_union(ValueType &);
+ ValueType set_intersection(ValueType &);
+ ValueType set_difference(ValueType &);
+
+ ValueType binaryAnd(ValueType &);
+ ValueType binaryOr(ValueType &);
+ ValueType binaryXor(ValueType &);
+ ValueType concat(ValueType &, unsigned width);
+ ValueType add(ValueType &, unsigned width);
+ ValueType sub(ValueType &, unsigned width);
+ ValueType mul(ValueType &, unsigned width);
+ ValueType udiv(ValueType &, unsigned width);
+ ValueType sdiv(ValueType &, unsigned width);
+ ValueType urem(ValueType &, unsigned width);
+ ValueType srem(ValueType &, unsigned width);
+
+ uint64_t min();
+ uint64_t max();
+ int64_t minSigned(unsigned width);
+ int64_t maxSigned(unsigned width);
+}
+*/
+
+template<class T>
+class ExprRangeEvaluator {
+protected:
+ virtual T getInitialReadRange(const Array &os, T index) = 0;
+
+ T evalRead(const UpdateList &ul, T index);
+
+public:
+ ExprRangeEvaluator() {}
+ virtual ~ExprRangeEvaluator() {}
+
+ T evaluate(const ref<Expr> &e);
+};
+
+template<class T>
+T ExprRangeEvaluator<T>::evalRead(const UpdateList &ul,
+ T index) {
+ T res;
+
+ for (const UpdateNode *un=ul.head; un; un=un->next) {
+ T ui = evaluate(un->index);
+
+ if (ui.mustEqual(index)) {
+ return res.set_union(evaluate(un->value));
+ } else if (ui.mayEqual(index)) {
+ res = res.set_union(evaluate(un->value));
+ if (res.isFullRange(8)) {
+ return res;
+ }
+ }
+ }
+
+ return res.set_union(getInitialReadRange(*ul.root, index));
+}
+
+template<class T>
+T ExprRangeEvaluator<T>::evaluate(const ref<Expr> &e) {
+ switch (e.getKind()) {
+ case Expr::Constant:
+ return T(e.getConstantValue());
+
+ case Expr::NotOptimized:
+ break;
+
+ case Expr::Read: {
+ const ReadExpr *re = static_ref_cast<const ReadExpr>(e);
+ T index = evaluate(re->index);
+
+ assert(re->getWidth()==Expr::Int8 && "unexpected multibyte read");
+
+ return evalRead(re->updates, index);
+ }
+
+ case Expr::Select: {
+ const SelectExpr *se = static_ref_cast<const SelectExpr>(e);
+ T cond = evaluate(se->cond);
+
+ if (cond.mustEqual(1)) {
+ return evaluate(se->trueExpr);
+ } else if (cond.mustEqual(0)) {
+ return evaluate(se->falseExpr);
+ } else {
+ return evaluate(se->trueExpr).set_union(evaluate(se->falseExpr));
+ }
+ }
+
+ // XXX these should be unrolled to ensure nice inline
+ case Expr::Concat: {
+ const Expr *ep = e.get();
+ T res(0);
+ for (unsigned i=0; i<ep->getNumKids(); i++)
+ res = res.concat(evaluate(ep->getKid(i)),8);
+ return res;
+ }
+
+ // Arithmetic
+
+ case Expr::Add: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ unsigned width = be->left.getWidth();
+ return evaluate(be->left).add(evaluate(be->right), width);
+ }
+ case Expr::Sub: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ unsigned width = be->left.getWidth();
+ return evaluate(be->left).sub(evaluate(be->right), width);
+ }
+ case Expr::Mul: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ unsigned width = be->left.getWidth();
+ return evaluate(be->left).mul(evaluate(be->right), width);
+ }
+ case Expr::UDiv: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ unsigned width = be->left.getWidth();
+ return evaluate(be->left).udiv(evaluate(be->right), width);
+ }
+ case Expr::SDiv: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ unsigned width = be->left.getWidth();
+ return evaluate(be->left).sdiv(evaluate(be->right), width);
+ }
+ case Expr::URem: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ unsigned width = be->left.getWidth();
+ return evaluate(be->left).urem(evaluate(be->right), width);
+ }
+ case Expr::SRem: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ unsigned width = be->left.getWidth();
+ return evaluate(be->left).srem(evaluate(be->right), width);
+ }
+
+ // Binary
+
+ case Expr::And: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ return evaluate(be->left).binaryAnd(evaluate(be->right));
+ }
+ case Expr::Or: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ return evaluate(be->left).binaryOr(evaluate(be->right));
+ }
+ case Expr::Xor: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ return evaluate(be->left).binaryXor(evaluate(be->right));
+ }
+ case Expr::Shl: {
+ // BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ // unsigned width = be->left.getWidth();
+ // return evaluate(be->left).shl(evaluate(be->right), width);
+ break;
+ }
+ case Expr::LShr: {
+ // BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ // unsigned width = be->left.getWidth();
+ // return evaluate(be->left).lshr(evaluate(be->right), width);
+ break;
+ }
+ case Expr::AShr: {
+ // BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ // unsigned width = be->left.getWidth();
+ // return evaluate(be->left).ashr(evaluate(be->right), width);
+ break;
+ }
+
+ // Comparison
+
+ case Expr::Eq: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ T left = evaluate(be->left);
+ T right = evaluate(be->right);
+
+ if (left.mustEqual(right)) {
+ return T(1);
+ } else if (!left.mayEqual(right)) {
+ return T(0);
+ }
+ break;
+ }
+
+ case Expr::Ult: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ T left = evaluate(be->left);
+ T right = evaluate(be->right);
+
+ if (left.max() < right.min()) {
+ return T(1);
+ } else if (left.min() >= right.max()) {
+ return T(0);
+ }
+ break;
+ }
+ case Expr::Ule: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ T left = evaluate(be->left);
+ T right = evaluate(be->right);
+
+ if (left.max() <= right.min()) {
+ return T(1);
+ } else if (left.min() > right.max()) {
+ return T(0);
+ }
+ break;
+ }
+ case Expr::Slt: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ T left = evaluate(be->left);
+ T right = evaluate(be->right);
+ unsigned bits = be->left.getWidth();
+
+ if (left.maxSigned(bits) < right.minSigned(bits)) {
+ return T(1);
+ } else if (left.minSigned(bits) >= right.maxSigned(bits)) {
+ return T(0);
+ }
+ break;
+ }
+ case Expr::Sle: {
+ const BinaryExpr *be = static_ref_cast<const BinaryExpr>(e);
+ T left = evaluate(be->left);
+ T right = evaluate(be->right);
+ unsigned bits = be->left.getWidth();
+
+ if (left.maxSigned(bits) <= right.minSigned(bits)) {
+ return T(1);
+ } else if (left.minSigned(bits) > right.maxSigned(bits)) {
+ return T(0);
+ }
+ break;
+ }
+
+ case Expr::Ne:
+ case Expr::Ugt:
+ case Expr::Uge:
+ case Expr::Sgt:
+ case Expr::Sge:
+ assert(0 && "invalid expressions (uncanonicalized)");
+
+ default:
+ break;
+ }
+
+ return T(0, bits64::maxValueOfNBits(e.getWidth()));
+}
+
+}
+
+#endif
Added: klee/trunk/include/klee/util/ExprUtil.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/ExprUtil.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/ExprUtil.h (added)
+++ klee/trunk/include/klee/util/ExprUtil.h Wed May 20 23:36:41 2009
@@ -0,0 +1,43 @@
+//===-- ExprUtil.h ----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPRUTIL_H
+#define KLEE_EXPRUTIL_H
+
+#include <vector>
+
+namespace klee {
+ class Array;
+ class Expr;
+ class ReadExpr;
+ template<typename T> class ref;
+
+ /// Find all ReadExprs used in the expression DAG. If visitUpdates
+ /// is true then this will including those reachable by traversing
+ /// update lists. Note that this may be slow and return a large
+ /// number of results.
+ void findReads(ref<Expr> e,
+ bool visitUpdates,
+ std::vector< ref<ReadExpr> > &result);
+
+ /// Return a list of all unique symbolic objects referenced by the given
+ /// expression.
+ void findSymbolicObjects(ref<Expr> e,
+ std::vector<const Array*> &results);
+
+ /// Return a list of all unique symbolic objects referenced by the
+ /// given expression range.
+ template<typename InputIterator>
+ void findSymbolicObjects(InputIterator begin,
+ InputIterator end,
+ std::vector<const Array*> &results);
+
+}
+
+#endif
Added: klee/trunk/include/klee/util/ExprVisitor.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/ExprVisitor.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/ExprVisitor.h (added)
+++ klee/trunk/include/klee/util/ExprVisitor.h Wed May 20 23:36:41 2009
@@ -0,0 +1,95 @@
+//===-- ExprVisitor.h -------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXPRVISITOR_H
+#define KLEE_EXPRVISITOR_H
+
+#include "ExprHashMap.h"
+
+namespace klee {
+ class ExprVisitor {
+ protected:
+ // typed variant, but non-virtual for efficiency
+ class Action {
+ public:
+ enum Kind { SkipChildren, DoChildren, ChangeTo };
+
+ private:
+ // Action() {}
+ Action(Kind _kind)
+ : kind(_kind), argument(0,Expr::Bool) {}
+ Action(Kind _kind, const ref<Expr> &_argument)
+ : kind(_kind), argument(_argument) {}
+
+ friend class ExprVisitor;
+
+ public:
+ Kind kind;
+ ref<Expr> argument;
+
+ static Action changeTo(const ref<Expr> &expr) { return Action(ChangeTo,expr); }
+ static Action doChildren() { return Action(DoChildren); }
+ static Action skipChildren() { return Action(SkipChildren); }
+ };
+
+ protected:
+ explicit
+ ExprVisitor(bool _recursive=false) : recursive(_recursive) {}
+ virtual ~ExprVisitor() {}
+
+ virtual Action visitExpr(const Expr&);
+ virtual Action visitExprPost(const Expr&);
+
+ virtual Action visitNotOptimized(const NotOptimizedExpr&);
+ virtual Action visitRead(const ReadExpr&);
+ virtual Action visitSelect(const SelectExpr&);
+ virtual Action visitConcat(const ConcatExpr&);
+ virtual Action visitExtract(const ExtractExpr&);
+ virtual Action visitZExt(const ZExtExpr&);
+ virtual Action visitSExt(const SExtExpr&);
+ virtual Action visitAdd(const AddExpr&);
+ virtual Action visitSub(const SubExpr&);
+ virtual Action visitMul(const MulExpr&);
+ virtual Action visitUDiv(const UDivExpr&);
+ virtual Action visitSDiv(const SDivExpr&);
+ virtual Action visitURem(const URemExpr&);
+ virtual Action visitSRem(const SRemExpr&);
+ virtual Action visitAnd(const AndExpr&);
+ virtual Action visitOr(const OrExpr&);
+ virtual Action visitXor(const XorExpr&);
+ virtual Action visitShl(const ShlExpr&);
+ virtual Action visitLShr(const LShrExpr&);
+ virtual Action visitAShr(const AShrExpr&);
+ virtual Action visitEq(const EqExpr&);
+ virtual Action visitNe(const NeExpr&);
+ virtual Action visitUlt(const UltExpr&);
+ virtual Action visitUle(const UleExpr&);
+ virtual Action visitUgt(const UgtExpr&);
+ virtual Action visitUge(const UgeExpr&);
+ virtual Action visitSlt(const SltExpr&);
+ virtual Action visitSle(const SleExpr&);
+ virtual Action visitSgt(const SgtExpr&);
+ virtual Action visitSge(const SgeExpr&);
+
+ private:
+ typedef ExprHashMap< ref<Expr> > visited_ty;
+ visited_ty visited;
+ bool recursive;
+
+ ref<Expr> visitActual(const ref<Expr> &e);
+
+ public:
+ // apply the visitor to the expression and return a possibly
+ // modified new expression.
+ ref<Expr> visit(const ref<Expr> &e);
+ };
+
+}
+
+#endif
Added: klee/trunk/include/klee/util/Ref.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/include/klee/util/Ref.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/include/klee/util/Ref.h (added)
+++ klee/trunk/include/klee/util/Ref.h Wed May 20 23:36:41 2009
@@ -0,0 +1,303 @@
+//===-- Ref.h ---------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_REF_H
+#define KLEE_REF_H
+
+#include <assert.h>
+
+class Expr;
+class BinaryExpr;
+class CastExpr;
+class CmpExpr;
+
+class ConstantExpr;
+class ReadExpr;
+class UpdateNode;
+class NotOptimizedExpr;
+class ReadExpr;
+class SelectExpr;
+class ConcatExpr;
+class ExtractExpr;
+class ZExtExpr;
+class SExtExpr;
+class AddExpr;
+class SubExpr;
+class MulExpr;
+class UDivExpr;
+class SDivExpr;
+class URemExpr;
+class SRemExpr;
+class AndExpr;
+class OrExpr;
+class XorExpr;
+class ShlExpr;
+class LShrExpr;
+class AShrExpr;
+class EqExpr;
+class NeExpr;
+class UltExpr;
+class UleExpr;
+class UgtExpr;
+class UgeExpr;
+class SltExpr;
+class SleExpr;
+class SgtExpr;
+class SgeExpr;
+class KModule;
+
+ class ExprVisitor;
+ class StackFrame;
+ class ObjectState;
+
+template<class T>
+class ref {
+public:
+ // default constructor: create a NULL reference
+ ref() : constantWidth(Expr::InvalidWidth) {
+ contents.ptr = 0;
+ }
+
+private:
+ // if NotConstant, not this ref is not a constant.
+ // otherwise, it's the width of the constant.
+ Expr::Width constantWidth;
+ static const Expr::Width NotConstant = (Expr::Width) 0;
+
+ union {
+ T *ptr;
+ uint64_t val;
+ } contents;
+
+ void inc() {
+ if (constantWidth == NotConstant &&
+ contents.ptr) {
+ contents.ptr->refCount++;
+ }
+ }
+
+ void dec() {
+ if (constantWidth == NotConstant &&
+ contents.ptr &&
+ --contents.ptr->refCount == 0) {
+ delete contents.ptr;
+ }
+ }
+
+ friend class ExprVisitor;
+ friend class Cell;
+ friend class ObjectState;
+ friend class KModule;
+
+public:
+ template<class U> friend class ref;
+ template<class U> friend U* dyn_ref_cast(ref &src);
+ template<class U> friend const U* dyn_ref_cast(const ref &src);
+ template<class U> friend U* static_ref_cast(ref &src);
+ template<class U> friend const U* static_ref_cast(const ref &src);
+
+ // constructor from pointer
+ ref(T *p) : constantWidth(NotConstant) {
+ contents.ptr = p;
+ inc();
+ }
+
+ // construct from constant
+ ref(uint64_t val, Expr::Width w) : constantWidth(w) {
+ contents.val = val;
+ }
+
+ // normal copy constructor
+ ref (const ref<T> &r)
+ : constantWidth(r.constantWidth), contents(r.contents) {
+ inc();
+ }
+
+ // conversion constructor
+ template<class U>
+ ref (const ref<U> &r) {
+ constantWidth = r.constantWidth;
+ contents.val = r.contents.val;
+ inc();
+ }
+
+ // pointer operations
+ T *get () {
+ // demand(constantWidth == NotConstant, "deref of constant");
+
+ // allocate
+ if (constantWidth != NotConstant) {
+ contents.ptr = dynamic_cast<T*>(Expr::createConstant(contents.val, constantWidth));
+ assert(contents.ptr && "error with lazy constant initialization");
+ constantWidth = NotConstant;
+
+ inc();
+ }
+ return contents.ptr;
+ }
+
+ T *get () const {
+ assert(constantWidth == NotConstant && "deref of constant");
+ return contents.ptr;
+ }
+
+ // method calls for the constant optimization
+ bool isConstant() const {
+ if (constantWidth != NotConstant) {
+ return true;
+ } else if (contents.ptr) {
+ return contents.ptr->getKind() == Expr::Constant;
+ } else {
+ return false; // should never happen, but nice check
+ }
+ }
+
+ uint64_t getConstantValue() const {
+ if (constantWidth) {
+ return contents.val;
+ } else {
+ return contents.ptr->getConstantValue();
+ }
+ }
+
+ unsigned hash() const {
+ if (constantWidth) {
+ return Expr::hashConstant(contents.val, constantWidth);
+ } else {
+ return contents.ptr->hash();
+ }
+ }
+
+ unsigned computeHash() const {
+ if (isConstant()) {
+ return Expr::hashConstant(contents.val, constantWidth);
+ } else {
+ return contents.ptr->computeHash();
+ }
+ }
+
+ void rehash() const {
+ if (!isConstant())
+ contents.ptr->computeHash();
+ }
+
+ Expr::Width getWidth() const {
+ if (constantWidth != NotConstant)
+ return constantWidth;
+ return contents.ptr->getWidth();
+ }
+
+ Expr::Kind getKind() const {
+ if (constantWidth != NotConstant)
+ return Expr::Constant;
+ return contents.ptr->getKind();
+ }
+
+ unsigned getNumKids() const {
+ if (constantWidth != NotConstant)
+ return 0;
+ return contents.ptr->getNumKids();
+ }
+
+ ref<Expr> getKid(unsigned k) {
+ if (constantWidth != NotConstant)
+ return 0;
+ return contents.ptr->getKid(k);
+ }
+
+ ~ref () { dec (); }
+
+ /* The copy assignment operator must also explicitly be defined,
+ * despite a redundant template. */
+ ref<T> &operator= (const ref<T> &r) {
+ dec();
+ constantWidth = r.constantWidth;
+ contents.val = r.contents.val;
+ inc();
+
+ return *this;
+ }
+
+ template<class U> ref<T> &operator= (const ref<U> &r) {
+ dec();
+ constantWidth = r.constantWidth;
+ contents.val = r.contents.val;
+ inc();
+
+ return *this;
+ }
+
+ bool isNull() const { return !constantWidth && !contents.ptr; }
+
+ // assumes non-null arguments
+ int compare(const ref &rhs) const {
+ Expr::Kind ak = getKind(), bk = rhs.getKind();
+ if (ak!=bk)
+ return (ak < bk) ? -1 : 1;
+ if (ak==Expr::Constant) {
+ Expr::Width at = getWidth(), bt = rhs.getWidth();
+ if (at!=bt)
+ return (at < bt) ? -1 : 1;
+ uint64_t av = getConstantValue(), bv = rhs.getConstantValue();
+ if (av<bv) {
+ return -1;
+ } else if (av>bv) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ return get()->compare(*rhs.get());
+ }
+ }
+
+ // assumes non-null arguments
+ bool operator<(const ref &rhs) const { return compare(rhs)<0; }
+ bool operator==(const ref &rhs) const { return compare(rhs)==0; }
+ bool operator!=(const ref &rhs) const { return compare(rhs)!=0; }
+};
+
+
+template<class T>
+inline std::ostream &operator<<(std::ostream &os, const ref<T> &e) {
+ if (e.isConstant()) {
+ os << e.getConstantValue();
+ } else {
+ os << *e.get();
+ }
+ return os;
+}
+
+template<class U>
+U* dyn_ref_cast(ref<Expr> &src) {
+ if (src.constantWidth != ref<Expr>::NotConstant)
+ return 0;
+
+ return dynamic_cast<U*>(src.contents.ptr);
+}
+
+template<class U>
+const U* dyn_ref_cast(const ref<Expr> &src) {
+ if (src.constantWidth != ref<Expr>::NotConstant)
+ return 0;
+
+ return dynamic_cast<const U*>(src.contents.ptr);
+}
+
+template<class U>
+U* static_ref_cast(ref<Expr> &src) {
+ return static_cast<U*>(src.contents.ptr);
+}
+
+template<class U>
+const U* static_ref_cast(const ref<Expr> &src) {
+ return static_cast<const U*>(src.contents.ptr);
+}
+
+#endif /* KLEE_REF_H */
Added: klee/trunk/lib/Basic/BOut.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Basic/BOut.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Basic/BOut.cpp (added)
+++ klee/trunk/lib/Basic/BOut.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,236 @@
+//===-- BOut.c ------------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "klee/Internal/ADT/BOut.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define BOUT_MAGIC "BOUT\n"
+#define BOUT_MAGIC_SIZE 5
+#define BOUT_VERSION 2
+
+/***/
+
+static int read_uint32(FILE *f, unsigned *value_out) {
+ unsigned char data[4];
+ if (fread(data, 4, 1, f)!=1)
+ return 0;
+ *value_out = (((((data[0]<<8) + data[1])<<8) + data[2])<<8) + data[3];
+ return 1;
+}
+
+static int write_uint32(FILE *f, unsigned value) {
+ unsigned char data[4];
+ data[0] = value>>24;
+ data[1] = value>>16;
+ data[2] = value>> 8;
+ data[3] = value>> 0;
+ return fwrite(data, 1, 4, f)==4;
+}
+
+static int read_string(FILE *f, char **value_out) {
+ unsigned len;
+ if (!read_uint32(f, &len))
+ return 0;
+ *value_out = (char*) malloc(len+1);
+ if (!*value_out)
+ return 0;
+ if (fread(*value_out, len, 1, f)!=1)
+ return 0;
+ (*value_out)[len] = 0;
+ return 1;
+}
+
+static int write_string(FILE *f, const char *value) {
+ unsigned len = strlen(value);
+ if (!write_uint32(f, len))
+ return 0;
+ if (fwrite(value, len, 1, f)!=1)
+ return 0;
+ return 1;
+}
+
+/***/
+
+
+unsigned bOut_getCurrentVersion() {
+ return BOUT_VERSION;
+}
+
+
+static int bOut_checkHeader(FILE *f) {
+ char header[BOUT_MAGIC_SIZE];
+ if (fread(header, BOUT_MAGIC_SIZE, 1, f)!=1)
+ return 0;
+ if (memcmp(header, BOUT_MAGIC, BOUT_MAGIC_SIZE))
+ return 0;
+ return 1;
+}
+
+int bOut_isBOutFile(const char *path) {
+ FILE *f = fopen(path, "rb");
+ int res;
+
+ if (!f)
+ return 0;
+ res = bOut_checkHeader(f);
+ fclose(f);
+
+ return res;
+}
+
+BOut *bOut_fromFile(const char *path) {
+ FILE *f = fopen(path, "rb");
+ BOut *res = 0;
+ unsigned i, version;
+
+ if (!f)
+ goto error;
+ if (!bOut_checkHeader(f))
+ goto error;
+
+ res = (BOut*) calloc(1, sizeof(*res));
+ if (!res)
+ goto error;
+
+ if (!read_uint32(f, &version))
+ goto error;
+
+ if (version > bOut_getCurrentVersion())
+ goto error;
+
+ res->version = version;
+
+ if (!read_uint32(f, &res->numArgs))
+ goto error;
+ res->args = (char**) calloc(res->numArgs, sizeof(*res->args));
+ if (!res->args)
+ goto error;
+
+ for (i=0; i<res->numArgs; i++)
+ if (!read_string(f, &res->args[i]))
+ goto error;
+
+ if (version >= 2) {
+ if (!read_uint32(f, &res->symArgvs))
+ goto error;
+ if (!read_uint32(f, &res->symArgvLen))
+ goto error;
+ }
+
+ if (!read_uint32(f, &res->numObjects))
+ goto error;
+ res->objects = (BOutObject*) calloc(res->numObjects, sizeof(*res->objects));
+ if (!res->objects)
+ goto error;
+ for (i=0; i<res->numObjects; i++) {
+ BOutObject *o = &res->objects[i];
+ if (!read_string(f, &o->name))
+ goto error;
+ if (!read_uint32(f, &o->numBytes))
+ goto error;
+ o->bytes = (unsigned char*) malloc(o->numBytes);
+ if (fread(o->bytes, o->numBytes, 1, f)!=1)
+ goto error;
+ }
+
+ fclose(f);
+
+ return res;
+ error:
+ if (res) {
+ if (res->args) {
+ for (i=0; i<res->numArgs; i++)
+ if (res->args[i])
+ free(res->args[i]);
+ free(res->args);
+ }
+ if (res->objects) {
+ for (i=0; i<res->numObjects; i++) {
+ BOutObject *bo = &res->objects[i];
+ if (bo->name)
+ free(bo->name);
+ if (bo->bytes)
+ free(bo->bytes);
+ }
+ free(res->objects);
+ }
+ free(res);
+ }
+
+ if (f) fclose(f);
+
+ return 0;
+}
+
+int bOut_toFile(BOut *bo, const char *path) {
+ FILE *f = fopen(path, "wb");
+ unsigned i;
+
+ if (!f)
+ goto error;
+ if (fwrite(BOUT_MAGIC, strlen(BOUT_MAGIC), 1, f)!=1)
+ goto error;
+ if (!write_uint32(f, BOUT_VERSION))
+ goto error;
+
+ if (!write_uint32(f, bo->numArgs))
+ goto error;
+ for (i=0; i<bo->numArgs; i++) {
+ if (!write_string(f, bo->args[i]))
+ goto error;
+ }
+
+ if (!write_uint32(f, bo->symArgvs))
+ goto error;
+ if (!write_uint32(f, bo->symArgvLen))
+ goto error;
+
+ if (!write_uint32(f, bo->numObjects))
+ goto error;
+ for (i=0; i<bo->numObjects; i++) {
+ BOutObject *o = &bo->objects[i];
+ if (!write_string(f, o->name))
+ goto error;
+ if (!write_uint32(f, o->numBytes))
+ goto error;
+ if (fwrite(o->bytes, o->numBytes, 1, f)!=1)
+ goto error;
+ }
+
+ fclose(f);
+
+ return 1;
+ error:
+ if (f) fclose(f);
+
+ return 0;
+}
+
+unsigned bOut_numBytes(BOut *bo) {
+ unsigned i, res = 0;
+ for (i=0; i<bo->numObjects; i++)
+ res += bo->objects[i].numBytes;
+ return res;
+}
+
+void bOut_free(BOut *bo) {
+ unsigned i;
+ for (i=0; i<bo->numArgs; i++)
+ free(bo->args[i]);
+ free(bo->args);
+ for (i=0; i<bo->numObjects; i++) {
+ free(bo->objects[i].name);
+ free(bo->objects[i].bytes);
+ }
+ free(bo->objects);
+ free(bo);
+}
Added: klee/trunk/lib/Basic/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Basic/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Basic/Makefile (added)
+++ klee/trunk/lib/Basic/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+#===-- lib/Basic/Makefile ----------------------------------*- Makefile -*--===#
+#
+# The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+LEVEL=../..
+
+LIBRARYNAME=kleeBasic
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+
+include $(LEVEL)/Makefile.common
Added: klee/trunk/lib/Basic/README.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Basic/README.txt?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Basic/README.txt (added)
+++ klee/trunk/lib/Basic/README.txt Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+This directory holds the most basic support facilities provided for
+both the klee and kleaver libraries. The code in this directory should
+have no dependencies on LLVM or any other klee libraries.
Added: klee/trunk/lib/Basic/Statistics.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Basic/Statistics.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Basic/Statistics.cpp (added)
+++ klee/trunk/lib/Basic/Statistics.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,84 @@
+//===-- Statistics.cpp ----------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "klee/Statistics.h"
+
+#include <vector>
+
+using namespace klee;
+
+StatisticManager::StatisticManager()
+ : enabled(true),
+ globalStats(0),
+ indexedStats(0),
+ contextStats(0),
+ index(0) {
+}
+
+StatisticManager::~StatisticManager() {
+ if (globalStats) delete[] globalStats;
+ if (indexedStats) delete[] indexedStats;
+}
+
+void StatisticManager::useIndexedStats(unsigned totalIndices) {
+ if (indexedStats) delete[] indexedStats;
+ indexedStats = new uint64_t[totalIndices * stats.size()];
+ memset(indexedStats, 0, sizeof(*indexedStats) * totalIndices * stats.size());
+}
+
+void StatisticManager::registerStatistic(Statistic &s) {
+ if (globalStats) delete[] globalStats;
+ s.id = stats.size();
+ stats.push_back(&s);
+ globalStats = new uint64_t[stats.size()];
+ memset(globalStats, 0, sizeof(*globalStats)*stats.size());
+}
+
+int StatisticManager::getStatisticID(const std::string &name) const {
+ for (unsigned i=0; i<stats.size(); i++)
+ if (stats[i]->getName() == name)
+ return i;
+ return -1;
+}
+
+Statistic *StatisticManager::getStatisticByName(const std::string &name) const {
+ for (unsigned i=0; i<stats.size(); i++)
+ if (stats[i]->getName() == name)
+ return stats[i];
+ return 0;
+}
+
+StatisticManager *klee::theStatisticManager = 0;
+
+static StatisticManager &getStatisticManager() {
+ static StatisticManager sm;
+ theStatisticManager = &sm;
+ return sm;
+}
+
+/* *** */
+
+Statistic::Statistic(const std::string &_name,
+ const std::string &_shortName)
+ : name(_name),
+ shortName(_shortName) {
+ getStatisticManager().registerStatistic(*this);
+}
+
+Statistic::~Statistic() {
+}
+
+Statistic &Statistic::operator +=(const uint64_t addend) {
+ theStatisticManager->incrementStatistic(*this, addend);
+ return *this;
+}
+
+uint64_t Statistic::getValue() const {
+ return theStatisticManager->getValue(*this);
+}
Added: klee/trunk/lib/Core/AddressSpace.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/AddressSpace.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/AddressSpace.cpp (added)
+++ klee/trunk/lib/Core/AddressSpace.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,334 @@
+//===-- AddressSpace.cpp --------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AddressSpace.h"
+#include "CoreStats.h"
+#include "Memory.h"
+#include "TimingSolver.h"
+
+#include "klee/Expr.h"
+#include "klee/TimerStatIncrementer.h"
+
+using namespace klee;
+
+///
+
+void AddressSpace::bindObject(const MemoryObject *mo, ObjectState *os) {
+ assert(os->copyOnWriteOwner==0 && "object already has owner");
+ os->copyOnWriteOwner = cowKey;
+ objects = objects.replace(std::make_pair(mo, os));
+}
+
+void AddressSpace::unbindObject(const MemoryObject *mo) {
+ objects = objects.remove(mo);
+}
+
+const ObjectState *AddressSpace::findObject(const MemoryObject *mo) const {
+ const MemoryMap::value_type *res = objects.lookup(mo);
+
+ return res ? res->second : 0;
+}
+
+ObjectState *AddressSpace::getWriteable(const MemoryObject *mo,
+ const ObjectState *os) {
+ assert(!os->readOnly);
+
+ if (cowKey==os->copyOnWriteOwner) {
+ return const_cast<ObjectState*>(os);
+ } else {
+ ObjectState *n = new ObjectState(*os);
+ n->copyOnWriteOwner = cowKey;
+ objects = objects.replace(std::make_pair(mo, n));
+ return n;
+ }
+}
+
+///
+
+bool AddressSpace::resolveOne(uint64_t addr64, ObjectPair &result) {
+ unsigned address = (unsigned) addr64;
+ MemoryObject hack(address);
+
+ if (const MemoryMap::value_type *res = objects.lookup_previous(&hack)) {
+ const MemoryObject *mo = res->first;
+ if ((mo->size==0 && address==mo->address) ||
+ (address - mo->address < mo->size)) {
+ result = *res;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool AddressSpace::resolveOne(ExecutionState &state,
+ TimingSolver *solver,
+ ref<Expr> address,
+ ObjectPair &result,
+ bool &success) {
+ if (address.isConstant()) {
+ success = resolveOne(address.getConstantValue(), result);
+ return true;
+ } else {
+ TimerStatIncrementer timer(stats::resolveTime);
+
+ // try cheap search, will succeed for any inbounds pointer
+
+ ref<Expr> cex(0);
+ if (!solver->getValue(state, address, cex))
+ return false;
+ unsigned example = (unsigned) cex.getConstantValue();
+ MemoryObject hack(example);
+ const MemoryMap::value_type *res = objects.lookup_previous(&hack);
+
+ if (res) {
+ const MemoryObject *mo = res->first;
+ if (example - mo->address < mo->size) {
+ result = *res;
+ success = true;
+ return true;
+ }
+ }
+
+ // didn't work, now we have to search
+
+ MemoryMap::iterator oi = objects.upper_bound(&hack);
+ MemoryMap::iterator begin = objects.begin();
+ MemoryMap::iterator end = objects.end();
+
+ MemoryMap::iterator start = oi;
+ while (oi!=begin) {
+ --oi;
+ const MemoryObject *mo = oi->first;
+
+ bool mayBeTrue;
+ if (!solver->mayBeTrue(state,
+ mo->getBoundsCheckPointer(address), mayBeTrue))
+ return false;
+ if (mayBeTrue) {
+ result = *oi;
+ success = true;
+ return true;
+ } else {
+ bool mustBeTrue;
+ if (!solver->mustBeTrue(state,
+ UgeExpr::create(address, mo->getBaseExpr()),
+ mustBeTrue))
+ return false;
+ if (mustBeTrue)
+ break;
+ }
+ }
+
+ // search forwards
+ for (oi=start; oi!=end; ++oi) {
+ const MemoryObject *mo = oi->first;
+
+ bool mustBeTrue;
+ if (!solver->mustBeTrue(state,
+ UltExpr::create(address, mo->getBaseExpr()),
+ mustBeTrue))
+ return false;
+ if (mustBeTrue) {
+ break;
+ } else {
+ bool mayBeTrue;
+
+ if (!solver->mayBeTrue(state,
+ mo->getBoundsCheckPointer(address),
+ mayBeTrue))
+ return false;
+ if (mayBeTrue) {
+ result = *oi;
+ success = true;
+ return true;
+ }
+ }
+ }
+
+ success = false;
+ return true;
+ }
+}
+
+bool AddressSpace::resolve(ExecutionState &state,
+ TimingSolver *solver,
+ ref<Expr> p,
+ ResolutionList &rl,
+ unsigned maxResolutions,
+ double timeout) {
+ if (p.isConstant()) {
+ ObjectPair res;
+ if (resolveOne(p.getConstantValue(), res))
+ rl.push_back(res);
+ return false;
+ } else {
+ TimerStatIncrementer timer(stats::resolveTime);
+ uint64_t timeout_us = (uint64_t) (timeout*1000000.);
+
+ // XXX in general this isn't exactly what we want... for
+ // a multiple resolution case (or for example, a \in {b,c,0})
+ // we want to find the first object, find a cex assuming
+ // not the first, find a cex assuming not the second...
+ // etc.
+
+ // XXX how do we smartly amortize the cost of checking to
+ // see if we need to keep searching up/down, in bad cases?
+ // maybe we don't care?
+
+ // XXX we really just need a smart place to start (although
+ // if its a known solution then the code below is guaranteed
+ // to hit the fast path with exactly 2 queries). we could also
+ // just get this by inspection of the expr.
+
+ ref<Expr> cex(0);
+ if (!solver->getValue(state, p, cex))
+ return true;
+ unsigned example = (unsigned) cex.getConstantValue();
+ MemoryObject hack(example);
+
+ MemoryMap::iterator oi = objects.upper_bound(&hack);
+ MemoryMap::iterator begin = objects.begin();
+ MemoryMap::iterator end = objects.end();
+
+ MemoryMap::iterator start = oi;
+
+ // XXX in the common case we can save one query if we ask
+ // mustBeTrue before mayBeTrue for the first result. easy
+ // to add I just want to have a nice symbolic test case first.
+
+ // search backwards, start with one minus because this
+ // is the object that p *should* be within, which means we
+ // get write off the end with 4 queries (XXX can be better,
+ // no?)
+ while (oi!=begin) {
+ --oi;
+ const MemoryObject *mo = oi->first;
+ if (timeout_us && timeout_us < timer.check())
+ return true;
+
+ // XXX I think there is some query wasteage here?
+ ref<Expr> inBounds = mo->getBoundsCheckPointer(p);
+ bool mayBeTrue;
+ if (!solver->mayBeTrue(state, inBounds, mayBeTrue))
+ return true;
+ if (mayBeTrue) {
+ rl.push_back(*oi);
+
+ // fast path check
+ unsigned size = rl.size();
+ if (size==1) {
+ bool mustBeTrue;
+ if (!solver->mustBeTrue(state, inBounds, mustBeTrue))
+ return true;
+ if (mustBeTrue)
+ return false;
+ } else if (size==maxResolutions) {
+ return true;
+ }
+ }
+
+ bool mustBeTrue;
+ if (!solver->mustBeTrue(state,
+ UgeExpr::create(p, mo->getBaseExpr()),
+ mustBeTrue))
+ return true;
+ if (mustBeTrue)
+ break;
+ }
+ // search forwards
+ for (oi=start; oi!=end; ++oi) {
+ const MemoryObject *mo = oi->first;
+ if (timeout_us && timeout_us < timer.check())
+ return true;
+
+ bool mustBeTrue;
+ if (!solver->mustBeTrue(state,
+ UltExpr::create(p, mo->getBaseExpr()),
+ mustBeTrue))
+ return true;
+ if (mustBeTrue)
+ break;
+
+ // XXX I think there is some query wasteage here?
+ ref<Expr> inBounds = mo->getBoundsCheckPointer(p);
+ bool mayBeTrue;
+ if (!solver->mayBeTrue(state, inBounds, mayBeTrue))
+ return true;
+ if (mayBeTrue) {
+ rl.push_back(*oi);
+
+ // fast path check
+ unsigned size = rl.size();
+ if (size==1) {
+ bool mustBeTrue;
+ if (!solver->mustBeTrue(state, inBounds, mustBeTrue))
+ return true;
+ if (mustBeTrue)
+ return false;
+ } else if (size==maxResolutions) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// These two are pretty big hack so we can sort of pass memory back
+// and forth to externals. They work by abusing the concrete cache
+// store inside of the object states, which allows them to
+// transparently avoid screwing up symbolics (if the byte is symbolic
+// then its concrete cache byte isn't being used) but is just a hack.
+
+void AddressSpace::copyOutConcretes() {
+ for (MemoryMap::iterator it = objects.begin(), ie = objects.end();
+ it != ie; ++it) {
+ const MemoryObject *mo = it->first;
+
+ if (!mo->isUserSpecified) {
+ ObjectState *os = it->second;
+ uint8_t *address = (uint8_t*) (unsigned long) mo->address;
+
+ if (!os->readOnly)
+ memcpy(address, os->concreteStore, mo->size);
+ }
+ }
+}
+
+bool AddressSpace::copyInConcretes() {
+ for (MemoryMap::iterator it = objects.begin(), ie = objects.end();
+ it != ie; ++it) {
+ const MemoryObject *mo = it->first;
+
+ if (!mo->isUserSpecified) {
+ const ObjectState *os = it->second;
+ uint8_t *address = (uint8_t*) (unsigned long) mo->address;
+
+ if (memcmp(address, os->concreteStore, mo->size)!=0) {
+ if (os->readOnly) {
+ return false;
+ } else {
+ ObjectState *wos = getWriteable(mo, os);
+ memcpy(wos->concreteStore, address, mo->size);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/***/
+
+bool MemoryObjectLT::operator()(const MemoryObject *a, const MemoryObject *b) const {
+ return a->address < b->address;
+}
+
Added: klee/trunk/lib/Core/AddressSpace.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/AddressSpace.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/AddressSpace.h (added)
+++ klee/trunk/lib/Core/AddressSpace.h Wed May 20 23:36:41 2009
@@ -0,0 +1,131 @@
+//===-- AddressSpace.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_ADDRESSSPACE_H
+#define KLEE_ADDRESSSPACE_H
+
+#include "ObjectHolder.h"
+
+#include "klee/Expr.h"
+#include "klee/Internal/ADT/ImmutableMap.h"
+
+namespace klee {
+ class ExecutionState;
+ class MemoryObject;
+ class ObjectState;
+ class TimingSolver;
+
+ template<class T> class ref;
+
+ typedef std::pair<const MemoryObject*, const ObjectState*> ObjectPair;
+ typedef std::vector<ObjectPair> ResolutionList;
+
+ /// Function object ordering MemoryObject's by address.
+ struct MemoryObjectLT {
+ bool operator()(const MemoryObject *a, const MemoryObject *b) const;
+ };
+
+ typedef ImmutableMap<const MemoryObject*, ObjectHolder, MemoryObjectLT> MemoryMap;
+
+ class AddressSpace {
+ private:
+ /// Epoch counter used to control ownership of objects.
+ mutable unsigned cowKey;
+
+ /// Unsupported, use copy constructor
+ AddressSpace &operator=(const AddressSpace&);
+
+ public:
+ /// The MemoryObject -> ObjectState map that constitutes the
+ /// address space.
+ ///
+ /// The set of objects where o->copyOnWriteOwner == cowKey are the
+ /// objects that we own.
+ ///
+ /// \invariant forall o in objects, o->copyOnWriteOwner <= cowKey
+ MemoryMap objects;
+
+ public:
+ AddressSpace() : cowKey(1) {}
+ AddressSpace(const AddressSpace &b) : cowKey(++b.cowKey), objects(b.objects) { }
+ ~AddressSpace() {}
+
+ /// Resolve address to an ObjectPair in result.
+ /// \return true iff an object was found.
+ bool resolveOne(uint64_t address,
+ ObjectPair &result);
+
+ /// Resolve address to an ObjectPair in result.
+ ///
+ /// \param state The state this address space is part of.
+ /// \param solver A solver used to determine possible
+ /// locations of the \a address.
+ /// \param address The address to search for.
+ /// \param[out] result An ObjectPair this address can resolve to
+ /// (when returning true).
+ /// \return true iff an object was found at \a address.
+ bool resolveOne(ExecutionState &state,
+ TimingSolver *solver,
+ ref<Expr> address,
+ ObjectPair &result,
+ bool &success);
+
+ /// Resolve address to a list of ObjectPairs it can point to. If
+ /// maxResolutions is non-zero then no more than that many pairs
+ /// will be returned.
+ ///
+ /// \return true iff the resolution is incomplete (maxResolutions
+ /// is non-zero and the search terminated early, or a query timed out).
+ bool resolve(ExecutionState &state,
+ TimingSolver *solver,
+ ref<Expr> address,
+ ResolutionList &rl,
+ unsigned maxResolutions=0,
+ double timeout=0.);
+
+ /***/
+
+ /// Add a binding to the address space.
+ void bindObject(const MemoryObject *mo, ObjectState *os);
+
+ /// Remove a binding from the address space.
+ void unbindObject(const MemoryObject *mo);
+
+ /// Lookup a binding from a MemoryObject.
+ const ObjectState *findObject(const MemoryObject *mo) const;
+
+ /// \brief Obtain an ObjectState suitable for writing.
+ ///
+ /// This returns a writeable object state, creating a new copy of
+ /// the given ObjectState if necessary. If the address space owns
+ /// the ObjectState then this routine effectively just strips the
+ /// const qualifier it.
+ ///
+ /// \param mo The MemoryObject to get a writeable ObjectState for.
+ /// \param os The current binding of the MemoryObject.
+ /// \return A writeable ObjectState (\a os or a copy).
+ ObjectState *getWriteable(const MemoryObject *mo, const ObjectState *os);
+
+ /// Copy the concrete values of all managed ObjectStates into the
+ /// actual system memory location they were allocated at.
+ void copyOutConcretes();
+
+ /// Copy the concrete values of all managed ObjectStates back from
+ /// the actual system memory location they were allocated
+ /// at. ObjectStates will only be written to (and thus,
+ /// potentially copied) if the memory values are different from
+ /// the current concrete values.
+ ///
+ /// \retval true The copy succeeded.
+ /// \retval false The copy failed because a read-only object was modified.
+ bool copyInConcretes();
+ };
+} // End klee namespace
+
+#endif
Added: klee/trunk/lib/Core/CallPathManager.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/CallPathManager.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/CallPathManager.cpp (added)
+++ klee/trunk/lib/Core/CallPathManager.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,103 @@
+//===-- CallPathManager.cpp -----------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CallPathManager.h"
+
+#include "klee/Statistics.h"
+
+#include <map>
+#include <vector>
+#include "llvm/Function.h"
+#include "llvm/Support/Streams.h"
+
+using namespace llvm;
+using namespace klee;
+
+///
+
+CallPathNode::CallPathNode(CallPathNode *_parent,
+ Instruction *_callSite,
+ Function *_function)
+ : parent(_parent),
+ callSite(_callSite),
+ function(_function),
+ count(0) {
+}
+
+void CallPathNode::print() {
+ llvm::cerr << " (Function: " << this->function->getName() << ", "
+ << "Callsite: " << callSite << ", "
+ << "Count: " << this->count << ")";
+ if (parent && parent->callSite) {
+ llvm::cerr << ";\n";
+ parent->print();
+ }
+ else llvm::cerr << "\n";
+}
+
+///
+
+CallPathManager::CallPathManager() : root(0, 0, 0) {
+}
+
+CallPathManager::~CallPathManager() {
+ for (std::vector<CallPathNode*>::iterator it = paths.begin(),
+ ie = paths.end(); it != ie; ++it)
+ delete *it;
+}
+
+void CallPathManager::getSummaryStatistics(CallSiteSummaryTable &results) {
+ results.clear();
+
+ for (std::vector<CallPathNode*>::iterator it = paths.begin(),
+ ie = paths.end(); it != ie; ++it)
+ (*it)->summaryStatistics = (*it)->statistics;
+
+ // compute summary bottom up, while building result table
+ for (std::vector<CallPathNode*>::reverse_iterator it = paths.rbegin(),
+ ie = paths.rend(); it != ie; ++it) {
+ CallPathNode *cp = *it;
+ cp->parent->summaryStatistics += cp->summaryStatistics;
+
+ CallSiteInfo &csi = results[cp->callSite][cp->function];
+ csi.count += cp->count;
+ csi.statistics += cp->summaryStatistics;
+ }
+}
+
+
+CallPathNode *CallPathManager::computeCallPath(CallPathNode *parent,
+ Instruction *cs,
+ Function *f) {
+ for (CallPathNode *p=parent; p; p=p->parent)
+ if (cs==p->callSite && f==p->function)
+ return p;
+
+ CallPathNode *cp = new CallPathNode(parent, cs, f);
+ paths.push_back(cp);
+ return cp;
+}
+
+CallPathNode *CallPathManager::getCallPath(CallPathNode *parent,
+ Instruction *cs,
+ Function *f) {
+ std::pair<Instruction*,Function*> key(cs, f);
+ if (!parent)
+ parent = &root;
+
+ CallPathNode::children_ty::iterator it = parent->children.find(key);
+ if (it==parent->children.end()) {
+ CallPathNode *cp = computeCallPath(parent, cs, f);
+ parent->children.insert(std::make_pair(key, cp));
+ return cp;
+ } else {
+ return it->second;
+ }
+}
+
Added: klee/trunk/lib/Core/CallPathManager.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/CallPathManager.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/CallPathManager.h (added)
+++ klee/trunk/lib/Core/CallPathManager.h Wed May 20 23:36:41 2009
@@ -0,0 +1,83 @@
+//===-- CallPathManager.h ---------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UTIL_CALLPATHMANAGER_H__
+#define __UTIL_CALLPATHMANAGER_H__
+
+#include "klee/Statistics.h"
+
+#include <map>
+#include <vector>
+
+namespace llvm {
+ class Instruction;
+ class Function;
+}
+
+namespace klee {
+ class StatisticRecord;
+
+ struct CallSiteInfo {
+ unsigned count;
+ StatisticRecord statistics;
+
+ public:
+ CallSiteInfo() : count(0) {}
+ };
+
+ typedef std::map<llvm::Instruction*,
+ std::map<llvm::Function*, CallSiteInfo> > CallSiteSummaryTable;
+
+ class CallPathNode {
+ friend class CallPathManager;
+
+ public:
+ typedef std::map<std::pair<llvm::Instruction*,
+ llvm::Function*>, CallPathNode*> children_ty;
+
+ // form list of (callSite,function) path
+ CallPathNode *parent;
+ llvm::Instruction *callSite;
+ llvm::Function *function;
+ children_ty children;
+
+ StatisticRecord statistics;
+ StatisticRecord summaryStatistics;
+ unsigned count;
+
+ public:
+ CallPathNode(CallPathNode *parent,
+ llvm::Instruction *callSite,
+ llvm::Function *function);
+
+ void print();
+ };
+
+ class CallPathManager {
+ CallPathNode root;
+ std::vector<CallPathNode*> paths;
+
+ private:
+ CallPathNode *computeCallPath(CallPathNode *parent,
+ llvm::Instruction *callSite,
+ llvm::Function *f);
+
+ public:
+ CallPathManager();
+ ~CallPathManager();
+
+ void getSummaryStatistics(CallSiteSummaryTable &result);
+
+ CallPathNode *getCallPath(CallPathNode *parent,
+ llvm::Instruction *callSite,
+ llvm::Function *f);
+ };
+}
+
+#endif
Added: klee/trunk/lib/Core/Common.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Common.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Common.cpp (added)
+++ klee/trunk/lib/Core/Common.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,110 @@
+//===-- Common.cpp --------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+
+#include <set>
+
+using namespace klee;
+
+FILE* klee::klee_warning_file = NULL;
+FILE* klee::klee_message_file = NULL;
+
+
+/* Prints a message/warning.
+
+ If pfx is NULL, this is a regular message, and it's sent to
+ klee_message_file (messages.txt). Otherwise, it is sent to
+ klee_warning_file (warnings.txt).
+
+ Iff onlyToFile is false, the message is also printed on stderr.
+*/
+static void klee_vmessage(const char *pfx, bool onlyToFile, const char *msg, va_list ap) {
+ FILE *f = stderr;
+ if (!onlyToFile) {
+ fprintf(f, "KLEE: ");
+ if (pfx) fprintf(f, "%s: ", pfx);
+ vfprintf(f, msg, ap);
+ fprintf(f, "\n");
+ fflush(f);
+ }
+
+ if (pfx == NULL)
+ f = klee_message_file;
+ else f = klee_warning_file;
+
+ if (f) {
+ fprintf(f, "KLEE: ");
+ if (pfx) fprintf(f, "%s: ", pfx);
+ vfprintf(f, msg, ap);
+ fprintf(f, "\n");
+ fflush(f);
+ }
+}
+
+
+void klee::klee_message(const char *msg, ...) {
+ va_list ap;
+ va_start(ap, msg);
+ klee_vmessage(NULL, false, msg, ap);
+ va_end(ap);
+}
+
+/* Message to be written only to file */
+void klee::klee_message_to_file(const char *msg, ...) {
+ va_list ap;
+ va_start(ap, msg);
+ klee_vmessage(NULL, true, msg, ap);
+ va_end(ap);
+}
+
+void klee::klee_error(const char *msg, ...) {
+ va_list ap;
+ va_start(ap, msg);
+ klee_vmessage("ERROR", false, msg, ap);
+ va_end(ap);
+ exit(1);
+}
+
+void klee::klee_warning(const char *msg, ...) {
+ va_list ap;
+ va_start(ap, msg);
+ klee_vmessage("WARNING", false, msg, ap);
+ va_end(ap);
+}
+
+
+/* Prints a warning once per message. */
+void klee::klee_warning_once(const void *id, const char *msg, ...) {
+ static std::set< std::pair<const void*, const char*> > keys;
+ std::pair<const void*, const char*> key;
+
+
+ /* "calling external" messages contain the actual arguments with
+ which we called the external function, so we need to ignore them
+ when computing the key. */
+ if (strncmp(msg, "calling external", strlen("calling external")) != 0)
+ key = std::make_pair(id, msg);
+ else key = std::make_pair(id, "calling external");
+
+ if (!keys.count(key)) {
+ keys.insert(key);
+
+ va_list ap;
+ va_start(ap, msg);
+ klee_vmessage("WARNING", false, msg, ap);
+ va_end(ap);
+ }
+}
Added: klee/trunk/lib/Core/Common.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Common.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Common.h (added)
+++ klee/trunk/lib/Core/Common.h Wed May 20 23:36:41 2009
@@ -0,0 +1,56 @@
+//===-- Common.h ------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __KLEE_COMMON_H__
+#define __KLEE_COMMON_H__
+
+#ifdef __CYGWIN__
+#ifndef WINDOWS
+#define WINDOWS
+#endif
+#endif
+
+#include <stdio.h>
+
+// XXX ugh
+namespace klee {
+ class Solver;
+
+ extern FILE* klee_warning_file;
+ extern FILE* klee_message_file;
+
+ /// Print "KLEE: ERROR" followed by the msg in printf format and a
+ /// newline on stderr and to warnings.txt, then exit with an error.
+ void klee_error(const char *msg, ...)
+ __attribute__ ((format (printf, 1, 2), noreturn));
+
+ /// Print "KLEE: " followed by the msg in printf format and a
+ /// newline on stderr and to messages.txt.
+ void klee_message(const char *msg, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+ /// Print "KLEE: " followed by the msg in printf format and a
+ /// newline to messages.txt.
+ void klee_message_to_file(const char *msg, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+ /// Print "KLEE: WARNING" followed by the msg in printf format and a
+ /// newline on stderr and to warnings.txt.
+ void klee_warning(const char *msg, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+ /// Print "KLEE: WARNING" followed by the msg in printf format and a
+ /// newline on stderr and to warnings.txt. However, the warning is only
+ /// printed once for each unique (id, msg) pair (as pointers).
+ void klee_warning_once(const void *id,
+ const char *msg, ...)
+ __attribute__ ((format (printf, 2, 3)));
+}
+
+#endif /* __KLEE_COMMON_H__ */
Added: klee/trunk/lib/Core/CoreStats.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/CoreStats.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/CoreStats.cpp (added)
+++ klee/trunk/lib/Core/CoreStats.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,29 @@
+//===-- CoreStats.cpp -----------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CoreStats.h"
+
+using namespace klee;
+
+Statistic stats::allocations("Allocations", "Alloc");
+Statistic stats::coveredInstructions("CoveredInstructions", "Icov");
+Statistic stats::falseBranches("FalseBranches", "Bf");
+Statistic stats::forkTime("ForkTime", "Ftime");
+Statistic stats::forks("Forks", "Forks");
+Statistic stats::instructionRealTime("InstructionRealTimes", "Ireal");
+Statistic stats::instructionTime("InstructionTimes", "Itime");
+Statistic stats::instructions("Instructions", "I");
+Statistic stats::minDistToReturn("MinDistToReturn", "Rdist");
+Statistic stats::minDistToUncovered("MinDistToUncovered", "UCdist");
+Statistic stats::reachableUncovered("ReachableUncovered", "IuncovReach");
+Statistic stats::resolveTime("ResolveTime", "Rtime");
+Statistic stats::solverTime("SolverTime", "Stime");
+Statistic stats::states("States", "States");
+Statistic stats::trueBranches("TrueBranches", "Bt");
+Statistic stats::uncoveredInstructions("UncoveredInstructions", "Iuncov");
Added: klee/trunk/lib/Core/CoreStats.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/CoreStats.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/CoreStats.h (added)
+++ klee/trunk/lib/Core/CoreStats.h Wed May 20 23:36:41 2009
@@ -0,0 +1,53 @@
+//===-- CoreStats.h ---------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_CORESTATS_H
+#define KLEE_CORESTATS_H
+
+#include "klee/Statistic.h"
+
+namespace klee {
+namespace stats {
+
+ extern Statistic allocations;
+ extern Statistic resolveTime;
+ extern Statistic instructions;
+ extern Statistic instructionTime;
+ extern Statistic instructionRealTime;
+ extern Statistic coveredInstructions;
+ extern Statistic uncoveredInstructions;
+ extern Statistic trueBranches;
+ extern Statistic falseBranches;
+ extern Statistic forkTime;
+ extern Statistic solverTime;
+
+ /// The number of process forks.
+ extern Statistic forks;
+
+ /// Number of states, this is a "fake" statistic used by istats, it
+ /// isn't normally up-to-date.
+ extern Statistic states;
+
+ /// Instruction level statistic for tracking number of reachable
+ /// uncovered instructions.
+ extern Statistic reachableUncovered;
+
+ /// Instruction level statistic tracking the minimum intraprocedural
+ /// distance to an uncovered instruction; this is only periodically
+ /// updated.
+ extern Statistic minDistToUncovered;
+
+ /// Instruction level statistic tracking the minimum intraprocedural
+ /// distance to a function return.
+ extern Statistic minDistToReturn;
+
+}
+}
+
+#endif
Added: klee/trunk/lib/Core/ExecutionState.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ExecutionState.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ExecutionState.cpp (added)
+++ klee/trunk/lib/Core/ExecutionState.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,417 @@
+//===-- ExecutionState.cpp ------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "klee/ExecutionState.h"
+
+#include "klee/Internal/Module/Cell.h"
+#include "klee/Internal/Module/InstructionInfoTable.h"
+#include "klee/Internal/Module/KInstruction.h"
+#include "klee/Internal/Module/KModule.h"
+
+#include "klee/Expr.h"
+
+#include "Memory.h"
+
+#include "llvm/Function.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <iostream>
+#include <cassert>
+#include <map>
+#include <set>
+#include <stdarg.h>
+
+using namespace llvm;
+using namespace klee;
+
+namespace {
+ cl::opt<bool>
+ DebugLogStateMerge("debug-log-state-merge");
+}
+
+/***/
+
+StackFrame::StackFrame(KInstIterator _caller, KFunction *_kf)
+ : caller(_caller), kf(_kf), callPathNode(0),
+ minDistToUncoveredOnReturn(0), varargs(0) {
+ locals = new Cell[kf->numRegisters];
+}
+
+StackFrame::StackFrame(const StackFrame &s)
+ : caller(s.caller),
+ kf(s.kf),
+ callPathNode(s.callPathNode),
+ allocas(s.allocas),
+ minDistToUncoveredOnReturn(s.minDistToUncoveredOnReturn),
+ varargs(s.varargs) {
+ locals = new Cell[s.kf->numRegisters];
+ for (unsigned i=0; i<s.kf->numRegisters; i++)
+ locals[i] = s.locals[i];
+}
+
+StackFrame::~StackFrame() {
+ delete[] locals;
+}
+
+/***/
+
+ExecutionState::ExecutionState(KFunction *kf)
+ : fakeState(false),
+ underConstrained(false),
+ depth(0),
+ pc(kf->instructions),
+ prevPC(pc),
+ queryCost(0.),
+ weight(1),
+ instsSinceCovNew(0),
+ coveredNew(false),
+ forkDisabled(false),
+ ptreeNode(0) {
+ pushFrame(0, kf);
+}
+
+ExecutionState::ExecutionState(const std::vector<ref<Expr> > &assumptions)
+ : fakeState(true),
+ underConstrained(false),
+ constraints(assumptions),
+ queryCost(0.),
+ ptreeNode(0) {
+}
+
+ExecutionState::~ExecutionState() {
+ while (!stack.empty()) popFrame();
+}
+
+ExecutionState *ExecutionState::branch() {
+ depth++;
+
+ ExecutionState *falseState = new ExecutionState(*this);
+ falseState->coveredNew = false;
+ falseState->coveredLines.clear();
+
+ weight *= .5;
+ falseState->weight -= weight;
+
+ return falseState;
+}
+
+void ExecutionState::pushFrame(KInstIterator caller, KFunction *kf) {
+ stack.push_back(StackFrame(caller,kf));
+}
+
+void ExecutionState::popFrame() {
+ StackFrame &sf = stack.back();
+ for (std::vector<const MemoryObject*>::iterator it = sf.allocas.begin(),
+ ie = sf.allocas.end(); it != ie; ++it)
+ addressSpace.unbindObject(*it);
+ stack.pop_back();
+}
+
+///
+
+std::string ExecutionState::getFnAlias(std::string fn) {
+ std::map < std::string, std::string >::iterator it = fnAliases.find(fn);
+ if (it != fnAliases.end())
+ return it->second;
+ else return "";
+}
+
+void ExecutionState::addFnAlias(std::string old_fn, std::string new_fn) {
+ fnAliases[old_fn] = new_fn;
+}
+
+void ExecutionState::removeFnAlias(std::string fn) {
+ fnAliases.erase(fn);
+}
+
+/**/
+
+std::ostream &klee::operator<<(std::ostream &os, const MemoryMap &mm) {
+ os << "{";
+ MemoryMap::iterator it = mm.begin();
+ MemoryMap::iterator ie = mm.end();
+ if (it!=ie) {
+ os << "MO" << it->first->id << ":" << it->second;
+ for (++it; it!=ie; ++it)
+ os << ", MO" << it->first->id << ":" << it->second;
+ }
+ os << "}";
+ return os;
+}
+
+bool ExecutionState::merge(const ExecutionState &b) {
+ if (DebugLogStateMerge)
+ llvm::cerr << "-- attempting merge of A:"
+ << this << " with B:" << &b << "--\n";
+ if (pc != b.pc)
+ return false;
+
+ // XXX is it even possible for these to differ? does it matter? probably
+ // implies difference in object states?
+ if (symbolics!=b.symbolics)
+ return false;
+
+ {
+ std::vector<StackFrame>::const_iterator itA = stack.begin();
+ std::vector<StackFrame>::const_iterator itB = b.stack.begin();
+ while (itA!=stack.end() && itB!=b.stack.end()) {
+ // XXX vaargs?
+ if (itA->caller!=itB->caller || itA->kf!=itB->kf)
+ return false;
+ ++itA;
+ ++itB;
+ }
+ if (itA!=stack.end() || itB!=b.stack.end())
+ return false;
+ }
+
+ std::set< ref<Expr> > aConstraints(constraints.begin(), constraints.end());
+ std::set< ref<Expr> > bConstraints(b.constraints.begin(),
+ b.constraints.end());
+ std::set< ref<Expr> > commonConstraints, aSuffix, bSuffix;
+ std::set_intersection(aConstraints.begin(), aConstraints.end(),
+ bConstraints.begin(), bConstraints.end(),
+ std::inserter(commonConstraints, commonConstraints.begin()));
+ std::set_difference(aConstraints.begin(), aConstraints.end(),
+ commonConstraints.begin(), commonConstraints.end(),
+ std::inserter(aSuffix, aSuffix.end()));
+ std::set_difference(bConstraints.begin(), bConstraints.end(),
+ commonConstraints.begin(), commonConstraints.end(),
+ std::inserter(bSuffix, bSuffix.end()));
+ if (DebugLogStateMerge) {
+ llvm::cerr << "\tconstraint prefix: [";
+ for (std::set< ref<Expr> >::iterator it = commonConstraints.begin(),
+ ie = commonConstraints.end(); it != ie; ++it)
+ llvm::cerr << *it << ", ";
+ llvm::cerr << "]\n";
+ llvm::cerr << "\tA suffix: [";
+ for (std::set< ref<Expr> >::iterator it = aSuffix.begin(),
+ ie = aSuffix.end(); it != ie; ++it)
+ llvm::cerr << *it << ", ";
+ llvm::cerr << "]\n";
+ llvm::cerr << "\tB suffix: [";
+ for (std::set< ref<Expr> >::iterator it = bSuffix.begin(),
+ ie = bSuffix.end(); it != ie; ++it)
+ llvm::cerr << *it << ", ";
+ llvm::cerr << "]\n";
+ }
+
+ // We cannot merge if addresses would resolve differently in the
+ // states. This means:
+ //
+ // 1. Any objects created since the branch in either object must
+ // have been free'd.
+ //
+ // 2. We cannot have free'd any pre-existing object in one state
+ // and not the other
+
+ if (DebugLogStateMerge) {
+ llvm::cerr << "\tchecking object states\n";
+ llvm::cerr << "A: " << addressSpace.objects << "\n";
+ llvm::cerr << "B: " << b.addressSpace.objects << "\n";
+ }
+
+ std::set<const MemoryObject*> mutated;
+ MemoryMap::iterator ai = addressSpace.objects.begin();
+ MemoryMap::iterator bi = b.addressSpace.objects.begin();
+ MemoryMap::iterator ae = addressSpace.objects.end();
+ MemoryMap::iterator be = b.addressSpace.objects.end();
+ for (; ai!=ae && bi!=be; ++ai, ++bi) {
+ if (ai->first != bi->first) {
+ if (DebugLogStateMerge) {
+ if (ai->first < bi->first) {
+ llvm::cerr << "\t\tB misses binding for: " << ai->first->id << "\n";
+ } else {
+ llvm::cerr << "\t\tA misses binding for: " << bi->first->id << "\n";
+ }
+ }
+ return false;
+ }
+ if (ai->second != bi->second) {
+ if (DebugLogStateMerge)
+ llvm::cerr << "\t\tmutated: " << ai->first->id << "\n";
+ mutated.insert(ai->first);
+ }
+ }
+ if (ai!=ae || bi!=be) {
+ if (DebugLogStateMerge)
+ llvm::cerr << "\t\tmappings differ\n";
+ return false;
+ }
+
+ // merge stack
+
+ ref<Expr> inA(1, Expr::Bool), inB(1, Expr::Bool);
+ for (std::set< ref<Expr> >::iterator it = aSuffix.begin(),
+ ie = aSuffix.end(); it != ie; ++it)
+ inA = AndExpr::create(inA, *it);
+ for (std::set< ref<Expr> >::iterator it = bSuffix.begin(),
+ ie = bSuffix.end(); it != ie; ++it)
+ inB = AndExpr::create(inB, *it);
+
+ // XXX should we have a preference as to which predicate to use?
+ // it seems like it can make a difference, even though logically
+ // they must contradict each other and so inA => !inB
+
+ std::vector<StackFrame>::iterator itA = stack.begin();
+ std::vector<StackFrame>::const_iterator itB = b.stack.begin();
+ for (; itA!=stack.end(); ++itA, ++itB) {
+ StackFrame &af = *itA;
+ const StackFrame &bf = *itB;
+ for (unsigned i=0; i<af.kf->numRegisters; i++) {
+ ref<Expr> &av = af.locals[i].value;
+ const ref<Expr> &bv = bf.locals[i].value;
+ if (av.isNull() || bv.isNull()) {
+ // if one is null then by implication (we are at same pc)
+ // we cannot reuse this local, so just ignore
+ } else {
+ av = SelectExpr::create(inA, av, bv);
+ }
+ }
+ }
+
+ for (std::set<const MemoryObject*>::iterator it = mutated.begin(),
+ ie = mutated.end(); it != ie; ++it) {
+ const MemoryObject *mo = *it;
+ const ObjectState *os = addressSpace.findObject(mo);
+ const ObjectState *otherOS = b.addressSpace.findObject(mo);
+ assert(os && !os->readOnly &&
+ "objects mutated but not writable in merging state");
+ assert(otherOS);
+
+ ObjectState *wos = addressSpace.getWriteable(mo, os);
+ for (unsigned i=0; i<mo->size; i++) {
+ ref<Expr> av = wos->read8(i);
+ ref<Expr> bv = otherOS->read8(i);
+ wos->write(i, SelectExpr::create(inA, av, bv));
+ }
+ }
+
+ constraints = ConstraintManager();
+ for (std::set< ref<Expr> >::iterator it = commonConstraints.begin(),
+ ie = commonConstraints.end(); it != ie; ++it)
+ constraints.addConstraint(*it);
+ constraints.addConstraint(OrExpr::create(inA, inB));
+
+ return true;
+}
+
+/**/
+
+/*
+ Used for tainting: create a clone of os that we can revirt to with
+ the behavior that all constraints are preserved, but writes are
+ discarded. When we revirt it will be at the same address.
+ */
+ObjectState *ExecutionState::cloneObject(ObjectState *os,
+ MemoryObject *mo) {
+ MemoryMap::iterator it = shadowObjects.find(mo);
+ if (it != shadowObjects.end())
+ assert(0 && "Cannot exist already!");
+
+ llvm::cerr << "DRE: Inserting a cloned object: " << mo << "\n";
+ shadowObjects = shadowObjects.replace(std::make_pair(mo, os));
+ os = new ObjectState(*os);
+ addressSpace.bindObject(mo, os);
+ return os;
+}
+
+/***/
+
+
+ExecutionTraceEvent::ExecutionTraceEvent(ExecutionState& state,
+ KInstruction* ki)
+ : consecutiveCount(1)
+{
+ file = ki->info->file;
+ line = ki->info->line;
+ funcName = state.stack.back().kf->function->getName();
+ stackDepth = state.stack.size();
+}
+
+bool ExecutionTraceEvent::ignoreMe() const {
+ // ignore all events occurring in certain pesky uclibc files:
+ if (file.find("libc/stdio/") != std::string::npos) {
+ return true;
+ }
+
+ return false;
+}
+
+void ExecutionTraceEvent::print(std::ostream &os) const {
+ os.width(stackDepth);
+ os << ' ';
+ printDetails(os);
+ os << ' ' << file << ':' << line << ':' << funcName;
+ if (consecutiveCount > 1)
+ os << " (" << consecutiveCount << "x)\n";
+ else
+ os << '\n';
+}
+
+
+bool ExecutionTraceEventEquals(ExecutionTraceEvent* e1, ExecutionTraceEvent* e2) {
+ // first see if their base class members are identical:
+ if (!((e1->file == e2->file) &&
+ (e1->line == e2->line) &&
+ (e1->funcName == e2->funcName)))
+ return false;
+
+ // fairly ugly, but i'm no OOP master, so this is the way i'm
+ // doing it for now ... lemme know if there's a cleaner way:
+ BranchTraceEvent* be1 = dynamic_cast<BranchTraceEvent*>(e1);
+ BranchTraceEvent* be2 = dynamic_cast<BranchTraceEvent*>(e2);
+ if (be1 && be2) {
+ return ((be1->trueTaken == be2->trueTaken) &&
+ (be1->canForkGoBothWays == be2->canForkGoBothWays));
+ }
+
+ // don't tolerate duplicates in anything else:
+ return false;
+}
+
+
+void BranchTraceEvent::printDetails(std::ostream &os) const {
+ os << "BRANCH " << (trueTaken ? "T" : "F") << ' ' <<
+ (canForkGoBothWays ? "2-way" : "1-way");
+}
+
+void ExecutionTraceManager::addEvent(ExecutionTraceEvent* evt) {
+ // don't trace anything before __user_main, except for global events
+ if (!hasSeenUserMain) {
+ if (evt->funcName == "__user_main") {
+ hasSeenUserMain = true;
+ }
+ else if (evt->funcName != "global_def") {
+ return;
+ }
+ }
+
+ // custom ignore events:
+ if (evt->ignoreMe())
+ return;
+
+ if (events.size() > 0) {
+ // compress consecutive duplicates:
+ ExecutionTraceEvent* last = events.back();
+ if (ExecutionTraceEventEquals(last, evt)) {
+ last->consecutiveCount++;
+ return;
+ }
+ }
+
+ events.push_back(evt);
+}
+
+void ExecutionTraceManager::printAllEvents(std::ostream &os) const {
+ for (unsigned i = 0; i != events.size(); ++i)
+ events[i]->print(os);
+}
+
+/***/
Added: klee/trunk/lib/Core/Executor.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Executor.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Executor.cpp (added)
+++ klee/trunk/lib/Core/Executor.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,3260 @@
+//===-- Executor.cpp ------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "Executor.h"
+
+#include "CoreStats.h"
+#include "ExternalDispatcher.h"
+#include "ImpliedValue.h"
+#include "Memory.h"
+#include "MemoryManager.h"
+#include "PTree.h"
+#include "Searcher.h"
+#include "SeedInfo.h"
+#include "SpecialFunctionHandler.h"
+#include "StatsTracker.h"
+#include "TimingSolver.h"
+#include "UserSearcher.h"
+#include "../Solver/SolverStats.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Expr.h"
+#include "klee/Interpreter.h"
+#include "klee/Machine.h"
+#include "klee/TimerStatIncrementer.h"
+#include "klee/util/Assignment.h"
+#include "klee/util/ExprPPrinter.h"
+#include "klee/util/ExprUtil.h"
+#include "klee/Config/config.h"
+#include "klee/Internal/ADT/BOut.h"
+#include "klee/Internal/ADT/RNG.h"
+#include "klee/Internal/Module/Cell.h"
+#include "klee/Internal/Module/InstructionInfoTable.h"
+#include "klee/Internal/Module/KInstruction.h"
+#include "klee/Internal/Module/KModule.h"
+#include "klee/Internal/Support/FloatEvaluation.h"
+#include "klee/Internal/System/Time.h"
+
+#include "llvm/Attributes.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Module.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#include "llvm/System/Process.h"
+#include "llvm/Target/TargetData.h"
+
+#include <cassert>
+#include <algorithm>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <sstream>
+#include <vector>
+#include <string>
+
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <cxxabi.h>
+
+using namespace llvm;
+using namespace klee;
+
+// omg really hard to share cl opts across files ...
+bool WriteTraces = false;
+
+namespace {
+ cl::opt<bool>
+ DumpStatesOnHalt("dump-states-on-halt",
+ cl::init(true));
+
+ cl::opt<bool>
+ NoPreferCex("no-prefer-cex",
+ cl::init(false));
+
+ cl::opt<bool>
+ UseAsmAddresses("use-asm-addresses",
+ cl::init(false));
+
+ cl::opt<bool>
+ RandomizeFork("randomize-fork",
+ cl::init(false));
+
+ cl::opt<bool>
+ AllowExternalSymCalls("allow-external-sym-calls",
+ cl::init(false));
+
+ cl::opt<bool>
+ DebugPrintInstructions("debug-print-instructions",
+ cl::desc("Print instructions during execution."));
+
+ cl::opt<bool>
+ DebugCheckForImpliedValues("debug-check-for-implied-values");
+
+
+ cl::opt<bool>
+ SimplifySymIndices("simplify-sym-indices",
+ cl::init(false));
+
+ cl::opt<unsigned>
+ MaxSymArraySize("max-sym-array-size",
+ cl::init(0));
+
+ cl::opt<bool>
+ DebugValidateSolver("debug-validate-solver",
+ cl::init(false));
+
+ cl::opt<bool>
+ SuppressExternalWarnings("suppress-external-warnings");
+
+ cl::opt<bool>
+ AllExternalWarnings("all-external-warnings");
+
+ cl::opt<bool>
+ OnlyOutputStatesCoveringNew("only-output-states-covering-new",
+ cl::init(false));
+
+ cl::opt<bool>
+ AlwaysOutputSeeds("always-output-seeds",
+ cl::init(true));
+
+ cl::opt<bool>
+ UseFastCexSolver("use-fast-cex-solver",
+ cl::init(false));
+
+ cl::opt<bool>
+ UseIndependentSolver("use-independent-solver",
+ cl::init(true),
+ cl::desc("Use constraint independence"));
+
+ cl::opt<bool>
+ EmitAllErrors("emit-all-errors",
+ cl::init(false),
+ cl::desc("Generate tests cases for all errors "
+ "(default=one per (error,instruction) pair)"));
+
+ cl::opt<bool>
+ UseCexCache("use-cex-cache",
+ cl::init(true),
+ cl::desc("Use counterexample caching"));
+
+ cl::opt<bool>
+ UseQueryLog("use-query-log",
+ cl::init(false));
+
+ cl::opt<bool>
+ UseQueryPCLog("use-query-pc-log",
+ cl::init(false));
+
+ cl::opt<bool>
+ UseSTPQueryPCLog("use-stp-query-pc-log",
+ cl::init(false));
+
+ cl::opt<bool>
+ NoExternals("no-externals",
+ cl::desc("Do not allow external functin calls"));
+
+ cl::opt<bool>
+ UseCache("use-cache",
+ cl::init(true),
+ cl::desc("Use validity caching"));
+
+ cl::opt<bool>
+ OnlyReplaySeeds("only-replay-seeds",
+ cl::desc("Discard states that do not have a seed."));
+
+ cl::opt<bool>
+ OnlySeed("only-seed",
+ cl::desc("Stop execution after seeding is done without doing regular search."));
+
+ cl::opt<bool>
+ AllowSeedExtension("allow-seed-extension",
+ cl::desc("Allow extra (unbound) values to become symbolic during seeding."));
+
+ cl::opt<bool>
+ ZeroSeedExtension("zero-seed-extension");
+
+ cl::opt<bool>
+ AllowSeedTruncation("allow-seed-truncation",
+ cl::desc("Allow smaller buffers than in seeds."));
+
+ cl::opt<bool>
+ NamedSeedMatching("named-seed-matching",
+ cl::desc("Use names to match symbolic objects to inputs."));
+
+ cl::opt<double>
+ MaxStaticForkPct("max-static-fork-pct", cl::init(1.));
+ cl::opt<double>
+ MaxStaticSolvePct("max-static-solve-pct", cl::init(1.));
+ cl::opt<double>
+ MaxStaticCPForkPct("max-static-cpfork-pct", cl::init(1.));
+ cl::opt<double>
+ MaxStaticCPSolvePct("max-static-cpsolve-pct", cl::init(1.));
+
+ cl::opt<double>
+ MaxInstructionTime("max-instruction-time",
+ cl::desc("Only allow a single instruction to take this much time (default=0 (off))"),
+ cl::init(0));
+
+ cl::opt<double>
+ SeedTime("seed-time",
+ cl::desc("Amount of time to dedicate to seeds, before normal search (default=0 (off))"),
+ cl::init(0));
+
+ cl::opt<double>
+ MaxSTPTime("max-stp-time",
+ cl::desc("Maximum amount of time for a single query (default=120s)"),
+ cl::init(120.0));
+
+ cl::opt<unsigned int>
+ StopAfterNInstructions("stop-after-n-instructions",
+ cl::desc("Stop execution after specified number of instructions (0=off)"),
+ cl::init(0));
+
+ cl::opt<unsigned>
+ MaxForks("max-forks",
+ cl::desc("Only fork this many times (-1=off)"),
+ cl::init(~0u));
+
+ cl::opt<unsigned>
+ MaxDepth("max-depth",
+ cl::desc("Only allow this many symbolic branches (0=off)"),
+ cl::init(0));
+
+ cl::opt<unsigned>
+ MaxMemory("max-memory",
+ cl::desc("Refuse to fork when more above this about of memory (in MB, 0=off)"),
+ cl::init(0));
+
+ cl::opt<bool>
+ MaxMemoryInhibit("max-memory-inhibit",
+ cl::desc("Inhibit forking at memory cap (vs. random terminat)"),
+ cl::init(true));
+
+ // use 'external storage' because also needed by tools/klee/main.cpp
+ cl::opt<bool, true>
+ WriteTracesProxy("write-traces",
+ cl::desc("Write .trace file for each terminated state"),
+ cl::location(WriteTraces),
+ cl::init(false));
+
+ cl::opt<bool>
+ UseForkedSTP("use-forked-stp",
+ cl::desc("Run STP in forked process"));
+}
+
+
+static void *theMMap = 0;
+static unsigned theMMapSize = 0;
+
+namespace klee {
+ RNG theRNG;
+}
+
+Solver *constructSolverChain(STPSolver *stpSolver,
+ std::string queryLogPath,
+ std::string stpQueryLogPath,
+ std::string queryPCLogPath,
+ std::string stpQueryPCLogPath) {
+ Solver *solver = stpSolver;
+
+ if (UseSTPQueryPCLog)
+ solver = createPCLoggingSolver(solver,
+ stpQueryLogPath);
+
+ if (UseFastCexSolver)
+ solver = createFastCexSolver(solver);
+
+ if (UseCexCache)
+ solver = createCexCachingSolver(solver);
+
+ if (UseCache)
+ solver = createCachingSolver(solver);
+
+ if (UseIndependentSolver)
+ solver = createIndependentSolver(solver);
+
+ if (DebugValidateSolver)
+ solver = createValidatingSolver(solver, stpSolver);
+
+ if (UseQueryPCLog)
+ solver = createPCLoggingSolver(solver,
+ queryPCLogPath);
+
+ return solver;
+}
+
+Executor::Executor(const InterpreterOptions &opts,
+ InterpreterHandler *ih)
+ : Interpreter(opts),
+ kmodule(0),
+ interpreterHandler(ih),
+ searcher(0),
+ externalDispatcher(new ExternalDispatcher()),
+ statsTracker(0),
+ pathWriter(0),
+ symPathWriter(0),
+ specialFunctionHandler(0),
+ processTree(0),
+ replayOut(0),
+ replayPath(0),
+ usingSeeds(0),
+ atMemoryLimit(false),
+ inhibitForking(false),
+ haltExecution(false),
+ ivcEnabled(false),
+ stpTimeout(std::min(MaxSTPTime,MaxInstructionTime)) {
+ STPSolver *stpSolver = new STPSolver(UseForkedSTP);
+ Solver *solver =
+ constructSolverChain(stpSolver,
+ interpreterHandler->getOutputFilename("queries.qlog"),
+ interpreterHandler->getOutputFilename("stp-queries.qlog"),
+ interpreterHandler->getOutputFilename("queries.pc"),
+ interpreterHandler->getOutputFilename("stp-queries.pc"));
+
+ this->solver = new TimingSolver(solver, stpSolver);
+
+ memory = new MemoryManager();
+}
+
+
+const Module *Executor::setModule(llvm::Module *module,
+ const ModuleOptions &opts) {
+ assert(!kmodule && module && "can only register one module"); // XXX gross
+
+ kmodule = new KModule(module);
+
+ specialFunctionHandler = new SpecialFunctionHandler(*this);
+
+ specialFunctionHandler->prepare();
+ kmodule->prepare(opts, interpreterHandler);
+ specialFunctionHandler->bind();
+
+ if (StatsTracker::useStatistics()) {
+ statsTracker =
+ new StatsTracker(*this,
+ interpreterHandler->getOutputFilename("assembly.ll"),
+ userSearcherRequiresMD2U());
+ }
+
+ return module;
+}
+
+Executor::~Executor() {
+ delete memory;
+ delete externalDispatcher;
+ if (processTree)
+ delete processTree;
+ if (specialFunctionHandler)
+ delete specialFunctionHandler;
+ if (statsTracker)
+ delete statsTracker;
+ delete solver;
+ delete kmodule;
+}
+
+/***/
+
+void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os,
+ Constant *c,
+ unsigned offset) {
+ TargetData *targetData = kmodule->targetData;
+ if (ConstantVector *cp = dyn_cast<ConstantVector>(c)) {
+ unsigned elementSize =
+ targetData->getTypeStoreSize(cp->getType()->getElementType());
+ for (unsigned i=0, e=cp->getNumOperands(); i != e; ++i)
+ initializeGlobalObject(state, os, cp->getOperand(i),
+ offset + i*elementSize);
+ } else if (isa<ConstantAggregateZero>(c)) {
+ unsigned i, size = targetData->getTypeStoreSize(c->getType());
+ for (i=0; i<size; i++)
+ os->write8(offset+i, (uint8_t) 0);
+ } else if (ConstantArray *ca = dyn_cast<ConstantArray>(c)) {
+ unsigned elementSize =
+ targetData->getTypeStoreSize(ca->getType()->getElementType());
+ for (unsigned i=0, e=ca->getNumOperands(); i != e; ++i)
+ initializeGlobalObject(state, os, ca->getOperand(i),
+ offset + i*elementSize);
+ } else if (ConstantStruct *cs = dyn_cast<ConstantStruct>(c)) {
+ const StructLayout *sl =
+ targetData->getStructLayout(cast<StructType>(cs->getType()));
+ for (unsigned i=0, e=cs->getNumOperands(); i != e; ++i)
+ initializeGlobalObject(state, os, cs->getOperand(i),
+ offset + sl->getElementOffset(i));
+ } else {
+ os->write(offset, evalConstant(c));
+ }
+}
+
+MemoryObject * Executor::addExternalObject(ExecutionState &state,
+ void *addr, unsigned size,
+ bool isReadOnly) {
+ MemoryObject *mo = memory->allocateFixed((uint64_t) (unsigned long) addr,
+ size, 0);
+ ObjectState *os = bindObjectInState(state, mo, false);
+ for(unsigned i = 0; i < size; i++)
+ os->write8(i, ((uint8_t*)addr)[i]);
+ if(isReadOnly)
+ os->setReadOnly(true);
+ return mo;
+}
+
+void Executor::initializeGlobals(ExecutionState &state) {
+ Module *m = kmodule->module;
+
+ if (m->getModuleInlineAsm() != "")
+ klee_warning("executable has module level assembly (ignoring)");
+
+ assert(m->lib_begin() == m->lib_end() &&
+ "XXX do not support dependent libraries");
+
+ // represent function globals using the address of the actual llvm function
+ // object. given that we use malloc to allocate memory in states this also
+ // ensures that we won't conflict. we don't need to allocate a memory object
+ // since reading/writing via a function pointer is unsupported anyway.
+ for (Module::iterator i = m->begin(), ie = m->end(); i != ie; ++i) {
+ Function *f = i;
+ ref<Expr> addr(0);
+
+ // If the symbol has external weak linkage then it is implicitly
+ // not defined in this module; if it isn't resolvable then it
+ // should be null.
+ if (f->hasExternalWeakLinkage() &&
+ !externalDispatcher->resolveSymbol(f->getName())) {
+ addr = Expr::createPointer(0);
+ } else {
+ addr = Expr::createPointer((unsigned long) (void*) f);
+ legalFunctions.insert(f);
+ }
+
+ globalAddresses.insert(std::make_pair(f, addr));
+ }
+
+ // Disabled, we don't want to promote use of live externals.
+#ifdef HAVE_CTYPE_EXTERNALS
+#ifndef WINDOWS
+#ifndef DARWIN
+ /* From /usr/include/errno.h: it [errno] is a per-thread variable. */
+ int *errno_addr = __errno_location();
+ addExternalObject(state, (void *)errno_addr, sizeof *errno_addr, false);
+
+ /* from /usr/include/ctype.h:
+ These point into arrays of 384, so they can be indexed by any `unsigned
+ char' value [0,255]; by EOF (-1); or by any `signed char' value
+ [-128,-1). ISO C requires that the ctype functions work for `unsigned */
+ const uint16_t **addr = __ctype_b_loc();
+ addExternalObject(state, (void *)(*addr-128),
+ 384 * sizeof **addr, true);
+ addExternalObject(state, addr, 4, true);
+
+ const int32_t **lower_addr = __ctype_tolower_loc();
+ addExternalObject(state, (void *)(*lower_addr-128),
+ 384 * sizeof **lower_addr, true);
+ addExternalObject(state, lower_addr, 4, true);
+
+ const int32_t **upper_addr = __ctype_toupper_loc();
+ addExternalObject(state, (void *)(*upper_addr-128),
+ 384 * sizeof **upper_addr, true);
+ addExternalObject(state, upper_addr, 4, true);
+#endif
+#endif
+#endif
+
+ // allocate and initialize globals, done in two passes since we may
+ // need address of a global in order to initialize some other one.
+
+ // allocate memory objects for all globals
+ for (Module::const_global_iterator i = m->global_begin(),
+ e = m->global_end();
+ i != e; ++i) {
+ if (i->isDeclaration()) {
+ // FIXME: We have no general way of handling unknown external
+ // symbols. If we really cared about making external stuff work
+ // better we could support user definition, or use the EXE style
+ // hack where we check the object file information.
+
+ const Type *ty = i->getType()->getElementType();
+ const std::string &name = i->getName();
+ uint64_t size = kmodule->targetData->getTypeStoreSize(ty);
+
+ // XXX - DWD - hardcode some things until we decide how to fix.
+#ifndef WINDOWS
+ if (name == "_ZTVN10__cxxabiv117__class_type_infoE") {
+ size = 0x2C;
+ } else if (name == "_ZTVN10__cxxabiv120__si_class_type_infoE") {
+ size = 0x2C;
+ } else if (name == "_ZTVN10__cxxabiv121__vmi_class_type_infoE") {
+ size = 0x2C;
+ }
+#endif
+
+ if (size == 0) {
+ llvm::cerr << "Unable to find size for global variable: " << i->getName()
+ << " (use will result in out of bounds access)\n";
+ }
+
+ MemoryObject *mo = memory->allocate(size, false, true, i);
+ ObjectState *os = bindObjectInState(state, mo, false);
+ globalObjects.insert(std::make_pair(i, mo));
+ globalAddresses.insert(std::make_pair(i, mo->getBaseExpr()));
+
+ // Program already running = object already initialized. Read
+ // concrete value and write it to our copy.
+ if (size) {
+ void *addr;
+ if (name=="__dso_handle") {
+ extern void *__dso_handle __attribute__ ((__weak__));
+ addr = &__dso_handle; // wtf ?
+ } else {
+ addr = externalDispatcher->resolveSymbol(name);
+ }
+ if (!addr)
+ klee_error("unable to load symbol(%s) while initializing globals.",
+ name.c_str());
+
+ for (unsigned offset=0; offset<mo->size; offset++)
+ os->write8(offset, ((unsigned char*)addr)[offset]);
+ }
+ } else {
+ const std::string &name = i->getName();
+ const Type *ty = i->getType()->getElementType();
+ uint64_t size = kmodule->targetData->getTypeStoreSize(ty);
+ MemoryObject *mo = 0;
+
+ if (UseAsmAddresses && name[0]=='\01') {
+ char *end;
+ uint64_t address = ::strtoll(name.c_str()+1, &end, 0);
+
+ if (end && *end == '\0') {
+ klee_message("NOTE: allocated global at asm specified address: %#08llx"
+ " (%llu bytes)",
+ address, size);
+ mo = memory->allocateFixed(address, size, &*i);
+ mo->isUserSpecified = true; // XXX hack;
+ }
+ }
+
+ if (!mo)
+ mo = memory->allocate(size, false, true, &*i);
+ assert(mo && "out of memory");
+ ObjectState *os = bindObjectInState(state, mo, false);
+ globalObjects.insert(std::make_pair(i, mo));
+ globalAddresses.insert(std::make_pair(i, mo->getBaseExpr()));
+
+ if (!i->hasInitializer())
+ os->initializeToRandom();
+ }
+ }
+
+ // link aliases to their definitions (if bound)
+ for (Module::alias_iterator i = m->alias_begin(), ie = m->alias_end();
+ i != ie; ++i) {
+ // Map the alias to its aliasee's address. This works because we have
+ // addresses for everything, even undefined functions.
+ globalAddresses.insert(std::make_pair(i, evalConstant(i->getAliasee())));
+ }
+
+ // once all objects are allocated, do the actual initialization
+ for (Module::const_global_iterator i = m->global_begin(),
+ e = m->global_end();
+ i != e; ++i) {
+ if (i->hasInitializer()) {
+ MemoryObject *mo = globalObjects.find(i)->second;
+ const ObjectState *os = state.addressSpace.findObject(mo);
+ assert(os);
+ ObjectState *wos = state.addressSpace.getWriteable(mo, os);
+
+ initializeGlobalObject(state, wos, i->getInitializer(), 0);
+ // if(i->isConstant()) os->setReadOnly(true);
+ }
+ }
+}
+
+void Executor::branch(ExecutionState &state,
+ const std::vector< ref<Expr> > &conditions,
+ std::vector<ExecutionState*> &result) {
+ TimerStatIncrementer timer(stats::forkTime);
+ unsigned N = conditions.size();
+ assert(N);
+
+ stats::forks += N-1;
+
+ // XXX do proper balance or keep random?
+ result.push_back(&state);
+ for (unsigned i=1; i<N; ++i) {
+ ExecutionState *es = result[theRNG.getInt32() % i];
+ ExecutionState *ns = es->branch();
+ addedStates.insert(ns);
+ result.push_back(ns);
+ es->ptreeNode->data = 0;
+ std::pair<PTree::Node*,PTree::Node*> res =
+ processTree->split(es->ptreeNode, ns, es);
+ ns->ptreeNode = res.first;
+ es->ptreeNode = res.second;
+ }
+
+ // If necessary redistribute seeds to match conditions, killing
+ // states if necessary due to OnlyReplaySeeds (inefficient but
+ // simple).
+
+ std::map< ExecutionState*, std::vector<SeedInfo> >::iterator it =
+ seedMap.find(&state);
+ if (it != seedMap.end()) {
+ std::vector<SeedInfo> seeds = it->second;
+ seedMap.erase(it);
+
+ // Assume each seed only satisfies one condition (necessarily true
+ // when conditions are mutually exclusive and their conjunction is
+ // a tautology).
+ for (std::vector<SeedInfo>::iterator siit = seeds.begin(),
+ siie = seeds.end(); siit != siie; ++siit) {
+ unsigned i;
+ for (i=0; i<N; ++i) {
+ ref<Expr> res;
+ bool success =
+ solver->getValue(state, siit->assignment.evaluate(conditions[i]),
+ res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res.getConstantValue())
+ break;
+ }
+
+ // If we didn't find a satisfying condition randomly pick one
+ // (the seed will be patched).
+ if (i==N)
+ i = theRNG.getInt32() % N;
+
+ seedMap[result[i]].push_back(*siit);
+ }
+
+ if (OnlyReplaySeeds) {
+ for (unsigned i=0; i<N; ++i) {
+ if (!seedMap.count(result[i])) {
+ terminateState(*result[i]);
+ result[i] = NULL;
+ }
+ }
+ }
+ }
+
+ for (unsigned i=0; i<N; ++i)
+ if (result[i])
+ addConstraint(*result[i], conditions[i]);
+}
+
+Executor::StatePair
+Executor::fork(ExecutionState ¤t, ref<Expr> condition, bool isInternal) {
+ Solver::Validity res;
+ std::map< ExecutionState*, std::vector<SeedInfo> >::iterator it =
+ seedMap.find(¤t);
+ bool isSeeding = it != seedMap.end();
+
+ if (!isSeeding &&
+ !condition.isConstant() &&
+ (MaxStaticForkPct!=1. || MaxStaticSolvePct != 1. ||
+ MaxStaticCPForkPct!=1. || MaxStaticCPSolvePct != 1.) &&
+ statsTracker->elapsed() > 60.) {
+ StatisticManager &sm = *theStatisticManager;
+ CallPathNode *cpn = current.stack.back().callPathNode;
+ if ((MaxStaticForkPct<1. &&
+ sm.getIndexedValue(stats::forks, sm.getIndex()) >
+ stats::forks*MaxStaticForkPct) ||
+ (MaxStaticCPForkPct<1. &&
+ cpn && (cpn->statistics.getValue(stats::forks) >
+ stats::forks*MaxStaticCPForkPct)) ||
+ (MaxStaticSolvePct<1 &&
+ sm.getIndexedValue(stats::solverTime, sm.getIndex()) >
+ stats::solverTime*MaxStaticSolvePct) ||
+ (MaxStaticCPForkPct<1. &&
+ cpn && (cpn->statistics.getValue(stats::solverTime) >
+ stats::solverTime*MaxStaticCPSolvePct))) {
+ ref<Expr> value;
+ bool success = solver->getValue(current, condition, value);
+ assert(success && "FIXME: Unhandled solver failure");
+ addConstraint(current, EqExpr::create(value, condition));
+ condition = value;
+ }
+ }
+
+ double timeout = stpTimeout;
+ if (isSeeding)
+ timeout *= it->second.size();
+ solver->setTimeout(timeout);
+ bool success = solver->evaluate(current, condition, res);
+ solver->setTimeout(0);
+ if (!success) {
+ current.pc = current.prevPC;
+ terminateStateEarly(current, "query timed out");
+ return StatePair(0, 0);
+ }
+
+ if (!isSeeding) {
+ if (replayPath && !isInternal) {
+ assert(replayPosition<replayPath->size() &&
+ "ran out of branches in replay path mode");
+ bool branch = (*replayPath)[replayPosition++];
+
+ if (res==Solver::True) {
+ assert(branch && "hit invalid branch in replay path mode");
+ } else if (res==Solver::False) {
+ assert(!branch && "hit invalid branch in replay path mode");
+ } else {
+ // add constraints
+ if(branch) {
+ res = Solver::True;
+ addConstraint(current, condition);
+ } else {
+ res = Solver::False;
+ addConstraint(current, Expr::createNot(condition));
+ }
+ }
+ } else if (res==Solver::Unknown) {
+ assert(!replayOut && "in replay mode, only one branch can be true.");
+
+ if ((MaxMemoryInhibit && atMemoryLimit) ||
+ current.forkDisabled ||
+ inhibitForking ||
+ (MaxForks!=~0u && stats::forks >= MaxForks)) {
+ TimerStatIncrementer timer(stats::forkTime);
+ if (theRNG.getBool()) {
+ addConstraint(current, condition);
+ res = Solver::True;
+ } else {
+ addConstraint(current, Expr::createNot(condition));
+ res = Solver::False;
+ }
+ }
+ }
+ }
+
+ // Fix branch in only-replay-seed mode, if we don't have both true
+ // and false seeds.
+ if (isSeeding &&
+ (current.forkDisabled || OnlyReplaySeeds) &&
+ res == Solver::Unknown) {
+ bool trueSeed=false, falseSeed=false;
+ // Is seed extension still ok here?
+ for (std::vector<SeedInfo>::iterator siit = it->second.begin(),
+ siie = it->second.end(); siit != siie; ++siit) {
+ ref<Expr> res;
+ bool success =
+ solver->getValue(current, siit->assignment.evaluate(condition), res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res.isConstant()) {
+ if (res.getConstantValue()) {
+ trueSeed = true;
+ } else {
+ falseSeed = true;
+ }
+ if (trueSeed && falseSeed)
+ break;
+ }
+ }
+ if (!(trueSeed && falseSeed)) {
+ assert(trueSeed || falseSeed);
+
+ res = trueSeed ? Solver::True : Solver::False;
+ addConstraint(current, trueSeed ? condition : Expr::createNot(condition));
+ }
+ }
+
+
+ // XXX - even if the constraint is provable one way or the other we
+ // can probably benefit by adding this constraint and allowing it to
+ // reduce the other constraints. For example, if we do a binary
+ // search on a particular value, and then see a comparison against
+ // the value it has been fixed at, we should take this as a nice
+ // hint to just use the single constraint instead of all the binary
+ // search ones. If that makes sense.
+ if (res==Solver::True) {
+ if (!isInternal) {
+ if (pathWriter) {
+ current.pathOS << "1";
+ }
+ }
+
+ return StatePair(¤t, 0);
+ } else if (res==Solver::False) {
+ if (!isInternal) {
+ if (pathWriter) {
+ current.pathOS << "0";
+ }
+ }
+
+ return StatePair(0, ¤t);
+ } else {
+ TimerStatIncrementer timer(stats::forkTime);
+ ExecutionState *falseState, *trueState = ¤t;
+
+ ++stats::forks;
+
+ falseState = trueState->branch();
+ addedStates.insert(falseState);
+
+ if (RandomizeFork && theRNG.getBool())
+ std::swap(trueState, falseState);
+
+ if (it != seedMap.end()) {
+ std::vector<SeedInfo> seeds = it->second;
+ it->second.clear();
+ std::vector<SeedInfo> &trueSeeds = seedMap[trueState];
+ std::vector<SeedInfo> &falseSeeds = seedMap[falseState];
+ for (std::vector<SeedInfo>::iterator siit = seeds.begin(),
+ siie = seeds.end(); siit != siie; ++siit) {
+ ref<Expr> res;
+ bool success =
+ solver->getValue(current, siit->assignment.evaluate(condition), res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res.getConstantValue()) {
+ trueSeeds.push_back(*siit);
+ } else {
+ falseSeeds.push_back(*siit);
+ }
+ }
+
+ bool swapInfo = false;
+ if (trueSeeds.empty()) {
+ if (¤t == trueState) swapInfo = true;
+ seedMap.erase(trueState);
+ }
+ if (falseSeeds.empty()) {
+ if (¤t == falseState) swapInfo = true;
+ seedMap.erase(falseState);
+ }
+ if (swapInfo) {
+ std::swap(trueState->coveredNew, falseState->coveredNew);
+ std::swap(trueState->coveredLines, falseState->coveredLines);
+ }
+ }
+
+ current.ptreeNode->data = 0;
+ std::pair<PTree::Node*, PTree::Node*> res =
+ processTree->split(current.ptreeNode, falseState, trueState);
+ falseState->ptreeNode = res.first;
+ trueState->ptreeNode = res.second;
+
+ if (!isInternal) {
+ if (pathWriter) {
+ falseState->pathOS = pathWriter->open(current.pathOS);
+ trueState->pathOS << "1";
+ falseState->pathOS << "0";
+ }
+ if (symPathWriter) {
+ falseState->symPathOS = symPathWriter->open(current.symPathOS);
+ trueState->symPathOS << "1";
+ falseState->symPathOS << "0";
+ }
+ }
+
+ addConstraint(*trueState, condition);
+ addConstraint(*falseState, Expr::createNot(condition));
+
+ // Kinda gross, do we even really still want this option?
+ if (MaxDepth && MaxDepth<=trueState->depth) {
+ terminateStateEarly(*trueState, "max-depth exceeded");
+ terminateStateEarly(*falseState, "max-depth exceeded");
+ return StatePair(0, 0);
+ }
+
+ return StatePair(trueState, falseState);
+ }
+}
+
+void Executor::addConstraint(ExecutionState &state, ref<Expr> condition) {
+ if (condition.isConstant()) {
+ assert(condition.getConstantValue() &&
+ "attempt to add invalid constraint");
+ return;
+ }
+
+ // Check to see if this constraint violates seeds.
+ std::map< ExecutionState*, std::vector<SeedInfo> >::iterator it =
+ seedMap.find(&state);
+ if (it != seedMap.end()) {
+ bool warn = false;
+ for (std::vector<SeedInfo>::iterator siit = it->second.begin(),
+ siie = it->second.end(); siit != siie; ++siit) {
+ bool res;
+ bool success =
+ solver->mustBeFalse(state, siit->assignment.evaluate(condition), res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res) {
+ siit->patchSeed(state, condition, solver);
+ warn = true;
+ }
+ }
+ if (warn)
+ klee_warning("seeds patched for violating constraint");
+ }
+
+ state.addConstraint(condition);
+ if (ivcEnabled)
+ doImpliedValueConcretization(state, condition, ref<Expr>(1, Expr::Bool));
+}
+
+ref<Expr> Executor::evalConstant(Constant *c) {
+ if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(c)) {
+ return evalConstantExpr(ce);
+ } else {
+ if (const ConstantInt *ci = dyn_cast<ConstantInt>(c)) {
+ switch(ci->getBitWidth()) {
+ case 1: return ConstantExpr::create(ci->getZExtValue(), Expr::Bool);
+ case 8: return ConstantExpr::create(ci->getZExtValue(), Expr::Int8);
+ case 16: return ConstantExpr::create(ci->getZExtValue(), Expr::Int16);
+ case 32: return ConstantExpr::create(ci->getZExtValue(), Expr::Int32);
+ case 64: return ConstantExpr::create(ci->getZExtValue(), Expr::Int64);
+ default:
+ assert(0 && "XXX arbitrary bit width constants unhandled");
+ }
+ } else if (const ConstantFP *cf = dyn_cast<ConstantFP>(c)) {
+ switch(cf->getType()->getTypeID()) {
+ case Type::FloatTyID: {
+ float f = cf->getValueAPF().convertToFloat();
+ return ConstantExpr::create(floats::FloatAsUInt64(f), Expr::Int32);
+ }
+ case Type::DoubleTyID: {
+ double d = cf->getValueAPF().convertToDouble();
+ return ConstantExpr::create(floats::DoubleAsUInt64(d), Expr::Int64);
+ }
+ case Type::X86_FP80TyID: {
+ // FIXME: This is really broken, but for now we just convert
+ // to a double. This isn't going to work at all in general,
+ // but we need support for wide constants.
+ APFloat apf = cf->getValueAPF();
+ bool ignored;
+ APFloat::opStatus r = apf.convert(APFloat::IEEEdouble,
+ APFloat::rmNearestTiesToAway,
+ &ignored);
+ (void) r;
+ //assert(!(r & APFloat::opOverflow) && !(r & APFloat::opUnderflow) &&
+ // "Overflow/underflow while converting from FP80 (x87) to 64-bit double");
+ double d = apf.convertToDouble();
+ return ConstantExpr::create(floats::DoubleAsUInt64(d), Expr::Int64);
+ }
+ default:
+ llvm::cerr << "Constant of type " << cf->getType()->getDescription()
+ << " not supported\n";
+ llvm::cerr << "Constant used at ";
+ KConstant *kc = kmodule->getKConstant((Constant*) cf);
+ if (kc && kc->ki && kc->ki->info)
+ llvm::cerr << kc->ki->info->file << ":" << kc->ki->info->line << "\n";
+ else llvm::cerr << "<unknown>\n";
+
+ assert(0 && "Arbitrary bit width floating point constants unsupported");
+ }
+ } else if (const GlobalValue *gv = dyn_cast<GlobalValue>(c)) {
+ return globalAddresses.find(gv)->second;
+ } else if (isa<ConstantPointerNull>(c)) {
+ return Expr::createPointer(0);
+ } else if (isa<UndefValue>(c)) {
+ return ConstantExpr::create(0, Expr::getWidthForLLVMType(c->getType()));
+ } else {
+ // Constant{AggregateZero,Array,Struct,Vector}
+ assert(0 && "invalid argument to evalConstant()");
+ }
+ }
+}
+
+ref<Expr> Executor::eval(KInstruction *ki,
+ unsigned index,
+ ExecutionState &state) {
+ assert(index < ki->inst->getNumOperands());
+ int vnumber = ki->operands[index];
+
+ // Determine if this is a constant or not.
+ if (vnumber < 0) {
+ unsigned index = -vnumber - 2;
+ Cell &c = kmodule->constantTable[index];
+ return c.value;
+ } else {
+ unsigned index = vnumber;
+ StackFrame &sf = state.stack.back();
+ Cell &c = sf.locals[index];
+ return c.value;
+ }
+}
+
+void Executor::bindLocal(KInstruction *target, ExecutionState &state,
+ ref<Expr> value) {
+ StackFrame &sf = state.stack.back();
+ unsigned reg = target->dest;
+ Cell &c = sf.locals[reg];
+ c.value = value;
+}
+
+void Executor::bindArgument(KFunction *kf, unsigned index,
+ ExecutionState &state, ref<Expr> value) {
+ StackFrame &sf = state.stack.back();
+ unsigned reg = kf->getArgRegister(index);
+ Cell &c = sf.locals[reg];
+ c.value = value;
+}
+
+ref<Expr> Executor::toUnique(const ExecutionState &state,
+ ref<Expr> &e) {
+ ref<Expr> result = e;
+
+ if (!e.isConstant()) {
+ ref<Expr> value(0);
+ bool isTrue = false;
+
+ solver->setTimeout(stpTimeout);
+ if (solver->getValue(state, e, value) &&
+ solver->mustBeTrue(state, EqExpr::create(e, value), isTrue) &&
+ isTrue)
+ result = value;
+ solver->setTimeout(0);
+ }
+
+ return result;
+}
+
+
+/* Concretize the given expression, and return a possible constant value.
+ 'reason' is just a documentation string stating the reason for concretization. */
+ref<Expr> Executor::toConstant(ExecutionState &state,
+ ref<Expr> e,
+ const char *reason) {
+ e = state.constraints.simplifyExpr(e);
+ if (!e.isConstant()) {
+ ref<Expr> value;
+ bool success = solver->getValue(state, e, value);
+ assert(success && "FIXME: Unhandled solver failure");
+
+ std::ostringstream os;
+ os << "silently concretizing (reason: " << reason << ") expression " << e
+ << " to value " << value
+ << " (" << (*(state.pc)).info->file << ":" << (*(state.pc)).info->line << ")";
+
+ if (AllExternalWarnings)
+ klee_warning(reason, os.str().c_str());
+ else
+ klee_warning_once(reason, "%s", os.str().c_str());
+
+ addConstraint(state, EqExpr::create(e, value));
+
+ return value;
+ } else {
+ return e;
+ }
+}
+
+void Executor::executeGetValue(ExecutionState &state,
+ ref<Expr> e,
+ KInstruction *target) {
+ e = state.constraints.simplifyExpr(e);
+ std::map< ExecutionState*, std::vector<SeedInfo> >::iterator it =
+ seedMap.find(&state);
+ if (it==seedMap.end() || e.isConstant()) {
+ ref<Expr> value;
+ bool success = solver->getValue(state, e, value);
+ assert(success && "FIXME: Unhandled solver failure");
+ bindLocal(target, state, value);
+ } else {
+ std::set< ref<Expr> > values;
+ for (std::vector<SeedInfo>::iterator siit = it->second.begin(),
+ siie = it->second.end(); siit != siie; ++siit) {
+ ref<Expr> value;
+ bool success =
+ solver->getValue(state, siit->assignment.evaluate(e), value);
+ assert(success && "FIXME: Unhandled solver failure");
+ values.insert(value);
+ }
+
+ std::vector< ref<Expr> > conditions;
+ for (std::set< ref<Expr> >::iterator vit = values.begin(),
+ vie = values.end(); vit != vie; ++vit)
+ conditions.push_back(EqExpr::create(e, *vit));
+
+ std::vector<ExecutionState*> branches;
+ branch(state, conditions, branches);
+
+ std::vector<ExecutionState*>::iterator bit = branches.begin();
+ for (std::set< ref<Expr> >::iterator vit = values.begin(),
+ vie = values.end(); vit != vie; ++vit) {
+ ExecutionState *es = *bit;
+ if (es)
+ bindLocal(target, *es, *vit);
+ ++bit;
+ }
+ }
+}
+
+void Executor::stepInstruction(ExecutionState &state) {
+ if (DebugPrintInstructions) {
+ printFileLine(state, state.pc);
+ llvm::cerr << std::setw(10) << stats::instructions << " " << *state.pc->inst;
+ }
+
+ if (statsTracker)
+ statsTracker->stepInstruction(state);
+
+ ++stats::instructions;
+ state.prevPC = state.pc;
+ ++state.pc;
+
+ if (stats::instructions==StopAfterNInstructions)
+ haltExecution = true;
+}
+
+void Executor::executeCall(ExecutionState &state,
+ KInstruction *ki,
+ Function *f,
+ std::vector< ref<Expr> > &arguments) {
+ if (WriteTraces) {
+ // don't print out special debug stop point 'function' calls
+ if (f->getIntrinsicID() != Intrinsic::dbg_stoppoint) {
+ const std::string& calleeFuncName = f->getName();
+ state.exeTraceMgr.addEvent(new FunctionCallTraceEvent(state, ki, calleeFuncName));
+ }
+ }
+
+ Instruction *i = ki->inst;
+ if (f && f->isDeclaration()) {
+ if (f!=kmodule->dbgStopPointFn) { // special case speed hack
+ switch(f->getIntrinsicID()) {
+ case Intrinsic::dbg_stoppoint:
+ case Intrinsic::dbg_region_start:
+ case Intrinsic::dbg_region_end:
+ case Intrinsic::dbg_func_start:
+ case Intrinsic::dbg_declare:
+ case Intrinsic::not_intrinsic:
+ // state may be destroyed by this call, cannot touch
+ callExternalFunction(state, ki, f, arguments);
+ break;
+
+ // vararg is handled by caller and intrinsic lowering,
+ // see comment for ExecutionState::varargs
+ case Intrinsic::vastart: {
+ StackFrame &sf = state.stack.back();
+ assert(sf.varargs &&
+ "vastart called in function with no vararg object");
+ executeMemoryOperation(state, true, arguments[0],
+ sf.varargs->getBaseExpr(), 0);
+ break;
+ }
+ case Intrinsic::vaend: // va_end is a noop for the interpreter
+ break;
+
+ case Intrinsic::vacopy: // should be lowered
+ default:
+ klee_error("unknown intrinsic: %s", f->getName().c_str());
+ }
+ }
+
+ if (InvokeInst *ii = dyn_cast<InvokeInst>(i)) {
+ transferToBasicBlock(ii->getNormalDest(), i->getParent(), state);
+ }
+ } else {
+ // XXX not really happy about this reliance on prevPC but is ok I
+ // guess. This just done to avoid having to pass KInstIterator
+ // everywhere instead of the actual instruction, since we can't
+ // make a KInstIterator from just an instruction (unlike LLVM).
+ KFunction *kf = kmodule->functionMap[f];
+ state.pushFrame(state.prevPC, kf);
+ state.pc = kf->instructions;
+
+ if (statsTracker)
+ statsTracker->framePushed(state, &state.stack[state.stack.size()-2]);
+
+ unsigned callingArgs = arguments.size();
+ unsigned funcArgs = f->arg_size();
+ if (!f->isVarArg()) {
+ if (callingArgs > funcArgs) {
+ klee_warning_once(f, "calling %s with extra arguments.",
+ f->getName().c_str());
+ } else if (callingArgs < funcArgs) {
+ terminateStateOnError(state, "calling function with too few arguments",
+ "user.err");
+ return;
+ }
+ } else {
+ if (callingArgs < funcArgs) {
+ terminateStateOnError(state, "calling function with too few arguments",
+ "user.err");
+ return;
+ }
+
+ StackFrame &sf = state.stack.back();
+ unsigned size = 0;
+ for (unsigned i = funcArgs; i < callingArgs; i++)
+ size += Expr::getMinBytesForWidth(arguments[i].getWidth());
+
+ MemoryObject *mo = sf.varargs = memory->allocate(size, true, false,
+ state.prevPC->inst);
+ if (!mo) {
+ terminateStateOnExecError(state, "out of memory (varargs)");
+ return;
+ }
+ ObjectState *os = bindObjectInState(state, mo, true);
+ unsigned offset = 0;
+ for (unsigned i = funcArgs; i < callingArgs; i++) {
+ // XXX: DRE: i think we bind memory objects here?
+ os->write(offset, arguments[i]);
+ offset += Expr::getMinBytesForWidth(arguments[i].getWidth());
+ }
+ }
+
+ unsigned numFormals = f->arg_size();
+ for (unsigned i=0; i<numFormals; ++i)
+ bindArgument(kf, i, state, arguments[i]);
+ }
+}
+
+void Executor::transferToBasicBlock(BasicBlock *dst, BasicBlock *src,
+ ExecutionState &state) {
+ // Note that in general phi nodes can reuse phi values from the same
+ // block but the incoming value is the eval() result *before* the
+ // execution of any phi nodes. this is pathological and doesn't
+ // really seem to occur, but just in case we run the PhiCleanerPass
+ // which makes sure this cannot happen and so it is safe to just
+ // eval things in order. The PhiCleanerPass also makes sure that all
+ // incoming blocks have the same order for each PHINode so we only
+ // have to compute the index once.
+ //
+ // With that done we simply set an index in the state so that PHI
+ // instructions know which argument to eval, set the pc, and continue.
+
+ // XXX this lookup has to go ?
+ KFunction *kf = state.stack.back().kf;
+ unsigned entry = kf->basicBlockEntry[dst];
+ state.pc = &kf->instructions[entry];
+ if (state.pc->inst->getOpcode() == Instruction::PHI) {
+ PHINode *first = static_cast<PHINode*>(state.pc->inst);
+ state.incomingBBIndex = first->getBasicBlockIndex(src);
+ }
+}
+
+void Executor::printFileLine(ExecutionState &state, KInstruction *ki) {
+ const InstructionInfo &ii = *ki->info;
+ if (ii.file != "")
+ llvm::cerr << " " << ii.file << ":" << ii.line << ":";
+ else
+ llvm::cerr << " [no debug info]:";
+}
+
+
+Function* Executor::getCalledFunction(CallSite &cs, ExecutionState &state) {
+ Function *f = cs.getCalledFunction();
+
+ if (f) {
+ std::string alias = state.getFnAlias(f->getName());
+ if (alias != "") {
+ //llvm::cerr << f->getName() << "() is aliased with " << alias << "()\n";
+ llvm::Module* currModule = kmodule->module;
+ Function* old_f = f;
+ f = currModule->getFunction(alias);
+ if (!f) {
+ llvm::cerr << "Function " << alias << "(), alias for " << old_f->getName() << " not found!\n";
+ assert(f && "function alias not found");
+ }
+ }
+ }
+
+ return f;
+}
+
+
+void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
+ Instruction *i = ki->inst;
+ switch (i->getOpcode()) {
+ // Control flow
+ case Instruction::Ret: {
+ ReturnInst *ri = cast<ReturnInst>(i);
+ KInstIterator kcaller = state.stack.back().caller;
+ Instruction *caller = kcaller ? kcaller->inst : 0;
+ bool isVoidReturn = (ri->getNumOperands() == 0);
+ ref<Expr> result(0,Expr::Bool);
+
+ if (WriteTraces) {
+ state.exeTraceMgr.addEvent(new FunctionReturnTraceEvent(state, ki));
+ }
+
+ if (!isVoidReturn) {
+ result = eval(ki, 0, state);
+ }
+
+ if (state.stack.size() <= 1) {
+ assert(!caller && "caller set on initial stack frame");
+ terminateStateOnExit(state);
+ } else {
+ state.popFrame();
+
+ if (statsTracker)
+ statsTracker->framePopped(state);
+
+ if (InvokeInst *ii = dyn_cast<InvokeInst>(caller)) {
+ transferToBasicBlock(ii->getNormalDest(), caller->getParent(), state);
+ } else {
+ state.pc = kcaller;
+ ++state.pc;
+ }
+
+ if (!isVoidReturn) {
+ const Type *t = caller->getType();
+ if (t != Type::VoidTy) {
+ // may need to do coercion due to bitcasts
+ Expr::Width from = result.getWidth();
+ Expr::Width to = Expr::getWidthForLLVMType(t);
+
+ if (from != to) {
+ CallSite cs = (isa<InvokeInst>(caller) ? CallSite(cast<InvokeInst>(caller)) :
+ CallSite(cast<CallInst>(caller)));
+
+ // XXX need to check other param attrs ?
+ if (cs.paramHasAttr(0, llvm::Attribute::SExt)) {
+ result = SExtExpr::create(result, to);
+ } else {
+ result = ZExtExpr::create(result, to);
+ }
+ }
+
+ bindLocal(kcaller, state, result);
+ }
+ } else {
+ // We check that the return value has no users instead of
+ // checking the type, since C defaults to returning int for
+ // undeclared functions.
+ if (!caller->use_empty()) {
+ terminateStateOnExecError(state, "return void when caller expected a result");
+ }
+ }
+ }
+ break;
+ }
+ case Instruction::Unwind: {
+ for (;;) {
+ KInstruction *kcaller = state.stack.back().caller;
+ state.popFrame();
+
+ if (statsTracker)
+ statsTracker->framePopped(state);
+
+ if (state.stack.empty()) {
+ terminateStateOnExecError(state, "unwind from initial stack frame");
+ break;
+ } else {
+ Instruction *caller = kcaller->inst;
+ if (InvokeInst *ii = dyn_cast<InvokeInst>(caller)) {
+ transferToBasicBlock(ii->getUnwindDest(), caller->getParent(), state);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case Instruction::Br: {
+ BranchInst *bi = cast<BranchInst>(i);
+ if (bi->isUnconditional()) {
+ transferToBasicBlock(bi->getSuccessor(0), bi->getParent(), state);
+ } else {
+ // FIXME: Find a way that we don't have this hidden dependency.
+ assert(bi->getCondition() == bi->getOperand(0) &&
+ "Wrong operand index!");
+ ref<Expr> cond = eval(ki, 0, state);
+ Executor::StatePair branches = fork(state, cond, false);
+
+ if (WriteTraces) {
+ bool isTwoWay = (branches.first && branches.second);
+
+ if (branches.first) {
+ branches.first->exeTraceMgr.addEvent(
+ new BranchTraceEvent(state, ki, true, isTwoWay));
+ }
+
+ if (branches.second) {
+ branches.second->exeTraceMgr.addEvent(
+ new BranchTraceEvent(state, ki, false, isTwoWay));
+ }
+ }
+
+ // NOTE: There is a hidden dependency here, markBranchVisited
+ // requires that we still be in the context of the branch
+ // instruction (it reuses its statistic id). Should be cleaned
+ // up with convenient instruction specific data.
+ if (statsTracker && state.stack.back().kf->trackCoverage)
+ statsTracker->markBranchVisited(branches.first, branches.second);
+
+ if (branches.first)
+ transferToBasicBlock(bi->getSuccessor(0), bi->getParent(), *branches.first);
+ if (branches.second)
+ transferToBasicBlock(bi->getSuccessor(1), bi->getParent(), *branches.second);
+ }
+ break;
+ }
+ case Instruction::Switch: {
+ SwitchInst *si = cast<SwitchInst>(i);
+ ref<Expr> cond = eval(ki, 0, state);
+ unsigned cases = si->getNumCases();
+ BasicBlock *bb = si->getParent();
+
+ cond = toUnique(state, cond);
+ if (cond.isConstant()) {
+ // Somewhat gross to create these all the time, but fine till we
+ // switch to an internal rep.
+ ConstantInt *ci = ConstantInt::get(si->getCondition()->getType(),
+ cond.getConstantValue());
+ unsigned index = si->findCaseValue(ci);
+ transferToBasicBlock(si->getSuccessor(index), si->getParent(), state);
+ } else {
+ std::map<BasicBlock*, ref<Expr> > targets;
+ ref<Expr> isDefault(1,Expr::Bool);
+ for (unsigned i=1; i<cases; ++i) {
+ ref<Expr> value = evalConstant(si->getCaseValue(i));
+ ref<Expr> match = EqExpr::create(cond, value);
+ isDefault = AndExpr::create(isDefault, Expr::createNot(match));
+ bool result;
+ bool success = solver->mayBeTrue(state, match, result);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (result) {
+ std::map<BasicBlock*, ref<Expr> >::iterator it =
+ targets.insert(std::make_pair(si->getSuccessor(i),
+ ref<Expr>(0,Expr::Bool))).first;
+ it->second = OrExpr::create(match, it->second);
+ }
+ }
+ bool res;
+ bool success = solver->mayBeTrue(state, isDefault, res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res)
+ targets.insert(std::make_pair(si->getSuccessor(0), isDefault));
+
+ std::vector< ref<Expr> > conditions;
+ for (std::map<BasicBlock*, ref<Expr> >::iterator it =
+ targets.begin(), ie = targets.end();
+ it != ie; ++it)
+ conditions.push_back(it->second);
+
+ std::vector<ExecutionState*> branches;
+ branch(state, conditions, branches);
+
+ std::vector<ExecutionState*>::iterator bit = branches.begin();
+ for (std::map<BasicBlock*, ref<Expr> >::iterator it =
+ targets.begin(), ie = targets.end();
+ it != ie; ++it) {
+ ExecutionState *es = *bit;
+ if (es)
+ transferToBasicBlock(it->first, bb, *es);
+ ++bit;
+ }
+ }
+ break;
+ }
+ case Instruction::Unreachable:
+ // Note that this is not necessarily an internal bug, llvm will
+ // generate unreachable instructions in cases where it knows the
+ // program will crash. So it is effectively a SEGV or internal
+ // error.
+ terminateStateOnExecError(state, "reached \"unreachable\" instruction");
+ break;
+
+ case Instruction::Invoke:
+ case Instruction::Call: {
+ CallSite cs;
+ unsigned argStart;
+ if (i->getOpcode()==Instruction::Call) {
+ cs = CallSite(cast<CallInst>(i));
+ argStart = 1;
+ } else {
+ cs = CallSite(cast<InvokeInst>(i));
+ argStart = 3;
+ }
+
+ unsigned numArgs = cs.arg_size();
+ Function *f = getCalledFunction(cs, state);
+
+ // evaluate arguments
+ std::vector< ref<Expr> > arguments;
+ arguments.reserve(numArgs);
+
+ for (unsigned j=0; j<numArgs; ++j)
+ arguments.push_back(eval(ki, argStart+j, state));
+
+ if (!f) {
+ // special case the call with a bitcast case
+ Value *fp = cs.getCalledValue();
+ llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp);
+
+ if (ce && ce->getOpcode()==Instruction::BitCast) {
+ f = dyn_cast<Function>(ce->getOperand(0));
+ assert(f && "XXX unrecognized constant expression in call");
+ const FunctionType *fType =
+ dyn_cast<FunctionType>(cast<PointerType>(f->getType())->getElementType());
+ const FunctionType *ceType =
+ dyn_cast<FunctionType>(cast<PointerType>(ce->getType())->getElementType());
+ assert(fType && ceType && "unable to get function type");
+
+ // XXX check result coercion
+
+ // XXX this really needs thought and validation
+ unsigned i=0;
+ for (std::vector< ref<Expr> >::iterator
+ ai = arguments.begin(), ie = arguments.end();
+ ai != ie; ++ai) {
+ Expr::Width to, from = (*ai).getWidth();
+
+ if (i<fType->getNumParams()) {
+ to = Expr::getWidthForLLVMType(fType->getParamType(i));
+
+ if (from != to) {
+ // XXX need to check other param attrs ?
+ if (cs.paramHasAttr(i+1, llvm::Attribute::SExt)) {
+ arguments[i] = SExtExpr::create(arguments[i], to);
+ } else {
+ arguments[i] = ZExtExpr::create(arguments[i], to);
+ }
+ }
+ }
+
+ i++;
+ }
+ } else if (isa<InlineAsm>(fp)) {
+ terminateStateOnExecError(state, "inline assembly is unsupported");
+ break;
+ }
+ }
+
+ if (f) {
+ executeCall(state, ki, f, arguments);
+ } else {
+ ref<Expr> v = eval(ki, 0, state);
+
+ ExecutionState *free = &state;
+ bool hasInvalid = false, first = true;
+
+ /* XXX This is wasteful, no need to do a full evaluate since we
+ have already got a value. But in the end the caches should
+ handle it for us, albeit with some overhead. */
+ do {
+ ref<Expr> value;
+ bool success = solver->getValue(*free, v, value);
+ assert(success && "FIXME: Unhandled solver failure");
+ StatePair res = fork(*free, EqExpr::create(v, value), true);
+ if (res.first) {
+ void *addr = (void*) (unsigned long) value.getConstantValue();
+ std::set<void*>::iterator it = legalFunctions.find(addr);
+ if (it != legalFunctions.end()) {
+ f = (Function*) addr;
+
+ // Don't give warning on unique resolution
+ if (res.second || !first)
+ klee_warning_once(addr,
+ "resolved symbolic function pointer to: %s",
+ f->getName().c_str());
+
+ executeCall(*res.first, ki, f, arguments);
+ } else {
+ if (!hasInvalid) {
+ terminateStateOnExecError(state, "invalid function pointer");
+ hasInvalid = true;
+ }
+ }
+ }
+
+ first = false;
+ free = res.second;
+ } while (free);
+ }
+ break;
+ }
+ case Instruction::PHI: {
+ ref<Expr> result = eval(ki, state.incomingBBIndex * 2, state);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ // Special instructions
+ case Instruction::Select: {
+ SelectInst *SI = cast<SelectInst>(ki->inst);
+ assert(SI->getCondition() == SI->getOperand(0) &&
+ "Wrong operand index!");
+ ref<Expr> cond = eval(ki, 0, state);
+ ref<Expr> tExpr = eval(ki, 1, state);
+ ref<Expr> fExpr = eval(ki, 2, state);
+ ref<Expr> result = SelectExpr::create(cond, tExpr, fExpr);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::VAArg:
+ terminateStateOnExecError(state, "unexpected VAArg instruction");
+ break;
+
+ // Arithmetic / logical
+#define FP_CONSTANT_BINOP(op, type, l, r, target, state) \
+ bindLocal(target, state, \
+ ref<Expr>(op(toConstant(state, l, "floating point").getConstantValue(), \
+ toConstant(state, r, "floating point").getConstantValue(), \
+ type), type))
+ case Instruction::Add: {
+ BinaryOperator *bi = cast<BinaryOperator>(i);
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+
+ if( bi->getType()->getTypeID() == llvm::Type::IntegerTyID ) {
+ bindLocal(ki, state, AddExpr::create(left, right));
+ } else {
+ Expr::Width type = Expr::getWidthForLLVMType(bi->getType());
+ FP_CONSTANT_BINOP(floats::add, type, left, right, ki, state);
+ }
+
+ break;
+ }
+
+ case Instruction::Sub: {
+ BinaryOperator *bi = cast<BinaryOperator>(i);
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+
+ if( bi->getType()->getTypeID() == llvm::Type::IntegerTyID ) {
+ bindLocal(ki, state, SubExpr::create(left, right));
+ } else {
+ Expr::Width type = Expr::getWidthForLLVMType(bi->getType());
+ FP_CONSTANT_BINOP(floats::sub, type, left, right, ki, state);
+ }
+
+ break;
+ }
+
+ case Instruction::Mul: {
+ BinaryOperator *bi = cast<BinaryOperator>(i);
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+
+ if( bi->getType()->getTypeID() == llvm::Type::IntegerTyID ) {
+ bindLocal(ki, state, MulExpr::create(left, right));
+ } else {
+ Expr::Width type = Expr::getWidthForLLVMType(bi->getType());
+ FP_CONSTANT_BINOP(floats::mul, type, left, right, ki, state);
+ }
+
+ break;
+ }
+
+ case Instruction::UDiv: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = UDivExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::SDiv: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = SDivExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::URem: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = URemExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::SRem: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = SRemExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::And: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = AndExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::Or: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = OrExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::Xor: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = XorExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::Shl: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = ShlExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::LShr: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = LShrExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::AShr: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = AShrExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ // Compare
+
+ case Instruction::ICmp: {
+ CmpInst *ci = cast<CmpInst>(i);
+ ICmpInst *ii = cast<ICmpInst>(ci);
+
+ switch(ii->getPredicate()) {
+ case ICmpInst::ICMP_EQ: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = EqExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_NE: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = NeExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_UGT: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = UgtExpr::create(left, right);
+ bindLocal(ki, state,result);
+ break;
+ }
+
+ case ICmpInst::ICMP_UGE: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = UgeExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_ULT: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = UltExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_ULE: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = UleExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_SGT: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = SgtExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_SGE: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = SgeExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_SLT: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = SltExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case ICmpInst::ICMP_SLE: {
+ ref<Expr> left = eval(ki, 0, state);
+ ref<Expr> right = eval(ki, 1, state);
+ ref<Expr> result = SleExpr::create(left, right);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ default:
+ terminateStateOnExecError(state, "invalid ICmp predicate");
+ }
+ break;
+ }
+
+ // Memory instructions...
+ case Instruction::Alloca:
+ case Instruction::Malloc: {
+ AllocationInst *ai = cast<AllocationInst>(i);
+ unsigned elementSize =
+ kmodule->targetData->getTypeStoreSize(ai->getAllocatedType());
+ ref<Expr> size = Expr::createPointer(elementSize);
+ if (ai->isArrayAllocation()) {
+ // XXX coerce?
+ ref<Expr> count = eval(ki, 0, state);
+ size = MulExpr::create(count, size);
+ }
+ bool isLocal = i->getOpcode()==Instruction::Alloca;
+ executeAlloc(state, size, isLocal, ki);
+ break;
+ }
+ case Instruction::Free: {
+ executeFree(state, eval(ki, 0, state));
+ break;
+ }
+
+ case Instruction::Load: {
+ ref<Expr> base = eval(ki, 0, state);
+ executeMemoryOperation(state, false, base, 0, ki);
+ break;
+ }
+ case Instruction::Store: {
+ ref<Expr> base = eval(ki, 1, state);
+ ref<Expr> value = eval(ki, 0, state);
+ executeMemoryOperation(state, true, base, value, 0);
+ break;
+ }
+
+ case Instruction::GetElementPtr: {
+ KGEPInstruction *kgepi = static_cast<KGEPInstruction*>(ki);
+ ref<Expr> base = eval(ki, 0, state);
+
+ for (std::vector< std::pair<unsigned, unsigned> >::iterator
+ it = kgepi->indices.begin(), ie = kgepi->indices.end();
+ it != ie; ++it) {
+ unsigned elementSize = it->second;
+ ref<Expr> index = eval(ki, it->first, state);
+ base = AddExpr::create(base,
+ MulExpr::create(Expr::createCoerceToPointerType(index),
+ Expr::createPointer(elementSize)));
+ }
+ if (kgepi->offset)
+ base = AddExpr::create(base,
+ Expr::createPointer(kgepi->offset));
+ bindLocal(ki, state, base);
+ break;
+ }
+
+ // Conversion
+ case Instruction::Trunc: {
+ CastInst *ci = cast<CastInst>(i);
+ ref<Expr> result = ExtractExpr::createByteOff(eval(ki, 0, state),
+ 0,
+ Expr::getWidthForLLVMType(ci->getType()));
+ bindLocal(ki, state, result);
+ break;
+ }
+ case Instruction::ZExt: {
+ CastInst *ci = cast<CastInst>(i);
+ ref<Expr> result = ZExtExpr::create(eval(ki, 0, state),
+ Expr::getWidthForLLVMType(ci->getType()));
+ bindLocal(ki, state, result);
+ break;
+ }
+ case Instruction::SExt: {
+ CastInst *ci = cast<CastInst>(i);
+ ref<Expr> result = SExtExpr::create(eval(ki, 0, state),
+ Expr::getWidthForLLVMType(ci->getType()));
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::IntToPtr: {
+ CastInst *ci = cast<CastInst>(i);
+ Expr::Width pType = Expr::getWidthForLLVMType(ci->getType());
+ ref<Expr> arg = eval(ki, 0, state);
+ bindLocal(ki, state, ZExtExpr::create(arg, pType));
+ break;
+ }
+ case Instruction::PtrToInt: {
+ CastInst *ci = cast<CastInst>(i);
+ Expr::Width iType = Expr::getWidthForLLVMType(ci->getType());
+ ref<Expr> arg = eval(ki, 0, state);
+ bindLocal(ki, state, ZExtExpr::create(arg, iType));
+ break;
+ }
+
+ case Instruction::BitCast: {
+ ref<Expr> result = eval(ki, 0, state);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ // Floating Point specific instructions
+ case Instruction::FPTrunc: {
+ FPTruncInst *fi = cast<FPTruncInst>(i);
+ Expr::Width resultType = Expr::getWidthForLLVMType(fi->getType());
+ ref<Expr> arg = toConstant(state, eval(ki, 0, state),
+ "floating point");
+ uint64_t value = floats::trunc(arg.getConstantValue(),
+ resultType,
+ arg.getWidth());
+ ref<Expr> result(value, resultType);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::FPExt: {
+ FPExtInst *fi = cast<FPExtInst>(i);
+ Expr::Width resultType = Expr::getWidthForLLVMType(fi->getType());
+ ref<Expr> arg = toConstant(state, eval(ki, 0, state),
+ "floating point");
+ uint64_t value = floats::ext(arg.getConstantValue(),
+ resultType,
+ arg.getWidth());
+ ref<Expr> result(value, resultType);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::FPToUI: {
+ FPToUIInst *fi = cast<FPToUIInst>(i);
+ Expr::Width resultType = Expr::getWidthForLLVMType(fi->getType());
+ ref<Expr> arg = toConstant(state, eval(ki, 0, state),
+ "floating point");
+ uint64_t value = floats::toUnsignedInt(arg.getConstantValue(),
+ resultType,
+ arg.getWidth());
+ ref<Expr> result(value, resultType);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::FPToSI: {
+ FPToSIInst *fi = cast<FPToSIInst>(i);
+ Expr::Width resultType = Expr::getWidthForLLVMType(fi->getType());
+ ref<Expr> arg = toConstant(state, eval(ki, 0, state),
+ "floating point");
+ uint64_t value = floats::toSignedInt(arg.getConstantValue(),
+ resultType,
+ arg.getWidth());
+ ref<Expr> result(value, resultType);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::UIToFP: {
+ UIToFPInst *fi = cast<UIToFPInst>(i);
+ Expr::Width resultType = Expr::getWidthForLLVMType(fi->getType());
+ ref<Expr> arg = toConstant(state, eval(ki, 0, state),
+ "floating point");
+ uint64_t value = floats::UnsignedIntToFP(arg.getConstantValue(),
+ resultType);
+ ref<Expr> result(value, resultType);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::SIToFP: {
+ SIToFPInst *fi = cast<SIToFPInst>(i);
+ Expr::Width resultType = Expr::getWidthForLLVMType(fi->getType());
+ ref<Expr> arg = toConstant(state, eval(ki, 0, state),
+ "floating point");
+ uint64_t value = floats::SignedIntToFP(arg.getConstantValue(),
+ resultType,
+ arg.getWidth());
+ ref<Expr> result(value, resultType);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::FCmp: {
+ FCmpInst *fi = cast<FCmpInst>(i);
+ Expr::Width resultType = Expr::getWidthForLLVMType(fi->getType());
+ ref<Expr> left = toConstant(state, eval(ki, 0, state),
+ "floating point");
+ ref<Expr> right = toConstant(state, eval(ki, 1, state),
+ "floating point");
+ uint64_t leftVal = left.getConstantValue();
+ uint64_t rightVal = right.getConstantValue();
+
+ //determine whether the operands are NANs
+ unsigned inWidth = left.getWidth();
+ bool leftIsNaN = floats::isNaN( leftVal, inWidth );
+ bool rightIsNaN = floats::isNaN( rightVal, inWidth );
+
+ //handle NAN based on whether the predicate is "ordered" or "unordered"
+ uint64_t ret = (uint64_t)-1;
+ bool done = false;
+ switch( fi->getPredicate() ) {
+ //predicates which only care about whether or not the operands are NaNs
+ case FCmpInst::FCMP_ORD:
+ done = true;
+ ret = !leftIsNaN && !rightIsNaN;
+ break;
+
+ case FCmpInst::FCMP_UNO:
+ done = true;
+ ret = leftIsNaN || rightIsNaN;
+ break;
+
+ //ordered comparisons return false if either operand is NaN
+ case FCmpInst::FCMP_OEQ:
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_OGE:
+ case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_OLE:
+ case FCmpInst::FCMP_ONE:
+ if( !leftIsNaN && !rightIsNaN) //only fall through and return false if there are NaN(s)
+ break;
+
+ case FCmpInst::FCMP_FALSE: { //always return false for this predicate
+ done = true;
+ ret = false;
+ break;
+ }
+
+ //unordered comparisons return true if either operand is NaN
+ case FCmpInst::FCMP_UEQ:
+ case FCmpInst::FCMP_UGT:
+ case FCmpInst::FCMP_UGE:
+ case FCmpInst::FCMP_ULT:
+ case FCmpInst::FCMP_ULE:
+ case FCmpInst::FCMP_UNE:
+ if( !leftIsNaN && !rightIsNaN) //only fall through and return true if there are NaN(s)
+ break;
+
+ case FCmpInst::FCMP_TRUE: //always return true for this predicate
+ done = true;
+ ret = true;
+
+ default:
+ case FCmpInst::BAD_FCMP_PREDICATE: /* will fall through and trigger fatal in the next switch */
+ break;
+ }
+
+ //if not done, then we need to actually do a comparison to get the result
+ if( !done ) {
+ switch( fi->getPredicate() ) {
+ //ordered comparisons return false if either operand is NaN
+ case FCmpInst::FCMP_OEQ:
+ case FCmpInst::FCMP_UEQ:
+ ret = floats::eq( leftVal, rightVal, inWidth );
+ break;
+
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_UGT:
+ ret = floats::gt( leftVal, rightVal, inWidth );
+ break;
+
+ case FCmpInst::FCMP_OGE:
+ case FCmpInst::FCMP_UGE:
+ ret = floats::ge( leftVal, rightVal, inWidth );
+ break;
+
+ case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_ULT:
+ ret = floats::lt( leftVal, rightVal, inWidth );
+ break;
+
+ case FCmpInst::FCMP_OLE:
+ case FCmpInst::FCMP_ULE:
+ ret = floats::le( leftVal, rightVal, inWidth );
+ break;
+
+ case FCmpInst::FCMP_ONE:
+ case FCmpInst::FCMP_UNE:
+ ret = floats::ne( leftVal, rightVal, inWidth );
+ break;
+
+ default:
+ terminateStateOnExecError(state, "invalid FCmp predicate");
+ }
+ }
+
+ ref<Expr> result(ret, resultType);
+ bindLocal(ki, state, result);
+ break;
+ }
+
+ case Instruction::FDiv: {
+ BinaryOperator *bi = cast<BinaryOperator>(i);
+
+ ref<Expr> dividend = eval(ki, 0, state);
+ ref<Expr> divisor = eval(ki, 1, state);
+ Expr::Width type = Expr::getWidthForLLVMType(bi->getType());
+ FP_CONSTANT_BINOP(floats::div, type, dividend, divisor, ki, state);
+ break;
+ }
+
+ case Instruction::FRem: {
+ BinaryOperator *bi = cast<BinaryOperator>(i);
+
+ ref<Expr> dividend = eval(ki, 0, state);
+ ref<Expr> divisor = eval(ki, 1, state);
+ Expr::Width type = Expr::getWidthForLLVMType(bi->getType());
+ FP_CONSTANT_BINOP(floats::mod, type, dividend, divisor, ki, state);
+ break;
+ }
+
+
+ // Other instructions...
+ // Unhandled
+ case Instruction::ExtractElement:
+ case Instruction::InsertElement:
+ case Instruction::ShuffleVector:
+ terminateStateOnError(state, "XXX vector instructions unhandled",
+ "xxx.err");
+ break;
+
+ default:
+ terminateStateOnExecError(state, "invalid instruction");
+ break;
+ }
+}
+
+void Executor::updateStates(ExecutionState *current) {
+ if (searcher) {
+ searcher->update(current, addedStates, removedStates);
+ }
+
+ states.insert(addedStates.begin(), addedStates.end());
+ addedStates.clear();
+
+ for (std::set<ExecutionState*>::iterator
+ it = removedStates.begin(), ie = removedStates.end();
+ it != ie; ++it) {
+ ExecutionState *es = *it;
+ std::set<ExecutionState*>::iterator it2 = states.find(es);
+ assert(it2!=states.end());
+ states.erase(it2);
+ std::map<ExecutionState*, std::vector<SeedInfo> >::iterator it3 =
+ seedMap.find(es);
+ if (it3 != seedMap.end())
+ seedMap.erase(it3);
+ processTree->remove(es->ptreeNode);
+ delete es;
+ }
+ removedStates.clear();
+}
+
+void Executor::bindInstructionConstants(KInstruction *KI) {
+ GetElementPtrInst *gepi = dyn_cast<GetElementPtrInst>(KI->inst);
+ if (!gepi)
+ return;
+
+ KGEPInstruction *kgepi = static_cast<KGEPInstruction*>(KI);
+ ref<Expr> constantOffset = Expr::createPointer(0);
+ unsigned index = 1;
+ for (gep_type_iterator ii = gep_type_begin(gepi), ie = gep_type_end(gepi);
+ ii != ie; ++ii) {
+ if (const StructType *st = dyn_cast<StructType>(*ii)) {
+ const StructLayout *sl =
+ kmodule->targetData->getStructLayout(st);
+ const ConstantInt *ci = cast<ConstantInt>(ii.getOperand());
+ ref<Expr> addend = Expr::createPointer(sl->getElementOffset((unsigned)
+ ci->getZExtValue()));
+ constantOffset = AddExpr::create(constantOffset, addend);
+ } else {
+ const SequentialType *st = cast<SequentialType>(*ii);
+ unsigned elementSize =
+ kmodule->targetData->getTypeStoreSize(st->getElementType());
+ Value *operand = ii.getOperand();
+ if (Constant *c = dyn_cast<Constant>(operand)) {
+ ref<Expr> index = evalConstant(c);
+ ref<Expr> addend = MulExpr::create(Expr::createCoerceToPointerType(index),
+ Expr::createPointer(elementSize));
+ constantOffset = AddExpr::create(constantOffset, addend);
+ } else {
+ kgepi->indices.push_back(std::make_pair(index, elementSize));
+ }
+ }
+ index++;
+ }
+ assert(constantOffset.isConstant());
+ kgepi->offset = constantOffset.getConstantValue();
+}
+
+void Executor::bindModuleConstants() {
+ for (std::vector<KFunction*>::iterator it = kmodule->functions.begin(),
+ ie = kmodule->functions.end(); it != ie; ++it) {
+ KFunction *kf = *it;
+ for (unsigned i=0; i<kf->numInstructions; ++i)
+ bindInstructionConstants(kf->instructions[i]);
+ }
+
+ kmodule->constantTable = new Cell[kmodule->constants.size()];
+ for (unsigned i=0; i<kmodule->constants.size(); ++i) {
+ Cell &c = kmodule->constantTable[i];
+ c.value = evalConstant(kmodule->constants[i]);
+ }
+}
+
+void Executor::run(ExecutionState &initialState) {
+ bindModuleConstants();
+
+ // Delay init till now so that ticks don't accrue during
+ // optimization and such.
+ initTimers();
+
+ states.insert(&initialState);
+
+ if (usingSeeds) {
+ std::vector<SeedInfo> &v = seedMap[&initialState];
+
+ for (std::vector<BOut*>::const_iterator it = usingSeeds->begin(),
+ ie = usingSeeds->end(); it != ie; ++it)
+ v.push_back(SeedInfo(*it));
+
+ int lastNumSeeds = usingSeeds->size()+10;
+ double lastTime, startTime = lastTime = util::getWallTime();
+ ExecutionState *lastState = 0;
+ while (!seedMap.empty()) {
+ if (haltExecution) goto dump;
+
+ std::map<ExecutionState*, std::vector<SeedInfo> >::iterator it =
+ seedMap.upper_bound(lastState);
+ if (it == seedMap.end())
+ it = seedMap.begin();
+ lastState = it->first;
+ unsigned numSeeds = it->second.size();
+ ExecutionState &state = *lastState;
+ KInstruction *ki = state.pc;
+ stepInstruction(state);
+
+ executeInstruction(state, ki);
+ processTimers(&state, MaxInstructionTime * numSeeds);
+ updateStates(&state);
+
+ if ((stats::instructions % 1000) == 0) {
+ int numSeeds = 0, numStates = 0;
+ for (std::map<ExecutionState*, std::vector<SeedInfo> >::iterator
+ it = seedMap.begin(), ie = seedMap.end();
+ it != ie; ++it) {
+ numSeeds += it->second.size();
+ numStates++;
+ }
+ double time = util::getWallTime();
+ if (SeedTime>0. && time > startTime + SeedTime) {
+ klee_warning("seed time expired, %d seeds remain over %d states",
+ numSeeds, numStates);
+ break;
+ } else if (numSeeds<=lastNumSeeds-10 ||
+ time >= lastTime+10) {
+ lastTime = time;
+ lastNumSeeds = numSeeds;
+ klee_message("%d seeds remaining over: %d states",
+ numSeeds, numStates);
+ }
+ }
+ }
+
+ klee_message("seeding done (%d states remain)", (int) states.size());
+
+ // XXX total hack, just because I like non uniform better but want
+ // seed results to be equally weighted.
+ for (std::set<ExecutionState*>::iterator
+ it = states.begin(), ie = states.end();
+ it != ie; ++it) {
+ (*it)->weight = 1.;
+ }
+
+ if (OnlySeed)
+ goto dump;
+ }
+
+ searcher = constructUserSearcher(*this);
+
+ searcher->update(0, states, std::set<ExecutionState*>());
+
+ while (!states.empty() && !haltExecution) {
+ ExecutionState &state = searcher->selectState();
+ KInstruction *ki = state.pc;
+ stepInstruction(state);
+
+ executeInstruction(state, ki);
+ processTimers(&state, MaxInstructionTime);
+
+ if (MaxMemory) {
+ if ((stats::instructions & 0xFFFF) == 0) {
+ // We need to avoid calling GetMallocUsage() often because it
+ // is O(elts on freelist). This is really bad since we start
+ // to pummel the freelist once we hit the memory cap.
+ unsigned mbs = sys::Process::GetTotalMemoryUsage() >> 20;
+
+ if (mbs > MaxMemory) {
+ if (mbs > MaxMemory + 100) {
+ // just guess at how many to kill
+ unsigned numStates = states.size();
+ unsigned toKill = std::max(1U, numStates - numStates*MaxMemory/mbs);
+
+ if (MaxMemoryInhibit)
+ klee_warning("killing %d states (over memory cap)",
+ toKill);
+
+ std::vector<ExecutionState*> arr(states.begin(), states.end());
+ for (unsigned i=0,N=arr.size(); N && i<toKill; ++i,--N) {
+ unsigned idx = rand() % N;
+
+ // Make two pulls to try and not hit a state that
+ // covered new code.
+ if (arr[idx]->coveredNew)
+ idx = rand() % N;
+
+ std::swap(arr[idx], arr[N-1]);
+ terminateStateEarly(*arr[N-1], "memory limit");
+ }
+ }
+ atMemoryLimit = true;
+ } else {
+ atMemoryLimit = false;
+ }
+ }
+ }
+
+ updateStates(&state);
+ }
+
+ delete searcher;
+ searcher = 0;
+
+ dump:
+ if (DumpStatesOnHalt && !states.empty()) {
+ llvm::cerr << "KLEE: halting execution, dumping remaining states\n";
+ for (std::set<ExecutionState*>::iterator
+ it = states.begin(), ie = states.end();
+ it != ie; ++it) {
+ ExecutionState &state = **it;
+ stepInstruction(state); // keep stats rolling
+ terminateStateEarly(state, "execution halting");
+ }
+ updateStates(0);
+ }
+}
+
+std::string Executor::getAddressInfo(ExecutionState &state,
+ ref<Expr> address) const{
+ std::ostringstream info;
+ info << "\taddress: " << address << "\n";
+ uint64_t example;
+ if (address.isConstant()) {
+ example = address.getConstantValue();
+ } else {
+ ref<Expr> value;
+ bool success = solver->getValue(state, address, value);
+ assert(success && "FIXME: Unhandled solver failure");
+ example = value.getConstantValue();
+ info << "\texample: " << example << "\n";
+ std::pair< ref<Expr>, ref<Expr> > res = solver->getRange(state, address);
+ info << "\trange: [" << res.first << ", " << res.second <<"]\n";
+ }
+
+ MemoryObject hack((unsigned) example);
+ MemoryMap::iterator lower = state.addressSpace.objects.upper_bound(&hack);
+ info << "\tnext: ";
+ if (lower==state.addressSpace.objects.end()) {
+ info << "none\n";
+ } else {
+ const MemoryObject *mo = lower->first;
+ info << "object at " << mo->address
+ << " of size " << mo->size << "\n";
+ }
+ if (lower!=state.addressSpace.objects.begin()) {
+ --lower;
+ info << "\tprev: ";
+ if (lower==state.addressSpace.objects.end()) {
+ info << "none\n";
+ } else {
+ const MemoryObject *mo = lower->first;
+ info << "object at " << mo->address
+ << " of size " << mo->size << "\n";
+ }
+ }
+
+ return info.str();
+}
+
+void Executor::terminateState(ExecutionState &state) {
+ if (replayOut && replayPosition!=replayOut->numObjects) {
+ klee_warning_once(replayOut, "replay did not consume all objects in .bout input.");
+ }
+
+ interpreterHandler->incPathsExplored();
+
+ std::set<ExecutionState*>::iterator it = addedStates.find(&state);
+ if (it==addedStates.end()) {
+ state.pc = state.prevPC;
+
+ removedStates.insert(&state);
+ } else {
+ // never reached searcher, just delete immediately
+ std::map< ExecutionState*, std::vector<SeedInfo> >::iterator it3 =
+ seedMap.find(&state);
+ if (it3 != seedMap.end())
+ seedMap.erase(it3);
+ addedStates.erase(it);
+ processTree->remove(state.ptreeNode);
+ delete &state;
+ }
+}
+
+void Executor::terminateStateEarly(ExecutionState &state, std::string message) {
+ if (!OnlyOutputStatesCoveringNew || state.coveredNew ||
+ (AlwaysOutputSeeds && seedMap.count(&state)))
+ interpreterHandler->processTestCase(state, (message + "\n").c_str(), "early");
+ terminateState(state);
+}
+
+void Executor::terminateStateOnExit(ExecutionState &state) {
+ if (!OnlyOutputStatesCoveringNew || state.coveredNew ||
+ (AlwaysOutputSeeds && seedMap.count(&state)))
+ interpreterHandler->processTestCase(state, 0, 0);
+ terminateState(state);
+}
+
+void Executor::terminateStateOnError(ExecutionState &state,
+ const std::string &message,
+ const std::string &suffix,
+ const std::string &info) {
+ static std::set< std::pair<Instruction*, std::string> > emittedErrors;
+ const InstructionInfo &ii = *state.prevPC->info;
+
+ if (EmitAllErrors ||
+ emittedErrors.insert(std::make_pair(state.prevPC->inst,message)).second) {
+ if (ii.file != "") {
+ klee_message("ERROR: %s:%d: %s", ii.file.c_str(), ii.line, message.c_str());
+ } else {
+ klee_message("ERROR: %s", message.c_str());
+ }
+ if (!EmitAllErrors)
+ klee_message("NOTE: now ignoring this error at this location");
+
+ std::ostringstream msg;
+ msg << "Error: " << message << "\n";
+ if (ii.file != "") {
+ msg << "File: " << ii.file << "\n";
+ msg << "Line: " << ii.line << "\n";
+ }
+ msg << "Stack: \n";
+ unsigned idx = 0;
+ const KInstruction *target = state.prevPC;
+ for (ExecutionState::stack_ty::reverse_iterator
+ it = state.stack.rbegin(), ie = state.stack.rend();
+ it != ie; ++it) {
+ StackFrame &sf = *it;
+ Function *f = sf.kf->function;
+ const InstructionInfo &ii = *target->info;
+ msg << "\t#" << idx++
+ << " " << std::setw(8) << std::setfill('0') << ii.assemblyLine
+ << " in " << f->getName() << " (";
+ // Yawn, we could go up and print varargs if we wanted to.
+ unsigned index = 0;
+ for (Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end();
+ ai != ae; ++ai) {
+ if (ai!=f->arg_begin()) msg << ", ";
+
+ msg << ai->getName();
+ // XXX should go through function
+ ref<Expr> value = sf.locals[sf.kf->getArgRegister(index++)].value;
+ if (value.isConstant())
+ msg << "=" << value;
+ }
+ msg << ")";
+ if (ii.file != "")
+ msg << " at " << ii.file << ":" << ii.line;
+ msg << "\n";
+ target = sf.caller;
+ }
+
+ if (info != "")
+ msg << "Info: \n" << info;
+ interpreterHandler->processTestCase(state, msg.str().c_str(), suffix.c_str());
+ }
+
+ terminateState(state);
+}
+
+// XXX shoot me
+static const char *okExternalsList[] = { "printf",
+ "fprintf",
+ "puts",
+ "getpid" };
+static std::set<std::string> okExternals(okExternalsList,
+ okExternalsList +
+ (sizeof(okExternalsList)/sizeof(okExternalsList[0])));
+
+void Executor::callExternalFunction(ExecutionState &state,
+ KInstruction *target,
+ Function *function,
+ std::vector< ref<Expr> > &arguments) {
+ // check if specialFunctionHandler wants it
+ if (specialFunctionHandler->handle(state, function, target, arguments))
+ return;
+
+ if (NoExternals && !okExternals.count(function->getName())) {
+ llvm::cerr << "KLEE:ERROR: Calling not-OK external function : " << function->getName() << "\n";
+ terminateStateOnError(state, "externals disallowed", "user.err");
+ return;
+ }
+
+ // normal external function handling path
+ uint64_t *args = (uint64_t*) alloca(sizeof(*args) * (arguments.size() + 1));
+ memset(args, 0, sizeof(*args) * (arguments.size() + 1));
+
+ unsigned i = 1;
+ for (std::vector<ref<Expr> >::iterator ai = arguments.begin(), ae = arguments.end();
+ ai!=ae; ++ai, ++i) {
+ if (AllowExternalSymCalls) { // don't bother checking uniqueness
+ ref<Expr> ce;
+ bool success = solver->getValue(state, *ai, ce);
+ assert(success && "FIXME: Unhandled solver failure");
+ static_cast<ConstantExpr*>(ce.get())->toMemory((void*) &args[i]);
+ } else {
+ ref<Expr> arg = toUnique(state, *ai);
+ if (arg.isConstant()) {
+ // XXX kick toMemory functions from here
+ static_cast<ConstantExpr*>(arg.get())->toMemory((void*) &args[i]);
+ } else {
+ std::string msg = "external call with symbolic argument: " + function->getName();
+ terminateStateOnExecError(state, msg);
+ return;
+ }
+ }
+ }
+
+ state.addressSpace.copyOutConcretes();
+
+ if (!SuppressExternalWarnings) {
+ std::ostringstream os;
+ os << "calling external: " << function->getName().c_str() << "(";
+ for (unsigned i=0; i<arguments.size(); i++) {
+ os << arguments[i];
+ if (i != arguments.size()-1)
+ os << ", ";
+ }
+ os << ")";
+
+ if (AllExternalWarnings)
+ klee_warning("%s", os.str().c_str());
+ else
+ klee_warning_once(function, "%s", os.str().c_str());
+ }
+
+ bool success = externalDispatcher->executeCall(function, target->inst, args);
+ if (!success) {
+ terminateStateOnError(state, "failed external call: " + function->getName(), "external.err");
+ return;
+ }
+
+ if (!state.addressSpace.copyInConcretes()) {
+ terminateStateOnError(state, "external modified read-only object", "external.err");
+ return;
+ }
+
+ const Type *resultType = target->inst->getType();
+ if (resultType != Type::VoidTy) {
+ ref<Expr> e = ConstantExpr::fromMemory((void*) args,
+ Expr::getWidthForLLVMType(resultType));
+ bindLocal(target, state, e);
+ }
+}
+
+/***/
+
+ref<Expr> Executor::replaceReadWithSymbolic(ExecutionState &state,
+ ref<Expr> e) {
+ unsigned n = interpreterOpts.MakeConcreteSymbolic;
+ if (!n || replayOut || replayPath)
+ return e;
+
+ // right now, we don't replace symbolics (is there any reason too?)
+ if (!e.isConstant())
+ return e;
+
+ if (n != 1 && random() % n)
+ return e;
+
+ // create a new fresh location, assert it is equal to concrete value in e
+ // and return it.
+
+ const MemoryObject *mo = memory->allocate(Expr::getMinBytesForWidth(e.getWidth()),
+ false, false,
+ state.prevPC->inst);
+ assert(mo && "out of memory");
+ ref<Expr> res = Expr::createTempRead(mo->array, e.getWidth());
+ ref<Expr> eq = NotOptimizedExpr::create(EqExpr::create(e, res));
+ llvm::cerr << "Making symbolic: " << eq << "\n";
+ state.addConstraint(eq);
+ return res;
+}
+
+ObjectState *Executor::bindObjectInState(ExecutionState &state, const MemoryObject *mo,
+ bool isLocal) {
+ ObjectState *os = new ObjectState(mo, mo->size);
+ state.addressSpace.bindObject(mo, os);
+
+ // Its possible that multiple bindings of the same mo in the state
+ // will put multiple copies on this list, but it doesn't really
+ // matter because all we use this list for is to unbind the object
+ // on function return.
+ if (isLocal)
+ state.stack.back().allocas.push_back(mo);
+
+ return os;
+}
+
+void Executor::executeAllocN(ExecutionState &state,
+ uint64_t nelems,
+ uint64_t size,
+ uint64_t alignment,
+ bool isLocal,
+ KInstruction *target) {
+#if 0
+ // over-allocate so that we can properly align the whole buffer
+ uint64_t address = (uint64_t) (unsigned) malloc(nelems * size + alignment - 1);
+ address += (alignment - address % alignment);
+#else
+ theMMap =
+ mmap((void*) 0x90000000,
+ nelems*size, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE
+#ifdef MAP_ANONYMOUS
+ |MAP_ANONYMOUS
+#endif
+ , 0, 0);
+ uint64_t address = (uintptr_t) theMMap;
+ theMMapSize = nelems*size;
+#endif
+
+ for (unsigned i = 0; i < nelems; i++) {
+ MemoryObject *mo = memory->allocateFixed(address + i*size, size, state.prevPC->inst);
+ ObjectState *os = bindObjectInState(state, mo, isLocal);
+ os->initializeToRandom();
+
+ // bind the local to the first memory object in the whole array
+ if (i == 0)
+ bindLocal(target, state, mo->getBaseExpr());
+ }
+
+ llvm::cerr << "KLEE: allocN at: " << address << "\n";
+}
+
+void Executor::executeAlloc(ExecutionState &state,
+ ref<Expr> size,
+ bool isLocal,
+ KInstruction *target,
+ bool zeroMemory,
+ const ObjectState *reallocFrom) {
+ size = toUnique(state, size);
+ if (size.isConstant()) {
+ MemoryObject *mo = memory->allocate(size.getConstantValue(), isLocal, false,
+ state.prevPC->inst);
+ if (!mo) {
+ bindLocal(target, state, ref<Expr>(0, kMachinePointerType));
+ } else {
+ ObjectState *os = bindObjectInState(state, mo, isLocal);
+ if (zeroMemory) {
+ os->initializeToZero();
+ } else {
+ os->initializeToRandom();
+ }
+ bindLocal(target, state, mo->getBaseExpr());
+
+ if (reallocFrom) {
+ unsigned count = std::min(reallocFrom->size, os->size);
+ for (unsigned i=0; i<count; i++)
+ os->write(i, reallocFrom->read8(i));
+ state.addressSpace.unbindObject(reallocFrom->getObject());
+ }
+ }
+ } else {
+ // XXX For now we just pick a size. Ideally we would support
+ // symbolic sizes fully but even if we don't it would be better to
+ // "smartly" pick a value, for example we could fork and pick the
+ // min and max values and perhaps some intermediate (reasonable
+ // value).
+ //
+ // It would also be nice to recognize the case when size has
+ // exactly two values and just fork (but we need to get rid of
+ // return argument first). This shows up in pcre when llvm
+ // collapses the size expression with a select.
+
+ ref<Expr> example;
+ bool success = solver->getValue(state, size, example);
+ assert(success && "FIXME: Unhandled solver failure");
+
+ // Try and start with a small example
+ while (example.getConstantValue()>128) {
+ ref<Expr> tmp = ref<Expr>(example.getConstantValue() >> 1,
+ example.getWidth());
+ bool res;
+ bool success = solver->mayBeTrue(state, EqExpr::create(tmp, size), res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (!res)
+ break;
+ example = tmp;
+ }
+
+ StatePair fixedSize = fork(state, EqExpr::create(example, size), true);
+
+ if (fixedSize.second) {
+ // Check for exactly two values
+ ref<Expr> tmp;
+ bool success = solver->getValue(*fixedSize.second, size, tmp);
+ assert(success && "FIXME: Unhandled solver failure");
+ bool res;
+ success = solver->mustBeTrue(*fixedSize.second,
+ EqExpr::create(tmp, size),
+ res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res) {
+ executeAlloc(*fixedSize.second, tmp, isLocal,
+ target, zeroMemory, reallocFrom);
+ } else {
+ // See if a *really* big value is possible. If so assume
+ // malloc will fail for it, so lets fork and return 0.
+ StatePair hugeSize = fork(*fixedSize.second,
+ UltExpr::create(ref<Expr>(1<<31, Expr::Int32), size),
+ true);
+ if (hugeSize.first) {
+ klee_message("NOTE: found huge malloc, returing 0");
+ bindLocal(target, *hugeSize.first, ref<Expr>(0,kMachinePointerType));
+ }
+
+ if (hugeSize.second) {
+ std::ostringstream info;
+ ExprPPrinter::printOne(info, " size expr", size);
+ info << " concretization : " << example << "\n";
+ info << " unbound example: " << tmp << "\n";
+ terminateStateOnError(*hugeSize.second,
+ "concretized symbolic size",
+ "model.err",
+ info.str());
+ }
+ }
+ }
+
+ if (fixedSize.first) // can be zero when fork fails
+ executeAlloc(*fixedSize.first, example, isLocal,
+ target, zeroMemory, reallocFrom);
+ }
+}
+
+void Executor::executeFree(ExecutionState &state,
+ ref<Expr> address,
+ KInstruction *target) {
+ StatePair zeroPointer = fork(state, Expr::createIsZero(address), true);
+ if (zeroPointer.first) {
+ if (target)
+ bindLocal(target, *zeroPointer.first, Expr::createPointer(0));
+ }
+ if (zeroPointer.second) { // address != 0
+ ExactResolutionList rl;
+ resolveExact(*zeroPointer.second, address, rl, "free");
+
+ for (Executor::ExactResolutionList::iterator it = rl.begin(),
+ ie = rl.end(); it != ie; ++it) {
+ const MemoryObject *mo = it->first.first;
+ if (mo->isLocal) {
+ terminateStateOnError(*it->second,
+ "free of alloca",
+ "free.err",
+ getAddressInfo(*it->second, address));
+ } else if (mo->isGlobal) {
+ terminateStateOnError(*it->second,
+ "free of global",
+ "free.err",
+ getAddressInfo(*it->second, address));
+ } else {
+ it->second->addressSpace.unbindObject(mo);
+ if (target)
+ bindLocal(target, *it->second, Expr::createPointer(0));
+ }
+ }
+ }
+}
+
+void Executor::resolveExact(ExecutionState &state,
+ ref<Expr> p,
+ ExactResolutionList &results,
+ const std::string &name) {
+ // XXX we may want to be capping this?
+ ResolutionList rl;
+ state.addressSpace.resolve(state, solver, p, rl);
+
+ ExecutionState *unbound = &state;
+ for (ResolutionList::iterator it = rl.begin(), ie = rl.end();
+ it != ie; ++it) {
+ ref<Expr> inBounds = EqExpr::create(p, it->first->getBaseExpr());
+
+ StatePair branches = fork(*unbound, inBounds, true);
+
+ if (branches.first)
+ results.push_back(std::make_pair(*it, branches.first));
+
+ unbound = branches.second;
+ if (!unbound) // Fork failure
+ break;
+ }
+
+ if (unbound) {
+ terminateStateOnError(*unbound,
+ "memory error: invalid pointer: " + name,
+ "ptr.err",
+ getAddressInfo(*unbound, p));
+ }
+}
+
+void Executor::executeMemoryOperation(ExecutionState &state,
+ bool isWrite,
+ ref<Expr> address,
+ ref<Expr> value /* undef if read */,
+ KInstruction *target /* undef if write */) {
+ Expr::Width type = (isWrite ? value.getWidth() :
+ Expr::getWidthForLLVMType(target->inst->getType()));
+ unsigned bytes = Expr::getMinBytesForWidth(type);
+
+ if (SimplifySymIndices) {
+ if (!address.isConstant())
+ address = state.constraints.simplifyExpr(address);
+ if (isWrite && !value.isConstant())
+ value = state.constraints.simplifyExpr(value);
+ }
+
+ // fast path: single in-bounds resolution
+ ObjectPair op;
+ bool success;
+ solver->setTimeout(stpTimeout);
+ if (!state.addressSpace.resolveOne(state, solver, address, op, success)) {
+ address = toConstant(state, address, "resolveOne failure");
+ success = state.addressSpace.resolveOne(address.getConstantValue(), op);
+ }
+ solver->setTimeout(0);
+
+ if (success) {
+ const MemoryObject *mo = op.first;
+
+ if (MaxSymArraySize && mo->size>=MaxSymArraySize) {
+ address = toConstant(state, address, "max-sym-array-size");
+ }
+
+ ref<Expr> offset = mo->getOffsetExpr(address);
+
+ bool inBounds;
+ solver->setTimeout(stpTimeout);
+ bool success = solver->mustBeTrue(state,
+ mo->getBoundsCheckOffset(offset, bytes),
+ inBounds);
+ solver->setTimeout(0);
+ if (!success) {
+ state.pc = state.prevPC;
+ terminateStateEarly(state, "query timed out");
+ return;
+ }
+
+ if (inBounds) {
+ const ObjectState *os = op.second;
+ if (isWrite) {
+ if (os->readOnly) {
+ terminateStateOnError(state,
+ "memory error: object read only",
+ "readonly.err");
+ } else {
+ ObjectState *wos = state.addressSpace.getWriteable(mo, os);
+ wos->write(offset, value);
+ }
+ } else {
+ ref<Expr> result = os->read(offset, type);
+
+ if (interpreterOpts.MakeConcreteSymbolic)
+ result = replaceReadWithSymbolic(state, result);
+
+ bindLocal(target, state, result);
+ }
+
+ return;
+ }
+ }
+
+ // we are on an error path (no resolution, multiple resolution, one
+ // resolution with out of bounds)
+
+ ResolutionList rl;
+ solver->setTimeout(stpTimeout);
+ bool incomplete = state.addressSpace.resolve(state, solver, address, rl,
+ 0, stpTimeout);
+ solver->setTimeout(0);
+
+ // XXX there is some query wasteage here. who cares?
+ ExecutionState *unbound = &state;
+
+ for (ResolutionList::iterator i = rl.begin(), ie = rl.end(); i != ie; ++i) {
+ const MemoryObject *mo = i->first;
+ const ObjectState *os = i->second;
+ ref<Expr> inBounds = mo->getBoundsCheckPointer(address, bytes);
+
+ StatePair branches = fork(*unbound, inBounds, true);
+ ExecutionState *bound = branches.first;
+
+ // bound can be 0 on failure or overlapped
+ if (bound) {
+ if (isWrite) {
+ if (os->readOnly) {
+ terminateStateOnError(*bound,
+ "memory error: object read only",
+ "readonly.err");
+ } else {
+ ObjectState *wos = bound->addressSpace.getWriteable(mo, os);
+ wos->write(mo->getOffsetExpr(address), value);
+ }
+ } else {
+ ref<Expr> result = os->read(mo->getOffsetExpr(address), type);
+ bindLocal(target, *bound, result);
+ }
+ }
+
+ unbound = branches.second;
+ if (!unbound)
+ break;
+ }
+
+ // XXX should we distinguish out of bounds and overlapped cases?
+ if (unbound) {
+ if (incomplete) {
+ terminateStateEarly(*unbound, "query timed out (resolve)");
+ } else {
+ terminateStateOnError(*unbound,
+ "memory error: out of bound pointer",
+ "ptr.err",
+ getAddressInfo(*unbound, address));
+ }
+ }
+}
+
+void Executor::executeMakeSymbolic(ExecutionState &state,
+ const MemoryObject *mo) {
+ // make a new one and rebind, we use bind here because we want to
+ // create a flat out new state, not a copy. although I'm not really
+ // sure it matters.
+ ObjectState *os = bindObjectInState(state, mo, false);
+ if (!replayOut) {
+ os->makeSymbolic();
+ state.addSymbolic(mo);
+
+ std::map< ExecutionState*, std::vector<SeedInfo> >::iterator it =
+ seedMap.find(&state);
+ if (it!=seedMap.end()) { // In seed mode we need to add this as a
+ // binding.
+ for (std::vector<SeedInfo>::iterator siit = it->second.begin(),
+ siie = it->second.end(); siit != siie; ++siit) {
+ SeedInfo &si = *siit;
+ BOutObject *obj = si.getNextInput(mo,
+ NamedSeedMatching);
+
+ if (!obj) {
+ if (ZeroSeedExtension) {
+ std::vector<unsigned char> &values =
+ si.assignment.bindings[mo->array];
+ values = std::vector<unsigned char>(mo->size, '\0');
+ } else if (!AllowSeedExtension) {
+ terminateStateOnError(state,
+ "ran out of inputs during seeding",
+ "user.err");
+ break;
+ }
+ } else {
+ if (obj->numBytes != mo->size &&
+ ((!(AllowSeedExtension || ZeroSeedExtension)
+ && obj->numBytes < mo->size) ||
+ (!AllowSeedTruncation && obj->numBytes > mo->size))) {
+ std::stringstream msg;
+ msg << "replace size mismatch: "
+ << mo->name << "[" << mo->size << "]"
+ << " vs " << obj->name << "[" << obj->numBytes << "]"
+ << " in bout\n";
+
+ terminateStateOnError(state,
+ msg.str(),
+ "user.err");
+ break;
+ } else {
+ std::vector<unsigned char> &values =
+ si.assignment.bindings[mo->array];
+ values.insert(values.begin(), obj->bytes,
+ obj->bytes + std::min(obj->numBytes, mo->size));
+ if (ZeroSeedExtension) {
+ for (unsigned i=obj->numBytes; i<mo->size; ++i)
+ values.push_back('\0');
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (replayPosition >= replayOut->numObjects) {
+ terminateStateOnError(state, "replay count mismatch", "user.err");
+ } else {
+ BOutObject *obj = &replayOut->objects[replayPosition++];
+ if (obj->numBytes != mo->size) {
+ terminateStateOnError(state, "replay size mismatch", "user.err");
+ } else {
+ for (unsigned i=0; i<mo->size; i++)
+ os->write8(i, obj->bytes[i]);
+ }
+ }
+ }
+}
+
+/***/
+
+void Executor::runFunctionAsMain(Function *f,
+ int argc,
+ char **argv,
+ char **envp) {
+ std::vector<ref<Expr> > arguments;
+
+ // force deterministic initialization of memory objects
+ srand(1);
+ srandom(1);
+
+ MemoryObject *argvMO = 0;
+
+ // In order to make uclibc happy and be closer to what the system is
+ // doing we lay out the environments at the end of the argv array
+ // (both are terminated by a null). There is also a final terminating
+ // null that uclibc seems to expect, possibly the ELF header?
+
+ int envc;
+ for (envc=0; envp[envc]; ++envc) ;
+
+ KFunction *kf = kmodule->functionMap[f];
+ assert(kf);
+ Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end();
+ if (ai!=ae) {
+ arguments.push_back(ref<Expr>(argc, Expr::Int32));
+
+ if (++ai!=ae) {
+ argvMO = memory->allocate((argc+1+envc+1+1) * kMachinePointerSize, false, true,
+ f->begin()->begin());
+
+ arguments.push_back(argvMO->getBaseExpr());
+
+ if (++ai!=ae) {
+ uint64_t envp_start = argvMO->address + (argc+1)*kMachinePointerSize;
+ arguments.push_back(Expr::createPointer(envp_start));
+
+ if (++ai!=ae)
+ klee_error("invalid main function (expect 0-3 arguments)");
+ }
+ }
+ }
+
+ ExecutionState *state = new ExecutionState(kmodule->functionMap[f]);
+
+ if (pathWriter)
+ state->pathOS = pathWriter->open();
+ if (symPathWriter)
+ state->symPathOS = symPathWriter->open();
+
+
+ if (statsTracker)
+ statsTracker->framePushed(*state, 0);
+
+ assert(arguments.size() == f->arg_size() && "wrong number of arguments");
+ for (unsigned i = 0, e = f->arg_size(); i != e; ++i)
+ bindArgument(kf, i, *state, arguments[i]);
+
+ if (argvMO) {
+ ObjectState *argvOS = bindObjectInState(*state, argvMO, false);
+
+ for (int i=0; i<argc+1+envc+1+1; i++) {
+ MemoryObject *arg;
+
+ if (i==argc || i>=argc+1+envc) {
+ arg = 0;
+ } else {
+ char *s = i<argc ? argv[i] : envp[i-(argc+1)];
+ int j, len = strlen(s);
+
+ arg = memory->allocate(len+1, false, true, state->pc->inst);
+ ObjectState *os = bindObjectInState(*state, arg, false);
+ for (j=0; j<len+1; j++)
+ os->write8(j, s[j]);
+ }
+
+ if (arg) {
+ argvOS->write(i * kMachinePointerSize, arg->getBaseExpr());
+ } else {
+ argvOS->write(i * kMachinePointerSize, Expr::createPointer(0));
+ }
+ }
+ }
+
+ initializeGlobals(*state);
+
+ processTree = new PTree(state);
+ state->ptreeNode = processTree->root;
+ run(*state);
+ delete processTree;
+ processTree = 0;
+
+ // hack to clear memory objects
+ delete memory;
+ memory = new MemoryManager();
+
+ globalObjects.clear();
+ globalAddresses.clear();
+
+ if (statsTracker)
+ statsTracker->done();
+
+ if (theMMap) {
+ munmap(theMMap, theMMapSize);
+ theMMap = 0;
+ }
+}
+
+unsigned Executor::getPathStreamID(const ExecutionState &state) {
+ assert(pathWriter);
+ return state.pathOS.getID();
+}
+
+unsigned Executor::getSymbolicPathStreamID(const ExecutionState &state) {
+ assert(symPathWriter);
+ return state.symPathOS.getID();
+}
+
+void Executor::getConstraintLog(const ExecutionState &state,
+ std::string &res,
+ bool asCVC) {
+ if (asCVC) {
+ Query query(state.constraints, ref<Expr>(0, Expr::Bool));
+ char *log = solver->stpSolver->getConstraintLog(query);
+ res = std::string(log);
+ free(log);
+ } else {
+ std::ostringstream info;
+ ExprPPrinter::printConstraints(info, state.constraints);
+ res = info.str();
+ }
+}
+
+bool Executor::getSymbolicSolution(const ExecutionState &state,
+ std::vector<
+ std::pair<std::string,
+ std::vector<unsigned char> > >
+ &res) {
+ solver->setTimeout(stpTimeout);
+
+ ExecutionState tmp(state);
+ if (!NoPreferCex) {
+ for (std::vector<const MemoryObject*>::const_iterator
+ it = state.symbolics.begin(), ie = state.symbolics.end();
+ it != ie; ++it) {
+ const MemoryObject *mo = *it;
+ std::vector< ref<Expr> >::const_iterator pi =
+ mo->cexPreferences.begin(), pie = mo->cexPreferences.end();
+ for (; pi != pie; ++pi) {
+ bool mustBeTrue;
+ bool success = solver->mustBeTrue(tmp, Expr::createNot(*pi),
+ mustBeTrue);
+ if (!success) break;
+ if (!mustBeTrue) tmp.addConstraint(*pi);
+ }
+ if (pi!=pie) break;
+ }
+ }
+
+ std::vector< std::vector<unsigned char> > values;
+ std::vector<const Array*> objects;
+ for (unsigned i = 0; i != state.symbolics.size(); ++i)
+ objects.push_back(state.symbolics[i]->array);
+ bool success = solver->getInitialValues(tmp, objects, values);
+ solver->setTimeout(0);
+ if (!success) {
+ klee_warning("unable to compute initial values (invalid constraints?)!");
+ ExprPPrinter::printQuery(std::cerr,
+ state.constraints,
+ ref<Expr>(0,Expr::Bool));
+ return false;
+ }
+
+ unsigned i = 0;
+ for (std::vector<const MemoryObject*>::const_iterator
+ it = state.symbolics.begin(), ie = state.symbolics.end();
+ it != ie; ++it) {
+ res.push_back(std::make_pair((*it)->name, values[i]));
+ ++i;
+ }
+ return true;
+}
+
+void Executor::getCoveredLines(const ExecutionState &state,
+ std::map<const std::string*, std::set<unsigned> > &res) {
+ res = state.coveredLines;
+}
+
+void Executor::doImpliedValueConcretization(ExecutionState &state,
+ ref<Expr> e,
+ ref<Expr> value) {
+ assert(value.isConstant() && "non-constant passed in place of constant");
+
+ if (DebugCheckForImpliedValues)
+ ImpliedValue::checkForImpliedValues(solver->solver, e, value);
+
+ ImpliedValueList results;
+ ImpliedValue::getImpliedValues(e, value, results);
+ for (ImpliedValueList::iterator it = results.begin(), ie = results.end();
+ it != ie; ++it) {
+ ReadExpr *re = it->first.get();
+
+ if (re->index.isConstant()) {
+ // FIXME: This is the sole remaining usage of the Array object
+ // variable. Kill me.
+ const MemoryObject *mo = re->updates.root->object;
+ const ObjectState *os = state.addressSpace.findObject(mo);
+
+ if (!os) {
+ // object has been free'd, no need to concretize (although as
+ // in other cases we would like to concretize the outstanding
+ // reads, but we have no facility for that yet)
+ } else {
+ assert(!os->readOnly && "not possible? read only object with static read?");
+ ObjectState *wos = state.addressSpace.getWriteable(mo, os);
+ wos->write(re->index.getConstantValue(), it->second);
+ }
+ }
+ }
+}
+
+///
+
+Interpreter *Interpreter::create(const InterpreterOptions &opts,
+ InterpreterHandler *ih) {
+ return new Executor(opts, ih);
+}
Added: klee/trunk/lib/Core/Executor.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Executor.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Executor.h (added)
+++ klee/trunk/lib/Core/Executor.h Wed May 20 23:36:41 2009
@@ -0,0 +1,445 @@
+//===-- Executor.h ----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Class to perform actual execution, hides implementation details from external
+// interpreter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXECUTOR_H
+#define KLEE_EXECUTOR_H
+
+#include "klee/Interpreter.h"
+#include "llvm/Support/CallSite.h"
+#include <vector>
+#include <string>
+#include <map>
+#include <set>
+
+struct BOut;
+
+namespace llvm {
+ class BasicBlock;
+ class BranchInst;
+ class CallInst;
+ class Constant;
+ class ConstantExpr;
+ class Function;
+ class GlobalValue;
+ class Instruction;
+ class TargetData;
+ class Value;
+}
+
+namespace klee {
+ class ExecutionState;
+ class ExternalDispatcher;
+ class Expr;
+ class InstructionInfoTable;
+ class KFunction;
+ class KInstruction;
+ class KInstIterator;
+ class KModule;
+ class MemoryManager;
+ class MemoryObject;
+ class ObjectState;
+ class PTree;
+ class Searcher;
+ class SeedInfo;
+ class SpecialFunctionHandler;
+ class StackFrame;
+ class StatsTracker;
+ class TimingSolver;
+ class TreeStreamWriter;
+ template<class T> class ref;
+
+ /// \todo Add a context object to keep track of data only live
+ /// during an instruction step. Should contain addedStates,
+ /// removedStates, and haltExecution, among others.
+
+class Executor : public Interpreter {
+ friend class BumpMergingSearcher;
+ friend class MergingSearcher;
+ friend class RandomPathSearcher;
+ friend class OwningSearcher;
+ friend class WeightedRandomSearcher;
+ friend class SpecialFunctionHandler;
+ friend class StatsTracker;
+
+public:
+ class Timer {
+ public:
+ Timer();
+ virtual ~Timer();
+
+ /// The event callback.
+ virtual void run() = 0;
+ };
+
+ typedef std::pair<ExecutionState*,ExecutionState*> StatePair;
+
+private:
+ class TimerInfo;
+
+ KModule *kmodule;
+ InterpreterHandler *interpreterHandler;
+ Searcher *searcher;
+
+ ExternalDispatcher *externalDispatcher;
+ TimingSolver *solver;
+ MemoryManager *memory;
+ std::set<ExecutionState*> states;
+ StatsTracker *statsTracker;
+ TreeStreamWriter *pathWriter, *symPathWriter;
+ SpecialFunctionHandler *specialFunctionHandler;
+ std::vector<TimerInfo*> timers;
+ PTree *processTree;
+
+ /// Used to track states that have been added during the current
+ /// instructions step.
+ /// \invariant \ref addedStates is a subset of \ref states.
+ /// \invariant \ref addedStates and \ref removedStates are disjoint.
+ std::set<ExecutionState*> addedStates;
+ /// Used to track states that have been removed during the current
+ /// instructions step.
+ /// \invariant \ref removedStates is a subset of \ref states.
+ /// \invariant \ref addedStates and \ref removedStates are disjoint.
+ std::set<ExecutionState*> removedStates;
+
+ /// When non-empty the Executor is running in "seed" mode. The
+ /// states in this map will be executed in an arbitrary order
+ /// (outside the normal search interface) until they terminate. When
+ /// the states reach a symbolic branch then either direction that
+ /// satisfies one or more seeds will be added to this map. What
+ /// happens with other states (that don't satisfy the seeds) depends
+ /// on as-yet-to-be-determined flags.
+ std::map<ExecutionState*, std::vector<SeedInfo> > seedMap;
+
+ /// Map of globals to their representative memory object.
+ std::map<const llvm::GlobalValue*, MemoryObject*> globalObjects;
+
+ /// Map of globals to their bound address. This also includes
+ /// globals that have no representative object (i.e. functions).
+ std::map<const llvm::GlobalValue*, ref<Expr> > globalAddresses;
+
+ /// The set of legal function addresses, used to validate function
+ /// pointers.
+ std::set<void*> legalFunctions;
+
+ /// When non-null the bindings that will be used for calls to
+ /// klee_make_symbolic in order replay.
+ const struct BOut *replayOut;
+ /// When non-null a list of branch decisions to be used for replay.
+ const std::vector<bool> *replayPath;
+ /// The index into the current \ref replayOut or \ref replayPath
+ /// object.
+ unsigned replayPosition;
+
+ /// When non-null a list of "seed" inputs which will be used to
+ /// drive execution.
+ const std::vector<struct BOut *> *usingSeeds;
+
+ /// Disables forking, instead a random path is chosen. Enabled as
+ /// needed to control memory usage. \see fork()
+ bool atMemoryLimit;
+
+ /// Disables forking, set by client. \see setInhibitForking()
+ bool inhibitForking;
+
+ /// Signals the executor to halt execution at the next instruction
+ /// step.
+ bool haltExecution;
+
+ /// Whether implied-value concretization is enabled. Currently
+ /// false, it is buggy (it needs to validate its writes).
+ bool ivcEnabled;
+
+ /// The maximum time to allow for a single stp query.
+ double stpTimeout;
+
+ llvm::Function* getCalledFunction(llvm::CallSite &cs, ExecutionState &state);
+
+ void executeInstruction(ExecutionState &state, KInstruction *ki);
+
+ void printFileLine(ExecutionState &state, KInstruction *ki);
+
+ void run(ExecutionState &initialState);
+
+ // Given a concrete object in our [klee's] address space, add it to
+ // objects checked code can reference.
+ MemoryObject *addExternalObject(ExecutionState &state, void *addr,
+ unsigned size, bool isReadOnly);
+
+ void initializeGlobalObject(ExecutionState &state, ObjectState *os,
+ llvm::Constant *c,
+ unsigned offset);
+ void initializeGlobals(ExecutionState &state);
+
+ void stepInstruction(ExecutionState &state);
+ void updateStates(ExecutionState *current);
+ void transferToBasicBlock(llvm::BasicBlock *dst,
+ llvm::BasicBlock *src,
+ ExecutionState &state);
+
+ void callExternalFunction(ExecutionState &state,
+ KInstruction *target,
+ llvm::Function *function,
+ std::vector< ref<Expr> > &arguments);
+
+ ObjectState *bindObjectInState(ExecutionState &state, const MemoryObject *mo,
+ bool isLocal);
+
+ /// Resolve a pointer to the memory objects it could point to the
+ /// start of, forking execution when necessary and generating errors
+ /// for pointers to invalid locations (either out of bounds or
+ /// address inside the middle of objects).
+ ///
+ /// \param results[out] A list of ((MemoryObject,ObjectState),
+ /// state) pairs for each object the given address can point to the
+ /// beginning of.
+ typedef std::vector< std::pair<std::pair<const MemoryObject*, const ObjectState*>,
+ ExecutionState*> > ExactResolutionList;
+ void resolveExact(ExecutionState &state,
+ ref<Expr> p,
+ ExactResolutionList &results,
+ const std::string &name);
+
+ /// Allocate and bind a new object in a particular state. NOTE: This
+ /// function may fork.
+ ///
+ /// \param isLocal Flag to indicate if the object should be
+ /// automatically deallocated on function return (this also makes it
+ /// illegal to free directly).
+ ///
+ /// \param target Value at which to bind the base address of the new
+ /// object.
+ ///
+ /// \param reallocFrom If non-zero and the allocation succeeds,
+ /// initialize the new object from the given one and unbind it when
+ /// done (realloc semantics). The initialized bytes will be the
+ /// minimum of the size of the old and new objects, with remaining
+ /// bytes initialized as specified by zeroMemory.
+ void executeAlloc(ExecutionState &state,
+ ref<Expr> size,
+ bool isLocal,
+ KInstruction *target,
+ bool zeroMemory=false,
+ const ObjectState *reallocFrom=0);
+
+ /// XXX not for public use (this is for histar, it allocations a
+ /// contiguous set of objects, while guaranteeing page alignment)
+ void executeAllocN(ExecutionState &state,
+ uint64_t nelems,
+ uint64_t size,
+ uint64_t alignment,
+ bool isLocal,
+ KInstruction *target);
+
+ /// Free the given address with checking for errors. If target is
+ /// given it will be bound to 0 in the resulting states (this is a
+ /// convenience for realloc). Note that this function can cause the
+ /// state to fork and that \ref state cannot be safely accessed
+ /// afterwards.
+ void executeFree(ExecutionState &state,
+ ref<Expr> address,
+ KInstruction *target = 0);
+
+ void executeCall(ExecutionState &state,
+ KInstruction *ki,
+ llvm::Function *f,
+ std::vector< ref<Expr> > &arguments);
+
+ // do address resolution / object binding / out of bounds checking
+ // and perform the operation
+ void executeMemoryOperation(ExecutionState &state,
+ bool isWrite,
+ ref<Expr> address,
+ ref<Expr> value /* undef if read */,
+ KInstruction *target /* undef if write */);
+
+ void executeMakeSymbolic(ExecutionState &state, const MemoryObject *mo);
+
+ /// Create a new state where each input condition has been added as
+ /// a constraint and return the results. The input state is included
+ /// as one of the results. Note that the output vector may included
+ /// NULL pointers for states which were unable to be created.
+ void branch(ExecutionState &state,
+ const std::vector< ref<Expr> > &conditions,
+ std::vector<ExecutionState*> &result);
+
+ // Fork current and return states in which condition holds / does
+ // not hold, respectively. One of the states is necessarily the
+ // current state, and one of the states may be null.
+ StatePair fork(ExecutionState ¤t, ref<Expr> condition, bool isInternal);
+
+ /// Add the given (boolean) condition as a constraint on state. This
+ /// function is a wrapper around the state's addConstraint function
+ /// which also manages manages propogation of implied values,
+ /// validity checks, and seed patching.
+ void addConstraint(ExecutionState &state, ref<Expr> condition);
+
+ // Called on [for now] concrete reads, replaces constant with a symbolic
+ // Used for testing.
+ ref<Expr> replaceReadWithSymbolic(ExecutionState &state, ref<Expr> e);
+
+ ref<Expr> eval(KInstruction *ki,
+ unsigned index,
+ ExecutionState &state);
+
+ void bindLocal(KInstruction *target,
+ ExecutionState &state,
+ ref<Expr> value);
+ void bindArgument(KFunction *kf,
+ unsigned index,
+ ExecutionState &state,
+ ref<Expr> value);
+
+ ref<Expr> evalConstantExpr(llvm::ConstantExpr *ce);
+
+ /// Return a unique constant value for the given expression in the
+ /// given state, if it has one (i.e. it provably only has a single
+ /// value). Otherwise return the original expression.
+ ref<Expr> toUnique(const ExecutionState &state, ref<Expr> &e);
+
+ /// Return a constant value for the given expression, forcing it to
+ /// be constant in the given state by adding a constraint if
+ /// necessary. Note that this function breaks completeness and
+ /// should generally be avoided.
+ ///
+ /// \param purpose An identify string to printed in case of concretization.
+ ref<Expr> toConstant(ExecutionState &state, ref<Expr> e, const char *purpose);
+
+ /// Bind a constant value for e to the given target. NOTE: This
+ /// function may fork state if the state has multiple seeds.
+ void executeGetValue(ExecutionState &state, ref<Expr> e, KInstruction *target);
+
+ /// Get textual information regarding a memory address.
+ std::string getAddressInfo(ExecutionState &state, ref<Expr> address) const;
+
+ // remove state from queue and delete
+ void terminateState(ExecutionState &state);
+ // call exit handler and terminate state
+ void terminateStateEarly(ExecutionState &state, std::string message);
+ // call exit handler and terminate state
+ void terminateStateOnExit(ExecutionState &state);
+ // call error handler and terminate state
+ void terminateStateOnError(ExecutionState &state,
+ const std::string &message,
+ const std::string &suffix,
+ const std::string &longMessage="");
+
+ // call error handler and terminate state, for execution errors
+ // (things that should not be possible, like illegal instruction or
+ // unlowered instrinsic, or are unsupported, like inline assembly)
+ void terminateStateOnExecError(ExecutionState &state,
+ const std::string &message,
+ const std::string &info="") {
+ terminateStateOnError(state, message, "exec.err", info);
+ }
+
+ /// bindModuleConstants - Initialize the module constant table.
+ void bindModuleConstants();
+
+ /// bindInstructionConstants - Initialize any necessary per instruction
+ /// constant values.
+ void bindInstructionConstants(KInstruction *KI);
+
+ void handlePointsToObj(ExecutionState &state,
+ KInstruction *target,
+ const std::vector<ref<Expr> > &arguments);
+
+ void doImpliedValueConcretization(ExecutionState &state,
+ ref<Expr> e,
+ ref<Expr> value);
+
+ /// Add a timer to be executed periodically.
+ ///
+ /// \param timer The timer object to run on firings.
+ /// \param rate The approximate delay (in seconds) between firings.
+ void addTimer(Timer *timer, double rate);
+
+ void initTimers();
+ void processTimers(ExecutionState *current,
+ double maxInstTime);
+
+public:
+ Executor(const InterpreterOptions &opts, InterpreterHandler *ie);
+ virtual ~Executor();
+
+ const InterpreterHandler& getHandler() {
+ return *interpreterHandler;
+ }
+
+ // XXX should just be moved out to utility module
+ ref<Expr> evalConstant(llvm::Constant *c);
+
+ virtual void setPathWriter(TreeStreamWriter *tsw) {
+ pathWriter = tsw;
+ }
+ virtual void setSymbolicPathWriter(TreeStreamWriter *tsw) {
+ symPathWriter = tsw;
+ }
+
+ virtual void setReplayOut(const struct BOut *out) {
+ assert(!replayPath && "cannot replay both buffer and path");
+ replayOut = out;
+ replayPosition = 0;
+ }
+
+ virtual void setReplayPath(const std::vector<bool> *path) {
+ assert(!replayOut && "cannot replay both buffer and path");
+ replayPath = path;
+ replayPosition = 0;
+ }
+
+ virtual const llvm::Module *
+ setModule(llvm::Module *module, const ModuleOptions &opts);
+
+ virtual void useSeeds(const std::vector<struct BOut *> *seeds) {
+ usingSeeds = seeds;
+ }
+
+ virtual void runFunctionAsMain(llvm::Function *f,
+ int argc,
+ char **argv,
+ char **envp);
+
+ /*** Runtime options ***/
+
+ virtual void setHaltExecution(bool value) {
+ haltExecution = value;
+ }
+
+ virtual void setInhibitForking(bool value) {
+ inhibitForking = value;
+ }
+
+ /*** State accessor methods ***/
+
+ virtual unsigned getPathStreamID(const ExecutionState &state);
+
+ virtual unsigned getSymbolicPathStreamID(const ExecutionState &state);
+
+ virtual void getConstraintLog(const ExecutionState &state,
+ std::string &res,
+ bool asCVC = false);
+
+ virtual bool getSymbolicSolution(const ExecutionState &state,
+ std::vector<
+ std::pair<std::string,
+ std::vector<unsigned char> > >
+ &res);
+
+ virtual void getCoveredLines(const ExecutionState &state,
+ std::map<const std::string*, std::set<unsigned> > &res);
+};
+
+} // End klee namespace
+
+#endif
Added: klee/trunk/lib/Core/ExecutorTimers.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ExecutorTimers.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ExecutorTimers.cpp (added)
+++ klee/trunk/lib/Core/ExecutorTimers.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,220 @@
+//===-- ExecutorTimers.cpp ------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "CoreStats.h"
+#include "Executor.h"
+#include "PTree.h"
+#include "StatsTracker.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Internal/Module/InstructionInfoTable.h"
+#include "klee/Internal/Module/KInstruction.h"
+#include "klee/Internal/Module/KModule.h"
+#include "klee/Internal/System/Time.h"
+
+#include "llvm/Function.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <math.h>
+
+
+using namespace llvm;
+using namespace klee;
+
+cl::opt<double>
+MaxTime("max-time",
+ cl::desc("Halt execution after the specified number of seconds (0=off)"),
+ cl::init(0));
+
+///
+
+class HaltTimer : public Executor::Timer {
+ Executor *executor;
+
+public:
+ HaltTimer(Executor *_executor) : executor(_executor) {}
+ ~HaltTimer() {}
+
+ void run() {
+ llvm::cerr << "KLEE: HaltTimer invoked\n";
+ executor->setHaltExecution(true);
+ }
+};
+
+///
+
+static const double kSecondsPerTick = .1;
+static volatile unsigned timerTicks = 0;
+
+// XXX hack
+extern "C" unsigned dumpStates, dumpPTree;
+unsigned dumpStates = 0, dumpPTree = 0;
+
+static void onAlarm(int) {
+ ++timerTicks;
+}
+
+// oooogalay
+static void setupHandler() {
+ struct itimerval t;
+ struct timeval tv;
+
+ tv.tv_sec = (long) kSecondsPerTick;
+ tv.tv_usec = (long) (fmod(kSecondsPerTick, 1.)*1000000);
+
+ t.it_interval = t.it_value = tv;
+
+ ::setitimer(ITIMER_REAL, &t, 0);
+ ::signal(SIGALRM, onAlarm);
+}
+
+void Executor::initTimers() {
+ static bool first = true;
+
+ if (first) {
+ first = false;
+ setupHandler();
+ }
+
+ if (MaxTime) {
+ addTimer(new HaltTimer(this), MaxTime);
+ }
+}
+
+///
+
+Executor::Timer::Timer() {}
+
+Executor::Timer::~Timer() {}
+
+class Executor::TimerInfo {
+public:
+ Timer *timer;
+
+ /// Approximate delay per timer firing.
+ double rate;
+ /// Wall time for next firing.
+ double nextFireTime;
+
+public:
+ TimerInfo(Timer *_timer, double _rate)
+ : timer(_timer),
+ rate(_rate),
+ nextFireTime(util::getWallTime() + rate) {}
+ ~TimerInfo() { delete timer; }
+};
+
+void Executor::addTimer(Timer *timer, double rate) {
+ timers.push_back(new TimerInfo(timer, rate));
+}
+
+void Executor::processTimers(ExecutionState *current,
+ double maxInstTime) {
+ static unsigned callsWithoutCheck = 0;
+ unsigned ticks = timerTicks;
+
+ if (!ticks && ++callsWithoutCheck > 1000) {
+ setupHandler();
+ ticks = 1;
+ }
+
+ if (ticks || dumpPTree || dumpStates) {
+ if (dumpPTree) {
+ char name[32];
+ sprintf(name, "ptree%08d.dot", (int) stats::instructions);
+ std::ostream *os = interpreterHandler->openOutputFile(name);
+ if (os) {
+ processTree->dump(*os);
+ delete os;
+ }
+
+ dumpPTree = 0;
+ }
+
+ if (dumpStates) {
+ std::ostream *os = interpreterHandler->openOutputFile("states.txt");
+
+ if (os) {
+ for (std::set<ExecutionState*>::const_iterator it = states.begin(),
+ ie = states.end(); it != ie; ++it) {
+ ExecutionState *es = *it;
+ *os << "(" << es << ",";
+ *os << "[";
+ ExecutionState::stack_ty::iterator next = es->stack.begin();
+ ++next;
+ for (ExecutionState::stack_ty::iterator sfIt = es->stack.begin(),
+ sf_ie = es->stack.end(); sfIt != sf_ie; ++sfIt) {
+ *os << "('" << sfIt->kf->function->getName() << "',";
+ if (next == es->stack.end()) {
+ *os << es->prevPC->info->line << "), ";
+ } else {
+ *os << next->caller->info->line << "), ";
+ ++next;
+ }
+ }
+ *os << "], ";
+
+ StackFrame &sf = es->stack.back();
+ uint64_t md2u = computeMinDistToUncovered(es->pc,
+ sf.minDistToUncoveredOnReturn);
+ uint64_t icnt = theStatisticManager->getIndexedValue(stats::instructions,
+ es->pc->info->id);
+ uint64_t cpicnt = sf.callPathNode->statistics.getValue(stats::instructions);
+
+ *os << "{";
+ *os << "'depth' : " << es->depth << ", ";
+ *os << "'weight' : " << es->weight << ", ";
+ *os << "'queryCost' : " << es->queryCost << ", ";
+ *os << "'coveredNew' : " << es->coveredNew << ", ";
+ *os << "'instsSinceCovNew' : " << es->instsSinceCovNew << ", ";
+ *os << "'md2u' : " << md2u << ", ";
+ *os << "'icnt' : " << icnt << ", ";
+ *os << "'CPicnt' : " << cpicnt << ", ";
+ *os << "}";
+ *os << ")\n";
+ }
+
+ delete os;
+ }
+
+ dumpStates = 0;
+ }
+
+ if (maxInstTime>0 && current && !removedStates.count(current)) {
+ if (timerTicks*kSecondsPerTick > maxInstTime) {
+ klee_warning("max-instruction-time exceeded: %.2fs",
+ timerTicks*kSecondsPerTick);
+ terminateStateEarly(*current, "max-instruction-time exceeded");
+ }
+ }
+
+ if (!timers.empty()) {
+ double time = util::getWallTime();
+
+ for (std::vector<TimerInfo*>::iterator it = timers.begin(),
+ ie = timers.end(); it != ie; ++it) {
+ TimerInfo *ti = *it;
+
+ if (time >= ti->nextFireTime) {
+ ti->timer->run();
+ ti->nextFireTime = time + ti->rate;
+ }
+ }
+ }
+
+ timerTicks = 0;
+ callsWithoutCheck = 0;
+ }
+}
+
Added: klee/trunk/lib/Core/ExecutorUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ExecutorUtil.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ExecutorUtil.cpp (added)
+++ klee/trunk/lib/Core/ExecutorUtil.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,144 @@
+//===-- ExecutorUtil.cpp --------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Executor.h"
+
+#include "klee/Expr.h"
+#include "klee/Interpreter.h"
+#include "klee/Machine.h"
+#include "klee/Solver.h"
+
+#include "klee/Internal/Module/KModule.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Target/TargetData.h"
+#include <iostream>
+#include <cassert>
+
+using namespace klee;
+using namespace llvm;
+
+namespace klee {
+
+ref<Expr>
+Executor::evalConstantExpr(llvm::ConstantExpr *ce) {
+ const llvm::Type *type = ce->getType();
+
+ ref<Expr> op1(0,Expr::Bool), op2(0,Expr::Bool), op3(0,Expr::Bool);
+ int numOperands = ce->getNumOperands();
+
+ if (numOperands > 0) op1 = evalConstant(ce->getOperand(0));
+ if (numOperands > 1) op2 = evalConstant(ce->getOperand(1));
+ if (numOperands > 2) op3 = evalConstant(ce->getOperand(2));
+
+ switch (ce->getOpcode()) {
+ case Instruction::Trunc: return ExtractExpr::createByteOff(op1,
+ 0,
+ Expr::getWidthForLLVMType(type));
+ case Instruction::ZExt: return ZExtExpr::create(op1,
+ Expr::getWidthForLLVMType(type));
+ case Instruction::SExt: return SExtExpr::create(op1,
+ Expr::getWidthForLLVMType(type));
+ case Instruction::Add: return AddExpr::create(op1, op2);
+ case Instruction::Sub: return SubExpr::create(op1, op2);
+ case Instruction::Mul: return MulExpr::create(op1, op2);
+ case Instruction::SDiv: return SDivExpr::create(op1, op2);
+ case Instruction::UDiv: return UDivExpr::create(op1, op2);
+ case Instruction::SRem: return SRemExpr::create(op1, op2);
+ case Instruction::URem: return URemExpr::create(op1, op2);
+ case Instruction::And: return AndExpr::create(op1, op2);
+ case Instruction::Or: return OrExpr::create(op1, op2);
+ case Instruction::Xor: return XorExpr::create(op1, op2);
+ case Instruction::Shl: return ShlExpr::create(op1, op2);
+ case Instruction::LShr: return LShrExpr::create(op1, op2);
+ case Instruction::AShr: return AShrExpr::create(op1, op2);
+ case Instruction::BitCast: return op1;
+
+ case Instruction::IntToPtr: {
+ return ZExtExpr::create(op1, Expr::getWidthForLLVMType(type));
+ }
+
+ case Instruction::PtrToInt: {
+ return ZExtExpr::create(op1, Expr::getWidthForLLVMType(type));
+ }
+
+ case Instruction::GetElementPtr: {
+ ref<Expr> base = op1;
+
+ for (gep_type_iterator ii = gep_type_begin(ce), ie = gep_type_end(ce);
+ ii != ie; ++ii) {
+ ref<Expr> addend(0, kMachinePointerType);
+
+ if (const StructType *st = dyn_cast<StructType>(*ii)) {
+ const StructLayout *sl = kmodule->targetData->getStructLayout(st);
+ const ConstantInt *ci = cast<ConstantInt>(ii.getOperand());
+
+ addend = Expr::createPointer(sl->getElementOffset((unsigned)
+ ci->getZExtValue()));
+ } else {
+ const SequentialType *st = cast<SequentialType>(*ii);
+ ref<Expr> index = evalConstant(cast<Constant>(ii.getOperand()));
+ unsigned elementSize = kmodule->targetData->getTypeStoreSize(st->getElementType());
+
+ index = Expr::createCoerceToPointerType(index);
+ addend = MulExpr::create(index,
+ Expr::createPointer(elementSize));
+ }
+
+ base = AddExpr::create(base, addend);
+ }
+
+ return base;
+ }
+
+ case Instruction::ICmp: {
+ switch(ce->getPredicate()) {
+ case ICmpInst::ICMP_EQ: return EqExpr::create(op1, op2);
+ case ICmpInst::ICMP_NE: return NeExpr::create(op1, op2);
+ case ICmpInst::ICMP_UGT: return UgtExpr::create(op1, op2);
+ case ICmpInst::ICMP_UGE: return UgeExpr::create(op1, op2);
+ case ICmpInst::ICMP_ULT: return UltExpr::create(op1, op2);
+ case ICmpInst::ICMP_ULE: return UleExpr::create(op1, op2);
+ case ICmpInst::ICMP_SGT: return SgtExpr::create(op1, op2);
+ case ICmpInst::ICMP_SGE: return SgeExpr::create(op1, op2);
+ case ICmpInst::ICMP_SLT: return SltExpr::create(op1, op2);
+ case ICmpInst::ICMP_SLE: return SleExpr::create(op1, op2);
+ default:
+ assert(0 && "unhandled ICmp predicate");
+ }
+ }
+
+ case Instruction::Select: {
+ return SelectExpr::create(op1, op2, op3);
+ }
+
+ case Instruction::FDiv:
+ case Instruction::FRem:
+ case Instruction::FPTrunc:
+ case Instruction::FPExt:
+ case Instruction::UIToFP:
+ case Instruction::SIToFP:
+ case Instruction::FPToUI:
+ case Instruction::FPToSI:
+ case Instruction::FCmp:
+ assert(0 && "floating point ConstantExprs unsupported");
+
+ default :
+ assert(0 && "unknown ConstantExpr type");
+ }
+}
+
+}
Added: klee/trunk/lib/Core/ExternalDispatcher.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ExternalDispatcher.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ExternalDispatcher.cpp (added)
+++ klee/trunk/lib/Core/ExternalDispatcher.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,230 @@
+//===-- ExternalDispatcher.cpp --------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExternalDispatcher.h"
+
+#include "llvm/Module.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/System/DynamicLibrary.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/raw_ostream.h"
+#include <setjmp.h>
+#include <signal.h>
+
+using namespace llvm;
+using namespace klee;
+
+/***/
+
+static jmp_buf escapeCallJmpBuf;
+
+extern "C" {
+
+static void sigsegv_handler(int signal, siginfo_t *info, void *context) {
+ longjmp(escapeCallJmpBuf, 1);
+}
+
+}
+
+void *ExternalDispatcher::resolveSymbol(const std::string &name) {
+ assert(executionEngine);
+
+ const char *str = name.c_str();
+
+ // We use this to validate that function names can be resolved so we
+ // need to match how the JIT does it. Unfortunately we can't
+ // directly access the JIT resolution function
+ // JIT::getPointerToNamedFunction so we emulate the important points.
+
+ if (str[0] == 1) // asm specifier, skipped
+ ++str;
+
+ void *addr = dl_symbols.SearchForAddressOfSymbol(str);
+ if (addr)
+ return addr;
+
+ // If it has an asm specifier and starts with an underscore we retry
+ // without the underscore. I (DWD) don't know why.
+ if (name[0] == 1 && str[0]=='_') {
+ ++str;
+ addr = dl_symbols.SearchForAddressOfSymbol(str);
+ }
+
+ return addr;
+}
+
+ExternalDispatcher::ExternalDispatcher() {
+ dispatchModule = new Module("ExternalDispatcher");
+ ExistingModuleProvider* MP = new ExistingModuleProvider(dispatchModule);
+
+ std::string error;
+ executionEngine = ExecutionEngine::createJIT(MP, &error);
+ if (!executionEngine) {
+ llvm::cerr << "unable to make jit: " << error << "\n";
+ abort();
+ }
+
+ // from ExecutionEngine::create
+ if (executionEngine) {
+ // Make sure we can resolve symbols in the program as well. The zero arg
+ // to the function tells DynamicLibrary to load the program, not a library.
+ try {
+ dl_symbols.LoadLibraryPermanently(0);
+ } catch (...) {
+ assert(0 && "Exception in LoadLibraryPermantently.\n");
+ }
+ }
+
+#ifdef WINDOWS
+ preboundFunctions["getpid"] = (void*) (long) getpid;
+ preboundFunctions["putchar"] = (void*) (long) putchar;
+ preboundFunctions["printf"] = (void*) (long) printf;
+ preboundFunctions["fprintf"] = (void*) (long) fprintf;
+ preboundFunctions["sprintf"] = (void*) (long) sprintf;
+#endif
+}
+
+ExternalDispatcher::~ExternalDispatcher() {
+ delete executionEngine;
+}
+
+bool ExternalDispatcher::executeCall(Function *f, Instruction *i, uint64_t *args) {
+ dispatchers_ty::iterator it = dispatchers.find(i);
+ Function *dispatcher;
+
+ if (it == dispatchers.end()) {
+#ifdef WINDOWS
+ std::map<std::string, void*>::iterator it2 =
+ preboundFunctions.find(f->getName()));
+
+ if (it2 != preboundFunctions.end()) {
+ // only bind once
+ if (it2->second) {
+ executionEngine->addGlobalMapping(f, it2->second);
+ it2->second = 0;
+ }
+ }
+#endif
+
+ dispatcher = createDispatcher(f,i);
+
+ dispatchers.insert(std::make_pair(i, dispatcher));
+
+ if (dispatcher) {
+ // force the JIT execution engine to go ahead and build the
+ // function. this ensures that any errors or assertions in the
+ // compilation process will trigger crashes instead of being
+ // caught as aborts in the external function.
+ executionEngine->recompileAndRelinkFunction(dispatcher);
+ }
+ } else {
+ dispatcher = it->second;
+ }
+
+ return runProtectedCall(dispatcher, args);
+}
+
+// XXX not reentrant
+static uint64_t *gTheArgsP;
+
+bool ExternalDispatcher::runProtectedCall(Function *f, uint64_t *args) {
+ struct sigaction segvAction, segvActionOld;
+ bool res;
+
+ if (!f)
+ return false;
+
+ std::vector<GenericValue> gvArgs;
+ gTheArgsP = args;
+
+ segvAction.sa_handler = 0;
+ memset(&segvAction.sa_mask, 0, sizeof(segvAction.sa_mask));
+ segvAction.sa_flags = SA_SIGINFO;
+ segvAction.sa_sigaction = ::sigsegv_handler;
+ sigaction(SIGSEGV, &segvAction, &segvActionOld);
+
+ if (setjmp(escapeCallJmpBuf)) {
+ res = false;
+ } else {
+ executionEngine->runFunction(f, gvArgs);
+ res = true;
+ }
+
+ sigaction(SIGSEGV, &segvActionOld, 0);
+ return res;
+}
+
+// for performance purposes we construct the stub in such a way that
+// the arguments pointer is passed through the static global variable
+// gTheArgsP in this file. This is done so that the stub function
+// prototype trivially matches the special cases that the JIT knows
+// how to directly call. If this is not done, then the jit will end up
+// generating a nullary stub just to call our stub, for every single
+// function call.
+Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *inst) {
+ if (!resolveSymbol(target->getName()))
+ return 0;
+
+ CallSite cs;
+ if (inst->getOpcode()==Instruction::Call) {
+ cs = CallSite(cast<CallInst>(inst));
+ } else {
+ cs = CallSite(cast<InvokeInst>(inst));
+ }
+
+ Value **args = new Value*[cs.arg_size()];
+
+ std::vector<const Type*> nullary;
+
+ Function *dispatcher = Function::Create(FunctionType::get(Type::VoidTy,
+ nullary, false),
+ GlobalVariable::ExternalLinkage,
+ "",
+ dispatchModule);
+
+
+ BasicBlock *dBB = BasicBlock::Create("entry", dispatcher);
+
+ Instruction *argI64sp = new IntToPtrInst(ConstantInt::get(Type::Int64Ty, (long) (void*) &gTheArgsP),
+ PointerType::getUnqual(PointerType::getUnqual(Type::Int64Ty)),
+ "argsp",
+ dBB);
+ Instruction *argI64s = new LoadInst(argI64sp, "args", dBB);
+
+ unsigned i = 0;
+ for (CallSite::arg_iterator ai = cs.arg_begin(), ae = cs.arg_end();
+ ai!=ae; ++ai, ++i) {
+ Value *index = ConstantInt::get(Type::Int32Ty, i+1);
+
+ Instruction *argI64p = GetElementPtrInst::Create(argI64s, index, "", dBB);
+ Instruction *argp = new BitCastInst(argI64p,
+ PointerType::getUnqual((*ai)->getType()), "", dBB);
+ args[i] = new LoadInst(argp, "", dBB);
+ }
+
+ Instruction *result = CallInst::Create(target, args, args+i, "", dBB);
+
+ if (result->getType() != Type::VoidTy) {
+ Instruction *resp = new BitCastInst(argI64s,
+ PointerType::getUnqual(result->getType()), "", dBB);
+ new StoreInst(result, resp, dBB);
+ }
+
+ ReturnInst::Create(dBB);
+
+ delete[] args;
+
+ return dispatcher;
+}
Added: klee/trunk/lib/Core/ExternalDispatcher.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ExternalDispatcher.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ExternalDispatcher.h (added)
+++ klee/trunk/lib/Core/ExternalDispatcher.h Wed May 20 23:36:41 2009
@@ -0,0 +1,50 @@
+//===-- ExternalDispatcher.h ------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_EXTERNALDISPATCHER_H
+#define KLEE_EXTERNALDISPATCHER_H
+
+#include <map>
+#include "llvm/System/DynamicLibrary.h"
+
+namespace llvm {
+ class ExecutionEngine;
+ class Instruction;
+ class Function;
+ class FunctionType;
+ class Module;
+}
+
+namespace klee {
+ class ExternalDispatcher {
+ private:
+ typedef std::map<const llvm::Instruction*,llvm::Function*> dispatchers_ty;
+ dispatchers_ty dispatchers;
+ llvm::Module *dispatchModule;
+ llvm::ExecutionEngine *executionEngine;
+ llvm::sys::DynamicLibrary dl_symbols;
+ std::map<std::string, void*> preboundFunctions;
+
+ llvm::Function *createDispatcher(llvm::Function *f, llvm::Instruction *i);
+ bool runProtectedCall(llvm::Function *f, uint64_t *args);
+
+ public:
+ ExternalDispatcher();
+ ~ExternalDispatcher();
+
+ /* Call the given function using the parameter passing convention of
+ * ci with arguments in args[1], args[2], ... and writing the result
+ * into args[0].
+ */
+ bool executeCall(llvm::Function *function, llvm::Instruction *i, uint64_t *args);
+ void *resolveSymbol(const std::string &name);
+ };
+}
+
+#endif
Added: klee/trunk/lib/Core/ImpliedValue.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ImpliedValue.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ImpliedValue.cpp (added)
+++ klee/trunk/lib/Core/ImpliedValue.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,274 @@
+//===-- ImpliedValue.cpp --------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ImpliedValue.h"
+
+#include "klee/Constraints.h"
+#include "klee/Expr.h"
+#include "klee/Solver.h"
+// FIXME: Use APInt.
+#include "klee/Internal/Support/IntEvaluation.h"
+
+#include "klee/util/ExprUtil.h"
+
+#include <iostream>
+#include <map>
+#include <set>
+
+using namespace klee;
+
+// XXX we really want to do some sort of canonicalization of exprs
+// globally so that cases below become simpler
+static void _getImpliedValue(ref<Expr> e,
+ uint64_t value,
+ ImpliedValueList &results) {
+ switch (e.getKind()) {
+
+ case Expr::Constant: {
+ assert(value == e.getConstantValue() && "error in implied value calculation");
+ break;
+ }
+
+ // Special
+
+ case Expr::NotOptimized: break;
+
+ case Expr::Read: {
+ // XXX in theory it is possible to descend into a symbolic index
+ // under certain circumstances (all values known, known value
+ // unique, or range known, max / min hit). Seems unlikely this
+ // would work often enough to be worth the effort.
+ ReadExpr *re = static_ref_cast<ReadExpr>(e);
+ results.push_back(std::make_pair(re,
+ ConstantExpr::create(value, e.getWidth())));
+ break;
+ }
+
+ case Expr::Select: {
+ // not much to do, could improve with range analysis
+ SelectExpr *se = static_ref_cast<SelectExpr>(e);
+
+ if (se->trueExpr.isConstant()) {
+ if (se->falseExpr.isConstant()) {
+ if (se->trueExpr.getConstantValue() != se->falseExpr.getConstantValue()) {
+ if (value == se->trueExpr.getConstantValue()) {
+ _getImpliedValue(se->cond, 1, results);
+ } else {
+ assert(value == se->falseExpr.getConstantValue() &&
+ "err in implied value calculation");
+ _getImpliedValue(se->cond, 0, results);
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ case Expr::Concat: {
+ ConcatExpr *ce = static_ref_cast<ConcatExpr>(e);
+ _getImpliedValue(ce->getKid(0), (value >> ce->getKid(1).getWidth()) & ((1 << ce->getKid(0).getWidth()) - 1), results);
+ _getImpliedValue(ce->getKid(1), value & ((1 << ce->getKid(1).getWidth()) - 1), results);
+ break;
+ }
+
+ case Expr::Extract: {
+ // XXX, could do more here with "some bits" mask
+ break;
+ }
+
+ // Casting
+
+ case Expr::ZExt:
+ case Expr::SExt: {
+ CastExpr *ce = static_ref_cast<CastExpr>(e);
+ _getImpliedValue(ce->src,
+ bits64::truncateToNBits(value,
+ ce->src.getWidth()),
+ results);
+ break;
+ }
+
+ // Arithmetic
+
+ case Expr::Add: { // constants on left
+ BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ if (be->left.isConstant()) {
+ uint64_t nvalue = ints::sub(value,
+ be->left.getConstantValue(),
+ be->left.getWidth());
+ _getImpliedValue(be->right, nvalue, results);
+ }
+ break;
+ }
+ case Expr::Sub: { // constants on left
+ BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ if (be->left.isConstant()) {
+ uint64_t nvalue = ints::sub(be->left.getConstantValue(),
+ value,
+ be->left.getWidth());
+ _getImpliedValue(be->right, nvalue, results);
+ }
+ break;
+ }
+ case Expr::Mul: {
+ // XXX can do stuff here, but need valid mask and other things
+ // because of bits that might be lost
+ break;
+ }
+
+ case Expr::UDiv:
+ case Expr::SDiv:
+ case Expr::URem:
+ case Expr::SRem:
+ // no, no, no
+ break;
+
+ // Binary
+
+ case Expr::And: {
+ BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ if (be->getWidth() == Expr::Bool) {
+ if (value) {
+ _getImpliedValue(be->left, value, results);
+ _getImpliedValue(be->right, value, results);
+ }
+ } else {
+ // XXX, we can basically propogate a mask here
+ // where we know "some bits". may or may not be
+ // useful.
+ }
+ break;
+ }
+ case Expr::Or: {
+ BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ if (!value) {
+ _getImpliedValue(be->left, 0, results);
+ _getImpliedValue(be->right, 0, results);
+ } else {
+ // XXX, can do more?
+ }
+ break;
+ }
+ case Expr::Xor: { // constants on left
+ BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ if (be->left.isConstant()) {
+ _getImpliedValue(be->right, value ^ be->left.getConstantValue(), results);
+ }
+ break;
+ }
+
+ // Comparison
+ case Expr::Ne:
+ value = !value;
+ /* fallthru */
+ case Expr::Eq: {
+ EqExpr *ee = static_ref_cast<EqExpr>(e);
+ if (value) {
+ if (ee->left.isConstant())
+ _getImpliedValue(ee->right, ee->left.getConstantValue(), results);
+ } else {
+ // look for limited value range, woohoo
+ //
+ // in general anytime one side was restricted to two values we
+ // can apply this trick. the only obvious case where this
+ // occurs, aside from booleans, is as the result of a select
+ // expression where the true and false branches are single
+ // valued and distinct.
+
+ if (ee->left.isConstant()) {
+ if (ee->left.getWidth() == Expr::Bool) {
+ _getImpliedValue(ee->right, !ee->left.getConstantValue(), results);
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void ImpliedValue::getImpliedValues(ref<Expr> e,
+ ref<Expr> value,
+ ImpliedValueList &results) {
+ assert(value.isConstant() && "non-constant in place of constant");
+ _getImpliedValue(e, value.getConstantValue(), results);
+}
+
+void ImpliedValue::checkForImpliedValues(Solver *S, ref<Expr> e,
+ ref<Expr> value) {
+ assert(value.isConstant() && "non-constant in place of constant");
+
+ std::vector<ref<ReadExpr> > reads;
+ std::map<ref<ReadExpr>, ref<Expr> > found;
+ ImpliedValueList results;
+
+ getImpliedValues(e, value, results);
+
+ for (ImpliedValueList::iterator i = results.begin(), ie = results.end();
+ i != ie; ++i) {
+ std::map<ref<ReadExpr>, ref<Expr> >::iterator it = found.find(i->first);
+ if (it != found.end()) {
+ assert(it->second.getConstantValue() == i->second.getConstantValue() &&
+ "I don't think so Scott");
+ } else {
+ found.insert(std::make_pair(i->first, i->second));
+ }
+ }
+
+ findReads(e, false, reads);
+ std::set< ref<ReadExpr> > readsSet(reads.begin(), reads.end());
+ reads = std::vector< ref<ReadExpr> >(readsSet.begin(), readsSet.end());
+
+ std::vector<ref<Expr> > assumption;
+ assumption.push_back(EqExpr::create(e, value));
+
+ // obscure... we need to make sure that all the read indices are
+ // bounds checked. if we don't do this we can end up constructing
+ // invalid counterexamples because STP will happily make out of
+ // bounds indices which will not get picked up. this is of utmost
+ // importance if we are being backed by the CexCachingSolver.
+
+ for (std::vector< ref<ReadExpr> >::iterator i = reads.begin(),
+ ie = reads.end(); i != ie; ++i) {
+ ReadExpr *re = i->get();
+ ref<Expr> size = ref<Expr>(re->updates.root->size, kMachinePointerType);
+ assumption.push_back(UltExpr::create(re->index, size));
+ }
+
+ ConstraintManager assume(assumption);
+ for (std::vector< ref<ReadExpr> >::iterator i = reads.begin(),
+ ie = reads.end(); i != ie; ++i) {
+ ref<ReadExpr> var = *i;
+ ref<Expr> possible;
+ bool success = S->getValue(Query(assume, var), possible);
+ assert(success && "FIXME: Unhandled solver failure");
+ std::map<ref<ReadExpr>, ref<Expr> >::iterator it = found.find(var);
+ bool res;
+ success = S->mustBeTrue(Query(assume, EqExpr::create(var, possible)), res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res) {
+ if (it != found.end()) {
+ assert(possible.getConstantValue() == it->second.getConstantValue());
+ found.erase(it);
+ }
+ } else {
+ if (it!=found.end()) {
+ ref<Expr> binding = it->second;
+ llvm::cerr << "checkForImpliedValues: " << e << " = " << value << "\n"
+ << "\t\t implies " << var << " == " << binding
+ << " (error)\n";
+ assert(0);
+ }
+ }
+ }
+
+ assert(found.empty());
+}
Added: klee/trunk/lib/Core/ImpliedValue.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ImpliedValue.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ImpliedValue.h (added)
+++ klee/trunk/lib/Core/ImpliedValue.h Wed May 20 23:36:41 2009
@@ -0,0 +1,38 @@
+//===-- ImpliedValue.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_IMPLIEDVALUE_H
+#define KLEE_IMPLIEDVALUE_H
+
+#include "klee/Expr.h"
+
+#include <vector>
+
+// The idea of implied values is that often we know the result of some
+// expression e is a concrete value C. In many cases this directly
+// implies that some variable x embedded in e is also a concrete value
+// (derived from C). This module is used for finding such variables
+// and their computed values.
+
+namespace klee {
+ class ConstantExpr;
+ class Expr;
+ class ReadExpr;
+ class Solver;
+
+ typedef std::vector< std::pair<ref<ReadExpr>, ref<Expr> > > ImpliedValueList;
+
+ namespace ImpliedValue {
+ void getImpliedValues(ref<Expr> e, ref<Expr> cvalue, ImpliedValueList &result);
+ void checkForImpliedValues(Solver *S, ref<Expr> e, ref<Expr> cvalue);
+ }
+
+}
+
+#endif
Added: klee/trunk/lib/Core/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Makefile (added)
+++ klee/trunk/lib/Core/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+#===-- lib/Core/Makefile -----------------------------------*- Makefile -*--===#
+#
+# The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+LEVEL=../..
+
+LIBRARYNAME=kleeCore
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+
+include $(LEVEL)/Makefile.common
Propchange: klee/trunk/lib/Core/Makefile
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/lib/Core/Memory.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Memory.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Memory.cpp (added)
+++ klee/trunk/lib/Core/Memory.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,812 @@
+//===-- Memory.cpp --------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "Memory.h"
+
+#include "klee/Expr.h"
+#include "klee/Machine.h"
+#include "klee/Solver.h"
+#include "klee/util/BitArray.h"
+
+#include "ObjectHolder.h"
+
+#include <llvm/Function.h>
+#include <llvm/Instruction.h>
+#include <llvm/Value.h>
+
+#include <iostream>
+#include <cassert>
+#include <sstream>
+
+using namespace llvm;
+using namespace klee;
+
+/***/
+
+ObjectHolder::ObjectHolder(const ObjectHolder &b) : os(b.os) {
+ if (os) ++os->refCount;
+}
+
+ObjectHolder::ObjectHolder(ObjectState *_os) : os(_os) {
+ if (os) ++os->refCount;
+}
+
+ObjectHolder::~ObjectHolder() {
+ if (os && --os->refCount==0) delete os;
+}
+
+ObjectHolder &ObjectHolder::operator=(const ObjectHolder &b) {
+ if (b.os) ++b.os->refCount;
+ if (os && --os->refCount==0) delete os;
+ os = b.os;
+ return *this;
+}
+
+/***/
+
+int MemoryObject::counter = 0;
+
+extern "C" void vc_DeleteExpr(void*);
+
+MemoryObject::~MemoryObject() {
+ // FIXME: This shouldn't be necessary. Array's should be ref-counted
+ // just like everything else, and the interaction with the STP array
+ // should hide at least inside the Expr/Solver layers.
+ if (array) {
+ if (array->stpInitialArray) {
+ ::vc_DeleteExpr(array->stpInitialArray);
+ array->stpInitialArray = 0;
+ }
+ delete array;
+ }
+}
+
+void MemoryObject::getAllocInfo(std::string &result) const {
+ std::ostringstream info;
+
+ info << "MO" << id << "[" << size << "]";
+
+ if (allocSite) {
+ info << " allocated at ";
+ if (const Instruction *i = dyn_cast<Instruction>(allocSite)) {
+ info << i->getParent()->getParent()->getName() << "():";
+ info << *i;
+ } else if (const GlobalValue *gv = dyn_cast<GlobalValue>(allocSite)) {
+ info << "global:" << gv->getName();
+ } else {
+ info << "value:" << *allocSite;
+ }
+ } else {
+ info << " (no allocation info)";
+ }
+
+ result = info.str();
+}
+
+/***/
+
+ObjectState::ObjectState(const MemoryObject *mo, unsigned _size)
+ : copyOnWriteOwner(0),
+ refCount(0),
+ object(mo),
+ concreteStore(new uint8_t[_size]),
+ concreteMask(0),
+ flushMask(0),
+ knownSymbolics(0),
+ size(_size),
+ updates(mo->array, false, 0),
+ readOnly(false) {
+}
+
+ObjectState::ObjectState(const ObjectState &os)
+ : copyOnWriteOwner(0),
+ refCount(0),
+ object(os.object),
+ concreteStore(new uint8_t[os.size]),
+ concreteMask(os.concreteMask ? new BitArray(*os.concreteMask, os.size) : 0),
+ flushMask(os.flushMask ? new BitArray(*os.flushMask, os.size) : 0),
+ knownSymbolics(0),
+ size(os.size),
+ updates(os.updates),
+ readOnly(false) {
+ assert(!os.readOnly && "no need to copy read only object?");
+
+ if (os.knownSymbolics) {
+ knownSymbolics = new ref<Expr>[size];
+ for (unsigned i=0; i<size; i++)
+ knownSymbolics[i] = os.knownSymbolics[i];
+ }
+
+ memcpy(concreteStore, os.concreteStore, size*sizeof(*concreteStore));
+}
+
+ObjectState::~ObjectState() {
+ if (concreteMask) delete concreteMask;
+ if (flushMask) delete flushMask;
+ if (knownSymbolics) delete[] knownSymbolics;
+ delete[] concreteStore;
+}
+
+/***/
+
+void ObjectState::makeConcrete() {
+ if (concreteMask) delete concreteMask;
+ if (flushMask) delete flushMask;
+ if (knownSymbolics) delete[] knownSymbolics;
+ concreteMask = 0;
+ flushMask = 0;
+ knownSymbolics = 0;
+}
+
+void ObjectState::makeSymbolic() {
+ assert(!updates.head &&
+ "XXX makeSymbolic of objects with symbolic values is unsupported");
+ updates.isRooted = true;
+
+ // XXX simplify this, can just delete various arrays I guess
+ for (unsigned i=0; i<size; i++) {
+ markByteSymbolic(i);
+ setKnownSymbolic(i, 0);
+ markByteFlushed(i);
+ }
+}
+
+void ObjectState::initializeToZero() {
+ makeConcrete();
+ memset(concreteStore, 0, size);
+}
+
+void ObjectState::initializeToRandom() {
+ makeConcrete();
+ for (unsigned i=0; i<size; i++) {
+ // randomly selected by 256 sided die
+ concreteStore[i] = 0xAB;
+ }
+}
+
+/*
+Cache Invariants
+--
+isByteKnownSymbolic(i) => !isByteConcrete(i)
+isByteConcrete(i) => !isByteKnownSymbolic(i)
+!isByteFlushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i))
+ */
+
+void ObjectState::fastRangeCheckOffset(ref<Expr> offset,
+ unsigned *base_r,
+ unsigned *size_r) const {
+ *base_r = 0;
+ *size_r = size;
+}
+
+void ObjectState::flushRangeForRead(unsigned rangeBase,
+ unsigned rangeSize) const {
+ if (!flushMask) flushMask = new BitArray(size, true);
+
+ for (unsigned offset=rangeBase; offset<rangeBase+rangeSize; offset++) {
+ if (!isByteFlushed(offset)) {
+ if (isByteConcrete(offset)) {
+ updates.extend(ConstantExpr::create(offset, kMachinePointerType),
+ ConstantExpr::create(concreteStore[offset], Expr::Int8));
+ } else {
+ assert(isByteKnownSymbolic(offset) && "invalid bit set in flushMask");
+ updates.extend(ConstantExpr::create(offset, kMachinePointerType),
+ knownSymbolics[offset]);
+ }
+
+ flushMask->unset(offset);
+ }
+ }
+}
+
+void ObjectState::flushRangeForWrite(unsigned rangeBase,
+ unsigned rangeSize) {
+ if (!flushMask) flushMask = new BitArray(size, true);
+
+ for (unsigned offset=rangeBase; offset<rangeBase+rangeSize; offset++) {
+ if (!isByteFlushed(offset)) {
+ if (isByteConcrete(offset)) {
+ updates.extend(ConstantExpr::create(offset, kMachinePointerType),
+ ConstantExpr::create(concreteStore[offset], Expr::Int8));
+ markByteSymbolic(offset);
+ } else {
+ assert(isByteKnownSymbolic(offset) && "invalid bit set in flushMask");
+ updates.extend(ConstantExpr::create(offset, kMachinePointerType),
+ knownSymbolics[offset]);
+ setKnownSymbolic(offset, 0);
+ }
+
+ flushMask->unset(offset);
+ } else {
+ // flushed bytes that are written over still need
+ // to be marked out
+ if (isByteConcrete(offset)) {
+ markByteSymbolic(offset);
+ } else if (isByteKnownSymbolic(offset)) {
+ setKnownSymbolic(offset, 0);
+ }
+ }
+ }
+}
+
+bool ObjectState::isByteConcrete(unsigned offset) const {
+ return !concreteMask || concreteMask->get(offset);
+}
+
+bool ObjectState::isByteFlushed(unsigned offset) const {
+ return flushMask && !flushMask->get(offset);
+}
+
+bool ObjectState::isByteKnownSymbolic(unsigned offset) const {
+ return knownSymbolics && knownSymbolics[offset].get();
+}
+
+void ObjectState::markByteConcrete(unsigned offset) {
+ if (concreteMask)
+ concreteMask->set(offset);
+}
+
+void ObjectState::markByteSymbolic(unsigned offset) {
+ if (!concreteMask)
+ concreteMask = new BitArray(size, true);
+ concreteMask->unset(offset);
+}
+
+void ObjectState::markByteUnflushed(unsigned offset) {
+ if (flushMask)
+ flushMask->set(offset);
+}
+
+void ObjectState::markByteFlushed(unsigned offset) {
+ if (!flushMask) {
+ flushMask = new BitArray(size, false);
+ } else {
+ flushMask->unset(offset);
+ }
+}
+
+void ObjectState::setKnownSymbolic(unsigned offset,
+ Expr *value /* can be null */) {
+ if (knownSymbolics) {
+ knownSymbolics[offset] = value;
+ } else {
+ if (value) {
+ knownSymbolics = new ref<Expr>[size];
+ knownSymbolics[offset] = value;
+ }
+ }
+}
+
+/***/
+
+ref<Expr> ObjectState::read8(unsigned offset) const {
+ if (isByteConcrete(offset)) {
+ return ConstantExpr::create(concreteStore[offset], Expr::Int8);
+ } else if (isByteKnownSymbolic(offset)) {
+ return knownSymbolics[offset];
+ } else {
+ assert(isByteFlushed(offset) && "unflushed byte without cache value");
+
+ return ReadExpr::create(updates,
+ ConstantExpr::create(offset, kMachinePointerType));
+ }
+}
+
+ref<Expr> ObjectState::read8(ref<Expr> offset) const {
+ assert(!offset.isConstant() && "constant offset passed to symbolic read8");
+ unsigned base, size;
+ fastRangeCheckOffset(offset, &base, &size);
+ flushRangeForRead(base, size);
+
+ if (size>4096) {
+ std::string allocInfo;
+ object->getAllocInfo(allocInfo);
+ klee_warning_once(0, "flushing %d bytes on read, may be slow and/or crash: %s",
+ size,
+ allocInfo.c_str());
+ }
+
+ return ReadExpr::create(updates, offset);
+}
+
+void ObjectState::write8(unsigned offset, uint8_t value) {
+ //assert(read_only == false && "writing to read-only object!");
+ concreteStore[offset] = value;
+ setKnownSymbolic(offset, 0);
+
+ markByteConcrete(offset);
+ markByteUnflushed(offset);
+}
+
+void ObjectState::write8(unsigned offset, ref<Expr> value) {
+ // can happen when ExtractExpr special cases
+ if (value.isConstant()) {
+ write8(offset, (uint8_t) value.getConstantValue());
+ } else {
+ setKnownSymbolic(offset, value.get());
+
+ markByteSymbolic(offset);
+ markByteUnflushed(offset);
+ }
+}
+
+void ObjectState::write8(ref<Expr> offset, ref<Expr> value) {
+ assert(!offset.isConstant() && "constant offset passed to symbolic write8");
+ unsigned base, size;
+ fastRangeCheckOffset(offset, &base, &size);
+ flushRangeForWrite(base, size);
+
+ if (size>4096) {
+ std::string allocInfo;
+ object->getAllocInfo(allocInfo);
+ klee_warning_once(0, "flushing %d bytes on read, may be slow and/or crash: %s",
+ size,
+ allocInfo.c_str());
+ }
+
+ updates.extend(offset, value);
+}
+
+/***/
+
+ref<Expr> ObjectState::read(ref<Expr> offset, Expr::Width width) const {
+ if (offset.isConstant()) {
+ return read((unsigned) offset.getConstantValue(), width);
+ } else {
+ switch (width) {
+ case Expr::Bool: return read1(offset);
+ case Expr::Int8: return read8(offset);
+ case Expr::Int16: return read16(offset);
+ case Expr::Int32: return read32(offset);
+ case Expr::Int64: return read64(offset);
+ default: assert(0 && "invalid type");
+ }
+ }
+}
+
+ref<Expr> ObjectState::read(unsigned offset, Expr::Width width) const {
+ switch (width) {
+ case Expr::Bool: return read1(offset);
+ case Expr::Int8: return read8(offset);
+ case Expr::Int16: return read16(offset);
+ case Expr::Int32: return read32(offset);
+ case Expr::Int64: return read64(offset);
+ default: assert(0 && "invalid type");
+ }
+}
+
+ref<Expr> ObjectState::read1(unsigned offset) const {
+ return ExtractExpr::createByteOff(read8(offset), 0, Expr::Bool);
+}
+
+ref<Expr> ObjectState::read1(ref<Expr> offset) const {
+ return ExtractExpr::createByteOff(read8(offset), 0, Expr::Bool);
+}
+
+ref<Expr> ObjectState::read16(unsigned offset) const {
+ if (kMachineByteOrder == machine::MSB) {
+ return ConcatExpr::create(read8(offset+0),
+ read8(offset+1));
+ } else {
+ return ConcatExpr::create(read8(offset+1),
+ read8(offset+0));
+ }
+}
+
+ref<Expr> ObjectState::read16(ref<Expr> offset) const {
+ if (kMachineByteOrder == machine::MSB) {
+ return ConcatExpr::create
+ (read8(AddExpr::create(offset,
+ ConstantExpr::create(0,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(1,
+ kMachinePointerType))));
+ } else {
+ return ConcatExpr::create
+ (read8(AddExpr::create(offset,
+ ConstantExpr::create(1,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(0,
+ kMachinePointerType))));
+ }
+}
+
+ref<Expr> ObjectState::read32(unsigned offset) const {
+ if (kMachineByteOrder == machine::MSB) {
+ return ConcatExpr::create4(read8(offset+0),
+ read8(offset+1),
+ read8(offset+2),
+ read8(offset+3));
+ } else {
+ return ConcatExpr::create4(read8(offset+3),
+ read8(offset+2),
+ read8(offset+1),
+ read8(offset+0));
+ }
+}
+
+ref<Expr> ObjectState::read32(ref<Expr> offset) const {
+ if (kMachineByteOrder == machine::MSB) {
+ return ConcatExpr::create4
+ (read8(AddExpr::create(offset,
+ ConstantExpr::create(0,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(1,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(2,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(3,
+ kMachinePointerType))));
+ } else {
+ return ConcatExpr::create4
+ (read8(AddExpr::create(offset,
+ ConstantExpr::create(3,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(2,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(1,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(0,
+ kMachinePointerType))));
+ }
+}
+
+ref<Expr> ObjectState::read64(unsigned offset) const {
+ if (kMachineByteOrder == machine::MSB) {
+ return ConcatExpr::create8(read8(offset+0),
+ read8(offset+1),
+ read8(offset+2),
+ read8(offset+3),
+ read8(offset+4),
+ read8(offset+5),
+ read8(offset+6),
+ read8(offset+7));
+ } else {
+ return ConcatExpr::create8(read8(offset+7),
+ read8(offset+6),
+ read8(offset+5),
+ read8(offset+4),
+ read8(offset+3),
+ read8(offset+2),
+ read8(offset+1),
+ read8(offset+0));
+ }
+}
+
+ref<Expr> ObjectState::read64(ref<Expr> offset) const {
+ if (kMachineByteOrder == machine::MSB) {
+ return ConcatExpr::create8
+ (read8(AddExpr::create(offset,
+ ConstantExpr::create(0,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(1,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(2,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(3,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(4,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(5,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(6,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(7,
+ kMachinePointerType))));
+ } else {
+ return ConcatExpr::create8
+ (read8(AddExpr::create(offset,
+ ConstantExpr::create(7,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(6,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(5,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(4,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(3,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(2,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(1,
+ kMachinePointerType))),
+ read8(AddExpr::create(offset,
+ ConstantExpr::create(0,
+ kMachinePointerType))));
+ }
+}
+
+void ObjectState::write(ref<Expr> offset, ref<Expr> value) {
+ Expr::Width w = value.getWidth();
+ if (offset.isConstant()) {
+ write(offset.getConstantValue(), value);
+ } else {
+ switch(w) {
+ case Expr::Bool: write1(offset, value); break;
+ case Expr::Int8: write8(offset, value); break;
+ case Expr::Int16: write16(offset, value); break;
+ case Expr::Int32: write32(offset, value); break;
+ case Expr::Int64: write64(offset, value); break;
+ default: assert(0 && "invalid number of bytes in write");
+ }
+ }
+}
+
+void ObjectState::write(unsigned offset, ref<Expr> value) {
+ Expr::Width w = value.getWidth();
+ if (value.isConstant()) {
+ uint64_t val = value.getConstantValue();
+ switch(w) {
+ case Expr::Bool:
+ case Expr::Int8: write8(offset, val); break;
+ case Expr::Int16: write16(offset, val); break;
+ case Expr::Int32: write32(offset, val); break;
+ case Expr::Int64: write64(offset, val); break;
+ default: assert(0 && "invalid number of bytes in write");
+ }
+ } else {
+ switch(w) {
+ case Expr::Bool: write1(offset, value); break;
+ case Expr::Int8: write8(offset, value); break;
+ case Expr::Int16: write16(offset, value); break;
+ case Expr::Int32: write32(offset, value); break;
+ case Expr::Int64: write64(offset, value); break;
+ default: assert(0 && "invalid number of bytes in write");
+ }
+ }
+}
+
+void ObjectState::write1(unsigned offset, ref<Expr> value) {
+ write8(offset, ZExtExpr::create(value, Expr::Int8));
+}
+
+void ObjectState::write1(ref<Expr> offset, ref<Expr> value) {
+ write8(offset, ZExtExpr::create(value, Expr::Int8));
+}
+
+void ObjectState::write16(unsigned offset, uint16_t value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(offset+0, (uint8_t) (value >> 8));
+ write8(offset+1, (uint8_t) (value >> 0));
+ } else {
+ write8(offset+1, (uint8_t) (value >> 8));
+ write8(offset+0, (uint8_t) (value >> 0));
+ }
+}
+
+void ObjectState::write16(unsigned offset, ref<Expr> value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(offset+0, ExtractExpr::createByteOff(value, 1));
+ write8(offset+1, ExtractExpr::createByteOff(value, 0));
+ } else {
+ write8(offset+1, ExtractExpr::createByteOff(value, 1));
+ write8(offset+0, ExtractExpr::createByteOff(value, 0));
+ }
+}
+
+
+void ObjectState::write16(ref<Expr> offset, ref<Expr> value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(0, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,1));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(0, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,0));
+ } else {
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(1, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,1));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(0, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,0));
+ }
+}
+
+void ObjectState::write32(unsigned offset, uint32_t value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(offset+0, (uint8_t) (value >> 24));
+ write8(offset+1, (uint8_t) (value >> 16));
+ write8(offset+2, (uint8_t) (value >> 8));
+ write8(offset+3, (uint8_t) (value >> 0));
+ } else {
+ write8(offset+3, (uint8_t) (value >> 24));
+ write8(offset+2, (uint8_t) (value >> 16));
+ write8(offset+1, (uint8_t) (value >> 8));
+ write8(offset+0, (uint8_t) (value >> 0));
+ }
+}
+
+void ObjectState::write32(unsigned offset, ref<Expr> value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(offset+0, ExtractExpr::createByteOff(value, 3));
+ write8(offset+1, ExtractExpr::createByteOff(value, 2));
+ write8(offset+2, ExtractExpr::createByteOff(value, 1));
+ write8(offset+3, ExtractExpr::createByteOff(value, 0));
+ } else {
+ write8(offset+3, ExtractExpr::createByteOff(value, 3));
+ write8(offset+2, ExtractExpr::createByteOff(value, 2));
+ write8(offset+1, ExtractExpr::createByteOff(value, 1));
+ write8(offset+0, ExtractExpr::createByteOff(value, 0));
+ }
+}
+
+void ObjectState::write32(ref<Expr> offset, ref<Expr> value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(0, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,3));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(1, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,2));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(2, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,1));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(3, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,0));
+ } else {
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(3, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,3));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(2, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,2));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(1, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,1));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(0, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,0));
+ }
+}
+
+void ObjectState::write64(unsigned offset, uint64_t value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(offset+0, (uint8_t) (value >> 56));
+ write8(offset+1, (uint8_t) (value >> 48));
+ write8(offset+2, (uint8_t) (value >> 40));
+ write8(offset+3, (uint8_t) (value >> 32));
+ write8(offset+4, (uint8_t) (value >> 24));
+ write8(offset+5, (uint8_t) (value >> 16));
+ write8(offset+6, (uint8_t) (value >> 8));
+ write8(offset+7, (uint8_t) (value >> 0));
+ } else {
+ write8(offset+7, (uint8_t) (value >> 56));
+ write8(offset+6, (uint8_t) (value >> 48));
+ write8(offset+5, (uint8_t) (value >> 40));
+ write8(offset+4, (uint8_t) (value >> 32));
+ write8(offset+3, (uint8_t) (value >> 24));
+ write8(offset+2, (uint8_t) (value >> 16));
+ write8(offset+1, (uint8_t) (value >> 8));
+ write8(offset+0, (uint8_t) (value >> 0));
+ }
+}
+
+void ObjectState::write64(unsigned offset, ref<Expr> value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(offset+0, ExtractExpr::createByteOff(value, 7));
+ write8(offset+1, ExtractExpr::createByteOff(value, 6));
+ write8(offset+2, ExtractExpr::createByteOff(value, 5));
+ write8(offset+3, ExtractExpr::createByteOff(value, 4));
+ write8(offset+4, ExtractExpr::createByteOff(value, 3));
+ write8(offset+5, ExtractExpr::createByteOff(value, 2));
+ write8(offset+6, ExtractExpr::createByteOff(value, 1));
+ write8(offset+7, ExtractExpr::createByteOff(value, 0));
+ } else {
+ write8(offset+7, ExtractExpr::createByteOff(value, 7));
+ write8(offset+6, ExtractExpr::createByteOff(value, 6));
+ write8(offset+5, ExtractExpr::createByteOff(value, 5));
+ write8(offset+4, ExtractExpr::createByteOff(value, 4));
+ write8(offset+3, ExtractExpr::createByteOff(value, 3));
+ write8(offset+2, ExtractExpr::createByteOff(value, 2));
+ write8(offset+1, ExtractExpr::createByteOff(value, 1));
+ write8(offset+0, ExtractExpr::createByteOff(value, 0));
+ }
+}
+
+void ObjectState::write64(ref<Expr> offset, ref<Expr> value) {
+ if (kMachineByteOrder == machine::MSB) {
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(0, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,7));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(1, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,6));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(2, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,5));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(3, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,4));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(4, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,3));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(5, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,2));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(6, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,1));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(7, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,0));
+ } else {
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(7, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,7));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(6, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,6));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(5, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,5));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(4, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,4));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(3, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,3));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(2, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,2));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(1, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,1));
+ write8(AddExpr::create(offset,
+ ConstantExpr::create(0, kMachinePointerType)),
+ ExtractExpr::createByteOff(value,0));
+ }
+}
+
+void ObjectState::print() {
+ llvm::cerr << "-- ObjectState --\n";
+ llvm::cerr << "\tMemoryObject ID: " << object->id << "\n";
+ llvm::cerr << "\tRoot Object: " << updates.root << "\n";
+ llvm::cerr << "\tIs Rooted? " << updates.isRooted << "\n";
+ llvm::cerr << "\tSize: " << size << "\n";
+
+ llvm::cerr << "\tBytes:\n";
+ for (unsigned i=0; i<size; i++) {
+ llvm::cerr << "\t\t["<<i<<"]"
+ << " concrete? " << isByteConcrete(i)
+ << " known-sym? " << isByteKnownSymbolic(i)
+ << " flushed? " << isByteFlushed(i) << " = ";
+ ref<Expr> e = read8(i);
+ llvm::cerr << e << "\n";
+ }
+
+ llvm::cerr << "\tUpdates:\n";
+ for (const UpdateNode *un=updates.head; un; un=un->next) {
+ llvm::cerr << "\t\t[" << un->index << "] = " << un->value << "\n";
+ }
+}
Added: klee/trunk/lib/Core/Memory.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Memory.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Memory.h (added)
+++ klee/trunk/lib/Core/Memory.h Wed May 20 23:36:41 2009
@@ -0,0 +1,239 @@
+//===-- Memory.h ------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_MEMORY_H
+#define KLEE_MEMORY_H
+
+#include "klee/Expr.h"
+
+#include <vector>
+#include <string>
+
+namespace llvm {
+ class Value;
+}
+
+namespace klee {
+
+class BitArray;
+class MemoryManager;
+class Solver;
+
+class MemoryObject {
+ friend class STPBuilder;
+
+private:
+ static int counter;
+
+public:
+ unsigned id;
+ uint64_t address;
+ Array *array;
+
+ /// size in bytes
+ unsigned size;
+ std::string name;
+
+ bool isLocal;
+ bool isGlobal;
+ bool isFixed;
+
+ /// true if created by us.
+ bool fake_object;
+ bool isUserSpecified;
+
+ /// "Location" for which this memory object was allocated. This
+ /// should be either the allocating instruction or the global object
+ /// it was allocated for (or whatever else makes sense).
+ const llvm::Value *allocSite;
+
+ /// A list of boolean expressions the user has requested be true of
+ /// a counterexample. Mutable since we play a little fast and loose
+ /// with allowing it to be added to during execution (although
+ /// should sensibly be only at creation time).
+ mutable std::vector< ref<Expr> > cexPreferences;
+
+ // DO NOT IMPLEMENT
+ MemoryObject(const MemoryObject &b);
+ MemoryObject &operator=(const MemoryObject &b);
+
+public:
+ // XXX this is just a temp hack, should be removed
+ explicit
+ MemoryObject(uint64_t _address)
+ : id(counter++),
+ address(_address),
+ array(new Array(this, 0, id)),
+ size(0),
+ isFixed(true),
+ allocSite(0) {
+ }
+
+ MemoryObject(uint64_t _address, unsigned _size,
+ bool _isLocal, bool _isGlobal, bool _isFixed,
+ const llvm::Value *_allocSite)
+ : id(counter++),
+ address(_address),
+ array(new Array(this, id, _size)),
+ size(_size),
+ name("unnamed"),
+ isLocal(_isLocal),
+ isGlobal(_isGlobal),
+ isFixed(_isFixed),
+ fake_object(false),
+ isUserSpecified(false),
+ allocSite(_allocSite) {
+ }
+
+ ~MemoryObject();
+
+ /// Get an identifying string for this allocation.
+ void getAllocInfo(std::string &result) const;
+
+ void setName(std::string name) {
+ this->name = name;
+ }
+
+ ref<Expr> getBaseExpr() const {
+ return ConstantExpr::create(address, kMachinePointerType);
+ }
+ ref<Expr> getSizeExpr() const {
+ return ConstantExpr::create(size, kMachinePointerType);
+ }
+ ref<Expr> getOffsetExpr(ref<Expr> pointer) const {
+ return SubExpr::create(pointer, getBaseExpr());
+ }
+ ref<Expr> getBoundsCheckPointer(ref<Expr> pointer) const {
+ return getBoundsCheckOffset(getOffsetExpr(pointer));
+ }
+ ref<Expr> getBoundsCheckPointer(ref<Expr> pointer, unsigned bytes) const {
+ return getBoundsCheckOffset(getOffsetExpr(pointer), bytes);
+ }
+
+ ref<Expr> getBoundsCheckOffset(ref<Expr> offset) const {
+ if (size==0) {
+ return EqExpr::create(offset, ref<Expr>(0, kMachinePointerType));
+ } else {
+ return UltExpr::create(offset, getSizeExpr());
+ }
+ }
+ ref<Expr> getBoundsCheckOffset(ref<Expr> offset, unsigned bytes) const {
+ if (bytes<=size) {
+ return UltExpr::create(offset,
+ ref<Expr>(size - bytes + 1, kMachinePointerType));
+ } else {
+ return ref<Expr>(0, Expr::Bool);
+ }
+ }
+};
+
+class ObjectState {
+private:
+ friend class AddressSpace;
+ unsigned copyOnWriteOwner; // exclusively for AddressSpace
+
+ friend class ObjectHolder;
+ unsigned refCount;
+
+ const MemoryObject *object;
+
+ uint8_t *concreteStore;
+ // XXX cleanup name of flushMask (its backwards or something)
+ BitArray *concreteMask;
+
+ // mutable because may need flushed during read of const
+ mutable BitArray *flushMask;
+
+ ref<Expr> *knownSymbolics;
+
+public:
+ unsigned size;
+
+ // mutable because we may need flush during read of const
+ mutable UpdateList updates;
+
+ bool readOnly;
+
+public:
+ // initial contents are undefined but concrete, it is the creators
+ // responsibility to initialize the object contents appropriate
+ ObjectState(const MemoryObject *mo, unsigned size);
+ ObjectState(const ObjectState &os);
+ ~ObjectState();
+
+ const MemoryObject *getObject() const { return object; }
+
+ void setReadOnly(bool ro) { readOnly = ro; }
+
+ // make all bytes are concrete with undefined values
+ void makeConcrete();
+
+ void makeSymbolic();
+
+ // make contents all concrete and zero
+ void initializeToZero();
+ // make contents all concrete and random
+ void initializeToRandom();
+
+ ref<Expr> read(ref<Expr> offset, Expr::Width width) const;
+ ref<Expr> read(unsigned offset, Expr::Width width) const;
+ ref<Expr> read1(unsigned offset) const;
+ ref<Expr> read8(unsigned offset) const;
+ ref<Expr> read16(unsigned offset) const;
+ ref<Expr> read32(unsigned offset) const;
+ ref<Expr> read64(unsigned offset) const;
+
+ // return bytes written.
+ void write(unsigned offset, ref<Expr> value);
+ void write(ref<Expr> offset, ref<Expr> value);
+
+ void write8(unsigned offset, uint8_t value);
+ void write16(unsigned offset, uint16_t value);
+ void write32(unsigned offset, uint32_t value);
+ void write64(unsigned offset, uint64_t value);
+
+private:
+ ref<Expr> read1(ref<Expr> offset) const;
+ ref<Expr> read8(ref<Expr> offset) const;
+ ref<Expr> read16(ref<Expr> offset) const;
+ ref<Expr> read32(ref<Expr> offset) const;
+ ref<Expr> read64(ref<Expr> offset) const;
+
+ void write1(unsigned offset, ref<Expr> value);
+ void write1(ref<Expr> offset, ref<Expr> value);
+ void write8(unsigned offset, ref<Expr> value);
+ void write8(ref<Expr> offset, ref<Expr> value);
+ void write16(unsigned offset, ref<Expr> value);
+ void write16(ref<Expr> offset, ref<Expr> value);
+ void write32(unsigned offset, ref<Expr> value);
+ void write32(ref<Expr> offset, ref<Expr> value);
+ void write64(unsigned offset, ref<Expr> value);
+ void write64(ref<Expr> offset, ref<Expr> value);
+
+
+ void fastRangeCheckOffset(ref<Expr> offset, unsigned *base_r, unsigned *size_r) const;
+ void flushRangeForRead(unsigned rangeBase, unsigned rangeSize) const;
+ void flushRangeForWrite(unsigned rangeBase, unsigned rangeSize);
+
+ bool isByteConcrete(unsigned offset) const;
+ bool isByteFlushed(unsigned offset) const;
+ bool isByteKnownSymbolic(unsigned offset) const;
+
+ void markByteConcrete(unsigned offset);
+ void markByteSymbolic(unsigned offset);
+ void markByteFlushed(unsigned offset);
+ void markByteUnflushed(unsigned offset);
+ void setKnownSymbolic(unsigned offset, Expr *value);
+
+ void print();
+};
+
+} // End klee namespace
+
+#endif
Added: klee/trunk/lib/Core/MemoryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/MemoryManager.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/MemoryManager.cpp (added)
+++ klee/trunk/lib/Core/MemoryManager.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,69 @@
+//===-- MemoryManager.cpp -------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "CoreStats.h"
+#include "Memory.h"
+#include "MemoryManager.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Expr.h"
+#include "klee/Solver.h"
+
+#include "llvm/Support/CommandLine.h"
+
+using namespace klee;
+
+/***/
+
+MemoryManager::~MemoryManager() {
+ while (!objects.empty()) {
+ MemoryObject *mo = objects.back();
+ objects.pop_back();
+ delete mo;
+ }
+}
+
+MemoryObject *MemoryManager::allocate(uint64_t size, bool isLocal, bool isGlobal,
+ const llvm::Value *allocSite) {
+ if (size>10*1024*1024) {
+ klee_warning_once(0, "failing large alloc: %u bytes", (unsigned) size);
+ return 0;
+ }
+ uint64_t address = (uint64_t) (unsigned long) malloc((unsigned) size);
+ if (!address)
+ return 0;
+
+ ++stats::allocations;
+ MemoryObject *res = new MemoryObject(address, size, isLocal, isGlobal, false,
+ allocSite);
+ objects.push_back(res);
+ return res;
+}
+
+MemoryObject *MemoryManager::allocateFixed(uint64_t address, uint64_t size,
+ const llvm::Value *allocSite) {
+ for (objects_ty::iterator it = objects.begin(), ie = objects.end();
+ it != ie; ++it) {
+ MemoryObject *mo = *it;
+ assert(!(address+size > mo->address && address < mo->address+mo->size) &&
+ "allocated an overlapping object");
+ }
+
+ ++stats::allocations;
+ MemoryObject *res = new MemoryObject(address, size, false, true, true,
+ allocSite);
+ objects.push_back(res);
+ return res;
+}
+
+void MemoryManager::deallocate(const MemoryObject *mo) {
+ assert(0);
+}
Added: klee/trunk/lib/Core/MemoryManager.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/MemoryManager.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/MemoryManager.h (added)
+++ klee/trunk/lib/Core/MemoryManager.h Wed May 20 23:36:41 2009
@@ -0,0 +1,41 @@
+//===-- MemoryManager.h -----------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_MEMORYMANAGER_H
+#define KLEE_MEMORYMANAGER_H
+
+#include <vector>
+#include <stdint.h>
+
+namespace llvm {
+ class Value;
+}
+
+namespace klee {
+ class MemoryObject;
+
+ class MemoryManager {
+ private:
+ typedef std::vector<MemoryObject*> objects_ty;
+ objects_ty objects;
+
+ public:
+ MemoryManager() {}
+ ~MemoryManager();
+
+ MemoryObject *allocate(uint64_t size, bool isLocal, bool isGlobal,
+ const llvm::Value *allocSite);
+ MemoryObject *allocateFixed(uint64_t address, uint64_t size,
+ const llvm::Value *allocSite);
+ void deallocate(const MemoryObject *mo);
+ };
+
+} // End klee namespace
+
+#endif
Added: klee/trunk/lib/Core/ObjectHolder.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/ObjectHolder.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/ObjectHolder.h (added)
+++ klee/trunk/lib/Core/ObjectHolder.h Wed May 20 23:36:41 2009
@@ -0,0 +1,33 @@
+//===-- ObjectHolder.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_OBJECTHOLDER_H
+#define KLEE_OBJECTHOLDER_H
+
+namespace klee {
+ class ObjectState;
+
+ class ObjectHolder {
+ ObjectState *os;
+
+ public:
+ ObjectHolder() : os(0) {}
+ ObjectHolder(ObjectState *_os);
+ ObjectHolder(const ObjectHolder &b);
+ ~ObjectHolder();
+
+ ObjectHolder &operator=(const ObjectHolder &b);
+
+ operator class ObjectState *() { return os; }
+ operator class ObjectState *() const { return (ObjectState*) os; }
+ };
+}
+
+#endif
+
Added: klee/trunk/lib/Core/PTree.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/PTree.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/PTree.cpp (added)
+++ klee/trunk/lib/Core/PTree.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,103 @@
+//===-- PTree.cpp ---------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PTree.h"
+
+#include <klee/Expr.h>
+#include <klee/util/ExprPPrinter.h>
+
+#include <vector>
+#include <iostream>
+
+using namespace klee;
+
+ /* *** */
+
+PTree::PTree(const data_type &_root) : root(new Node(0,_root)) {
+}
+
+PTree::~PTree() {}
+
+std::pair<PTreeNode*, PTreeNode*>
+PTree::split(Node *n,
+ const data_type &leftData,
+ const data_type &rightData) {
+ assert(n && !n->left && !n->right);
+ n->left = new Node(n, leftData);
+ n->right = new Node(n, rightData);
+ return std::make_pair(n->left, n->right);
+}
+
+void PTree::remove(Node *n) {
+ assert(!n->left && !n->right);
+ do {
+ Node *p = n->parent;
+ delete n;
+ if (p) {
+ if (n == p->left) {
+ p->left = 0;
+ } else {
+ assert(n == p->right);
+ p->right = 0;
+ }
+ }
+ n = p;
+ } while (n && !n->left && !n->right);
+}
+
+void PTree::dump(std::ostream &os) {
+ ExprPPrinter *pp = ExprPPrinter::create(os);
+ pp->setNewline("\\l");
+ os << "digraph G {\n";
+ os << "\tsize=\"10,7.5\";\n";
+ os << "\tratio=fill;\n";
+ os << "\trotate=90;\n";
+ os << "\tcenter = \"true\";\n";
+ os << "\tnode [style=\"filled\",width=.1,height=.1,fontname=\"Terminus\"]\n";
+ os << "\tedge [arrowsize=.3]\n";
+ std::vector<PTree::Node*> stack;
+ stack.push_back(root);
+ while (!stack.empty()) {
+ PTree::Node *n = stack.back();
+ stack.pop_back();
+ if (n->condition.isNull()) {
+ os << "\tn" << n << " [label=\"\"";
+ } else {
+ os << "\tn" << n << " [label=\"";
+ pp->print(n->condition);
+ os << "\",shape=diamond";
+ }
+ if (n->data)
+ os << ",fillcolor=green";
+ os << "];\n";
+ if (n->left) {
+ os << "\tn" << n << " -> n" << n->left << ";\n";
+ stack.push_back(n->left);
+ }
+ if (n->right) {
+ os << "\tn" << n << " -> n" << n->right << ";\n";
+ stack.push_back(n->right);
+ }
+ }
+ os << "}\n";
+ delete pp;
+}
+
+PTreeNode::PTreeNode(PTreeNode *_parent,
+ ExecutionState *_data)
+ : parent(_parent),
+ left(0),
+ right(0),
+ data(_data),
+ condition(0) {
+}
+
+PTreeNode::~PTreeNode() {
+}
+
Added: klee/trunk/lib/Core/PTree.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/PTree.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/PTree.h (added)
+++ klee/trunk/lib/Core/PTree.h Wed May 20 23:36:41 2009
@@ -0,0 +1,53 @@
+//===-- PTree.h -------------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __UTIL_PTREE_H__
+#define __UTIL_PTREE_H__
+
+#include <klee/Expr.h>
+
+#include <utility>
+#include <cassert>
+#include <iostream>
+
+namespace klee {
+ class ExecutionState;
+
+ class PTree {
+ typedef ExecutionState* data_type;
+
+ public:
+ typedef class PTreeNode Node;
+ Node *root;
+
+ PTree(const data_type &_root);
+ ~PTree();
+
+ std::pair<Node*,Node*> split(Node *n,
+ const data_type &leftData,
+ const data_type &rightData);
+ void remove(Node *n);
+
+ void dump(std::ostream &os);
+ };
+
+ class PTreeNode {
+ friend class PTree;
+ public:
+ PTreeNode *parent, *left, *right;
+ ExecutionState *data;
+ ref<Expr> condition;
+
+ private:
+ PTreeNode(PTreeNode *_parent, ExecutionState *_data);
+ ~PTreeNode();
+ };
+}
+
+#endif
Added: klee/trunk/lib/Core/Searcher.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Searcher.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Searcher.cpp (added)
+++ klee/trunk/lib/Core/Searcher.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,575 @@
+//===-- Searcher.cpp ------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "Searcher.h"
+
+#include "CoreStats.h"
+#include "Executor.h"
+#include "PTree.h"
+#include "StatsTracker.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Statistics.h"
+#include "klee/Internal/Module/InstructionInfoTable.h"
+#include "klee/Internal/Module/KInstruction.h"
+#include "klee/Internal/Module/KModule.h"
+#include "klee/Internal/ADT/DiscretePDF.h"
+#include "klee/Internal/ADT/RNG.h"
+#include "klee/Internal/Support/ModuleUtil.h"
+#include "klee/Internal/System/Time.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <cassert>
+#include <fstream>
+#include <climits>
+
+using namespace klee;
+using namespace llvm;
+
+namespace {
+ cl::opt<bool>
+ DebugLogMerge("debug-log-merge");
+}
+
+namespace klee {
+ extern RNG theRNG;
+}
+
+Searcher::~Searcher() {
+}
+
+///
+
+ExecutionState &DFSSearcher::selectState() {
+ return *states.back();
+}
+
+void DFSSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ states.insert(states.end(),
+ addedStates.begin(),
+ addedStates.end());
+ for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
+ ie = removedStates.end(); it != ie; ++it) {
+ ExecutionState *es = *it;
+ if (es == states.back()) {
+ states.pop_back();
+ } else {
+ bool ok = false;
+
+ for (std::vector<ExecutionState*>::iterator it = states.begin(),
+ ie = states.end(); it != ie; ++it) {
+ if (es==*it) {
+ states.erase(it);
+ ok = true;
+ break;
+ }
+ }
+
+ assert(ok && "invalid state removed");
+ }
+ }
+}
+
+///
+
+ExecutionState &RandomSearcher::selectState() {
+ return *states[theRNG.getInt32()%states.size()];
+}
+
+void RandomSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ states.insert(states.end(),
+ addedStates.begin(),
+ addedStates.end());
+ for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
+ ie = removedStates.end(); it != ie; ++it) {
+ ExecutionState *es = *it;
+ bool ok = false;
+
+ for (std::vector<ExecutionState*>::iterator it = states.begin(),
+ ie = states.end(); it != ie; ++it) {
+ if (es==*it) {
+ states.erase(it);
+ ok = true;
+ break;
+ }
+ }
+
+ assert(ok && "invalid state removed");
+ }
+}
+
+///
+
+WeightedRandomSearcher::WeightedRandomSearcher(Executor &_executor,
+ WeightType _type)
+ : executor(_executor),
+ states(new DiscretePDF<ExecutionState*>()),
+ type(_type) {
+ switch(type) {
+ case Depth:
+ updateWeights = false;
+ break;
+ case InstCount:
+ case CPInstCount:
+ case QueryCost:
+ case MinDistToUncovered:
+ case CoveringNew:
+ updateWeights = true;
+ break;
+ default:
+ assert(0 && "invalid weight type");
+ }
+}
+
+WeightedRandomSearcher::~WeightedRandomSearcher() {
+ delete states;
+}
+
+ExecutionState &WeightedRandomSearcher::selectState() {
+ return *states->choose(theRNG.getDoubleL());
+}
+
+double WeightedRandomSearcher::getWeight(ExecutionState *es) {
+ switch(type) {
+ default:
+ case Depth:
+ return es->weight;
+ case InstCount: {
+ uint64_t count = theStatisticManager->getIndexedValue(stats::instructions,
+ es->pc->info->id);
+ double inv = 1. / std::max((uint64_t) 1, count);
+ return inv * inv;
+ }
+ case CPInstCount: {
+ StackFrame &sf = es->stack.back();
+ uint64_t count = sf.callPathNode->statistics.getValue(stats::instructions);
+ double inv = 1. / std::max((uint64_t) 1, count);
+ return inv;
+ }
+ case QueryCost:
+ return (es->queryCost < .1) ? 1. : 1./es->queryCost;
+ case CoveringNew:
+ case MinDistToUncovered: {
+ uint64_t md2u = computeMinDistToUncovered(es->pc,
+ es->stack.back().minDistToUncoveredOnReturn);
+
+ double invMD2U = 1. / (md2u ? md2u : 10000);
+ if (type==CoveringNew) {
+ double invCovNew = 0.;
+ if (es->instsSinceCovNew)
+ invCovNew = 1. / std::max(1, (int) es->instsSinceCovNew - 1000);
+ return (invCovNew * invCovNew + invMD2U * invMD2U);
+ } else {
+ return invMD2U * invMD2U;
+ }
+ }
+ }
+}
+
+void WeightedRandomSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ if (current && updateWeights && !removedStates.count(current))
+ states->update(current, getWeight(current));
+
+ for (std::set<ExecutionState*>::const_iterator it = addedStates.begin(),
+ ie = addedStates.end(); it != ie; ++it) {
+ ExecutionState *es = *it;
+ states->insert(es, getWeight(es));
+ }
+
+ for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
+ ie = removedStates.end(); it != ie; ++it) {
+ states->remove(*it);
+ }
+}
+
+bool WeightedRandomSearcher::empty() {
+ return states->empty();
+}
+
+///
+
+RandomPathSearcher::RandomPathSearcher(Executor &_executor)
+ : executor(_executor) {
+}
+
+RandomPathSearcher::~RandomPathSearcher() {
+}
+
+ExecutionState &RandomPathSearcher::selectState() {
+ unsigned flips=0, bits=0;
+ PTree::Node *n = executor.processTree->root;
+
+ while (!n->data) {
+ if (!n->left) {
+ n = n->right;
+ } else if (!n->right) {
+ n = n->left;
+ } else {
+ if (bits==0) {
+ flips = theRNG.getInt32();
+ bits = 32;
+ }
+ --bits;
+ n = (flips&(1<<bits)) ? n->left : n->right;
+ }
+ }
+
+ return *n->data;
+}
+
+void RandomPathSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+}
+
+bool RandomPathSearcher::empty() {
+ return executor.states.empty();
+}
+
+///
+
+BumpMergingSearcher::BumpMergingSearcher(Executor &_executor, Searcher *_baseSearcher)
+ : executor(_executor),
+ baseSearcher(_baseSearcher),
+ mergeFunction(executor.kmodule->kleeMergeFn) {
+}
+
+BumpMergingSearcher::~BumpMergingSearcher() {
+ delete baseSearcher;
+}
+
+///
+
+Instruction *BumpMergingSearcher::getMergePoint(ExecutionState &es) {
+ if (mergeFunction) {
+ Instruction *i = es.pc->inst;
+
+ if (i->getOpcode()==Instruction::Call) {
+ CallSite cs(cast<CallInst>(i));
+ if (mergeFunction==cs.getCalledFunction())
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+ExecutionState &BumpMergingSearcher::selectState() {
+entry:
+ // out of base states, pick one to pop
+ if (baseSearcher->empty()) {
+ std::map<llvm::Instruction*, ExecutionState*>::iterator it =
+ statesAtMerge.begin();
+ ExecutionState *es = it->second;
+ statesAtMerge.erase(it);
+ ++es->pc;
+
+ baseSearcher->addState(es);
+ }
+
+ ExecutionState &es = baseSearcher->selectState();
+
+ if (Instruction *mp = getMergePoint(es)) {
+ std::map<llvm::Instruction*, ExecutionState*>::iterator it =
+ statesAtMerge.find(mp);
+
+ baseSearcher->removeState(&es);
+
+ if (it==statesAtMerge.end()) {
+ statesAtMerge.insert(std::make_pair(mp, &es));
+ } else {
+ ExecutionState *mergeWith = it->second;
+ if (mergeWith->merge(es)) {
+ // hack, because we are terminating the state we need to let
+ // the baseSearcher know about it again
+ baseSearcher->addState(&es);
+ executor.terminateState(es);
+ } else {
+ it->second = &es; // the bump
+ ++mergeWith->pc;
+
+ baseSearcher->addState(mergeWith);
+ }
+ }
+
+ goto entry;
+ } else {
+ return es;
+ }
+}
+
+void BumpMergingSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ baseSearcher->update(current, addedStates, removedStates);
+}
+
+///
+
+MergingSearcher::MergingSearcher(Executor &_executor, Searcher *_baseSearcher)
+ : executor(_executor),
+ baseSearcher(_baseSearcher),
+ mergeFunction(executor.kmodule->kleeMergeFn) {
+}
+
+MergingSearcher::~MergingSearcher() {
+ delete baseSearcher;
+}
+
+///
+
+Instruction *MergingSearcher::getMergePoint(ExecutionState &es) {
+ if (mergeFunction) {
+ Instruction *i = es.pc->inst;
+
+ if (i->getOpcode()==Instruction::Call) {
+ CallSite cs(cast<CallInst>(i));
+ if (mergeFunction==cs.getCalledFunction())
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+ExecutionState &MergingSearcher::selectState() {
+ while (!baseSearcher->empty()) {
+ ExecutionState &es = baseSearcher->selectState();
+ if (getMergePoint(es)) {
+ baseSearcher->removeState(&es, &es);
+ statesAtMerge.insert(&es);
+ } else {
+ return es;
+ }
+ }
+
+ // build map of merge point -> state list
+ std::map<Instruction*, std::vector<ExecutionState*> > merges;
+ for (std::set<ExecutionState*>::const_iterator it = statesAtMerge.begin(),
+ ie = statesAtMerge.end(); it != ie; ++it) {
+ ExecutionState &state = **it;
+ Instruction *mp = getMergePoint(state);
+
+ merges[mp].push_back(&state);
+ }
+
+ if (DebugLogMerge)
+ llvm::cerr << "-- all at merge --\n";
+ for (std::map<Instruction*, std::vector<ExecutionState*> >::iterator
+ it = merges.begin(), ie = merges.end(); it != ie; ++it) {
+ if (DebugLogMerge) {
+ llvm::cerr << "\tmerge: " << it->first << " [";
+ for (std::vector<ExecutionState*>::iterator it2 = it->second.begin(),
+ ie2 = it->second.end(); it2 != ie2; ++it2) {
+ ExecutionState *state = *it2;
+ llvm::cerr << state << ", ";
+ }
+ llvm::cerr << "]\n";
+ }
+
+ // merge states
+ std::set<ExecutionState*> toMerge(it->second.begin(), it->second.end());
+ while (!toMerge.empty()) {
+ ExecutionState *base = *toMerge.begin();
+ toMerge.erase(toMerge.begin());
+
+ std::set<ExecutionState*> toErase;
+ for (std::set<ExecutionState*>::iterator it = toMerge.begin(),
+ ie = toMerge.end(); it != ie; ++it) {
+ ExecutionState *mergeWith = *it;
+
+ if (base->merge(*mergeWith)) {
+ toErase.insert(mergeWith);
+ }
+ }
+ if (DebugLogMerge && !toErase.empty()) {
+ llvm::cerr << "\t\tmerged: " << base << " with [";
+ for (std::set<ExecutionState*>::iterator it = toErase.begin(),
+ ie = toErase.end(); it != ie; ++it) {
+ if (it!=toErase.begin()) llvm::cerr << ", ";
+ llvm::cerr << *it;
+ }
+ llvm::cerr << "]\n";
+ }
+ for (std::set<ExecutionState*>::iterator it = toErase.begin(),
+ ie = toErase.end(); it != ie; ++it) {
+ std::set<ExecutionState*>::iterator it2 = toMerge.find(*it);
+ assert(it2!=toMerge.end());
+ executor.terminateState(**it);
+ toMerge.erase(it2);
+ }
+
+ // step past merge and toss base back in pool
+ statesAtMerge.erase(statesAtMerge.find(base));
+ ++base->pc;
+ baseSearcher->addState(base);
+ }
+ }
+
+ if (DebugLogMerge)
+ llvm::cerr << "-- merge complete, continuing --\n";
+
+ return selectState();
+}
+
+void MergingSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ if (!removedStates.empty()) {
+ std::set<ExecutionState *> alt = removedStates;
+ for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
+ ie = removedStates.end(); it != ie; ++it) {
+ ExecutionState *es = *it;
+ std::set<ExecutionState*>::const_iterator it = statesAtMerge.find(es);
+ if (it!=statesAtMerge.end()) {
+ statesAtMerge.erase(it);
+ alt.erase(alt.find(es));
+ }
+ }
+ baseSearcher->update(current, addedStates, alt);
+ } else {
+ baseSearcher->update(current, addedStates, removedStates);
+ }
+}
+
+///
+
+BatchingSearcher::BatchingSearcher(Searcher *_baseSearcher,
+ double _timeBudget,
+ unsigned _instructionBudget)
+ : baseSearcher(_baseSearcher),
+ timeBudget(_timeBudget),
+ instructionBudget(_instructionBudget),
+ lastState(0) {
+
+}
+
+BatchingSearcher::~BatchingSearcher() {
+ delete baseSearcher;
+}
+
+ExecutionState &BatchingSearcher::selectState() {
+ if (!lastState ||
+ (util::getWallTime()-lastStartTime)>timeBudget ||
+ (stats::instructions-lastStartInstructions)>instructionBudget) {
+ if (lastState) {
+ double delta = util::getWallTime()-lastStartTime;
+ if (delta>timeBudget*1.1) {
+ llvm::cerr << "KLEE: increased time budget from " << timeBudget << " to " << delta << "\n";
+ timeBudget = delta;
+ }
+ }
+ lastState = &baseSearcher->selectState();
+ lastStartTime = util::getWallTime();
+ lastStartInstructions = stats::instructions;
+ return *lastState;
+ } else {
+ return *lastState;
+ }
+}
+
+void BatchingSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ if (removedStates.count(lastState))
+ lastState = 0;
+ baseSearcher->update(current, addedStates, removedStates);
+}
+
+/***/
+
+IterativeDeepeningTimeSearcher::IterativeDeepeningTimeSearcher(Searcher *_baseSearcher)
+ : baseSearcher(_baseSearcher),
+ time(1.) {
+}
+
+IterativeDeepeningTimeSearcher::~IterativeDeepeningTimeSearcher() {
+ delete baseSearcher;
+}
+
+ExecutionState &IterativeDeepeningTimeSearcher::selectState() {
+ ExecutionState &res = baseSearcher->selectState();
+ startTime = util::getWallTime();
+ return res;
+}
+
+void IterativeDeepeningTimeSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ double elapsed = util::getWallTime() - startTime;
+
+ if (!removedStates.empty()) {
+ std::set<ExecutionState *> alt = removedStates;
+ for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
+ ie = removedStates.end(); it != ie; ++it) {
+ ExecutionState *es = *it;
+ std::set<ExecutionState*>::const_iterator it = pausedStates.find(es);
+ if (it!=pausedStates.end()) {
+ pausedStates.erase(it);
+ alt.erase(alt.find(es));
+ }
+ }
+ baseSearcher->update(current, addedStates, alt);
+ } else {
+ baseSearcher->update(current, addedStates, removedStates);
+ }
+
+ if (current && !removedStates.count(current) && elapsed>time) {
+ pausedStates.insert(current);
+ baseSearcher->removeState(current);
+ }
+
+ if (baseSearcher->empty()) {
+ time *= 2;
+ llvm::cerr << "KLEE: increasing time budget to: " << time << "\n";
+ baseSearcher->update(0, pausedStates, std::set<ExecutionState*>());
+ pausedStates.clear();
+ }
+}
+
+/***/
+
+InterleavedSearcher::InterleavedSearcher(const std::vector<Searcher*> &_searchers)
+ : searchers(_searchers),
+ index(1) {
+}
+
+InterleavedSearcher::~InterleavedSearcher() {
+ for (std::vector<Searcher*>::const_iterator it = searchers.begin(),
+ ie = searchers.end(); it != ie; ++it)
+ delete *it;
+}
+
+ExecutionState &InterleavedSearcher::selectState() {
+ Searcher *s = searchers[--index];
+ if (index==0) index = searchers.size();
+ return s->selectState();
+}
+
+void InterleavedSearcher::update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) {
+ for (std::vector<Searcher*>::const_iterator it = searchers.begin(),
+ ie = searchers.end(); it != ie; ++it)
+ (*it)->update(current, addedStates, removedStates);
+}
Added: klee/trunk/lib/Core/Searcher.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/Searcher.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/Searcher.h (added)
+++ klee/trunk/lib/Core/Searcher.h Wed May 20 23:36:41 2009
@@ -0,0 +1,279 @@
+//===-- Searcher.h ----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_SEARCHER_H
+#define KLEE_SEARCHER_H
+
+#include <vector>
+#include <set>
+#include <map>
+#include <queue>
+
+// FIXME: Move out of header, use llvm streams.
+#include <ostream>
+
+namespace llvm {
+ class BasicBlock;
+ class Function;
+ class Instruction;
+}
+
+namespace klee {
+ template<class T> class DiscretePDF;
+ class ExecutionState;
+ class Executor;
+
+ class Searcher {
+ public:
+ virtual ~Searcher();
+
+ virtual ExecutionState &selectState() = 0;
+
+ virtual void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates) = 0;
+
+ virtual bool empty() = 0;
+
+ // prints name of searcher as a klee_message()
+ // TODO: could probably make prettier or more flexible
+ virtual void printName(std::ostream &os) {
+ os << "<unnamed searcher>\n";
+ }
+
+ // pgbovine - to be called when a searcher gets activated and
+ // deactivated, say, by a higher-level searcher; most searchers
+ // don't need this functionality, so don't have to override.
+ virtual void activate() {};
+ virtual void deactivate() {};
+
+ // utility functions
+
+ void addState(ExecutionState *es, ExecutionState *current = 0) {
+ std::set<ExecutionState*> tmp;
+ tmp.insert(es);
+ update(current, tmp, std::set<ExecutionState*>());
+ }
+
+ void removeState(ExecutionState *es, ExecutionState *current = 0) {
+ std::set<ExecutionState*> tmp;
+ tmp.insert(es);
+ update(current, std::set<ExecutionState*>(), tmp);
+ }
+ };
+
+ class DFSSearcher : public Searcher {
+ std::vector<ExecutionState*> states;
+
+ public:
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty() { return states.empty(); }
+ void printName(std::ostream &os) {
+ os << "DFSSearcher\n";
+ }
+ };
+
+ class RandomSearcher : public Searcher {
+ std::vector<ExecutionState*> states;
+
+ public:
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty() { return states.empty(); }
+ void printName(std::ostream &os) {
+ os << "RandomSearcher\n";
+ }
+ };
+
+ class WeightedRandomSearcher : public Searcher {
+ public:
+ enum WeightType {
+ Depth,
+ QueryCost,
+ InstCount,
+ CPInstCount,
+ MinDistToUncovered,
+ CoveringNew
+ };
+
+ private:
+ Executor &executor;
+ DiscretePDF<ExecutionState*> *states;
+ WeightType type;
+ bool updateWeights;
+
+ double getWeight(ExecutionState*);
+
+ public:
+ WeightedRandomSearcher(Executor &executor, WeightType type);
+ ~WeightedRandomSearcher();
+
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty();
+ void printName(std::ostream &os) {
+ os << "WeightedRandomSearcher::";
+ switch(type) {
+ case Depth : os << "Depth\n"; return;
+ case QueryCost : os << "QueryCost\n"; return;
+ case InstCount : os << "InstCount\n"; return;
+ case CPInstCount : os << "CPInstCount\n"; return;
+ case MinDistToUncovered : os << "MinDistToUncovered\n"; return;
+ case CoveringNew : os << "CoveringNew\n"; return;
+ default : os << "<unknown type>\n"; return;
+ }
+ }
+ };
+
+ class RandomPathSearcher : public Searcher {
+ Executor &executor;
+
+ public:
+ RandomPathSearcher(Executor &_executor);
+ ~RandomPathSearcher();
+
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty();
+ void printName(std::ostream &os) {
+ os << "RandomPathSearcher\n";
+ }
+ };
+
+ class MergingSearcher : public Searcher {
+ Executor &executor;
+ std::set<ExecutionState*> statesAtMerge;
+ Searcher *baseSearcher;
+ llvm::Function *mergeFunction;
+
+ private:
+ llvm::Instruction *getMergePoint(ExecutionState &es);
+
+ public:
+ MergingSearcher(Executor &executor, Searcher *baseSearcher);
+ ~MergingSearcher();
+
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty() { return baseSearcher->empty() && statesAtMerge.empty(); }
+ void printName(std::ostream &os) {
+ os << "MergingSearcher\n";
+ }
+ };
+
+ class BumpMergingSearcher : public Searcher {
+ Executor &executor;
+ std::map<llvm::Instruction*, ExecutionState*> statesAtMerge;
+ Searcher *baseSearcher;
+ llvm::Function *mergeFunction;
+
+ private:
+ llvm::Instruction *getMergePoint(ExecutionState &es);
+
+ public:
+ BumpMergingSearcher(Executor &executor, Searcher *baseSearcher);
+ ~BumpMergingSearcher();
+
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty() { return baseSearcher->empty() && statesAtMerge.empty(); }
+ void printName(std::ostream &os) {
+ os << "BumpMergingSearcher\n";
+ }
+ };
+
+ class BatchingSearcher : public Searcher {
+ Searcher *baseSearcher;
+ double timeBudget;
+ unsigned instructionBudget;
+
+ ExecutionState *lastState;
+ double lastStartTime;
+ unsigned lastStartInstructions;
+
+ public:
+ BatchingSearcher(Searcher *baseSearcher,
+ double _timeBudget,
+ unsigned _instructionBudget);
+ ~BatchingSearcher();
+
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty() { return baseSearcher->empty(); }
+ void printName(std::ostream &os) {
+ os << "<BatchingSearcher> timeBudget: " << timeBudget
+ << ", instructionBudget: " << instructionBudget
+ << ", baseSearcher:\n";
+ baseSearcher->printName(os);
+ os << "</BatchingSearcher>\n";
+ }
+ };
+
+ class IterativeDeepeningTimeSearcher : public Searcher {
+ Searcher *baseSearcher;
+ double time, startTime;
+ std::set<ExecutionState*> pausedStates;
+
+ public:
+ IterativeDeepeningTimeSearcher(Searcher *baseSearcher);
+ ~IterativeDeepeningTimeSearcher();
+
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty() { return baseSearcher->empty() && pausedStates.empty(); }
+ void printName(std::ostream &os) {
+ os << "IterativeDeepeningTimeSearcher\n";
+ }
+ };
+
+ class InterleavedSearcher : public Searcher {
+ typedef std::vector<Searcher*> searchers_ty;
+
+ searchers_ty searchers;
+ unsigned index;
+
+ public:
+ explicit InterleavedSearcher(const searchers_ty &_searchers);
+ ~InterleavedSearcher();
+
+ ExecutionState &selectState();
+ void update(ExecutionState *current,
+ const std::set<ExecutionState*> &addedStates,
+ const std::set<ExecutionState*> &removedStates);
+ bool empty() { return searchers[0]->empty(); }
+ void printName(std::ostream &os) {
+ os << "<InterleavedSearcher> containing "
+ << searchers.size() << " searchers:\n";
+ for (searchers_ty::iterator it = searchers.begin(), ie = searchers.end();
+ it != ie; ++it)
+ (*it)->printName(os);
+ os << "</InterleavedSearcher>\n";
+ }
+ };
+
+}
+
+#endif
Added: klee/trunk/lib/Core/SeedInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/SeedInfo.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/SeedInfo.cpp (added)
+++ klee/trunk/lib/Core/SeedInfo.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,151 @@
+//===-- SeedInfo.cpp ------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "Memory.h"
+#include "SeedInfo.h"
+#include "TimingSolver.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Expr.h"
+#include "klee/util/ExprUtil.h"
+#include "klee/Internal/ADT/BOut.h"
+
+using namespace klee;
+
+BOutObject *SeedInfo::getNextInput(const MemoryObject *mo,
+ bool byName) {
+ if (byName) {
+ unsigned i;
+
+ for (i=0; i<input->numObjects; ++i) {
+ BOutObject *obj = &input->objects[i];
+ if (std::string(obj->name) == mo->name)
+ if (used.insert(obj).second)
+ return obj;
+ }
+
+ // If first unused input matches in size then accept that as
+ // well.
+ for (i=0; i<input->numObjects; ++i)
+ if (!used.count(&input->objects[i]))
+ break;
+ if (i<input->numObjects) {
+ BOutObject *obj = &input->objects[i];
+ if (obj->numBytes == mo->size) {
+ used.insert(obj);
+ klee_warning_once(mo, "using seed input %s[%d] for: %s (no name match)",
+ obj->name, obj->numBytes, mo->name.c_str());
+ return obj;
+ }
+ }
+
+ klee_warning_once(mo, "no seed input for: %s", mo->name.c_str());
+ return 0;
+ } else {
+ if (inputPosition >= input->numObjects) {
+ return 0;
+ } else {
+ return &input->objects[inputPosition++];
+ }
+ }
+}
+
+void SeedInfo::patchSeed(const ExecutionState &state,
+ ref<Expr> condition,
+ TimingSolver *solver) {
+ std::vector< ref<Expr> > required(state.constraints.begin(),
+ state.constraints.end());
+ ExecutionState tmp(required);
+ tmp.addConstraint(condition);
+
+ // Try and patch direct reads first, this is likely to resolve the
+ // problem quickly and avoids long traversal of all seed
+ // values. There are other smart ways to do this, the nicest is if
+ // we got a minimal counterexample from STP, in which case we would
+ // just inject those values back into the seed.
+ std::set< std::pair<const Array*, unsigned> > directReads;
+ std::vector< ref<ReadExpr> > reads;
+ findReads(condition, false, reads);
+ for (std::vector< ref<ReadExpr> >::iterator it = reads.begin(),
+ ie = reads.end(); it != ie; ++it) {
+ ReadExpr *re = it->get();
+ if (re->index.isConstant()) {
+ unsigned index = (unsigned) re->index.getConstantValue();
+ directReads.insert(std::make_pair(re->updates.root, index));
+ }
+ }
+
+ for (std::set< std::pair<const Array*, unsigned> >::iterator
+ it = directReads.begin(), ie = directReads.end(); it != ie; ++it) {
+ const Array *array = it->first;
+ unsigned i = it->second;
+ ref<Expr> read = ReadExpr::create(UpdateList(array, true, 0),
+ ref<Expr>(i, Expr::Int32));
+
+ // If not in bindings then this can't be a violation?
+ Assignment::bindings_ty::iterator it2 = assignment.bindings.find(array);
+ if (it2 != assignment.bindings.end()) {
+ ref<Expr> isSeed = EqExpr::create(read, ref<Expr>(it2->second[i], Expr::Int8));
+ bool res;
+ bool success = solver->mustBeFalse(tmp, isSeed, res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res) {
+ ref<Expr> value;
+ bool success = solver->getValue(tmp, read, value);
+ assert(success && "FIXME: Unhandled solver failure");
+ it2->second[i] = value.getConstantValue();
+ tmp.addConstraint(EqExpr::create(read, ref<Expr>(it2->second[i], Expr::Int8)));
+ } else {
+ tmp.addConstraint(isSeed);
+ }
+ }
+ }
+
+ bool res;
+ bool success = solver->mayBeTrue(state, assignment.evaluate(condition), res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res)
+ return;
+
+ // We could still do a lot better than this, for example by looking at
+ // independence. But really, this shouldn't be happening often.
+ for (Assignment::bindings_ty::iterator it = assignment.bindings.begin(),
+ ie = assignment.bindings.end(); it != ie; ++it) {
+ const Array *array = it->first;
+ for (unsigned i=0; i<array->size; ++i) {
+ ref<Expr> read = ReadExpr::create(UpdateList(array, true, 0),
+ ref<Expr>(i, Expr::Int32));
+ ref<Expr> isSeed = EqExpr::create(read, ref<Expr>(it->second[i], Expr::Int8));
+ bool res;
+ bool success = solver->mustBeFalse(tmp, isSeed, res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res) {
+ ref<Expr> value;
+ bool success = solver->getValue(tmp, read, value);
+ assert(success && "FIXME: Unhandled solver failure");
+ it->second[i] = value.getConstantValue();
+ tmp.addConstraint(EqExpr::create(read, ref<Expr>(it->second[i], Expr::Int8)));
+ } else {
+ tmp.addConstraint(isSeed);
+ }
+ }
+ }
+
+#ifndef NDEBUG
+ {
+ bool res;
+ bool success =
+ solver->mayBeTrue(state, assignment.evaluate(condition), res);
+ assert(success && "FIXME: Unhandled solver failure");
+ assert(res && "seed patching failed");
+ }
+#endif
+}
Added: klee/trunk/lib/Core/SeedInfo.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/SeedInfo.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/SeedInfo.h (added)
+++ klee/trunk/lib/Core/SeedInfo.h Wed May 20 23:36:41 2009
@@ -0,0 +1,48 @@
+//===-- SeedInfo.h ----------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_SEEDINFO_H
+#define KLEE_SEEDINFO_H
+
+#include "klee/util/Assignment.h"
+
+extern "C" {
+ struct BOut;
+ struct BOutObject;
+}
+
+namespace klee {
+ class ExecutionState;
+ class TimingSolver;
+
+ class SeedInfo {
+ public:
+ Assignment assignment;
+ BOut *input;
+ unsigned inputPosition;
+ std::set<struct BOutObject*> used;
+
+ public:
+ explicit
+ SeedInfo(BOut *_input) : assignment(true),
+ input(_input),
+ inputPosition(0) {}
+
+ BOutObject *getNextInput(const MemoryObject *mo,
+ bool byName);
+
+ /// Patch the seed so that condition is satisfied while retaining as
+ /// many of the seed values as possible.
+ void patchSeed(const ExecutionState &state,
+ ref<Expr> condition,
+ TimingSolver *solver);
+ };
+}
+
+#endif
Added: klee/trunk/lib/Core/SpecialFunctionHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/SpecialFunctionHandler.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/SpecialFunctionHandler.cpp (added)
+++ klee/trunk/lib/Core/SpecialFunctionHandler.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,727 @@
+//===-- SpecialFunctionHandler.cpp ----------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "Memory.h"
+#include "SpecialFunctionHandler.h"
+#include "TimingSolver.h"
+
+#include "klee/ExecutionState.h"
+
+#include "klee/Internal/Module/KInstruction.h"
+#include "klee/Internal/Module/KModule.h"
+
+#include "Executor.h"
+#include "MemoryManager.h"
+
+#include "llvm/Module.h"
+
+#include <errno.h>
+
+using namespace llvm;
+using namespace klee;
+
+/// \todo Almost all of the demands in this file should be replaced
+/// with terminateState calls.
+
+///
+
+struct HandlerInfo {
+ const char *name;
+ SpecialFunctionHandler::Handler handler;
+ bool doesNotReturn; /// Intrinsic terminates the process
+ bool hasReturnValue; /// Intrinsic has a return value
+ bool doNotOverride; /// Intrinsic should not be used if already defined
+};
+
+// FIXME: We are more or less committed to requiring an intrinsic
+// library these days. We can move some of this stuff there,
+// especially things like realloc which have complicated semantics
+// w.r.t. forking. Among other things this makes delayed query
+// dispatch easier to implement.
+HandlerInfo handlerInfo[] = {
+#define add(name, handler, ret) { name, \
+ &SpecialFunctionHandler::handler, \
+ false, ret, false }
+#define addDNR(name, handler) { name, \
+ &SpecialFunctionHandler::handler, \
+ true, false, false }
+ addDNR("__assert_rtn", handleAssertFail),
+ addDNR("__assert_fail", handleAssertFail),
+ addDNR("_assert", handleAssert),
+ addDNR("abort", handleAbort),
+ addDNR("_exit", handleExit),
+ { "exit", &SpecialFunctionHandler::handleExit, true, false, true },
+ addDNR("klee_abort", handleAbort),
+ addDNR("klee_silent_exit", handleSilentExit),
+ addDNR("klee_report_error", handleReportError),
+
+ add("calloc", handleCalloc, true),
+ add("free", handleFree, false),
+ add("klee_assume", handleAssume, false),
+ add("klee_check_memory_access", handleCheckMemoryAccess, false),
+ add("klee_get_value", handleGetValue, true),
+ add("klee_define_fixed_object", handleDefineFixedObject, false),
+ add("klee_get_obj_size", handleGetObjSize, true),
+ add("klee_get_errno", handleGetErrno, true),
+ add("klee_is_symbolic", handleIsSymbolic, true),
+ add("klee_make_symbolic_name", handleMakeSymbolic, false),
+ add("klee_mark_global", handleMarkGlobal, false),
+ add("klee_malloc_n", handleMallocN, true),
+ add("klee_merge", handleMerge, false),
+ add("klee_prefer_cex", handlePreferCex, false),
+ add("klee_print_expr", handlePrintExpr, false),
+ add("klee_print_range", handlePrintRange, false),
+ add("klee_set_forking", handleSetForking, false),
+ add("klee_warning", handleWarning, false),
+ add("klee_warning_once", handleWarningOnce, false),
+ add("klee_under_constrained", handleUnderConstrained, false),
+ add("klee_alias_function", handleAliasFunction, false),
+ add("malloc", handleMalloc, true),
+ add("realloc", handleRealloc, true),
+
+ // operator delete[](void*)
+ add("_ZdaPv", handleDeleteArray, false),
+ // operator delete(void*)
+ add("_ZdlPv", handleDelete, false),
+
+ // operator new[](unsigned int)
+ add("_Znaj", handleNewArray, true),
+ // operator new(unsigned int)
+ add("_Znwj", handleNew, true),
+
+ // FIXME-64: This is wrong for 64-bit long...
+
+ // operator new[](unsigned long)
+ add("_Znam", handleNewArray, true),
+ // operator new(unsigned long)
+ add("_Znwm", handleNew, true),
+
+#undef addDNR
+#undef add
+};
+
+SpecialFunctionHandler::SpecialFunctionHandler(Executor &_executor)
+ : executor(_executor) {}
+
+
+void SpecialFunctionHandler::prepare() {
+ unsigned N = sizeof(handlerInfo)/sizeof(handlerInfo[0]);
+
+ for (unsigned i=0; i<N; ++i) {
+ HandlerInfo &hi = handlerInfo[i];
+ Function *f = executor.kmodule->module->getFunction(hi.name);
+
+ // No need to create if the function doesn't exist, since it cannot
+ // be called in that case.
+
+ if (f && (!hi.doNotOverride || f->isDeclaration())) {
+ // Make sure NoReturn attribute is set, for optimization and
+ // coverage counting.
+ if (hi.doesNotReturn)
+ f->addFnAttr(Attribute::NoReturn);
+
+ // Change to a declaration since we handle internally (simplifies
+ // module and allows deleting dead code).
+ if (!f->isDeclaration())
+ f->deleteBody();
+ }
+ }
+}
+
+void SpecialFunctionHandler::bind() {
+ unsigned N = sizeof(handlerInfo)/sizeof(handlerInfo[0]);
+
+ for (unsigned i=0; i<N; ++i) {
+ HandlerInfo &hi = handlerInfo[i];
+ Function *f = executor.kmodule->module->getFunction(hi.name);
+
+ if (f && (!hi.doNotOverride || f->isDeclaration()))
+ handlers[f] = std::make_pair(hi.handler, hi.hasReturnValue);
+ }
+}
+
+
+bool SpecialFunctionHandler::handle(ExecutionState &state,
+ Function *f,
+ KInstruction *target,
+ std::vector< ref<Expr> > &arguments) {
+ handlers_ty::iterator it = handlers.find(f);
+ if (it != handlers.end()) {
+ Handler h = it->second.first;
+ bool hasReturnValue = it->second.second;
+ // FIXME: Check this... add test?
+ if (!hasReturnValue && !target->inst->use_empty()) {
+ executor.terminateStateOnExecError(state,
+ "expected return value from void special function");
+ } else {
+ (this->*h)(state, target, arguments);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/****/
+
+// reads a concrete string from memory
+std::string SpecialFunctionHandler::readStringAtAddress(ExecutionState &state,
+ ref<Expr> address) {
+ ObjectPair op;
+ address = executor.toUnique(state, address);
+ assert(address.isConstant() && "symbolic string arg to intrinsic");
+ if (!state.addressSpace.resolveOne(address.getConstantValue(), op))
+ assert(0 && "XXX out of bounds / multiple resolution unhandled");
+ bool res;
+ assert(executor.solver->mustBeTrue(state,
+ EqExpr::create(address,
+ op.first->getBaseExpr()),
+ res) &&
+ res &&
+ "XXX interior pointer unhandled");
+ const MemoryObject *mo = op.first;
+ const ObjectState *os = op.second;
+
+ char *buf = new char[mo->size];
+
+ unsigned i;
+ for (i = 0; i < mo->size - 1; i++) {
+ ref<Expr> cur = os->read8(i);
+ cur = executor.toUnique(state, cur);
+ assert(cur.isConstant() &&
+ "hit symbolic char while reading concrete string");
+ buf[i] = cur.getConstantValue();
+ }
+ buf[i] = 0;
+
+ std::string result(buf);
+ delete[] buf;
+ return result;
+}
+
+/****/
+
+void SpecialFunctionHandler::handleAbort(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==0 && "invalid number of arguments to abort");
+
+ //XXX:DRE:TAINT
+ if(state.underConstrained) {
+ llvm::cerr << "TAINT: skipping abort fail\n";
+ executor.terminateState(state);
+ } else {
+ executor.terminateStateOnError(state, "abort failure", "abort.err");
+ }
+}
+
+void SpecialFunctionHandler::handleExit(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 && "invalid number of arguments to exit");
+ executor.terminateStateOnExit(state);
+}
+
+void SpecialFunctionHandler::handleSilentExit(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 && "invalid number of arguments to exit");
+ executor.terminateState(state);
+}
+
+void SpecialFunctionHandler::handleAliasFunction(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to klee_alias_function");
+ std::string old_fn = readStringAtAddress(state, arguments[0]);
+ std::string new_fn = readStringAtAddress(state, arguments[1]);
+ //llvm::cerr << "Replacing " << old_fn << "() with " << new_fn << "()\n";
+ if (old_fn == new_fn)
+ state.removeFnAlias(old_fn);
+ else state.addFnAlias(old_fn, new_fn);
+}
+
+void SpecialFunctionHandler::handleAssert(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==3 && "invalid number of arguments to _assert");
+
+ //XXX:DRE:TAINT
+ if(state.underConstrained) {
+ llvm::cerr << "TAINT: skipping assertion:"
+ << readStringAtAddress(state, arguments[0]) << "\n";
+ executor.terminateState(state);
+ } else
+ executor.terminateStateOnError(state,
+ "ASSERTION FAIL: " + readStringAtAddress(state, arguments[0]),
+ "assert.err");
+}
+
+void SpecialFunctionHandler::handleAssertFail(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==4 && "invalid number of arguments to __assert_fail");
+
+ //XXX:DRE:TAINT
+ if(state.underConstrained) {
+ llvm::cerr << "TAINT: skipping assertion:"
+ << readStringAtAddress(state, arguments[0]) << "\n";
+ executor.terminateState(state);
+ } else
+ executor.terminateStateOnError(state,
+ "ASSERTION FAIL: " + readStringAtAddress(state, arguments[0]),
+ "assert.err");
+}
+
+void SpecialFunctionHandler::handleReportError(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==4 && "invalid number of arguments to klee_report_error");
+
+ // arguments[0], arguments[1] are file, line
+
+ //XXX:DRE:TAINT
+ if(state.underConstrained) {
+ llvm::cerr << "TAINT: skipping klee_report_error:"
+ << readStringAtAddress(state, arguments[2]) << ":"
+ << readStringAtAddress(state, arguments[3]) << "\n";
+ executor.terminateState(state);
+ } else
+ executor.terminateStateOnError(state,
+ readStringAtAddress(state, arguments[2]),
+ readStringAtAddress(state, arguments[3]));
+}
+
+void SpecialFunctionHandler::handleMerge(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // nop
+}
+
+void SpecialFunctionHandler::handleNew(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 && "invalid number of arguments to new");
+
+ executor.executeAlloc(state, arguments[0], false, target);
+}
+
+void SpecialFunctionHandler::handleDelete(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 && "invalid number of arguments to delete");
+ executor.executeFree(state, arguments[0]);
+}
+
+void SpecialFunctionHandler::handleNewArray(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 && "invalid number of arguments to new[]");
+ executor.executeAlloc(state, arguments[0], false, target);
+}
+
+void SpecialFunctionHandler::handleDeleteArray(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 && "invalid number of arguments to delete[]");
+ executor.executeFree(state, arguments[0]);
+}
+
+void SpecialFunctionHandler::handleMalloc(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 && "invalid number of arguments to malloc");
+ executor.executeAlloc(state, arguments[0], false, target);
+}
+
+void SpecialFunctionHandler::handleMallocN(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+
+ // XXX should type check args
+ assert(arguments.size() == 3 && "invalid number of arguments to malloc");
+
+ // mallocn(number, size, alignment)
+ ref<Expr> numElems = executor.toUnique(state, arguments[0]);
+ ref<Expr> elemSize = executor.toUnique(state, arguments[1]);
+ ref<Expr> elemAlignment = executor.toUnique(state, arguments[2]);
+
+ assert(numElems.isConstant() &&
+ elemSize.isConstant() &&
+ elemAlignment.isConstant() &&
+ "symbolic arguments passed to klee_mallocn");
+
+ executor.executeAllocN(state,
+ numElems.getConstantValue(),
+ elemSize.getConstantValue(),
+ elemAlignment.getConstantValue(),
+ false,
+ target);
+}
+
+void SpecialFunctionHandler::handleAssume(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 && "invalid number of arguments to klee_assume");
+
+ ref<Expr> e = arguments[0];
+
+ if(e.getWidth() != Expr::Bool)
+ e = NeExpr::create(e, ConstantExpr::create(0, e.getWidth()));
+
+ bool res;
+ bool success = executor.solver->mustBeFalse(state, e, res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res) {
+ executor.terminateStateOnError(state,
+ "invalid klee_assume call (provably false)",
+ "user.err");
+ } else {
+ executor.addConstraint(state, e);
+ }
+}
+
+void SpecialFunctionHandler::handleIsSymbolic(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 && "invalid number of arguments to klee_is_symbolic");
+
+ executor.bindLocal(target, state,
+ ConstantExpr::create(!arguments[0].isConstant(), Expr::Int32));
+}
+
+void SpecialFunctionHandler::handlePreferCex(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to klee_prefex_cex");
+
+ ref<Expr> cond = arguments[1];
+ if (cond.getWidth() != Expr::Bool)
+ cond = NeExpr::create(cond, ref<Expr>(0, cond.getWidth()));
+
+ Executor::ExactResolutionList rl;
+ executor.resolveExact(state, arguments[0], rl, "prefex_cex");
+
+ assert(rl.size() == 1 &&
+ "prefer_cex target must resolve to precisely one object");
+
+ rl[0].first.first->cexPreferences.push_back(cond);
+}
+
+void SpecialFunctionHandler::handlePrintExpr(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to klee_print_expr");
+
+ std::string msg_str = readStringAtAddress(state, arguments[0]);
+ llvm::cerr << msg_str << ":" << arguments[1] << "\n";
+}
+
+
+void SpecialFunctionHandler::handleUnderConstrained(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 &&
+ "invalid number of arguments to klee_under_constrained().");
+ assert(arguments[0].isConstant() &&
+ "symbolic argument given to klee_under_constrained!");
+
+ unsigned v = arguments[0].getConstantValue();
+ llvm::cerr << "argument = " << v << " under=" << state.underConstrained << "\n";
+ if(v) {
+ assert(state.underConstrained == false &&
+ "Bogus call to klee_under_constrained().");
+ state.underConstrained = v;
+ llvm::cerr << "turning on under!\n";
+ } else {
+ assert(state.underConstrained != 0 && "Bogus call to klee_taint_end()");
+ state.underConstrained = 0;
+ llvm::cerr << "turning off under!\n";
+ }
+}
+
+void SpecialFunctionHandler::handleSetForking(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 &&
+ "invalid number of arguments to klee_set_forking");
+ ref<Expr> value = executor.toUnique(state, arguments[0]);
+
+ if (!value.isConstant()) {
+ executor.terminateStateOnError(state,
+ "klee_set_forking requires a constant arg",
+ "user.err");
+ } else {
+ state.forkDisabled = !value.getConstantValue();
+ }
+}
+
+void SpecialFunctionHandler::handleWarning(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 && "invalid number of arguments to klee_warning");
+
+ std::string msg_str = readStringAtAddress(state, arguments[0]);
+ klee_warning("%s: %s", state.stack.back().kf->function->getName().c_str(),
+ msg_str.c_str());
+}
+
+void SpecialFunctionHandler::handleWarningOnce(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 &&
+ "invalid number of arguments to klee_warning_once");
+
+ std::string msg_str = readStringAtAddress(state, arguments[0]);
+ klee_warning_once(0, "%s: %s", state.stack.back().kf->function->getName().c_str(),
+ msg_str.c_str());
+}
+
+void SpecialFunctionHandler::handlePrintRange(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to klee_print_range");
+
+ std::string msg_str = readStringAtAddress(state, arguments[0]);
+ llvm::cerr << msg_str << ":" << arguments[1];
+ if (!arguments[1].isConstant()) {
+ // FIXME: Pull into a unique value method?
+ ref<Expr> value;
+ bool success = executor.solver->getValue(state, arguments[1], value);
+ assert(success && "FIXME: Unhandled solver failure");
+ bool res;
+ success = executor.solver->mustBeTrue(state,
+ EqExpr::create(arguments[1], value),
+ res);
+ assert(success && "FIXME: Unhandled solver failure");
+ if (res) {
+ llvm::cerr << " == " << value;
+ } else {
+ llvm::cerr << " ~= " << value;
+ std::pair< ref<Expr>, ref<Expr> > res =
+ executor.solver->getRange(state, arguments[1]);
+ llvm::cerr << " (in [" << res.first << ", " << res.second <<"])";
+ }
+ }
+ llvm::cerr << "\n";
+}
+
+void SpecialFunctionHandler::handleGetObjSize(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 &&
+ "invalid number of arguments to klee_get_obj_size");
+ Executor::ExactResolutionList rl;
+ executor.resolveExact(state, arguments[0], rl, "klee_get_obj_size");
+ for (Executor::ExactResolutionList::iterator it = rl.begin(),
+ ie = rl.end(); it != ie; ++it) {
+ executor.bindLocal(target, *it->second,
+ ConstantExpr::create(it->first.first->size, Expr::Int32));
+ }
+}
+
+void SpecialFunctionHandler::handleGetErrno(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==0 &&
+ "invalid number of arguments to klee_get_obj_size");
+ executor.bindLocal(target, state,
+ ConstantExpr::create(errno, Expr::Int32));
+}
+
+void SpecialFunctionHandler::handleCalloc(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to calloc");
+
+ ref<Expr> size = MulExpr::create(arguments[0],
+ arguments[1]);
+ executor.executeAlloc(state, size, false, target, true);
+}
+
+void SpecialFunctionHandler::handleRealloc(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to realloc");
+ ref<Expr> address = arguments[0];
+ ref<Expr> size = arguments[1];
+
+ Executor::StatePair zeroSize = executor.fork(state,
+ Expr::createIsZero(size),
+ true);
+
+ if (zeroSize.first) { // size == 0
+ executor.executeFree(*zeroSize.first, address, target);
+ }
+ if (zeroSize.second) { // size != 0
+ Executor::StatePair zeroPointer = executor.fork(*zeroSize.second,
+ Expr::createIsZero(address),
+ true);
+
+ if (zeroPointer.first) { // address == 0
+ executor.executeAlloc(*zeroPointer.first, size, false, target);
+ }
+ if (zeroPointer.second) { // address != 0
+ Executor::ExactResolutionList rl;
+ executor.resolveExact(*zeroPointer.second, address, rl, "realloc");
+
+ for (Executor::ExactResolutionList::iterator it = rl.begin(),
+ ie = rl.end(); it != ie; ++it) {
+ executor.executeAlloc(*it->second, size, false, target, false,
+ it->first.second);
+ }
+ }
+ }
+}
+
+void SpecialFunctionHandler::handleFree(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // XXX should type check args
+ assert(arguments.size()==1 &&
+ "invalid number of arguments to free");
+ executor.executeFree(state, arguments[0]);
+}
+
+void SpecialFunctionHandler::handleCheckMemoryAccess(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to klee_check_memory_access");
+
+ ref<Expr> address = executor.toUnique(state, arguments[0]);
+ ref<Expr> size = executor.toUnique(state, arguments[1]);
+ if (!address.isConstant() || !size.isConstant()) {
+ executor.terminateStateOnError(state,
+ "check_memory_access requires constant args",
+ "user.err");
+ } else {
+ ObjectPair op;
+
+ if (!state.addressSpace.resolveOne(address.getConstantValue(), op)) {
+ executor.terminateStateOnError(state,
+ "check_memory_access: memory error",
+ "ptr.err",
+ executor.getAddressInfo(state, address));
+ } else {
+ ref<Expr> chk = op.first->getBoundsCheckPointer(address,
+ size.getConstantValue());
+ assert(chk.isConstant());
+ if (!chk.getConstantValue()) {
+ executor.terminateStateOnError(state,
+ "check_memory_access: memory error",
+ "ptr.err",
+ executor.getAddressInfo(state, address));
+ }
+ }
+ }
+}
+
+void SpecialFunctionHandler::handleGetValue(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 &&
+ "invalid number of arguments to klee_get_value");
+
+ executor.executeGetValue(state, arguments[0], target);
+}
+
+void SpecialFunctionHandler::handleDefineFixedObject(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==2 &&
+ "invalid number of arguments to klee_define_fixed_object");
+ assert(arguments[0].isConstant() &&
+ "expect constant address argument to klee_define_fixed_object");
+ assert(arguments[1].isConstant() &&
+ "expect constant size argument to klee_define_fixed_object");
+
+ uint64_t address = arguments[0].getConstantValue();
+ uint64_t size = arguments[1].getConstantValue();
+ MemoryObject *mo = executor.memory->allocateFixed(address, size, state.prevPC->inst);
+ executor.bindObjectInState(state, mo, false);
+ mo->isUserSpecified = true; // XXX hack;
+}
+
+void SpecialFunctionHandler::handleMakeSymbolic(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==3 &&
+ "invalid number of arguments to klee_make_symbolic[_name]");
+
+ Executor::ExactResolutionList rl;
+ executor.resolveExact(state, arguments[0], rl, "make_symbolic");
+
+ for (Executor::ExactResolutionList::iterator it = rl.begin(),
+ ie = rl.end(); it != ie; ++it) {
+ MemoryObject *mo = (MemoryObject*) it->first.first;
+ std::string name = readStringAtAddress(state, arguments[2]);
+ mo->setName(name);
+
+ const ObjectState *old = it->first.second;
+ ExecutionState *s = it->second;
+
+ if (old->readOnly) {
+ executor.terminateStateOnError(*s,
+ "cannot make readonly object symbolic",
+ "user.err");
+ return;
+ }
+
+ bool res;
+ bool success =
+ executor.solver->mustBeTrue(*s, EqExpr::create(arguments[1],
+ mo->getSizeExpr()),
+ res);
+ assert(success && "FIXME: Unhandled solver failure");
+
+ if (res) {
+ executor.executeMakeSymbolic(*s, mo);
+ } else {
+ executor.terminateStateOnError(*s,
+ "wrong size given to klee_make_symbolic[_name]",
+ "user.err");
+ }
+ }
+}
+
+void SpecialFunctionHandler::handleMarkGlobal(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ assert(arguments.size()==1 &&
+ "invalid number of arguments to klee_mark_global");
+
+ Executor::ExactResolutionList rl;
+ executor.resolveExact(state, arguments[0], rl, "mark_global");
+
+ for (Executor::ExactResolutionList::iterator it = rl.begin(),
+ ie = rl.end(); it != ie; ++it) {
+ MemoryObject *mo = (MemoryObject*) it->first.first;
+ assert(!mo->isLocal);
+ mo->isGlobal = true;
+ }
+}
Added: klee/trunk/lib/Core/SpecialFunctionHandler.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/SpecialFunctionHandler.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/SpecialFunctionHandler.h (added)
+++ klee/trunk/lib/Core/SpecialFunctionHandler.h Wed May 20 23:36:41 2009
@@ -0,0 +1,106 @@
+//===-- SpecialFunctionHandler.h --------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_SPECIALFUNCTIONHANDLER_H
+#define KLEE_SPECIALFUNCTIONHANDLER_H
+
+#include <map>
+#include <vector>
+#include <string>
+
+namespace llvm {
+ class Function;
+}
+
+namespace klee {
+ class Executor;
+ class Expr;
+ class ExecutionState;
+ class KInstruction;
+ template<typename T> class ref;
+
+ class SpecialFunctionHandler {
+ public:
+ typedef void (SpecialFunctionHandler::*Handler)(ExecutionState &state,
+ KInstruction *target,
+ std::vector<ref<Expr> >
+ &arguments);
+ typedef std::map<const llvm::Function*,
+ std::pair<Handler,bool> > handlers_ty;
+
+ handlers_ty handlers;
+ class Executor &executor;
+
+ public:
+ SpecialFunctionHandler(Executor &_executor);
+
+ /// Perform any modifications on the LLVM module before it is
+ /// prepared for execution. At the moment this involves deleting
+ /// unused function bodies and marking intrinsics with appropriate
+ /// flags for use in optimizations.
+ void prepare();
+
+ /// Initialize the internal handler map after the module has been
+ /// prepared for execution.
+ void bind();
+
+ bool handle(ExecutionState &state,
+ llvm::Function *f,
+ KInstruction *target,
+ std::vector< ref<Expr> > &arguments);
+
+ /* Convenience routines */
+
+ std::string readStringAtAddress(ExecutionState &state, ref<Expr> address);
+
+ /* Handlers */
+
+#define HANDLER(name) void name(ExecutionState &state, \
+ KInstruction *target, \
+ std::vector< ref<Expr> > &arguments)
+ HANDLER(handleAbort);
+ HANDLER(handleAssert);
+ HANDLER(handleAssertFail);
+ HANDLER(handleAssume);
+ HANDLER(handleCalloc);
+ HANDLER(handleCheckMemoryAccess);
+ HANDLER(handleDefineFixedObject);
+ HANDLER(handleDelete);
+ HANDLER(handleDeleteArray);
+ HANDLER(handleExit);
+ HANDLER(handleAliasFunction);
+ HANDLER(handleFree);
+ HANDLER(handleGetErrno);
+ HANDLER(handleGetObjSize);
+ HANDLER(handleGetValue);
+ HANDLER(handleIsSymbolic);
+ HANDLER(handleMakeSymbolic);
+ HANDLER(handleMalloc);
+ HANDLER(handleMallocN);
+ HANDLER(handleMarkGlobal);
+ HANDLER(handleMerge);
+ HANDLER(handleNew);
+ HANDLER(handleNewArray);
+ HANDLER(handlePreferCex);
+ HANDLER(handlePrintExpr);
+ HANDLER(handlePrintRange);
+ HANDLER(handleRange);
+ HANDLER(handleRealloc);
+ HANDLER(handleReportError);
+ HANDLER(handleRevirtObjects);
+ HANDLER(handleSetForking);
+ HANDLER(handleSilentExit);
+ HANDLER(handleUnderConstrained);
+ HANDLER(handleWarning);
+ HANDLER(handleWarningOnce);
+#undef HANDLER
+ };
+} // End klee namespace
+
+#endif
Added: klee/trunk/lib/Core/StatsTracker.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/StatsTracker.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/StatsTracker.cpp (added)
+++ klee/trunk/lib/Core/StatsTracker.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,814 @@
+//===-- StatsTracker.cpp --------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "StatsTracker.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Statistics.h"
+#include "klee/Internal/Module/InstructionInfoTable.h"
+#include "klee/Internal/Module/KModule.h"
+#include "klee/Internal/Module/KInstruction.h"
+#include "klee/Internal/Support/ModuleUtil.h"
+#include "klee/Internal/System/Time.h"
+
+#include "CallPathManager.h"
+#include "CoreStats.h"
+#include "Executor.h"
+#include "MemoryManager.h"
+#include "UserSearcher.h"
+#include "../Solver/SolverStats.h"
+
+#include "llvm/BasicBlock.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/InlineAsm.h"
+#include "llvm/Module.h"
+#include "llvm/Type.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/System/Process.h"
+#include "llvm/System/Path.h"
+
+#include <iostream>
+#include <fstream>
+
+using namespace klee;
+using namespace llvm;
+
+///
+
+namespace {
+ cl::opt<bool>
+ TrackInstructionTime("track-instruction-time",
+ cl::desc("Enable tracking of time for individual instructions"),
+ cl::init(false));
+
+ cl::opt<bool>
+ OutputStats("output-stats",
+ cl::desc("Write running stats trace file"),
+ cl::init(true));
+
+ cl::opt<bool>
+ OutputIStats("output-istats",
+ cl::desc("Write instruction level statistics (in callgrind format)"),
+ cl::init(true));
+
+ cl::opt<double>
+ StatsWriteInterval("stats-write-interval",
+ cl::desc("Approximate number of seconds between stats writes (default: 1.0)"),
+ cl::init(1.));
+
+ cl::opt<double>
+ IStatsWriteInterval("istats-write-interval",
+ cl::desc("Approximate number of seconds between istats writes (default: 10.0)"),
+ cl::init(10.));
+
+ /*
+ cl::opt<double>
+ BranchCovCountsWriteInterval("branch-cov-counts-write-interval",
+ cl::desc("Approximate number of seconds between run.branches writes (default: 5.0)"),
+ cl::init(5.));
+ */
+
+ // XXX I really would like to have dynamic rate control for something like this.
+ cl::opt<double>
+ UncoveredUpdateInterval("uncovered-update-interval",
+ cl::init(30.));
+
+ cl::opt<bool>
+ UseCallPaths("use-call-paths",
+ cl::desc("Enable calltree tracking for instruction level statistics"),
+ cl::init(true));
+
+}
+
+///
+
+bool StatsTracker::useStatistics() {
+ return OutputStats || OutputIStats;
+}
+
+namespace klee {
+ class WriteIStatsTimer : public Executor::Timer {
+ StatsTracker *statsTracker;
+
+ public:
+ WriteIStatsTimer(StatsTracker *_statsTracker) : statsTracker(_statsTracker) {}
+ ~WriteIStatsTimer() {}
+
+ void run() { statsTracker->writeIStats(); }
+ };
+
+ class WriteStatsTimer : public Executor::Timer {
+ StatsTracker *statsTracker;
+
+ public:
+ WriteStatsTimer(StatsTracker *_statsTracker) : statsTracker(_statsTracker) {}
+ ~WriteStatsTimer() {}
+
+ void run() { statsTracker->writeStatsLine(); }
+ };
+
+ class UpdateReachableTimer : public Executor::Timer {
+ StatsTracker *statsTracker;
+
+ public:
+ UpdateReachableTimer(StatsTracker *_statsTracker) : statsTracker(_statsTracker) {}
+
+ void run() { statsTracker->computeReachableUncovered(); }
+ };
+
+}
+
+//
+
+/// Check for special cases where we statically know an instruction is
+/// uncoverable. Currently the case is an unreachable instruction
+/// following a noreturn call; the instruction is really only there to
+/// satisfy LLVM's termination requirement.
+static bool instructionIsCoverable(Instruction *i) {
+ if (i->getOpcode() == Instruction::Unreachable) {
+ BasicBlock *bb = i->getParent();
+ BasicBlock::iterator it(i);
+ if (it==bb->begin()) {
+ return true;
+ } else {
+ Instruction *prev = --it;
+ if (isa<CallInst>(prev) || isa<InvokeInst>(prev)) {
+ Function *target = getDirectCallTarget(prev);
+ if (target && target->doesNotReturn())
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename,
+ bool _updateMinDistToUncovered)
+ : executor(_executor),
+ objectFilename(_objectFilename),
+ statsFile(0),
+ istatsFile(0),
+ startWallTime(util::getWallTime()),
+ numBranches(0),
+ fullBranches(0),
+ partialBranches(0),
+ updateMinDistToUncovered(_updateMinDistToUncovered) {
+ KModule *km = executor.kmodule;
+
+ sys::Path module(objectFilename);
+ if (!sys::Path(objectFilename).isAbsolute()) {
+ sys::Path current = sys::Path::GetCurrentDirectory();
+ current.appendComponent(objectFilename);
+ if (current.exists())
+ objectFilename = current.c_str();
+ }
+
+ if (OutputIStats)
+ theStatisticManager->useIndexedStats(km->infos->getMaxID());
+
+ for (std::vector<KFunction*>::iterator it = km->functions.begin(),
+ ie = km->functions.end(); it != ie; ++it) {
+ KFunction *kf = *it;
+ kf->trackCoverage = 1;
+
+ for (unsigned i=0; i<kf->numInstructions; ++i) {
+ KInstruction *ki = kf->instructions[i];
+
+ if (OutputIStats) {
+ unsigned id = ki->info->id;
+ theStatisticManager->setIndex(id);
+ if (kf->trackCoverage && instructionIsCoverable(ki->inst))
+ ++stats::uncoveredInstructions;
+ }
+
+ if (kf->trackCoverage) {
+ if (BranchInst *bi = dyn_cast<BranchInst>(ki->inst))
+ if (!bi->isUnconditional())
+ numBranches++;
+ }
+ }
+ }
+
+ if (OutputStats) {
+ statsFile = executor.interpreterHandler->openOutputFile("run.stats");
+ assert(statsFile && "unable to open statistics trace file");
+ writeStatsHeader();
+ writeStatsLine();
+
+ executor.addTimer(new WriteStatsTimer(this), StatsWriteInterval);
+
+ if (updateMinDistToUncovered)
+ executor.addTimer(new UpdateReachableTimer(this), UncoveredUpdateInterval);
+ }
+
+ if (OutputIStats) {
+ istatsFile = executor.interpreterHandler->openOutputFile("run.istats");
+ assert(istatsFile && "unable to open istats file");
+
+ executor.addTimer(new WriteIStatsTimer(this), IStatsWriteInterval);
+ }
+}
+
+StatsTracker::~StatsTracker() {
+ if (statsFile)
+ delete statsFile;
+ if (istatsFile)
+ delete istatsFile;
+}
+
+void StatsTracker::done() {
+ if (statsFile)
+ writeStatsLine();
+ if (OutputIStats)
+ writeIStats();
+}
+
+void StatsTracker::stepInstruction(ExecutionState &es) {
+ if (OutputIStats) {
+ if (TrackInstructionTime) {
+ static sys::TimeValue lastNowTime(0,0),lastUserTime(0,0);
+
+ if (lastUserTime.seconds()==0 && lastUserTime.nanoseconds()==0) {
+ sys::TimeValue sys(0,0);
+ sys::Process::GetTimeUsage(lastNowTime,lastUserTime,sys);
+ } else {
+ sys::TimeValue now(0,0),user(0,0),sys(0,0);
+ sys::Process::GetTimeUsage(now,user,sys);
+ sys::TimeValue delta = user - lastUserTime;
+ sys::TimeValue deltaNow = now - lastNowTime;
+ stats::instructionTime += delta.usec();
+ stats::instructionRealTime += deltaNow.usec();
+ lastUserTime = user;
+ lastNowTime = now;
+ }
+ }
+
+ Instruction *inst = es.pc->inst;
+ const InstructionInfo &ii = *es.pc->info;
+ StackFrame &sf = es.stack.back();
+ theStatisticManager->setIndex(ii.id);
+ if (UseCallPaths)
+ theStatisticManager->setContext(&sf.callPathNode->statistics);
+
+ if (es.instsSinceCovNew)
+ ++es.instsSinceCovNew;
+
+ if (sf.kf->trackCoverage && instructionIsCoverable(inst)) {
+ if (!theStatisticManager->getIndexedValue(stats::coveredInstructions, ii.id)) {
+ // Checking for actual stoppoints avoids inconsistencies due
+ // to line number propogation.
+ if (isa<DbgStopPointInst>(inst))
+ es.coveredLines[&ii.file].insert(ii.line);
+ es.coveredNew = true;
+ es.instsSinceCovNew = 1;
+ ++stats::coveredInstructions;
+ stats::uncoveredInstructions += (uint64_t)-1;
+ }
+ }
+ }
+}
+
+///
+
+/* Should be called _after_ the es->pushFrame() */
+void StatsTracker::framePushed(ExecutionState &es, StackFrame *parentFrame) {
+ if (OutputIStats) {
+ StackFrame &sf = es.stack.back();
+
+ if (UseCallPaths) {
+ CallPathNode *parent = parentFrame ? parentFrame->callPathNode : 0;
+ CallPathNode *cp = callPathManager.getCallPath(parent,
+ sf.caller ? sf.caller->inst : 0,
+ sf.kf->function);
+ sf.callPathNode = cp;
+ cp->count++;
+ }
+
+ if (updateMinDistToUncovered) {
+ uint64_t minDistAtRA = 0;
+ if (parentFrame)
+ minDistAtRA = parentFrame->minDistToUncoveredOnReturn;
+
+ sf.minDistToUncoveredOnReturn = sf.caller ?
+ computeMinDistToUncovered(sf.caller, minDistAtRA) : 0;
+ }
+ }
+}
+
+/* Should be called _after_ the es->popFrame() */
+void StatsTracker::framePopped(ExecutionState &es) {
+ // XXX remove me?
+}
+
+
+void StatsTracker::markBranchVisited(ExecutionState *visitedTrue,
+ ExecutionState *visitedFalse) {
+ if (OutputIStats) {
+ unsigned id = theStatisticManager->getIndex();
+ uint64_t hasTrue = theStatisticManager->getIndexedValue(stats::trueBranches, id);
+ uint64_t hasFalse = theStatisticManager->getIndexedValue(stats::falseBranches, id);
+ if (visitedTrue && !hasTrue) {
+ visitedTrue->coveredNew = true;
+ visitedTrue->instsSinceCovNew = 1;
+ ++stats::trueBranches;
+ if (hasFalse) { ++fullBranches; --partialBranches; }
+ else ++partialBranches;
+ hasTrue = 1;
+ }
+ if (visitedFalse && !hasFalse) {
+ visitedFalse->coveredNew = true;
+ visitedFalse->instsSinceCovNew = 1;
+ ++stats::falseBranches;
+ if (hasTrue) { ++fullBranches; --partialBranches; }
+ else ++partialBranches;
+ }
+ }
+}
+
+void StatsTracker::writeStatsHeader() {
+ *statsFile << "('Instructions',"
+ << "'FullBranches',"
+ << "'PartialBranches',"
+ << "'NumBranches',"
+ << "'UserTime',"
+ << "'NumStates',"
+ << "'MallocUsage',"
+ << "'NumQueries',"
+ << "'NumQueryConstructs',"
+ << "'NumObjects',"
+ << "'WallTime',"
+ << "'CoveredInstructions',"
+ << "'UncoveredInstructions',"
+ << "'QueryTime',"
+ << "'SolverTime',"
+ << "'CexCacheTime',"
+ << "'ForkTime',"
+ << "'ResolveTime',"
+ << ")\n";
+ statsFile->flush();
+}
+
+double StatsTracker::elapsed() {
+ return util::getWallTime() - startWallTime;
+}
+
+void StatsTracker::writeStatsLine() {
+ *statsFile << "(" << stats::instructions
+ << "," << fullBranches
+ << "," << partialBranches
+ << "," << numBranches
+ << "," << util::getUserTime()
+ << "," << executor.states.size()
+ << "," << sys::Process::GetTotalMemoryUsage()
+ << "," << stats::queries
+ << "," << stats::queryConstructs
+ << "," << 0 // was numObjects
+ << "," << elapsed()
+ << "," << stats::coveredInstructions
+ << "," << stats::uncoveredInstructions
+ << "," << stats::queryTime / 1000000.
+ << "," << stats::solverTime / 1000000.
+ << "," << stats::cexCacheTime / 1000000.
+ << "," << stats::forkTime / 1000000.
+ << "," << stats::resolveTime / 1000000.
+ << ")\n";
+ statsFile->flush();
+}
+
+void StatsTracker::updateStateStatistics(uint64_t addend) {
+ for (std::set<ExecutionState*>::iterator it = executor.states.begin(),
+ ie = executor.states.end(); it != ie; ++it) {
+ ExecutionState &state = **it;
+ const InstructionInfo &ii = *state.pc->info;
+ theStatisticManager->incrementIndexedValue(stats::states, ii.id, addend);
+ if (UseCallPaths)
+ state.stack.back().callPathNode->statistics.incrementValue(stats::states, addend);
+ }
+}
+
+void StatsTracker::writeIStats() {
+ Module *m = executor.kmodule->module;
+ uint64_t istatsMask = 0;
+ std::ostream &of = *istatsFile;
+
+ of.seekp(0, std::ios::end);
+ unsigned istatsSize = of.tellp();
+ of.seekp(0);
+
+ of << "version: 1\n";
+ of << "creator: klee\n";
+ of << "pid: " << sys::Process::GetCurrentUserId() << "\n";
+ of << "cmd: " << m->getModuleIdentifier() << "\n\n";
+ of << "\n";
+
+ StatisticManager &sm = *theStatisticManager;
+ unsigned nStats = sm.getNumStatistics();
+
+ // Max is 13, sadly
+ istatsMask |= 1<<sm.getStatisticID("Queries");
+ istatsMask |= 1<<sm.getStatisticID("QueriesValid");
+ istatsMask |= 1<<sm.getStatisticID("QueriesInvalid");
+ istatsMask |= 1<<sm.getStatisticID("QueryTime");
+ istatsMask |= 1<<sm.getStatisticID("ResolveTime");
+ istatsMask |= 1<<sm.getStatisticID("Instructions");
+ istatsMask |= 1<<sm.getStatisticID("InstructionTimes");
+ istatsMask |= 1<<sm.getStatisticID("InstructionRealTimes");
+ istatsMask |= 1<<sm.getStatisticID("Forks");
+ istatsMask |= 1<<sm.getStatisticID("CoveredInstructions");
+ istatsMask |= 1<<sm.getStatisticID("UncoveredInstructions");
+ istatsMask |= 1<<sm.getStatisticID("States");
+ istatsMask |= 1<<sm.getStatisticID("MinDistToUncovered");
+
+ of << "positions: instr line\n";
+
+ for (unsigned i=0; i<nStats; i++) {
+ if (istatsMask & (1<<i)) {
+ Statistic &s = sm.getStatistic(i);
+ of << "event: " << s.getShortName() << " : "
+ << s.getName() << "\n";
+ }
+ }
+
+ of << "events: ";
+ for (unsigned i=0; i<nStats; i++) {
+ if (istatsMask & (1<<i))
+ of << sm.getStatistic(i).getShortName() << " ";
+ }
+ of << "\n";
+
+ // set state counts, decremented after we process so that we don't
+ // have to zero all records each time.
+ if (istatsMask & (1<<stats::states.getID()))
+ updateStateStatistics(1);
+
+ std::string sourceFile = "";
+
+ CallSiteSummaryTable callSiteStats;
+ if (UseCallPaths)
+ callPathManager.getSummaryStatistics(callSiteStats);
+
+ of << "ob=" << objectFilename << "\n";
+
+ for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
+ fnIt != fn_ie; ++fnIt) {
+ if (!fnIt->isDeclaration()) {
+ of << "fn=" << fnIt->getName() << "\n";
+ for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
+ bbIt != bb_ie; ++bbIt) {
+ for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
+ it != it; ++it) {
+ Instruction *instr = &*it;
+ const InstructionInfo &ii = executor.kmodule->infos->getInfo(instr);
+ unsigned index = ii.id;
+ if (ii.file!=sourceFile) {
+ of << "fl=" << ii.file << "\n";
+ sourceFile = ii.file;
+ }
+ of << ii.assemblyLine << " ";
+ of << ii.line << " ";
+ for (unsigned i=0; i<nStats; i++)
+ if (istatsMask&(1<<i))
+ of << sm.getIndexedValue(sm.getStatistic(i), index) << " ";
+ of << "\n";
+
+ if (UseCallPaths &&
+ (isa<CallInst>(instr) || isa<InvokeInst>(instr))) {
+ CallSiteSummaryTable::iterator it = callSiteStats.find(instr);
+ if (it!=callSiteStats.end()) {
+ for (std::map<llvm::Function*, CallSiteInfo>::iterator
+ fit = it->second.begin(), fie = it->second.end();
+ fit != fie; ++fit) {
+ Function *f = fit->first;
+ CallSiteInfo &csi = fit->second;
+ const InstructionInfo &fii =
+ executor.kmodule->infos->getFunctionInfo(f);
+
+ if (fii.file!="" && fii.file!=sourceFile)
+ of << "cfl=" << fii.file << "\n";
+ of << "cfn=" << f->getName() << "\n";
+ of << "calls=" << csi.count << " ";
+ of << fii.assemblyLine << " ";
+ of << fii.line << "\n";
+
+ of << ii.assemblyLine << " ";
+ of << ii.line << " ";
+ for (unsigned i=0; i<nStats; i++) {
+ if (istatsMask&(1<<i)) {
+ Statistic &s = sm.getStatistic(i);
+ uint64_t value;
+
+ // Hack, ignore things that don't make sense on
+ // call paths.
+ if (&s == &stats::uncoveredInstructions) {
+ value = 0;
+ } else {
+ value = csi.statistics.getValue(s);
+ }
+
+ of << value << " ";
+ }
+ }
+ of << "\n";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (istatsMask & (1<<stats::states.getID()))
+ updateStateStatistics((uint64_t)-1);
+
+ // Clear then end of the file if necessary (no truncate op?).
+ unsigned pos = of.tellp();
+ for (unsigned i=pos; i<istatsSize; ++i)
+ of << '\n';
+
+ of.flush();
+}
+
+///
+
+typedef std::map<Instruction*, std::vector<Function*> > calltargets_ty;
+
+static calltargets_ty callTargets;
+static std::map<Function*, std::vector<Instruction*> > functionCallers;
+static std::map<Function*, unsigned> functionShortestPath;
+
+static std::vector<Instruction*> getSuccs(Instruction *i) {
+ BasicBlock *bb = i->getParent();
+ std::vector<Instruction*> res;
+
+ if (i==bb->getTerminator()) {
+ for (succ_iterator it = succ_begin(bb), ie = succ_end(bb); it != ie; ++it)
+ res.push_back(it->begin());
+ } else {
+ res.push_back(++BasicBlock::iterator(i));
+ }
+
+ return res;
+}
+
+uint64_t klee::computeMinDistToUncovered(const KInstruction *ki,
+ uint64_t minDistAtRA) {
+ StatisticManager &sm = *theStatisticManager;
+ if (minDistAtRA==0) { // unreachable on return, best is local
+ return sm.getIndexedValue(stats::minDistToUncovered,
+ ki->info->id);
+ } else {
+ uint64_t minDistLocal = sm.getIndexedValue(stats::minDistToUncovered,
+ ki->info->id);
+ uint64_t distToReturn = sm.getIndexedValue(stats::minDistToReturn,
+ ki->info->id);
+
+ if (distToReturn==0) { // return unreachable, best is local
+ return minDistLocal;
+ } else if (!minDistLocal) { // no local reachable
+ return distToReturn + minDistAtRA;
+ } else {
+ return std::min(minDistLocal, distToReturn + minDistAtRA);
+ }
+ }
+}
+
+void StatsTracker::computeReachableUncovered() {
+ KModule *km = executor.kmodule;
+ Module *m = km->module;
+ static bool init = true;
+ const InstructionInfoTable &infos = *km->infos;
+ StatisticManager &sm = *theStatisticManager;
+
+ if (init) {
+ init = false;
+
+ // Compute call targets. It would be nice to use alias information
+ // instead of assuming all indirect calls hit all escaping
+ // functions, eh?
+ for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
+ fnIt != fn_ie; ++fnIt) {
+ for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
+ bbIt != bb_ie; ++bbIt) {
+ for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
+ it != it; ++it) {
+ if (isa<CallInst>(it) || isa<InvokeInst>(it)) {
+ if (isa<InlineAsm>(it->getOperand(0))) {
+ // We can never call through here so assume no targets
+ // (which should be correct anyhow).
+ callTargets.insert(std::make_pair(it,
+ std::vector<Function*>()));
+ } else if (Function *target = getDirectCallTarget(it)) {
+ callTargets[it].push_back(target);
+ } else {
+ callTargets[it] =
+ std::vector<Function*>(km->escapingFunctions.begin(),
+ km->escapingFunctions.end());
+ }
+ }
+ }
+ }
+ }
+
+ // Compute function callers as reflexion of callTargets.
+ for (calltargets_ty::iterator it = callTargets.begin(),
+ ie = callTargets.end(); it != ie; ++it)
+ for (std::vector<Function*>::iterator fit = it->second.begin(),
+ fie = it->second.end(); fit != fie; ++fit)
+ functionCallers[*fit].push_back(it->first);
+
+ // Initialize minDistToReturn to shortest paths through
+ // functions. 0 is unreachable.
+ std::vector<Instruction *> instructions;
+ for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
+ fnIt != fn_ie; ++fnIt) {
+ if (fnIt->isDeclaration()) {
+ if (fnIt->doesNotReturn()) {
+ functionShortestPath[fnIt] = 0;
+ } else {
+ functionShortestPath[fnIt] = 1; // whatever
+ }
+ } else {
+ functionShortestPath[fnIt] = 0;
+ }
+
+ // Not sure if I should bother to preorder here. XXX I should.
+ for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
+ bbIt != bb_ie; ++bbIt) {
+ for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
+ it != it; ++it) {
+ instructions.push_back(it);
+ unsigned id = infos.getInfo(it).id;
+ sm.setIndexedValue(stats::minDistToReturn,
+ id,
+ isa<ReturnInst>(it) || isa<UnwindInst>(it));
+ }
+ }
+ }
+
+ std::reverse(instructions.begin(), instructions.end());
+
+ // I'm so lazy it's not even worklisted.
+ bool changed;
+ do {
+ changed = false;
+ for (std::vector<Instruction*>::iterator it = instructions.begin(),
+ ie = instructions.end(); it != ie; ++it) {
+ Instruction *inst = *it;
+ unsigned bestThrough = 0;
+
+ if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
+ std::vector<Function*> &targets = callTargets[inst];
+ for (std::vector<Function*>::iterator fnIt = targets.begin(),
+ ie = targets.end(); fnIt != ie; ++fnIt) {
+ uint64_t dist = functionShortestPath[*fnIt];
+ if (dist) {
+ dist = 1+dist; // count instruction itself
+ if (bestThrough==0 || dist<bestThrough)
+ bestThrough = dist;
+ }
+ }
+ } else {
+ bestThrough = 1;
+ }
+
+ if (bestThrough) {
+ unsigned id = infos.getInfo(*it).id;
+ uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToReturn, id);
+ std::vector<Instruction*> succs = getSuccs(*it);
+ for (std::vector<Instruction*>::iterator it2 = succs.begin(),
+ ie = succs.end(); it2 != ie; ++it2) {
+ uint64_t dist = sm.getIndexedValue(stats::minDistToReturn,
+ infos.getInfo(*it2).id);
+ if (dist) {
+ uint64_t val = bestThrough + dist;
+ if (best==0 || val<best)
+ best = val;
+ }
+ }
+ if (best != cur) {
+ sm.setIndexedValue(stats::minDistToReturn, id, best);
+ changed = true;
+
+ // Update shortest path if this is the entry point.
+ Function *f = inst->getParent()->getParent();
+ if (inst==f->begin()->begin())
+ functionShortestPath[f] = best;
+ }
+ }
+ }
+ } while (changed);
+ }
+
+ // compute minDistToUncovered, 0 is unreachable
+ std::vector<Instruction *> instructions;
+ for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
+ fnIt != fn_ie; ++fnIt) {
+ // Not sure if I should bother to preorder here.
+ for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
+ bbIt != bb_ie; ++bbIt) {
+ for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
+ it != it; ++it) {
+ unsigned id = infos.getInfo(it).id;
+ instructions.push_back(&*it);
+ sm.setIndexedValue(stats::minDistToUncovered,
+ id,
+ sm.getIndexedValue(stats::uncoveredInstructions, id));
+ }
+ }
+ }
+
+ std::reverse(instructions.begin(), instructions.end());
+
+ // I'm so lazy it's not even worklisted.
+ bool changed;
+ do {
+ changed = false;
+ for (std::vector<Instruction*>::iterator it = instructions.begin(),
+ ie = instructions.end(); it != ie; ++it) {
+ Instruction *inst = *it;
+ uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToUncovered,
+ infos.getInfo(inst).id);
+ unsigned bestThrough = 0;
+
+ if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
+ std::vector<Function*> &targets = callTargets[inst];
+ for (std::vector<Function*>::iterator fnIt = targets.begin(),
+ ie = targets.end(); fnIt != ie; ++fnIt) {
+ uint64_t dist = functionShortestPath[*fnIt];
+ if (dist) {
+ dist = 1+dist; // count instruction itself
+ if (bestThrough==0 || dist<bestThrough)
+ bestThrough = dist;
+ }
+
+ if (!(*fnIt)->isDeclaration()) {
+ uint64_t calleeDist = sm.getIndexedValue(stats::minDistToUncovered,
+ infos.getFunctionInfo(*fnIt).id);
+ if (calleeDist) {
+ calleeDist = 1+calleeDist; // count instruction itself
+ if (best==0 || calleeDist<best)
+ best = calleeDist;
+ }
+ }
+ }
+ } else {
+ bestThrough = 1;
+ }
+
+ if (bestThrough) {
+ std::vector<Instruction*> succs = getSuccs(inst);
+ for (std::vector<Instruction*>::iterator it2 = succs.begin(),
+ ie = succs.end(); it2 != ie; ++it2) {
+ uint64_t dist = sm.getIndexedValue(stats::minDistToUncovered,
+ infos.getInfo(*it2).id);
+ if (dist) {
+ uint64_t val = bestThrough + dist;
+ if (best==0 || val<best)
+ best = val;
+ }
+ }
+ }
+
+ if (best != cur) {
+ sm.setIndexedValue(stats::minDistToUncovered,
+ infos.getInfo(inst).id,
+ best);
+ changed = true;
+ }
+ }
+ } while (changed);
+
+ for (std::set<ExecutionState*>::iterator it = executor.states.begin(),
+ ie = executor.states.end(); it != ie; ++it) {
+ ExecutionState *es = *it;
+ uint64_t currentFrameMinDist = 0;
+ for (ExecutionState::stack_ty::iterator sfIt = es->stack.begin(),
+ sf_ie = es->stack.end(); sfIt != sf_ie; ++sfIt) {
+ ExecutionState::stack_ty::iterator next = sfIt + 1;
+ KInstIterator kii;
+
+ if (next==es->stack.end()) {
+ kii = es->pc;
+ } else {
+ kii = next->caller;
+ ++kii;
+ }
+
+ sfIt->minDistToUncoveredOnReturn = currentFrameMinDist;
+
+ currentFrameMinDist = computeMinDistToUncovered(kii, currentFrameMinDist);
+ }
+ }
+}
Added: klee/trunk/lib/Core/StatsTracker.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/StatsTracker.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/StatsTracker.h (added)
+++ klee/trunk/lib/Core/StatsTracker.h Wed May 20 23:36:41 2009
@@ -0,0 +1,93 @@
+//===-- StatsTracker.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_STATSTRACKER_H
+#define KLEE_STATSTRACKER_H
+
+#include "CallPathManager.h"
+
+#include <iostream>
+#include <set>
+
+namespace llvm {
+ class BranchInst;
+ class Function;
+ class Instruction;
+}
+
+namespace klee {
+ class ExecutionState;
+ class Executor;
+ class InstructionInfoTable;
+ class InterpreterHandler;
+ class KInstruction;
+ class StackFrame;
+
+ class StatsTracker {
+ friend class WriteStatsTimer;
+ friend class WriteIStatsTimer;
+
+ Executor &executor;
+ std::string objectFilename;
+
+ std::ostream *statsFile, *istatsFile;
+ double startWallTime;
+
+ unsigned numBranches;
+ unsigned fullBranches, partialBranches;
+
+ CallPathManager callPathManager;
+
+ bool updateMinDistToUncovered;
+
+ public:
+ static bool useStatistics();
+
+ private:
+ void updateStateStatistics(uint64_t addend);
+ void writeStatsHeader();
+ void writeStatsLine();
+ void writeIStats();
+
+ public:
+ StatsTracker(Executor &_executor, std::string _objectFilename,
+ bool _updateMinDistToUncovered);
+ ~StatsTracker();
+
+ // called after a new StackFrame has been pushed (for callpath tracing)
+ void framePushed(ExecutionState &es, StackFrame *parentFrame);
+
+ // called after a StackFrame has been popped
+ void framePopped(ExecutionState &es);
+
+ // called when some side of a branch has been visited. it is
+ // imperative that this be called when the statistics index is at
+ // the index for the branch itself.
+ void markBranchVisited(ExecutionState *visitedTrue,
+ ExecutionState *visitedFalse);
+
+ // called when execution is done and stats files should be flushed
+ void done();
+
+ // process stats for a single instruction step, es is the state
+ // about to be stepped
+ void stepInstruction(ExecutionState &es);
+
+ /// Return time in seconds since execution start.
+ double elapsed();
+
+ void computeReachableUncovered();
+ };
+
+ uint64_t computeMinDistToUncovered(const KInstruction *ki,
+ uint64_t minDistAtRA);
+
+}
+
+#endif
Added: klee/trunk/lib/Core/TimingSolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/TimingSolver.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/TimingSolver.cpp (added)
+++ klee/trunk/lib/Core/TimingSolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,147 @@
+//===-- TimingSolver.cpp --------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TimingSolver.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Solver.h"
+#include "klee/Statistics.h"
+
+#include "CoreStats.h"
+
+#include "llvm/System/Process.h"
+
+using namespace klee;
+using namespace llvm;
+
+/***/
+
+bool TimingSolver::evaluate(const ExecutionState& state, ref<Expr> expr,
+ Solver::Validity &result) {
+ // Fast path, to avoid timer and OS overhead.
+ if (expr.isConstant()) {
+ result = expr.getConstantValue() ? Solver::True : Solver::False;
+ return true;
+ }
+
+ sys::TimeValue now(0,0),user(0,0),delta(0,0),sys(0,0);
+ sys::Process::GetTimeUsage(now,user,sys);
+
+ if (simplifyExprs)
+ expr = state.constraints.simplifyExpr(expr);
+
+ bool success = solver->evaluate(Query(state.constraints, expr), result);
+
+ sys::Process::GetTimeUsage(delta,user,sys);
+ delta -= now;
+ stats::solverTime += delta.usec();
+ state.queryCost += delta.usec()/1000000.;
+
+ return success;
+}
+
+bool TimingSolver::mustBeTrue(const ExecutionState& state, ref<Expr> expr,
+ bool &result) {
+ // Fast path, to avoid timer and OS overhead.
+ if (expr.isConstant()) {
+ result = expr.getConstantValue() ? true : false;
+ return true;
+ }
+
+ sys::TimeValue now(0,0),user(0,0),delta(0,0),sys(0,0);
+ sys::Process::GetTimeUsage(now,user,sys);
+
+ if (simplifyExprs)
+ expr = state.constraints.simplifyExpr(expr);
+
+ bool success = solver->mustBeTrue(Query(state.constraints, expr), result);
+
+ sys::Process::GetTimeUsage(delta,user,sys);
+ delta -= now;
+ stats::solverTime += delta.usec();
+ state.queryCost += delta.usec()/1000000.;
+
+ return success;
+}
+
+bool TimingSolver::mustBeFalse(const ExecutionState& state, ref<Expr> expr,
+ bool &result) {
+ return mustBeTrue(state, Expr::createNot(expr), result);
+}
+
+bool TimingSolver::mayBeTrue(const ExecutionState& state, ref<Expr> expr,
+ bool &result) {
+ bool res;
+ if (!mustBeFalse(state, expr, res))
+ return false;
+ result = !res;
+ return true;
+}
+
+bool TimingSolver::mayBeFalse(const ExecutionState& state, ref<Expr> expr,
+ bool &result) {
+ bool res;
+ if (!mustBeTrue(state, expr, res))
+ return false;
+ result = !res;
+ return true;
+}
+
+bool TimingSolver::getValue(const ExecutionState& state, ref<Expr> expr,
+ ref<Expr> &result) {
+ // Fast path, to avoid timer and OS overhead.
+ if (expr.isConstant()) {
+ result = expr;
+ return true;
+ }
+
+ sys::TimeValue now(0,0),user(0,0),delta(0,0),sys(0,0);
+ sys::Process::GetTimeUsage(now,user,sys);
+
+ if (simplifyExprs)
+ expr = state.constraints.simplifyExpr(expr);
+
+ bool success = solver->getValue(Query(state.constraints, expr), result);
+
+ sys::Process::GetTimeUsage(delta,user,sys);
+ delta -= now;
+ stats::solverTime += delta.usec();
+ state.queryCost += delta.usec()/1000000.;
+
+ return success;
+}
+
+bool
+TimingSolver::getInitialValues(const ExecutionState& state,
+ const std::vector<const Array*>
+ &objects,
+ std::vector< std::vector<unsigned char> >
+ &result) {
+ if (objects.empty())
+ return true;
+
+ sys::TimeValue now(0,0),user(0,0),delta(0,0),sys(0,0);
+ sys::Process::GetTimeUsage(now,user,sys);
+
+ bool success = solver->getInitialValues(Query(state.constraints,
+ ref<Expr>(0, Expr::Bool)),
+ objects, result);
+
+ sys::Process::GetTimeUsage(delta,user,sys);
+ delta -= now;
+ stats::solverTime += delta.usec();
+ state.queryCost += delta.usec()/1000000.;
+
+ return success;
+}
+
+std::pair< ref<Expr>, ref<Expr> >
+TimingSolver::getRange(const ExecutionState& state, ref<Expr> expr) {
+ return solver->getRange(Query(state.constraints, expr));
+}
Added: klee/trunk/lib/Core/TimingSolver.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/TimingSolver.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/TimingSolver.h (added)
+++ klee/trunk/lib/Core/TimingSolver.h Wed May 20 23:36:41 2009
@@ -0,0 +1,70 @@
+//===-- TimingSolver.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_TIMINGSOLVER_H
+#define KLEE_TIMINGSOLVER_H
+
+#include "klee/Expr.h"
+#include "klee/Solver.h"
+
+#include <vector>
+
+namespace klee {
+ class ExecutionState;
+ class Solver;
+ class STPSolver;
+
+ /// TimingSolver - A simple class which wraps a solver and handles
+ /// tracking the statistics that we care about.
+ class TimingSolver {
+ public:
+ Solver *solver;
+ STPSolver *stpSolver;
+ bool simplifyExprs;
+
+ public:
+ /// TimingSolver - Construct a new timing solver.
+ ///
+ /// \param _simplifyExprs - Whether expressions should be
+ /// simplified (via the constraint manager interface) prior to
+ /// querying.
+ TimingSolver(Solver *_solver, STPSolver *_stpSolver,
+ bool _simplifyExprs = true)
+ : solver(_solver), stpSolver(_stpSolver), simplifyExprs(_simplifyExprs) {}
+ ~TimingSolver() {
+ delete solver;
+ }
+
+ void setTimeout(double t) {
+ stpSolver->setTimeout(t);
+ }
+
+ bool evaluate(const ExecutionState&, ref<Expr>, Solver::Validity &result);
+
+ bool mustBeTrue(const ExecutionState&, ref<Expr>, bool &result);
+
+ bool mustBeFalse(const ExecutionState&, ref<Expr>, bool &result);
+
+ bool mayBeTrue(const ExecutionState&, ref<Expr>, bool &result);
+
+ bool mayBeFalse(const ExecutionState&, ref<Expr>, bool &result);
+
+ bool getValue(const ExecutionState &, ref<Expr> expr, ref<Expr> &result);
+
+ bool getInitialValues(const ExecutionState&,
+ const std::vector<const Array*> &objects,
+ std::vector< std::vector<unsigned char> > &result);
+
+ virtual std::pair< ref<Expr>, ref<Expr> >
+ getRange(const ExecutionState&, ref<Expr> query);
+ };
+
+}
+
+#endif
Added: klee/trunk/lib/Core/UserSearcher.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/UserSearcher.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/UserSearcher.cpp (added)
+++ klee/trunk/lib/Core/UserSearcher.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,175 @@
+//===-- UserSearcher.cpp --------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Common.h"
+
+#include "UserSearcher.h"
+
+#include "Searcher.h"
+#include "Executor.h"
+
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace klee;
+
+namespace {
+ cl::opt<bool>
+ UseRandomSearch("use-random-search");
+
+ cl::opt<bool>
+ UseInterleavedRS("use-interleaved-RS");
+
+ cl::opt<bool>
+ UseInterleavedNURS("use-interleaved-NURS");
+
+ cl::opt<bool>
+ UseInterleavedMD2UNURS("use-interleaved-MD2U-NURS");
+
+ cl::opt<bool>
+ UseInterleavedInstCountNURS("use-interleaved-icnt-NURS");
+
+ cl::opt<bool>
+ UseInterleavedCPInstCountNURS("use-interleaved-cpicnt-NURS");
+
+ cl::opt<bool>
+ UseInterleavedQueryCostNURS("use-interleaved-query-cost-NURS");
+
+ cl::opt<bool>
+ UseInterleavedCovNewNURS("use-interleaved-covnew-NURS");
+
+ cl::opt<bool>
+ UseNonUniformRandomSearch("use-non-uniform-random-search");
+
+ cl::opt<bool>
+ UseRandomPathSearch("use-random-path");
+
+ cl::opt<WeightedRandomSearcher::WeightType>
+ WeightType("weight-type", cl::desc("Set the weight type for --use-non-uniform-random-search"),
+ cl::values(clEnumValN(WeightedRandomSearcher::Depth, "none", "use (2^depth)"),
+ clEnumValN(WeightedRandomSearcher::InstCount, "icnt", "use current pc exec count"),
+ clEnumValN(WeightedRandomSearcher::CPInstCount, "cpicnt", "use current pc exec count"),
+ clEnumValN(WeightedRandomSearcher::QueryCost, "query-cost", "use query cost"),
+ clEnumValN(WeightedRandomSearcher::MinDistToUncovered, "md2u", "use min dist to uncovered"),
+ clEnumValN(WeightedRandomSearcher::CoveringNew, "covnew", "use min dist to uncovered + coveringNew flag"),
+ clEnumValEnd));
+
+ cl::opt<bool>
+ UseMerge("use-merge",
+ cl::desc("Enable support for klee_merge() (experimental)"));
+
+ cl::opt<bool>
+ UseBumpMerge("use-bump-merge",
+ cl::desc("Enable support for klee_merge() (extra experimental)"));
+
+ cl::opt<bool>
+ UseIterativeDeepeningTimeSearch("use-iterative-deepening-time-search",
+ cl::desc("(experimental)"));
+
+ cl::opt<bool>
+ UseBatchingSearch("use-batching-search",
+ cl::desc("Use batching searcher (keep running selected state for N instructions/time, see --batch-instructions and --batch-time"));
+
+ cl::opt<unsigned>
+ BatchInstructions("batch-instructions",
+ cl::desc("Number of instructions to batch when using --use-batching-search"),
+ cl::init(10000));
+
+ cl::opt<double>
+ BatchTime("batch-time",
+ cl::desc("Amount of time to batch when using --use-batching-search"),
+ cl::init(5.0));
+}
+
+bool klee::userSearcherRequiresMD2U() {
+ return (WeightType==WeightedRandomSearcher::MinDistToUncovered ||
+ WeightType==WeightedRandomSearcher::CoveringNew ||
+ UseInterleavedMD2UNURS ||
+ UseInterleavedCovNewNURS ||
+ UseInterleavedInstCountNURS ||
+ UseInterleavedCPInstCountNURS ||
+ UseInterleavedQueryCostNURS);
+}
+
+// FIXME: Remove.
+bool klee::userSearcherRequiresBranchSequences() {
+ return false;
+}
+
+Searcher *klee::constructUserSearcher(Executor &executor) {
+ Searcher *searcher = 0;
+
+ if (UseRandomPathSearch) {
+ searcher = new RandomPathSearcher(executor);
+ } else if (UseNonUniformRandomSearch) {
+ searcher = new WeightedRandomSearcher(executor, WeightType);
+ } else if (UseRandomSearch) {
+ searcher = new RandomSearcher();
+ } else {
+ searcher = new DFSSearcher();
+ }
+
+ if (UseInterleavedNURS || UseInterleavedMD2UNURS || UseInterleavedRS ||
+ UseInterleavedCovNewNURS || UseInterleavedInstCountNURS ||
+ UseInterleavedCPInstCountNURS || UseInterleavedQueryCostNURS) {
+ std::vector<Searcher *> s;
+ s.push_back(searcher);
+
+ if (UseInterleavedNURS)
+ s.push_back(new WeightedRandomSearcher(executor,
+ WeightedRandomSearcher::Depth));
+ if (UseInterleavedMD2UNURS)
+ s.push_back(new WeightedRandomSearcher(executor,
+ WeightedRandomSearcher::MinDistToUncovered));
+
+ if (UseInterleavedCovNewNURS)
+ s.push_back(new WeightedRandomSearcher(executor,
+ WeightedRandomSearcher::CoveringNew));
+
+ if (UseInterleavedInstCountNURS)
+ s.push_back(new WeightedRandomSearcher(executor,
+ WeightedRandomSearcher::InstCount));
+
+ if (UseInterleavedCPInstCountNURS)
+ s.push_back(new WeightedRandomSearcher(executor,
+ WeightedRandomSearcher::CPInstCount));
+
+ if (UseInterleavedQueryCostNURS)
+ s.push_back(new WeightedRandomSearcher(executor,
+ WeightedRandomSearcher::QueryCost));
+
+ if (UseInterleavedRS)
+ s.push_back(new RandomSearcher());
+
+ searcher = new InterleavedSearcher(s);
+ }
+
+ if (UseBatchingSearch) {
+ searcher = new BatchingSearcher(searcher, BatchTime, BatchInstructions);
+ }
+
+ if (UseMerge) {
+ assert(!UseBumpMerge);
+ searcher = new MergingSearcher(executor, searcher);
+ } else if (UseBumpMerge) {
+ searcher = new BumpMergingSearcher(executor, searcher);
+ }
+
+ if (UseIterativeDeepeningTimeSearch) {
+ searcher = new IterativeDeepeningTimeSearcher(searcher);
+ }
+
+ std::ostream &os = executor.getHandler().getInfoStream();
+
+ os << "BEGIN searcher description\n";
+ searcher->printName(os);
+ os << "END searcher description\n";
+
+ return searcher;
+}
Added: klee/trunk/lib/Core/UserSearcher.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Core/UserSearcher.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Core/UserSearcher.h (added)
+++ klee/trunk/lib/Core/UserSearcher.h Wed May 20 23:36:41 2009
@@ -0,0 +1,25 @@
+//===-- UserSearcher.h ------------------------------------------*- C++ -*-===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_USERSEARCHER_H
+#define KLEE_USERSEARCHER_H
+
+namespace klee {
+ class Executor;
+ class Searcher;
+
+ // XXX gross, should be on demand?
+ bool userSearcherRequiresMD2U();
+
+ bool userSearcherRequiresBranchSequences();
+
+ Searcher *constructUserSearcher(Executor &executor);
+}
+
+#endif
Added: klee/trunk/lib/Expr/Constraints.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/Constraints.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/lib/Expr/Constraints.cpp (added)
+++ klee/trunk/lib/Expr/Constraints.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,155 @@
+//===-- Constraints.cpp ---------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "klee/Constraints.h"
+
+#include "klee/util/ExprPPrinter.h"
+#include "klee/util/ExprVisitor.h"
+
+#include <iostream>
+#include <map>
+
+using namespace klee;
+
+class ExprReplaceVisitor : public ExprVisitor {
+private:
+ ref<Expr> src, dst;
+
+public:
+ ExprReplaceVisitor(ref<Expr> _src, ref<Expr> _dst) : src(_src), dst(_dst) {}
+
+ Action visitExpr(const Expr &e) {
+ if (e == *src.get()) {
+ return Action::changeTo(dst);
+ } else {
+ return Action::doChildren();
+ }
+ }
+
+ Action visitExprPost(const Expr &e) {
+ if (e == *src.get()) {
+ return Action::changeTo(dst);
+ } else {
+ return Action::doChildren();
+ }
+ }
+};
+
+class ExprReplaceVisitor2 : public ExprVisitor {
+private:
+ const std::map< ref<Expr>, ref<Expr> > &replacements;
+
+public:
+ ExprReplaceVisitor2(const std::map< ref<Expr>, ref<Expr> > &_replacements)
+ : ExprVisitor(true),
+ replacements(_replacements) {}
+
+ Action visitExprPost(const Expr &e) {
+ std::map< ref<Expr>, ref<Expr> >::const_iterator it =
+ replacements.find(ref<Expr>((Expr*) &e));
+ if (it!=replacements.end()) {
+ return Action::changeTo(it->second);
+ } else {
+ return Action::doChildren();
+ }
+ }
+};
+
+bool ConstraintManager::rewriteConstraints(ExprVisitor &visitor) {
+ ConstraintManager::constraints_ty old;
+ bool changed = false;
+
+ constraints.swap(old);
+ for (ConstraintManager::constraints_ty::iterator
+ it = old.begin(), ie = old.end(); it != ie; ++it) {
+ ref<Expr> &ce = *it;
+ ref<Expr> e = visitor.visit(ce);
+
+ if (e!=ce) {
+ addConstraintInternal(e); // enable further reductions
+ changed = true;
+ } else {
+ constraints.push_back(ce);
+ }
+ }
+
+ return changed;
+}
+
+void ConstraintManager::simplifyForValidConstraint(ref<Expr> e) {
+ // XXX
+}
+
+ref<Expr> ConstraintManager::simplifyExpr(ref<Expr> e) const {
+ if (e.isConstant())
+ return e;
+
+ std::map< ref<Expr>, ref<Expr> > equalities;
+
+ for (ConstraintManager::constraints_ty::const_iterator
+ it = constraints.begin(), ie = constraints.end(); it != ie; ++it) {
+ if (const EqExpr *ee = dyn_ref_cast<EqExpr>(*it)) {
+ if (ee->left.isConstant()) {
+ equalities.insert(std::make_pair(ee->right,
+ ee->left));
+ } else {
+ equalities.insert(std::make_pair(*it,
+ ref<Expr>(1,Expr::Bool)));
+ }
+ } else {
+ equalities.insert(std::make_pair(*it,
+ ref<Expr>(1,Expr::Bool)));
+ }
+ }
+
+ return ExprReplaceVisitor2(equalities).visit(e);
+}
+
+void ConstraintManager::addConstraintInternal(ref<Expr> e) {
+ // rewrite any known equalities
+
+ // XXX should profile the effects of this and the overhead.
+ // traversing the constraints looking for equalities is hardly the
+ // slowest thing we do, but it is probably nicer to have a
+ // ConstraintSet ADT which efficiently remembers obvious patterns
+ // (byte-constant comparison).
+
+ switch (e.getKind()) {
+ case Expr::Constant:
+ assert(e.getConstantValue() && "attempt to add invalid (false) constraint");
+ break;
+
+ // split to enable finer grained independence and other optimizations
+ case Expr::And: {
+ BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ addConstraintInternal(be->left);
+ addConstraintInternal(be->right);
+ break;
+ }
+
+ case Expr::Eq: {
+ BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+ if (be->left.isConstant()) {
+ ExprReplaceVisitor visitor(be->right, be->left);
+ rewriteConstraints(visitor);
+ }
+ constraints.push_back(e);
+ break;
+ }
+
+ default:
+ constraints.push_back(e);
+ break;
+ }
+}
+
+void ConstraintManager::addConstraint(ref<Expr> e) {
+ e = simplifyExpr(e);
+ addConstraintInternal(e);
+}
More information about the llvm-commits
mailing list