[llvm-commits] [klee] r72205 [2/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


Added: klee/trunk/lib/Expr/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/Expr.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/Expr.cpp (added)
+++ klee/trunk/lib/Expr/Expr.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,1122 @@
+//===-- Expr.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/Expr.h"
+
+
+#include "klee/Machine.h"
+// FIXME: This shouldn't be here.
+//#include "klee/Memory.h"
+#include "llvm/Type.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Streams.h"
+// FIXME: We shouldn't need this once fast constant support moves into
+// Core. If we need to do arithmetic, we probably want to use APInt.
+#include "klee/Internal/Support/IntEvaluation.h"
+
+#include "klee/util/ExprPPrinter.h"
+
+using namespace klee;
+using namespace llvm;
+
+namespace {
+  cl::opt<bool>
+  ConstArrayOpt("const-array-opt",
+	 cl::init(false),
+	 cl::desc("Enable various optimizations involving all-constant arrays."));
+}
+
+/***/
+
+unsigned Expr::count = 0;
+
+ref<Expr> Expr::createTempRead(const Array *array, Expr::Width w) {
+  UpdateList ul(array, true, 0);
+
+  switch (w) {
+  case Expr::Bool: 
+    return ZExtExpr::create(ReadExpr::create(ul, 
+                                             ref<Expr>(0,kMachinePointerType)),
+                            Expr::Bool);
+  case Expr::Int8: 
+    return ReadExpr::create(ul, 
+                            ref<Expr>(0,kMachinePointerType));
+  case Expr::Int16: 
+    return ConcatExpr::create(ReadExpr::create(ul, 
+                                               ref<Expr>(1,kMachinePointerType)),
+                              ReadExpr::create(ul, 
+                                               ref<Expr>(0,kMachinePointerType)));
+  case Expr::Int32: 
+    return ConcatExpr::create4(ReadExpr::create(ul, 
+                                                ref<Expr>(3,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(2,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(1,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(0,kMachinePointerType)));
+  case Expr::Int64: 
+    return ConcatExpr::create8(ReadExpr::create(ul, 
+                                                ref<Expr>(7,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(6,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(5,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(4,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(3,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(2,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(1,kMachinePointerType)),
+                               ReadExpr::create(ul, 
+                                                ref<Expr>(0,kMachinePointerType)));
+  default: assert(0 && "invalid width");
+  }
+}
+
+// returns 0 if b is structurally equal to *this
+int Expr::compare(const Expr &b) const {
+  if (this == &b) return 0;
+
+  Kind ak = getKind(), bk = b.getKind();
+  if (ak!=bk)
+    return (ak < bk) ? -1 : 1;
+
+  if (hashValue != b.hashValue) 
+    return (hashValue < b.hashValue) ? -1 : 1;
+
+  if (int res = compareContents(b)) 
+    return res;
+
+  unsigned aN = getNumKids();
+  for (unsigned i=0; i<aN; i++)
+    if (int res = getKid(i).compare(b.getKid(i)))
+      return res;
+
+  return 0;
+}
+
+void Expr::printKind(std::ostream &os, Kind k) {
+  switch(k) {
+#define X(C) case C: os << #C; break
+    X(Constant);
+    X(NotOptimized);
+    X(Read);
+    X(Select);
+    X(Concat);
+    X(Extract);
+    X(ZExt);
+    X(SExt);
+    X(Add);
+    X(Sub);
+    X(Mul);
+    X(UDiv);
+    X(SDiv);
+    X(URem);
+    X(SRem);
+    X(And);
+    X(Or);
+    X(Xor);
+    X(Shl);
+    X(LShr);
+    X(AShr);
+    X(Eq);
+    X(Ne);
+    X(Ult);
+    X(Ule);
+    X(Ugt);
+    X(Uge);
+    X(Slt);
+    X(Sle);
+    X(Sgt);
+    X(Sge);
+#undef X
+  default:
+    assert(0 && "invalid kind");
+    }
+}
+
+////////
+//
+// Simple hash functions for various kinds of Exprs
+//
+///////
+
+unsigned Expr::computeHash() {
+  unsigned res = getKind() * Expr::MAGIC_HASH_CONSTANT;
+
+  int n = getNumKids();
+  for (int i = 0; i < n; i++) {
+    res <<= 1;
+    res ^= getKid(i).hash() * Expr::MAGIC_HASH_CONSTANT;
+  }
+  
+  hashValue = res;
+  return hashValue;
+}
+
+unsigned ConstantExpr::computeHash() {
+  hashValue = Expr::hashConstant(asUInt64, width);
+  return hashValue;
+}
+
+unsigned CastExpr::computeHash() {
+  unsigned res = getWidth() * Expr::MAGIC_HASH_CONSTANT;
+  hashValue = res ^ src.hash() * Expr::MAGIC_HASH_CONSTANT;
+  return hashValue;
+}
+
+unsigned ExtractExpr::computeHash() {
+  unsigned res = offset * Expr::MAGIC_HASH_CONSTANT;
+  res ^= getWidth() * Expr::MAGIC_HASH_CONSTANT;
+  hashValue = res ^ expr.hash() * Expr::MAGIC_HASH_CONSTANT;
+  return hashValue;
+}
+
+unsigned ReadExpr::computeHash() {
+  unsigned res = index.hash() * Expr::MAGIC_HASH_CONSTANT;
+  res ^= updates.hash();
+  hashValue = res;
+  return hashValue;
+}
+
+uint64_t Expr::getConstantValue() const {
+  assert(getKind() == Constant);
+  return static_cast<const ConstantExpr*>(this)->asUInt64;
+}
+
+ref<Expr> Expr::createFromKind(Kind k, std::vector<CreateArg> args) {
+  unsigned numArgs = args.size();
+  
+  switch(k) {
+    case NotOptimized:
+      assert(numArgs == 1 && args[0].isExpr() &&
+             "invalid args array for given opcode");
+      return NotOptimizedExpr::create(args[0].expr);
+      
+    case Select:
+      assert(numArgs == 3 && args[0].isExpr() &&
+             args[1].isExpr() && args[2].isExpr() &&
+             "invalid args array for Select opcode");
+      return SelectExpr::create(args[0].expr,
+                                args[1].expr,
+                                args[2].expr);
+
+    case Concat: {
+      assert(numArgs == 2 && args[0].isExpr() && args[1].isExpr() && 
+             "invalid args array for Concat opcode");
+      
+      return ConcatExpr::create(args[0].expr, args[1].expr);
+    }
+      
+#define CAST_EXPR_CASE(T)                                    \
+      case T:                                                \
+        assert(numArgs == 2 &&				     \
+               args[0].isExpr() && args[1].isWidth() &&      \
+               "invalid args array for given opcode");       \
+      return T ## Expr::create(args[0].expr, args[1].width); \
+      
+#define BINARY_EXPR_CASE(T)                                 \
+      case T:                                               \
+        assert(numArgs == 2 &&                              \
+               args[0].isExpr() && args[1].isExpr() &&      \
+               "invalid args array for given opcode");      \
+      return T ## Expr::create(args[0].expr, args[1].expr); \
+
+      CAST_EXPR_CASE(ZExt);
+      CAST_EXPR_CASE(SExt);
+      
+      BINARY_EXPR_CASE(Add);
+      BINARY_EXPR_CASE(Sub);
+      BINARY_EXPR_CASE(Mul);
+      BINARY_EXPR_CASE(UDiv);
+      BINARY_EXPR_CASE(SDiv);
+      BINARY_EXPR_CASE(URem);
+      BINARY_EXPR_CASE(SRem);
+      BINARY_EXPR_CASE(And);
+      BINARY_EXPR_CASE(Or);
+      BINARY_EXPR_CASE(Xor);
+      BINARY_EXPR_CASE(Shl);
+      BINARY_EXPR_CASE(LShr);
+      BINARY_EXPR_CASE(AShr);
+      
+      BINARY_EXPR_CASE(Eq);
+      BINARY_EXPR_CASE(Ne);
+      BINARY_EXPR_CASE(Ult);
+      BINARY_EXPR_CASE(Ule);
+      BINARY_EXPR_CASE(Ugt);
+      BINARY_EXPR_CASE(Uge);
+      BINARY_EXPR_CASE(Slt);
+      BINARY_EXPR_CASE(Sle);
+      BINARY_EXPR_CASE(Sgt);
+      BINARY_EXPR_CASE(Sge);
+
+    case Constant:
+    case Extract:
+    case Read:
+    default:
+      assert(0 && "invalid kind");
+  }
+
+}
+
+
+void Expr::printWidth(std::ostream &os, Width width) {
+  switch(width) {
+  case Expr::Bool: os << "Expr::Bool"; break;
+  case Expr::Int8: os << "Expr::Int8"; break;
+  case Expr::Int16: os << "Expr::Int16"; break;
+  case Expr::Int32: os << "Expr::Int32"; break;
+  case Expr::Int64: os << "Expr::Int64"; break;
+  default: os << "<invalid type: " << (unsigned) width << ">";
+  }
+}
+
+Expr::Width Expr::getWidthForLLVMType(const llvm::Type *t) {
+  switch (t->getTypeID()) {
+  case llvm::Type::IntegerTyID: {
+    Width w = cast<IntegerType>(t)->getBitWidth();
+
+    // should remove this limitation soon
+    if (w == 1 || w == 8 || w == 16 || w == 32 || w == 64)
+      return w;
+    else {
+      assert(0 && "XXX arbitrary bit widths unsupported");
+      abort();
+    }
+  }
+  case llvm::Type::FloatTyID: return Expr::Int32;
+  case llvm::Type::DoubleTyID: return Expr::Int64;
+  case llvm::Type::X86_FP80TyID: return Expr::Int64; // XXX: needs to be fixed
+  case llvm::Type::PointerTyID: return kMachinePointerType;
+  default:
+    cerr << "non-primitive type argument to Expr::getTypeForLLVMType()\n";
+    abort();
+  }
+}
+
+ref<Expr> Expr::createImplies(ref<Expr> hyp, ref<Expr> conc) {
+  return OrExpr::create(Expr::createNot(hyp), conc);
+}
+
+ref<Expr> Expr::createIsZero(ref<Expr> e) {
+  return EqExpr::create(e, ConstantExpr::create(0, e.getWidth()));
+}
+
+ref<Expr> Expr::createCoerceToPointerType(ref<Expr> e) {
+  return ZExtExpr::create(e, kMachinePointerType);
+}
+
+ref<Expr> Expr::createNot(ref<Expr> e) {
+  return createIsZero(e);
+}
+
+ref<Expr> Expr::createPointer(uint64_t v) {
+  return ConstantExpr::create(v, kMachinePointerType);
+}
+
+Expr* Expr::createConstant(uint64_t val, Width w) {
+  Expr *r = new ConstantExpr(val, w);
+  r->computeHash();
+  return r;
+}
+
+void Expr::print(std::ostream &os) const {
+  const ref<Expr> tmp((Expr*)this);
+  ExprPPrinter::printOne(os, "", tmp);
+}
+
+/***/
+
+ref<ConstantExpr> ConstantExpr::fromMemory(void *address, Width width) {
+  switch (width) {
+  case  Expr::Bool: return ConstantExpr::create(*(( uint8_t*) address), width);
+  case  Expr::Int8: return ConstantExpr::create(*(( uint8_t*) address), width);
+  case Expr::Int16: return ConstantExpr::create(*((uint16_t*) address), width);
+  case Expr::Int32: return ConstantExpr::create(*((uint32_t*) address), width);
+  case Expr::Int64: return ConstantExpr::create(*((uint64_t*) address), width);
+  default: assert(0 && "invalid type");
+  }
+}
+
+void ConstantExpr::toMemory(void *address) {
+  switch (width) {
+  case  Expr::Bool: *(( uint8_t*) address) = asUInt64; break;
+  case  Expr::Int8: *(( uint8_t*) address) = asUInt64; break;
+  case Expr::Int16: *((uint16_t*) address) = asUInt64; break;
+  case Expr::Int32: *((uint32_t*) address) = asUInt64; break;
+  case Expr::Int64: *((uint64_t*) address) = asUInt64; break;
+  default: assert(0 && "invalid type");
+  }
+}
+
+/***/
+
+ref<Expr>  NotOptimizedExpr::create(ref<Expr> src) {
+  return NotOptimizedExpr::alloc(src);
+}
+
+ref<Expr> ReadExpr::create(const UpdateList &ul, ref<Expr> index) {
+  // rollback index when possible... 
+
+  // XXX this doesn't really belong here... there are basically two
+  // cases, one is rebuild, where we want to optimistically try various
+  // optimizations when the index has changed, and the other is 
+  // initial creation, where we expect the ObjectState to have constructed
+  // a smart UpdateList so it is not worth rescanning.
+
+  const UpdateNode *un = ul.head;
+  for (; un; un=un->next) {
+    ref<Expr> cond = EqExpr::create(index, un->index);
+    
+    if (cond.isConstant()) {
+      if (cond.getConstantValue())
+        return un->value;
+    } else {
+      break;
+    }
+  }
+
+  return ReadExpr::alloc(ul, index);
+}
+
+int ReadExpr::compareContents(const Expr &b) const { 
+  return updates.compare(static_cast<const ReadExpr&>(b).updates);
+}
+
+ref<Expr> SelectExpr::create(ref<Expr> c, ref<Expr> t, ref<Expr> f) {
+  Expr::Width kt = t.getWidth();
+
+  assert(c.getWidth()==Bool && "type mismatch");
+  assert(kt==f.getWidth() && "type mismatch");
+
+  if (c.isConstant()) {
+    return c.getConstantValue() ? t : f;
+  } else if (t==f) {
+    return t;
+  } else if (kt==Expr::Bool) { // c ? t : f  <=> (c and t) or (not c and f)
+    if (t.isConstant()) {      
+      if (t.getConstantValue()) {
+        return OrExpr::create(c, f);
+      } else {
+        return AndExpr::create(Expr::createNot(c), f);
+      }
+    } else if (f.isConstant()) {
+      if (f.getConstantValue()) {
+        return OrExpr::create(Expr::createNot(c), t);
+      } else {
+        return AndExpr::create(c, t);
+      }
+    }
+  }
+  
+  return SelectExpr::alloc(c, t, f);
+}
+
+/***/
+
+
+ref<Expr> ConcatExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
+  Expr::Width w = l.getWidth() + r.getWidth();
+  
+  /* Constant folding */
+  if (l.getKind() == Expr::Constant && r.getKind() == Expr::Constant) {
+    // XXX: should fix this constant limitation soon
+    assert(w <= 64 && "ConcatExpr::create(): don't support concats describing constants greater than 64 bits yet");
+    
+    uint64_t res = (l.getConstantValue() << r.getWidth()) + r.getConstantValue();
+    return ConstantExpr::create(res, w);
+  }
+
+  // Merge contiguous Extracts
+  if (l.getKind() == Expr::Extract && r.getKind() == Expr::Extract) {
+    const ExtractExpr* ee_left = static_ref_cast<ExtractExpr>(l);
+    const ExtractExpr* ee_right = static_ref_cast<ExtractExpr>(r);
+    if (ee_left->expr == ee_right->expr &&
+	ee_right->offset + ee_right->width == ee_left->offset) {
+      return ExtractExpr::create(ee_left->expr, ee_right->offset, w);
+    }
+  }
+
+  return ConcatExpr::alloc(l, r);
+}
+
+/// Shortcut to concat N kids.  The chain returned is unbalanced to the right
+ref<Expr> ConcatExpr::createN(unsigned n_kids, const ref<Expr> kids[]) {
+  assert(n_kids > 0);
+  if (n_kids == 1)
+    return kids[0];
+  
+  ref<Expr> r = ConcatExpr::create(kids[n_kids-2], kids[n_kids-1]);
+  for (int i=n_kids-3; i>=0; i--)
+    r = ConcatExpr::create(kids[i], r);
+  return r;
+}
+
+/// Shortcut to concat 4 kids.  The chain returned is unbalanced to the right
+ref<Expr> ConcatExpr::create4(const ref<Expr> &kid1, const ref<Expr> &kid2,
+				     const ref<Expr> &kid3, const ref<Expr> &kid4) {
+  return ConcatExpr::create(kid1, ConcatExpr::create(kid2, ConcatExpr::create(kid3, kid4)));
+}
+
+/// Shortcut to concat 8 kids.  The chain returned is unbalanced to the right
+ref<Expr> ConcatExpr::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) {
+  return ConcatExpr::create(kid1, ConcatExpr::create(kid2, ConcatExpr::create(kid3, 
+			      ConcatExpr::create(kid4, ConcatExpr::create4(kid5, kid6, kid7, kid8)))));
+}
+
+/***/
+
+ref<Expr> ExtractExpr::create(ref<Expr> expr, unsigned off, Width w) {
+  unsigned kw = expr.getWidth();
+  assert(w > 0 && off + w <= kw && "invalid extract");
+  
+  if (w == kw)
+    return expr;
+  else if (expr.isConstant()) {
+    return ConstantExpr::create(ints::trunc(expr.getConstantValue() >> off, w, kw), w);
+  } 
+  else 
+    // Extract(Concat)
+    if (ConcatExpr *ce = dyn_ref_cast<ConcatExpr>(expr)) {
+      // if the extract skips the right side of the concat
+      if (off >= ce->getRight().getWidth())
+	return ExtractExpr::create(ce->getLeft(), off - ce->getRight().getWidth(), w);
+      
+      // if the extract skips the left side of the concat
+      if (off + w <= ce->getRight().getWidth())
+	return ExtractExpr::create(ce->getRight(), off, w);
+
+      // E(C(x,y)) = C(E(x), E(y))
+      return ConcatExpr::create(ExtractExpr::create(ce->getKid(0), 0, w - ce->getKid(1).getWidth() + off),
+				ExtractExpr::create(ce->getKid(1), off, ce->getKid(1).getWidth() - off));
+    }
+  
+  return ExtractExpr::alloc(expr, off, w);
+}
+
+
+ref<Expr> ExtractExpr::createByteOff(ref<Expr> expr, unsigned offset, Width bits) {
+  return ExtractExpr::create(expr, 8*offset, bits);
+}
+
+/***/
+
+ref<Expr> ZExtExpr::create(const ref<Expr> &e, Width w) {
+  unsigned kBits = e.getWidth();
+  if (w == kBits) {
+    return e;
+  } else if (w < kBits) { // trunc
+    return ExtractExpr::createByteOff(e, 0, w);
+  } else {
+    if (e.isConstant()) {
+      return ConstantExpr::create(ints::zext(e.getConstantValue(), w, kBits),
+                                  w);
+    }
+    
+    return ZExtExpr::alloc(e, w);
+  }
+}
+
+ref<Expr> SExtExpr::create(const ref<Expr> &e, Width w) {
+  unsigned kBits = e.getWidth();
+  if (w == kBits) {
+    return e;
+  } else if (w < kBits) { // trunc
+    return ExtractExpr::createByteOff(e, 0, w);
+  } else {
+    if (e.isConstant()) {
+      return ConstantExpr::create(ints::sext(e.getConstantValue(), w, kBits),
+                                  w);
+    }
+    
+    return SExtExpr::alloc(e, w);
+  }
+}
+
+/***/
+
+static ref<Expr> AndExpr_create(Expr *l, Expr *r);
+static ref<Expr> XorExpr_create(Expr *l, Expr *r);
+
+static ref<Expr> EqExpr_createPartial(Expr *l, const ref<Expr> &cr);
+static ref<Expr> AndExpr_createPartialR(const ref<Expr> &cl, Expr *r);
+static ref<Expr> SubExpr_createPartialR(const ref<Expr> &cl, Expr *r);
+static ref<Expr> XorExpr_createPartialR(const ref<Expr> &cl, Expr *r);
+
+static ref<Expr> AddExpr_createPartialR(const ref<Expr> &cl, Expr *r) {
+  assert(cl.isConstant() && "non-constant passed in place of constant");
+  uint64_t value = cl.getConstantValue();
+  Expr::Width type = cl.getWidth();
+
+  if (type==Expr::Bool) {
+    return XorExpr_createPartialR(cl, r);
+  } else if (!value) {
+    return r;
+  } else {
+    Expr::Kind rk = r->getKind();
+    if (rk==Expr::Add && r->getKid(0).isConstant()) { // A + (B+c) == (A+B) + c
+      return AddExpr::create(AddExpr::create(cl, r->getKid(0)),
+                             r->getKid(1));
+    } else if (rk==Expr::Sub && r->getKid(0).isConstant()) { // A + (B-c) == (A+B) - c
+      return SubExpr::create(AddExpr::create(cl, r->getKid(0)),
+                             r->getKid(1));
+    } else {
+      return AddExpr::alloc(cl, r);
+    }
+  }
+}
+static ref<Expr> AddExpr_createPartial(Expr *l, const ref<Expr> &cr) {
+  return AddExpr_createPartialR(cr, l);
+}
+static ref<Expr> AddExpr_create(Expr *l, Expr *r) {
+  Expr::Width type = l->getWidth();
+
+  if (type == Expr::Bool) {
+    return XorExpr_create(l, r);
+  } else {
+    Expr::Kind lk = l->getKind(), rk = r->getKind();
+    if (lk==Expr::Add && l->getKid(0).isConstant()) { // (k+a)+b = k+(a+b)
+      return AddExpr::create(l->getKid(0),
+                             AddExpr::create(l->getKid(1), r));
+    } else if (lk==Expr::Sub && l->getKid(0).isConstant()) { // (k-a)+b = k+(b-a)
+      return AddExpr::create(l->getKid(0),
+                             SubExpr::create(r, l->getKid(1)));
+    } else if (rk==Expr::Add && r->getKid(0).isConstant()) { // a + (k+b) = k+(a+b)
+      return AddExpr::create(r->getKid(0),
+                             AddExpr::create(l, r->getKid(1)));
+    } else if (rk==Expr::Sub && r->getKid(0).isConstant()) { // a + (k-b) = k+(a-b)
+      return AddExpr::create(r->getKid(0),
+                             SubExpr::create(l, r->getKid(1)));
+    } else {
+      return AddExpr::alloc(l, r);
+    }
+  }  
+}
+
+static ref<Expr> SubExpr_createPartialR(const ref<Expr> &cl, Expr *r) {
+  assert(cl.isConstant() && "non-constant passed in place of constant");
+  Expr::Width type = cl.getWidth();
+
+  if (type==Expr::Bool) {
+    return XorExpr_createPartialR(cl, r);
+  } else {
+    Expr::Kind rk = r->getKind();
+    if (rk==Expr::Add && r->getKid(0).isConstant()) { // A - (B+c) == (A-B) - c
+      return SubExpr::create(SubExpr::create(cl, r->getKid(0)),
+                             r->getKid(1));
+    } else if (rk==Expr::Sub && r->getKid(0).isConstant()) { // A - (B-c) == (A-B) + c
+      return AddExpr::create(SubExpr::create(cl, r->getKid(0)),
+                             r->getKid(1));
+    } else {
+      return SubExpr::alloc(cl, r);
+    }
+  }
+}
+static ref<Expr> SubExpr_createPartial(Expr *l, const ref<Expr> &cr) {
+  assert(cr.isConstant() && "non-constant passed in place of constant");
+  uint64_t value = cr.getConstantValue();
+  Expr::Width width = cr.getWidth();
+  uint64_t nvalue = ints::sub(0, value, width);
+
+  return AddExpr_createPartial(l, ConstantExpr::create(nvalue, width));
+}
+static ref<Expr> SubExpr_create(Expr *l, Expr *r) {
+  Expr::Width type = l->getWidth();
+
+  if (type == Expr::Bool) {
+    return XorExpr_create(l, r);
+  } else if (*l==*r) {
+    return ref<Expr>(0, type);
+  } else {
+    Expr::Kind lk = l->getKind(), rk = r->getKind();
+    if (lk==Expr::Add && l->getKid(0).isConstant()) { // (k+a)-b = k+(a-b)
+      return AddExpr::create(l->getKid(0),
+                             SubExpr::create(l->getKid(1), r));
+    } else if (lk==Expr::Sub && l->getKid(0).isConstant()) { // (k-a)-b = k-(a+b)
+      return SubExpr::create(l->getKid(0),
+                             AddExpr::create(l->getKid(1), r));
+    } else if (rk==Expr::Add && r->getKid(0).isConstant()) { // a - (k+b) = (a-c) - k
+      return SubExpr::create(SubExpr::create(l, r->getKid(1)),
+                             r->getKid(0));
+    } else if (rk==Expr::Sub && r->getKid(0).isConstant()) { // a - (k-b) = (a+b) - k
+      return SubExpr::create(AddExpr::create(l, r->getKid(1)),
+                             r->getKid(0));
+    } else {
+      return SubExpr::alloc(l, r);
+    }
+  }  
+}
+
+static ref<Expr> MulExpr_createPartialR(const ref<Expr> &cl, Expr *r) {
+  assert(cl.isConstant() && "non-constant passed in place of constant");
+  uint64_t value = cl.getConstantValue();
+  Expr::Width type = cl.getWidth();
+
+  if (type == Expr::Bool) {
+    return AndExpr_createPartialR(cl, r);
+  } else if (value == 1) {
+    return r;
+  } else if (!value) {
+    return cl;
+  } else {
+    return MulExpr::alloc(cl, r);
+  }
+}
+static ref<Expr> MulExpr_createPartial(Expr *l, const ref<Expr> &cr) {
+  return MulExpr_createPartialR(cr, l);
+}
+static ref<Expr> MulExpr_create(Expr *l, Expr *r) {
+  Expr::Width type = l->getWidth();
+  
+  if (type == Expr::Bool) {
+    return AndExpr::alloc(l, r);
+  } else {
+    return MulExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> AndExpr_createPartial(Expr *l, const ref<Expr> &cr) {
+  assert(cr.isConstant() && "non-constant passed in place of constant");
+  uint64_t value = cr.getConstantValue();
+  Expr::Width width = cr.getWidth();;
+
+  if (value==ints::sext(1, width, 1)) {
+    return l;
+  } else if (!value) {
+    return cr;
+  } else {
+    return AndExpr::alloc(l, cr);
+  }
+}
+static ref<Expr> AndExpr_createPartialR(const ref<Expr> &cl, Expr *r) {
+  return AndExpr_createPartial(r, cl);
+}
+static ref<Expr> AndExpr_create(Expr *l, Expr *r) {
+  return AndExpr::alloc(l, r);
+}
+
+static ref<Expr> OrExpr_createPartial(Expr *l, const ref<Expr> &cr) {
+  assert(cr.isConstant() && "non-constant passed in place of constant");
+  uint64_t value = cr.getConstantValue();
+  Expr::Width width = cr.getWidth();
+
+  if (value == ints::sext(1, width, 1)) {
+    return cr;
+  } else if (!value) {
+    return l;
+  } else {
+    return OrExpr::alloc(l, cr);
+  }
+}
+static ref<Expr> OrExpr_createPartialR(const ref<Expr> &cl, Expr *r) {
+  return OrExpr_createPartial(r, cl);
+}
+static ref<Expr> OrExpr_create(Expr *l, Expr *r) {
+  return OrExpr::alloc(l, r);
+}
+
+static ref<Expr> XorExpr_createPartialR(const ref<Expr> &cl, Expr *r) {
+  assert(cl.isConstant() && "non-constant passed in place of constant");
+  uint64_t value = cl.getConstantValue();
+  Expr::Width type = cl.getWidth();
+
+  if (type==Expr::Bool) {
+    if (value) {
+      return EqExpr_createPartial(r, ConstantExpr::create(0, Expr::Bool));
+    } else {
+      return r;
+    }
+  } else if (!value) {
+    return r;
+  } else {
+    return XorExpr::alloc(cl, r);
+  }
+}
+
+static ref<Expr> XorExpr_createPartial(Expr *l, const ref<Expr> &cr) {
+  return XorExpr_createPartialR(cr, l);
+}
+static ref<Expr> XorExpr_create(Expr *l, Expr *r) {
+  return XorExpr::alloc(l, r);
+}
+
+static ref<Expr> UDivExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // r must be 1
+    return l;
+  } else{
+    return UDivExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> SDivExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // r must be 1
+    return l;
+  } else{
+    return SDivExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> URemExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // r must be 1
+    return ConstantExpr::create(0, Expr::Bool);
+  } else{
+    return URemExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> SRemExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // r must be 1
+    return ConstantExpr::create(0, Expr::Bool);
+  } else{
+    return SRemExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> ShlExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // l & !r
+    return AndExpr::create(l, Expr::createNot(r));
+  } else{
+    return ShlExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> LShrExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // l & !r
+    return AndExpr::create(l, Expr::createNot(r));
+  } else{
+    return LShrExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> AShrExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // l
+    return l;
+  } else{
+    return AShrExpr::alloc(l, r);
+  }
+}
+
+#define BCREATE_R(_e_op, _op, partialL, partialR) \
+ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
+  assert(l.getWidth()==r.getWidth() && "type mismatch"); \
+  if (l.isConstant()) {                                \
+    if (r.isConstant()) {                              \
+      Expr::Width width = l.getWidth(); \
+      uint64_t val = ints::_op(l.getConstantValue(),  \
+                               r.getConstantValue(), width);  \
+      return ConstantExpr::create(val, width); \
+    } else { \
+      return _e_op ## _createPartialR(l, r.get()); \
+    } \
+  } else if (r.isConstant()) {             \
+    return _e_op ## _createPartial(l.get(), r); \
+  } \
+  return _e_op ## _create(l.get(), r.get()); \
+}
+
+#define BCREATE(_e_op, _op) \
+ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
+  assert(l.getWidth()==r.getWidth() && "type mismatch"); \
+  if (l.isConstant()) {                                \
+    if (r.isConstant()) {                              \
+      Expr::Width width = l.getWidth(); \
+      uint64_t val = ints::_op(l.getConstantValue(), \
+                               r.getConstantValue(), width);  \
+      return ConstantExpr::create(val, width); \
+    } \
+  } \
+  return _e_op ## _create(l, r);                    \
+}
+
+BCREATE_R(AddExpr, add, AddExpr_createPartial, AddExpr_createPartialR)
+BCREATE_R(SubExpr, sub, SubExpr_createPartial, SubExpr_createPartialR)
+BCREATE_R(MulExpr, mul, MulExpr_createPartial, MulExpr_createPartialR)
+BCREATE_R(AndExpr, land, AndExpr_createPartial, AndExpr_createPartialR)
+BCREATE_R(OrExpr, lor, OrExpr_createPartial, OrExpr_createPartialR)
+BCREATE_R(XorExpr, lxor, XorExpr_createPartial, XorExpr_createPartialR)
+BCREATE(UDivExpr, udiv)
+BCREATE(SDivExpr, sdiv)
+BCREATE(URemExpr, urem)
+BCREATE(SRemExpr, srem)
+BCREATE(ShlExpr, shl)
+BCREATE(LShrExpr, lshr)
+BCREATE(AShrExpr, ashr)
+
+#define CMPCREATE(_e_op, _op) \
+ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
+  assert(l.getWidth()==r.getWidth() && "type mismatch"); \
+  if (l.isConstant()) {                                \
+    if (r.isConstant()) {                              \
+      Expr::Width width = l.getWidth(); \
+      uint64_t val = ints::_op(l.getConstantValue(), \
+                               r.getConstantValue(), width);  \
+      return ConstantExpr::create(val, Expr::Bool); \
+    } \
+  } \
+  return _e_op ## _create(l, r);                    \
+}
+
+#define CMPCREATE_T(_e_op, _op, _reflexive_e_op, partialL, partialR) \
+ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
+  assert(l.getWidth()==r.getWidth() && "type mismatch"); \
+  if (l.isConstant()) {                                \
+    if (r.isConstant()) {                              \
+      Expr::Width width = l.getWidth(); \
+      uint64_t val = ints::_op(l.getConstantValue(), \
+                               r.getConstantValue(), width);  \
+      return ConstantExpr::create(val, Expr::Bool); \
+    } else { \
+      return partialR(l, r.get()); \
+    } \
+  } else if (r.isConstant()) {                  \
+    return partialL(l.get(), r); \
+  } else { \
+    return _e_op ## _create(l.get(), r.get()); \
+  } \
+}
+  
+
+static ref<Expr> EqExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l == r) {
+    return ref<Expr>(1, Expr::Bool);
+  } else {
+    return EqExpr::alloc(l, r);
+  }
+}
+
+
+/// Tries to optimize EqExpr cl == rd, where cl is a ConstantExpr and
+/// rd a ReadExpr.  If rd is a read into an all-constant array,
+/// returns a disjunction of equalities on the index.  Otherwise,
+/// returns the initial equality expression. 
+static ref<Expr> TryConstArrayOpt(const ref<Expr> &cl, 
+				  ReadExpr *rd) {
+  assert(cl.isConstant() && "constant expression required");
+  assert(rd->getKind() == Expr::Read && "read expression required");
+  
+  uint64_t ct = cl.getConstantValue();
+  ref<Expr> first_idx_match;
+
+  // number of positions in the array that contain value ct
+  unsigned matches = 0;
+
+  //llvm::cerr << "Size updates/root: " << rd->updates.getSize() << " / " << (rd->updates.root)->size << "\n";
+
+  // for now, just assume standard "flushing" of a concrete array,
+  // where the concrete array has one update for each index, in order
+  bool all_const = true;
+  if (rd->updates.getSize() == rd->updates.root->size) {
+    unsigned k = rd->updates.getSize();
+    for (const UpdateNode *un = rd->updates.head; un; un = un->next) {
+      assert(k > 0);
+      k--;
+
+      ref<Expr> idx = un->index;
+      ref<Expr> val = un->value;
+      if (!idx.isConstant() || !val.isConstant()) {
+	all_const = false;
+	//llvm::cerr << "Idx or val not constant\n";
+	break;
+      }
+      else {
+	if (idx.getConstantValue() != k) {
+	  all_const = false;
+	  //llvm::cerr << "Wrong constant\n";
+	  break;
+	}
+	if (val.getConstantValue() == ct) {
+	  matches++;
+	  if (matches == 1)
+	    first_idx_match = un->index;
+	}
+      }
+    }
+  }
+  else all_const = false;
+  
+  if (all_const && matches <= 100) {
+    // apply optimization
+    //llvm::cerr << "\n\n=== Applying const array optimization ===\n\n";
+
+    if (matches == 0)
+      return ref<Expr>(0, Expr::Bool);
+
+    ref<Expr> res = EqExpr::create(first_idx_match, rd->index);
+    if (matches == 1)
+      return res;
+    
+    for (const UpdateNode *un = rd->updates.head; un; un = un->next) {
+      if (un->index != first_idx_match && un->value.getConstantValue() == ct) {
+	ref<Expr> curr_eq = EqExpr::create(un->index, rd->index);
+	res = OrExpr::create(curr_eq, res);
+      }
+    }
+    
+    return res;
+  }
+
+  return EqExpr_create(cl, ref<Expr>(rd));
+}
+
+
+static ref<Expr> EqExpr_createPartialR(const ref<Expr> &cl, Expr *r) {  
+  assert(cl.isConstant() && "non-constant passed in place of constant");
+  uint64_t value = cl.getConstantValue();
+  Expr::Width width = cl.getWidth();
+
+  Expr::Kind rk = r->getKind();
+  if (width == Expr::Bool) {
+    if (value) {
+      return r;
+    } else {
+      // 0 != ...
+      
+      if (rk == Expr::Eq) {
+        const EqExpr *ree = static_ref_cast<EqExpr>(r);
+
+        // eliminate double negation
+        if (ree->left.isConstant() &&
+            ree->left.getWidth()==Expr::Bool) {
+          assert(!ree->left.getConstantValue());
+          return ree->right;
+        }
+      } else if (rk == Expr::Or) {
+        const OrExpr *roe = static_ref_cast<OrExpr>(r);
+
+        // transform not(or(a,b)) to and(not a, not b)
+        return AndExpr::create(Expr::createNot(roe->left),
+                               Expr::createNot(roe->right));
+      }
+    }
+  } else if (rk == Expr::SExt) {
+    // (sext(a,T)==c) == (a==c)
+    const SExtExpr *see = static_ref_cast<SExtExpr>(r);
+    Expr::Width fromBits = see->src.getWidth();
+    uint64_t trunc = bits64::truncateToNBits(value, fromBits);
+
+    // pathological check, make sure it is possible to
+    // sext to this value *from any value*
+    if (value == ints::sext(trunc, width, fromBits)) {
+      return EqExpr::create(see->src, ConstantExpr::create(trunc, fromBits));
+    } else {
+      return ConstantExpr::create(0, Expr::Bool);
+    }
+  } else if (rk == Expr::ZExt) {
+    // (zext(a,T)==c) == (a==c)
+    const ZExtExpr *zee = static_ref_cast<ZExtExpr>(r);
+    Expr::Width fromBits = zee->src.getWidth();
+    uint64_t trunc = bits64::truncateToNBits(value, fromBits);
+    
+    // pathological check, make sure it is possible to
+    // zext to this value *from any value*
+    if (value == ints::zext(trunc, width, fromBits)) {
+      return EqExpr::create(zee->src, ConstantExpr::create(trunc, fromBits));
+    } else {
+      return ConstantExpr::create(0, Expr::Bool);
+    }
+  } else if (rk==Expr::Add) {
+    const AddExpr *ae = static_ref_cast<AddExpr>(r);
+    if (ae->left.isConstant()) {
+      // c0 = c1 + b => c0 - c1 = b
+      return EqExpr_createPartialR(SubExpr::create(cl, ae->left),
+                                   ae->right.get());
+    }
+  } else if (rk==Expr::Sub) {
+    const SubExpr *se = static_ref_cast<SubExpr>(r);
+    if (se->left.isConstant()) {
+      // c0 = c1 - b => c1 - c0 = b
+      return EqExpr_createPartialR(SubExpr::create(se->left, cl),
+                                   se->right.get());
+    }
+  } else if (rk == Expr::Read && ConstArrayOpt) {
+    return TryConstArrayOpt(cl, static_cast<ReadExpr*>(r));
+  }
+    
+  return EqExpr_create(cl, r);
+}
+
+static ref<Expr> EqExpr_createPartial(Expr *l, const ref<Expr> &cr) {  
+  return EqExpr_createPartialR(cr, l);
+}
+  
+ref<Expr> NeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
+  return EqExpr::create(ConstantExpr::create(0, Expr::Bool),
+                        EqExpr::create(l, r));
+}
+
+ref<Expr> UgtExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
+  return UltExpr::create(r, l);
+}
+ref<Expr> UgeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
+  return UleExpr::create(r, l);
+}
+
+ref<Expr> SgtExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
+  return SltExpr::create(r, l);
+}
+ref<Expr> SgeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
+  return SleExpr::create(r, l);
+}
+
+static ref<Expr> UltExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  Expr::Width t = l.getWidth();
+  if (t == Expr::Bool) { // !l && r
+    return AndExpr::create(Expr::createNot(l), r);
+  } else {
+    if (r.isConstant()) {      
+      uint64_t value = r.getConstantValue();
+      if (value <= 8) {
+        ref<Expr> res(0,Expr::Bool);
+        for (unsigned i=0; i<value; i++) {
+          res = OrExpr::create(EqExpr::create(l, ref<Expr>(i,t)), res);
+        }
+        //        llvm::cerr << l << "<" << r << "  <=>  " << res << "\n";
+        return res;
+      }
+    }
+    return UltExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> UleExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // !(l && !r)
+    return OrExpr::create(Expr::createNot(l), r);
+  } else {
+    return UleExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> SltExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // l && !r
+    return AndExpr::create(l, Expr::createNot(r));
+  } else {
+    return SltExpr::alloc(l, r);
+  }
+}
+
+static ref<Expr> SleExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
+  if (l.getWidth() == Expr::Bool) { // !(!l && r)
+    return OrExpr::create(l, Expr::createNot(r));
+  } else {
+    return SleExpr::alloc(l, r);
+  }
+}
+
+CMPCREATE_T(EqExpr, eq, EqExpr, EqExpr_createPartial, EqExpr_createPartialR)
+CMPCREATE(UltExpr, ult)
+CMPCREATE(UleExpr, ule)
+CMPCREATE(SltExpr, slt)
+CMPCREATE(SleExpr, sle)

Added: klee/trunk/lib/Expr/ExprEvaluator.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/ExprEvaluator.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/ExprEvaluator.cpp (added)
+++ klee/trunk/lib/Expr/ExprEvaluator.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,74 @@
+//===-- ExprEvaluator.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/util/ExprEvaluator.h"
+
+using namespace klee;
+
+ExprVisitor::Action ExprEvaluator::evalRead(const UpdateList &ul,
+                                            unsigned index) {
+  for (const UpdateNode *un=ul.head; un; un=un->next) {
+    ref<Expr> ui = visit(un->index);
+    
+    if (ui.isConstant()) {
+      if (ui.getConstantValue() == index)
+        return Action::changeTo(visit(un->value));
+    } else {
+      // update index is unknown, so may or may not be index, we
+      // cannot guarantee value. we can rewrite to read at this
+      // version though (mostly for debugging).
+      
+      UpdateList fwd(ul.root, un, 0);
+      return Action::changeTo(ReadExpr::create(fwd, 
+                                               ref<Expr>(index,Expr::Int32)));
+    }
+  }
+  
+  return Action::changeTo(getInitialValue(*ul.root, index));
+}
+
+ExprVisitor::Action ExprEvaluator::visitRead(const ReadExpr &re) {
+  ref<Expr> v = visit(re.index);
+  
+  if (v.isConstant()) {
+    return evalRead(re.updates, v.getConstantValue());
+  } else {
+    return Action::doChildren();
+  }
+}
+
+// we need to check for div by zero during partial evaluation,
+// if this occurs then simply ignore the 0 divisor and use the
+// original expression.
+ExprVisitor::Action ExprEvaluator::protectedDivOperation(const BinaryExpr &e) {
+  ref<Expr> kids[2] = { visit(e.left),
+                        visit(e.right) };
+
+  if (kids[1].isConstant() && !kids[1].getConstantValue())
+    kids[1] = e.right;
+
+  if (kids[0]!=e.left || kids[1]!=e.right) {
+    return Action::changeTo(e.rebuild(kids));
+  } else {
+    return Action::skipChildren();
+  }
+}
+
+ExprVisitor::Action ExprEvaluator::visitUDiv(const UDivExpr &e) { 
+  return protectedDivOperation(e); 
+}
+ExprVisitor::Action ExprEvaluator::visitSDiv(const SDivExpr &e) { 
+  return protectedDivOperation(e); 
+}
+ExprVisitor::Action ExprEvaluator::visitURem(const URemExpr &e) { 
+  return protectedDivOperation(e); 
+}
+ExprVisitor::Action ExprEvaluator::visitSRem(const SRemExpr &e) { 
+  return protectedDivOperation(e); 
+}

Added: klee/trunk/lib/Expr/ExprPPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/ExprPPrinter.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/ExprPPrinter.cpp (added)
+++ klee/trunk/lib/Expr/ExprPPrinter.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,478 @@
+//===-- ExprPPrinter.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/util/ExprPPrinter.h"
+
+#include "klee/Constraints.h"
+
+#include "llvm/Support/CommandLine.h"
+
+#include <map>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+using namespace klee;
+
+namespace {
+  llvm::cl::opt<bool>
+  PCWidthAsArg("pc-width-as-arg", llvm::cl::init(true));
+
+  llvm::cl::opt<bool>
+  PCAllWidths("pc-all-widths", llvm::cl::init(false));
+
+  llvm::cl::opt<bool>
+  PCPrefixWidth("pc-prefix-width", llvm::cl::init(true));
+
+  llvm::cl::opt<bool>
+  PCMultibyteReads("pc-multibyte-reads", llvm::cl::init(true));
+
+  llvm::cl::opt<bool>
+  PCAllConstWidths("pc-all-const-widths",  llvm::cl::init(false));
+}
+
+/// PrintContext - Helper class for storing extra information for
+/// the pretty printer.
+class PrintContext {
+private:
+  std::ostream &os;
+  std::stringstream ss;
+  std::string newline;
+
+public:
+  /// Number of characters on the current line.
+  unsigned pos;
+
+public:
+  PrintContext(std::ostream &_os) : os(_os), newline("\n"), pos(0) {}
+
+  void setNewline(const std::string &_newline) {
+    newline = _newline;
+  }
+
+  void breakLine(unsigned indent=0) {
+    os << newline;
+    if (indent)
+      os << std::setw(indent) << ' ';
+    pos = indent;
+  }
+
+  /// write - Output a string to the stream and update the
+  /// position. The stream should not have any newlines.
+  void write(const std::string &s) {
+    os << s;
+    pos += s.length();
+  }
+
+  template <typename T>
+  PrintContext &operator<<(T elt) {
+    ss.str("");
+    ss << elt;
+    write(ss.str());
+    return *this;
+  }
+};
+
+class PPrinter : public ExprPPrinter {
+  std::map<ref<Expr>, unsigned> bindings;
+  std::map<const UpdateNode*, unsigned> updateBindings;
+  std::set< ref<Expr> > couldPrint, shouldPrint;
+  std::set<const UpdateNode*> couldPrintUpdates, shouldPrintUpdates;
+  std::ostream &os;
+  unsigned counter;
+  unsigned updateCounter;
+  bool hasScan;
+  std::string newline;
+
+  /// shouldPrintWidth - Predicate for whether this expression should
+  /// be printed with its width.
+  bool shouldPrintWidth(ref<Expr> e) {
+    if (PCAllWidths)
+      return true;
+    return e.getWidth() != Expr::Bool;
+  }
+
+  bool isVerySimple(const ref<Expr> &e) { 
+    return e.isConstant() || bindings.find(e)!=bindings.end();
+  }
+
+  bool isVerySimpleUpdate(const UpdateNode *un) {
+    return !un || updateBindings.find(un)!=updateBindings.end();
+  }
+
+
+  // document me!
+  bool isSimple(const ref<Expr> &e) { 
+    if (isVerySimple(e)) {
+      return true;
+    } else if (const ReadExpr *re = dyn_ref_cast<ReadExpr>(e)) {
+      return isVerySimple(re->index) && isVerySimpleUpdate(re->updates.head);
+    } else {
+      Expr *ep = e.get();
+      for (unsigned i=0; i<ep->getNumKids(); i++)
+        if (!isVerySimple(ep->getKid(i)))
+          return false;
+      return true;
+    }
+  }
+
+  bool hasSimpleKids(const Expr *ep) {
+      for (unsigned i=0; i<ep->getNumKids(); i++)
+        if (!isSimple(ep->getKid(i)))
+          return false;
+      return true;
+  }
+  
+  void scanUpdate(const UpdateNode *un) {
+    if (un) {
+      if (couldPrintUpdates.insert(un).second) {
+        scanUpdate(un->next);
+        scan1(un->index);
+        scan1(un->value);
+      } else {
+        shouldPrintUpdates.insert(un);
+      }
+    }
+  }
+
+  void scan1(const ref<Expr> &e) {
+    if (!e.isConstant()) {
+      if (couldPrint.insert(e).second) {
+        Expr *ep = e.get();
+        for (unsigned i=0; i<ep->getNumKids(); i++)
+          scan1(ep->getKid(i));
+        if (const ReadExpr *re = dyn_ref_cast<ReadExpr>(e)) 
+          scanUpdate(re->updates.head);
+      } else {
+        shouldPrint.insert(e);
+      }
+    }
+  }
+
+  void printUpdateList(const UpdateList &updates, PrintContext &PC) {
+    const UpdateNode *head = updates.head;
+
+    // Special case empty list.
+    if (!head) {
+      if (updates.isRooted) {
+        PC << "arr" << updates.root->id;
+      } else {
+        PC << "[]";
+      }
+      return;
+    }
+
+    // FIXME: Explain this breaking policy.
+    bool openedList = false, nextShouldBreak = false;
+    unsigned outerIndent = PC.pos;
+    unsigned middleIndent = 0;
+    for (const UpdateNode *un = head; un; un = un->next) {      
+      // We are done if we hit the cache.
+      std::map<const UpdateNode*, unsigned>::iterator it = 
+        updateBindings.find(un);
+      if (it!=updateBindings.end()) {
+        if (openedList)
+          PC << "] @ ";
+        PC << "U" << it->second;
+        return;
+      } else if (!hasScan || shouldPrintUpdates.count(un)) {
+        if (openedList)
+          PC << "] @";
+        if (un != head)
+          PC.breakLine(outerIndent);
+        PC << "U" << updateCounter << ":"; 
+        updateBindings.insert(std::make_pair(un, updateCounter++));
+        openedList = nextShouldBreak = false;
+     }
+    
+      if (!openedList) {
+        openedList = 1;
+        PC << '[';
+        middleIndent = PC.pos;
+      } else {
+        PC << ',';
+        printSeparator(PC, !nextShouldBreak, middleIndent);
+      }
+      //PC << "(=";
+      //unsigned innerIndent = PC.pos;
+      print(un->index, PC);
+      //printSeparator(PC, isSimple(un->index), innerIndent);
+      PC << "=";
+      print(un->value, PC);
+      //PC << ')';
+      
+      nextShouldBreak = !(un->index.isConstant() && un->value.isConstant());
+    }
+
+    if (openedList)
+      PC << ']';
+
+    if (updates.isRooted)
+      PC << " @ arr" << updates.root->id;
+  }
+
+  void printWidth(PrintContext &PC, ref<Expr> e) {
+    if (!shouldPrintWidth(e))
+      return;
+
+    if (PCWidthAsArg) {
+      PC << ' ';
+      if (PCPrefixWidth)
+        PC << 'w';
+    }
+
+    PC << e.getWidth();
+  }
+
+  /// hasOrderedReads - True iff all children are reads with
+  /// consecutive offsets according to the given \arg stride.
+  bool hasOrderedReads(const Expr *ep, int stride) {
+    const ReadExpr *base = dyn_ref_cast<ReadExpr>(ep->getKid(0));
+    if (!base)
+      return false;
+
+    // Get stride expr in proper index width.
+    Expr::Width idxWidth = base->index.getWidth();
+    ref<Expr> strideExpr(stride, idxWidth), offset(0, idxWidth);
+    for (unsigned i=1; i<ep->getNumKids(); ++i) {
+      const ReadExpr *re = dyn_ref_cast<ReadExpr>(ep->getKid(i));
+      if (!re) 
+        return false;
+
+      // Check if the index follows the stride. 
+      // FIXME: How aggressive should this be simplified. The
+      // canonicalizing builder is probably the right choice, but this
+      // is yet another area where we would really prefer it to be
+      // global or else use static methods.
+      offset = AddExpr::create(offset, strideExpr);
+      if (SubExpr::create(re->index, base->index) != offset)
+        return false;
+    }
+
+    return true;
+  }
+
+  /// hasAllByteReads - True iff all children are byte level reads.
+  bool hasAllByteReads(const Expr *ep) {
+    for (unsigned i=0; i<ep->getNumKids(); ++i) {
+      const ReadExpr *re = dyn_ref_cast<ReadExpr>(ep->getKid(i));
+      if (!re || re->getWidth() != Expr::Int8)
+        return false;
+    }
+    return true;
+  }
+
+  void printRead(const ReadExpr *re, PrintContext &PC, unsigned indent) {
+    print(re->index, PC);
+    printSeparator(PC, isVerySimple(re->index), indent);
+    printUpdateList(re->updates, PC);
+  }
+
+  void printExtract(const ExtractExpr *ee, PrintContext &PC, unsigned indent) {
+    PC << ee->offset << ' ';
+    print(ee->expr, PC);
+  }
+
+  void printExpr(const Expr *ep, PrintContext &PC, unsigned indent, bool printConstWidth=false) {
+    bool simple = hasSimpleKids(ep);
+    
+    print(ep->getKid(0), PC);
+    for (unsigned i=1; i<ep->getNumKids(); i++) {
+      printSeparator(PC, simple, indent);
+      print(ep->getKid(i), PC, printConstWidth);
+    }
+  }
+
+public:
+  PPrinter(std::ostream &_os) : os(_os), newline("\n") {
+    reset();
+  }
+
+  void setNewline(const std::string &_newline) {
+    newline = _newline;
+  }
+
+  void reset() {
+    counter = 0;
+    updateCounter = 0;
+    hasScan = false;
+    bindings.clear();
+    updateBindings.clear();
+    couldPrint.clear();
+    shouldPrint.clear();
+    couldPrintUpdates.clear();
+    shouldPrintUpdates.clear();
+  }
+
+  void scan(const ref<Expr> &e) {
+    hasScan = true;
+    scan1(e);
+  }
+
+  void print(const ref<Expr> &e, unsigned level=0) {
+    PrintContext PC(os);
+    PC.pos = level;
+    print(e, PC);
+  }
+
+  void printConst(const ref<Expr> &e, PrintContext &PC, bool printWidth) {
+    assert(e.isConstant());
+
+    if (e.getWidth() == Expr::Bool)
+      PC << (e.getConstantValue() ? "true" : "false");
+    else {
+      if (PCAllConstWidths)
+	printWidth = true;
+    
+      if (printWidth)
+	PC << "(w" << e.getWidth() << " ";
+
+      PC << e.getConstantValue();
+
+      if (printWidth)
+	PC << ")";
+    }    
+  }
+
+  void print(const ref<Expr> &e, PrintContext &PC, bool printConstWidth=false) {
+    if (e.isConstant()) 
+      printConst(e, PC, printConstWidth);
+    else {
+      std::map<ref<Expr>, unsigned>::iterator it = bindings.find(e);
+      if (it!=bindings.end()) {
+        PC << 'N' << it->second;
+      } else {
+        if (!hasScan || shouldPrint.count(e)) {
+          PC << 'N' << counter << ':';
+          bindings.insert(std::make_pair(e, counter++));
+        }
+
+        // Detect Not.
+        // FIXME: This should be in common code.
+        if (const EqExpr *ee = dyn_ref_cast<EqExpr>(e)) {
+          if (ee->left == ref<Expr>(false, Expr::Bool)) {
+            PC << "(Not";
+            printWidth(PC, e);
+            PC << ' ';
+            // FIXME: This is a boom if right is a constant.
+            print(ee->right, PC);
+            PC << ')';
+            return;
+          }
+        }
+
+        // Detect multibyte reads.
+        // FIXME: Hrm. One problem with doing this is that we are
+        // masking the sharing of the indices which aren't
+        // visible. Need to think if this matters... probably not
+        // because if they are offset reads then its either constant,
+        // or they are (base + offset) and base will get printed with
+        // a declaration.
+        if (PCMultibyteReads && e.getKind() == Expr::Concat) {
+          const Expr *ep = e.get();
+          if (hasAllByteReads(ep)) {
+            bool isMSB = hasOrderedReads(ep, 1);
+            if (isMSB || hasOrderedReads(ep, -1)) {
+              PC << "(Read" << (isMSB ? "MSB" : "LSB");
+              printWidth(PC, e);
+              PC << ' ';
+              unsigned firstIdx = isMSB ? 0 : ep->getNumKids()-1;
+              printRead(static_ref_cast<ReadExpr>(ep->getKid(firstIdx)), 
+                        PC, PC.pos);
+              PC << ')';
+              return;
+            }
+          }
+        }
+
+	PC << '(' << e.getKind();
+        printWidth(PC, e);
+        PC << ' ';
+
+        // Indent at first argument and dispatch to appropriate print
+        // routine for exprs which require special handling.
+        unsigned indent = PC.pos;
+        if (const ReadExpr *re = dyn_ref_cast<ReadExpr>(e)) {
+          printRead(re, PC, indent);
+        } else if (const ExtractExpr *ee = dyn_ref_cast<ExtractExpr>(e)) {
+          printExtract(ee, PC, indent);
+        } else if (e.getKind() == Expr::Concat || e.getKind() == Expr::SExt)
+	  printExpr(e.get(), PC, indent, true);
+	else
+          printExpr(e.get(), PC, indent);	
+        PC << ")";
+      }
+    }
+  }
+
+  /* Public utility functions */
+
+  void printSeparator(PrintContext &PC, bool simple, unsigned indent) {
+    if (simple) {
+      PC << ' ';
+    } else {
+      PC.breakLine(indent);
+    }
+  }
+};
+
+ExprPPrinter *klee::ExprPPrinter::create(std::ostream &os) {
+  return new PPrinter(os);
+}
+
+void ExprPPrinter::printOne(std::ostream &os,
+                            const char *message, 
+                            const ref<Expr> &e) {
+  PPrinter p(os);
+  p.scan(e);
+
+  // FIXME: Need to figure out what to do here. Probably print as a
+  // "forward declaration" with whatever syntax we pick for that.
+  PrintContext PC(os);
+  PC << message << ": ";
+  p.print(e, PC);
+  PC.breakLine();
+}
+
+void ExprPPrinter::printConstraints(std::ostream &os,
+                                    const ConstraintManager &constraints) {
+  printQuery(os, constraints, ref<Expr>(false, Expr::Bool));
+}
+
+void ExprPPrinter::printQuery(std::ostream &os,
+                              const ConstraintManager &constraints,
+                              const ref<Expr> &q) {
+  PPrinter p(os);
+  
+  for (ConstraintManager::const_iterator it = constraints.begin(),
+         ie = constraints.end(); it != ie; ++it)
+    p.scan(*it);
+  p.scan(q);
+
+  PrintContext PC(os);
+  PC << "(query [";
+  
+  // Ident at constraint list;
+  unsigned indent = PC.pos;
+  for (ConstraintManager::const_iterator it = constraints.begin(),
+         ie = constraints.end(); it != ie;) {
+    p.print(*it, PC);
+    ++it;
+    if (it != ie)
+      PC.breakLine(indent);
+  }
+  PC << ']';
+
+  p.printSeparator(PC, constraints.empty(), indent-1);
+  p.print(q, PC);
+
+  PC << ')';
+  PC.breakLine();
+}

Added: klee/trunk/lib/Expr/ExprUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/ExprUtil.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/ExprUtil.cpp (added)
+++ klee/trunk/lib/Expr/ExprUtil.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,127 @@
+//===-- ExprUtil.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/util/ExprUtil.h"
+#include "klee/util/ExprHashMap.h"
+
+#include "klee/Expr.h"
+
+#include "klee/util/ExprVisitor.h"
+
+#include <set>
+
+using namespace klee;
+
+void klee::findReads(ref<Expr> e, 
+                     bool visitUpdates,
+                     std::vector< ref<ReadExpr> > &results) {
+  // Invariant: \forall_{i \in stack} !i.isConstant() && i \in visited 
+  std::vector< ref<Expr> > stack;
+  ExprHashSet visited;
+  std::set<const UpdateNode *> updates;
+  
+  if (!e.isConstant()) {
+    visited.insert(e);
+    stack.push_back(e);
+  }
+
+  while (!stack.empty()) {
+    ref<Expr> top = stack.back();
+    stack.pop_back();
+
+    if (ReadExpr *re = dyn_ref_cast<ReadExpr>(top)) {
+      // We memoized so can just add to list without worrying about
+      // repeats.
+      results.push_back(re);
+
+      if (!re->index.isConstant() &&
+          visited.insert(re->index).second)
+        stack.push_back(re->index);
+      
+      if (visitUpdates) {
+        // XXX this is probably suboptimal. We want to avoid a potential
+        // explosion traversing update lists which can be quite
+        // long. However, it seems silly to hash all of the update nodes
+        // especially since we memoize all the expr results anyway. So
+        // we take a simple approach of memoizing the results for the
+        // head, which often will be shared among multiple nodes.
+        if (updates.insert(re->updates.head).second) {
+          for (const UpdateNode *un=re->updates.head; un; un=un->next) {
+            if (!un->index.isConstant() &&
+                visited.insert(un->index).second)
+              stack.push_back(un->index);
+            if (!un->value.isConstant() &&
+                visited.insert(un->value).second)
+              stack.push_back(un->value);
+          }
+        }
+      }
+    } else if (!top.isConstant()) {
+      Expr *e = top.get();
+      for (unsigned i=0; i<e->getNumKids(); i++) {
+        ref<Expr> k = e->getKid(i);
+        if (!k.isConstant() &&
+            visited.insert(k).second)
+          stack.push_back(k);
+      }
+    }
+  }
+}
+
+///
+
+namespace klee {
+
+class SymbolicObjectFinder : public ExprVisitor {
+protected:
+  Action visitRead(const ReadExpr &re) {
+    const UpdateList &ul = re.updates;
+
+    // XXX should we memo better than what ExprVisitor is doing for us?
+    for (const UpdateNode *un=ul.head; un; un=un->next) {
+      visit(un->index);
+      visit(un->value);
+    }
+
+    if (ul.isRooted)
+      if (results.insert(ul.root).second)
+        objects.push_back(ul.root);
+
+    return Action::doChildren();
+  }
+
+public:
+  std::set<const Array*> results;
+  std::vector<const Array*> &objects;
+  
+  SymbolicObjectFinder(std::vector<const Array*> &_objects)
+    : objects(_objects) {}
+};
+
+}
+
+template<typename InputIterator>
+void klee::findSymbolicObjects(InputIterator begin, 
+                               InputIterator end,
+                               std::vector<const Array*> &results) {
+  SymbolicObjectFinder of(results);
+  for (; begin!=end; ++begin)
+    of.visit(*begin);
+}
+
+void klee::findSymbolicObjects(ref<Expr> e,
+                               std::vector<const Array*> &results) {
+  findSymbolicObjects(&e, &e+1, results);
+}
+
+typedef std::vector< ref<Expr> >::iterator A;
+template void klee::findSymbolicObjects<A>(A, A, std::vector<const Array*> &);
+
+typedef std::set< ref<Expr> >::iterator B;
+template void klee::findSymbolicObjects<B>(B, B, std::vector<const Array*> &);

Added: klee/trunk/lib/Expr/ExprVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/ExprVisitor.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/ExprVisitor.cpp (added)
+++ klee/trunk/lib/Expr/ExprVisitor.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,253 @@
+//===-- ExprVisitor.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/Expr.h"
+#include "klee/util/ExprVisitor.h"
+
+#include "llvm/Support/CommandLine.h"
+
+namespace {
+  llvm::cl::opt<bool>
+  UseVisitorHash("use-visitor-hash", 
+                 llvm::cl::desc("Use hash-consing during expr visitation."),
+                 llvm::cl::init(true));
+}
+
+using namespace klee;
+
+ref<Expr> ExprVisitor::visit(const ref<Expr> &e) {
+  if (!UseVisitorHash || e.isConstant()) {
+    return visitActual(e);
+  } else {
+    visited_ty::iterator it = visited.find(e);
+
+    if (it!=visited.end()) {
+      return it->second;
+    } else {
+      ref<Expr> res = visitActual(e);
+      visited.insert(std::make_pair(e, res));
+      return res;
+    }
+  }
+}
+
+ref<Expr> ExprVisitor::visitActual(const ref<Expr> &e) {
+  if (e.isConstant()) {    
+    return e;
+  } else {
+    Expr &ep = *e.get();
+
+    Action res = visitExpr(ep);
+    switch(res.kind) {
+    case Action::DoChildren:
+      // continue with normal action
+      break;
+    case Action::SkipChildren:
+      return e;
+    case Action::ChangeTo:
+      return res.argument;
+    }
+
+    switch(ep.getKind()) {
+    case Expr::NotOptimized: res = visitNotOptimized(static_cast<NotOptimizedExpr&>(ep)); break;
+    case Expr::Read: res = visitRead(static_cast<ReadExpr&>(ep)); break;
+    case Expr::Select: res = visitSelect(static_cast<SelectExpr&>(ep)); break;
+    case Expr::Concat: res = visitConcat(static_cast<ConcatExpr&>(ep)); break;
+    case Expr::Extract: res = visitExtract(static_cast<ExtractExpr&>(ep)); break;
+    case Expr::ZExt: res = visitZExt(static_cast<ZExtExpr&>(ep)); break;
+    case Expr::SExt: res = visitSExt(static_cast<SExtExpr&>(ep)); break;
+    case Expr::Add: res = visitAdd(static_cast<AddExpr&>(ep)); break;
+    case Expr::Sub: res = visitSub(static_cast<SubExpr&>(ep)); break;
+    case Expr::Mul: res = visitMul(static_cast<MulExpr&>(ep)); break;
+    case Expr::UDiv: res = visitUDiv(static_cast<UDivExpr&>(ep)); break;
+    case Expr::SDiv: res = visitSDiv(static_cast<SDivExpr&>(ep)); break;
+    case Expr::URem: res = visitURem(static_cast<URemExpr&>(ep)); break;
+    case Expr::SRem: res = visitSRem(static_cast<SRemExpr&>(ep)); break;
+    case Expr::And: res = visitAnd(static_cast<AndExpr&>(ep)); break;
+    case Expr::Or: res = visitOr(static_cast<OrExpr&>(ep)); break;
+    case Expr::Xor: res = visitXor(static_cast<XorExpr&>(ep)); break;
+    case Expr::Shl: res = visitShl(static_cast<ShlExpr&>(ep)); break;
+    case Expr::LShr: res = visitLShr(static_cast<LShrExpr&>(ep)); break;
+    case Expr::AShr: res = visitAShr(static_cast<AShrExpr&>(ep)); break;
+    case Expr::Eq: res = visitEq(static_cast<EqExpr&>(ep)); break;
+    case Expr::Ne: res = visitNe(static_cast<NeExpr&>(ep)); break;
+    case Expr::Ult: res = visitUlt(static_cast<UltExpr&>(ep)); break;
+    case Expr::Ule: res = visitUle(static_cast<UleExpr&>(ep)); break;
+    case Expr::Ugt: res = visitUgt(static_cast<UgtExpr&>(ep)); break;
+    case Expr::Uge: res = visitUge(static_cast<UgeExpr&>(ep)); break;
+    case Expr::Slt: res = visitSlt(static_cast<SltExpr&>(ep)); break;
+    case Expr::Sle: res = visitSle(static_cast<SleExpr&>(ep)); break;
+    case Expr::Sgt: res = visitSgt(static_cast<SgtExpr&>(ep)); break;
+    case Expr::Sge: res = visitSge(static_cast<SgeExpr&>(ep)); break;
+    case Expr::Constant:
+    default:
+      assert(0 && "invalid expression kind");
+    }
+
+    switch(res.kind) {
+    case Action::DoChildren: {  
+      bool rebuild = false;
+      ref<Expr> e(&ep), kids[8];
+      unsigned count = ep.getNumKids();
+      for (unsigned i=0; i<count; i++) {
+        ref<Expr> kid = ep.getKid(i);
+        kids[i] = visit(kid);
+        if (kids[i] != kid)
+          rebuild = true;
+      }
+      if (rebuild) {
+        e = ep.rebuild(kids);
+        if (recursive)
+          e = visit(e);
+      }
+      if (!e.isConstant()) {
+        res = visitExprPost(*e.get());
+        if (res.kind==Action::ChangeTo)
+          e = res.argument;
+      }
+      return e;
+    }
+    case Action::SkipChildren:
+      return e;
+    case Action::ChangeTo:
+      return res.argument;
+    default:
+      assert(0 && "invalid kind");
+    }
+  }
+}
+
+ExprVisitor::Action ExprVisitor::visitExpr(const Expr&) {
+  return Action::doChildren();
+}
+
+ExprVisitor::Action ExprVisitor::visitExprPost(const Expr&) {
+  return Action::skipChildren();
+}
+
+ExprVisitor::Action ExprVisitor::visitNotOptimized(const NotOptimizedExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitRead(const ReadExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSelect(const SelectExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitConcat(const ConcatExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitExtract(const ExtractExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitZExt(const ZExtExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSExt(const SExtExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitAdd(const AddExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSub(const SubExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitMul(const MulExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitUDiv(const UDivExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSDiv(const SDivExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitURem(const URemExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSRem(const SRemExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitAnd(const AndExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitOr(const OrExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitXor(const XorExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitShl(const ShlExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitLShr(const LShrExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitAShr(const AShrExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitEq(const EqExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitNe(const NeExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitUlt(const UltExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitUle(const UleExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitUgt(const UgtExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitUge(const UgeExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSlt(const SltExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSle(const SleExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSgt(const SgtExpr&) {
+  return Action::doChildren(); 
+}
+
+ExprVisitor::Action ExprVisitor::visitSge(const SgeExpr&) {
+  return Action::doChildren(); 
+}
+

Added: klee/trunk/lib/Expr/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/Lexer.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/Lexer.cpp (added)
+++ klee/trunk/lib/Expr/Lexer.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,261 @@
+//===-- Lexer.cpp ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "expr/Lexer.h"
+
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Streams.h"
+
+#include <iomanip>
+#include <iostream>
+#include <string.h>
+
+using namespace llvm;
+using namespace klee;
+using namespace klee::expr;
+
+///
+
+const char *Token::getKindName() const {
+  switch (kind) {
+  default:
+  case Unknown:    return "Unknown";
+  case Arrow:      return "Arrow";
+  case At:         return "At";
+  case Colon:      return "Colon";
+  case Comma:      return "Comma";
+  case Comment:    return "Comment";
+  case EndOfFile:  return "EndOfFile";
+  case Equals:     return "Equals";
+  case Identifier: return "Identifier";
+  case KWFalse:    return "KWFalse";
+  case KWQuery:    return "KWQuery";
+  case KWReserved: return "KWReserved";
+  case KWTrue:     return "KWTrue";
+  case KWWidth:    return "KWWidth";
+  case LBrace:     return "LBrace";
+  case LParen:     return "LParen";
+  case LSquare:    return "LSquare";
+  case Number:     return "Number";
+  case RBrace:     return "RBrace";
+  case RParen:     return "RParen";
+  case RSquare:    return "RSquare";
+  case Semicolon:  return "Semicolon";
+  }
+}
+
+void Token::dump() {
+  llvm::cerr << "(Token \"" << getKindName() << "\" "
+             << (void*) start << " " << length << " "
+             << line << " " << column << ")";
+}
+
+///
+
+static inline bool isInternalIdentifierChar(int Char) {
+  return isalnum(Char) || Char == '_' || Char == '.';
+}
+
+Lexer::Lexer(const llvm::MemoryBuffer *MB) 
+  : BufferPos(MB->getBufferStart()), BufferEnd(MB->getBufferEnd()), 
+    LineNumber(1), ColumnNumber(0) {
+}
+
+Lexer::~Lexer() {
+}
+
+int Lexer::PeekNextChar() {
+  if (BufferPos == BufferEnd)
+    return -1;
+  return *BufferPos;
+}
+
+int Lexer::GetNextChar() {
+  if (BufferPos == BufferEnd)
+    return -1;
+
+  // Handle DOS/Mac newlines here, by stripping duplicates and by
+  // returning '\n' for both.
+  char Result = *BufferPos++;
+  if (Result == '\n' || Result == '\r') {
+    if (BufferPos != BufferEnd && *BufferPos == ('\n' + '\r' - Result))
+      ++BufferPos;
+    Result = '\n';
+  }
+
+  if (Result == '\n') {
+    ++LineNumber;
+    ColumnNumber = 0;
+  } else {
+    ++ColumnNumber;
+  }
+
+  return Result;
+}
+
+Token &Lexer::SetTokenKind(Token &Result, Token::Kind k) {
+  Result.kind = k;
+  Result.length = BufferPos - Result.start;
+  return Result;
+}
+
+static bool isReservedKW(const char *Str, unsigned N) {
+    unsigned i;
+
+  // Check for i[0-9]+
+  if (N>1 && Str[0] == 'i') {
+    for (i=1; i<N; ++i)
+      if (!isdigit(Str[i]))
+        break;
+    if (i==N)
+      return true;
+  }
+
+  // Check for fp[0-9]+([.].*)?$
+  if (N>3 && Str[0]=='f' && Str[1]=='p' && isdigit(Str[2])) {
+    for (i=3; i<N; ++i)
+      if (!isdigit(Str[i]))
+        break;
+    if (i==N || Str[i]=='.')
+      return true;
+  }
+  
+  return false;
+}
+static bool isWidthKW(const char *Str, unsigned N) {
+  if (N<2 || Str[0] != 'w')
+    return false;
+  for (unsigned i=1; i<N; ++i)
+    if (!isdigit(Str[i]))
+      return false;
+  return true;
+}
+Token &Lexer::SetIdentifierTokenKind(Token &Result) {
+  unsigned Length = BufferPos - Result.start;
+  switch (Length) {
+  case 3:
+    if (memcmp("def", Result.start, 3) == 0)
+      return SetTokenKind(Result, Token::KWReserved);
+    if (memcmp("var", Result.start, 3) == 0)
+      return SetTokenKind(Result, Token::KWReserved);
+    break;
+
+  case 4:
+    if (memcmp("true", Result.start, 4) == 0)
+      return SetTokenKind(Result, Token::KWTrue);
+    break;
+
+  case 5:
+    if (memcmp("array", Result.start, 5) == 0)
+      return SetTokenKind(Result, Token::KWReserved);
+    if (memcmp("false", Result.start, 5) == 0)
+      return SetTokenKind(Result, Token::KWFalse);
+    if (memcmp("query", Result.start, 5) == 0)
+      return SetTokenKind(Result, Token::KWQuery);
+    break;      
+    
+  case 6:
+    if (memcmp("define", Result.start, 6) == 0)
+      return SetTokenKind(Result, Token::KWReserved);
+    break;
+
+  case 7:
+    if (memcmp("declare", Result.start, 7) == 0)
+      return SetTokenKind(Result, Token::KWReserved);
+    break;
+  }
+
+  if (isReservedKW(Result.start, Length))
+    return SetTokenKind(Result, Token::KWReserved);
+  if (isWidthKW(Result.start, Length))
+    return SetTokenKind(Result, Token::KWWidth);
+
+  return SetTokenKind(Result, Token::Identifier);
+}
+
+void Lexer::SkipToEndOfLine() {
+  for (;;) {
+    int Char = GetNextChar();
+    if (Char == -1 || Char =='\n')
+      break;
+  }
+}
+
+Token &Lexer::LexNumber(Token &Result) {
+  while (isalnum(PeekNextChar()) || PeekNextChar()=='_')
+    GetNextChar();
+  return SetTokenKind(Result, Token::Number);
+}
+
+Token &Lexer::LexIdentifier(Token &Result) {
+  while (isInternalIdentifierChar(PeekNextChar()))
+    GetNextChar();
+
+  // Recognize keywords specially.
+  return SetIdentifierTokenKind(Result);
+}
+
+Token &Lexer::Lex(Token &Result) {
+  Result.kind = Token::Unknown;
+  Result.length = 0;
+  Result.start = BufferPos;
+  
+  // Skip whitespace.
+  while (isspace(PeekNextChar()))
+    GetNextChar();
+
+  Result.start = BufferPos;
+  Result.line = LineNumber;
+  Result.column = ColumnNumber;
+  int Char = GetNextChar();
+  switch (Char) {
+  case -1:  return SetTokenKind(Result, Token::EndOfFile);
+    
+  case '(': return SetTokenKind(Result, Token::LParen);
+  case ')': return SetTokenKind(Result, Token::RParen);
+  case ',': return SetTokenKind(Result, Token::Comma);
+  case ':': return SetTokenKind(Result, Token::Colon);
+  case ';': return SetTokenKind(Result, Token::Semicolon);
+  case '=': return SetTokenKind(Result, Token::Equals);
+  case '@': return SetTokenKind(Result, Token::At);
+  case '[': return SetTokenKind(Result, Token::LSquare);
+  case ']': return SetTokenKind(Result, Token::RSquare);
+  case '{': return SetTokenKind(Result, Token::LBrace);
+  case '}': return SetTokenKind(Result, Token::RBrace);
+
+  case '#':
+    SkipToEndOfLine();
+    return SetTokenKind(Result, Token::Comment);
+
+  case '+': {
+    if (isdigit(PeekNextChar()))
+      return LexNumber(Result);
+    else
+      return SetTokenKind(Result, Token::Unknown);
+  }
+
+  case '-': {
+    int Next = PeekNextChar();
+    if (Next == '>')
+      return GetNextChar(), SetTokenKind(Result, Token::Arrow);
+    else if (isdigit(Next))
+      return LexNumber(Result);
+    else
+      return SetTokenKind(Result, Token::Unknown);
+    break;
+  }
+
+  default:
+    if (isdigit(Char))
+      return LexNumber(Result);
+    else if (isalpha(Char) || Char == '_')
+      return LexIdentifier(Result);
+    return SetTokenKind(Result, Token::Unknown);
+  }
+}

Added: klee/trunk/lib/Expr/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/Makefile (added)
+++ klee/trunk/lib/Expr/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+#===-- lib/Expr/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=kleaverExpr
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+
+include $(LEVEL)/Makefile.common

Added: klee/trunk/lib/Expr/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/Parser.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/Parser.cpp (added)
+++ klee/trunk/lib/Expr/Parser.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,1310 @@
+//===-- Parser.cpp --------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "expr/Parser.h"
+
+#include "expr/Lexer.h"
+
+#include "klee/Constraints.h"
+#include "klee/Solver.h"
+#include "klee/util/ExprPPrinter.h"
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Streams.h"
+
+#include <cassert>
+#include <iostream>
+#include <map>
+
+using namespace llvm;
+using namespace klee;
+using namespace klee::expr;
+
+namespace {
+  /// ParseResult - Represent a possibly invalid parse result.
+  template<typename T>
+  struct ParseResult {
+    bool IsValid;
+    T Value;
+
+  public:
+    ParseResult() : IsValid(false) {}
+    ParseResult(T _Value) : IsValid(true), Value(_Value) {}
+    ParseResult(bool _IsValid, T _Value) : IsValid(_IsValid), Value(_Value) {}
+
+    bool isValid() { 
+      return IsValid; 
+    }
+    T get() { 
+      assert(IsValid && "get() on invalid ParseResult!");
+      return Value; 
+    }
+  };
+  
+  typedef ParseResult<Decl*> DeclResult;
+  typedef ParseResult<ExprHandle> ExprResult;
+  typedef ParseResult<Expr::Width> TypeResult;
+  typedef ParseResult<VersionHandle> VersionResult;
+
+  /// NumberOrExprResult - Represent a number or expression. This is used to
+  /// wrap an expression production which may be a number, but for
+  /// which the type width is unknown.
+  class NumberOrExprResult {
+    Token AsNumber;
+    ExprResult AsExpr;
+    bool IsNumber;
+
+  public:
+    NumberOrExprResult() : IsNumber(false) {}
+    explicit NumberOrExprResult(Token _AsNumber) : AsNumber(_AsNumber),
+                                                   IsNumber(true) {}
+    explicit NumberOrExprResult(ExprResult _AsExpr) : AsExpr(_AsExpr),
+                                                      IsNumber(false) {}
+    
+    bool isNumber() const { return IsNumber; }
+    const Token &getNumber() const { 
+      assert(IsNumber && "Invalid accessor call.");
+      return AsNumber; 
+    }
+    const ExprResult &getExpr() const {
+      assert(!IsNumber && "Invalid accessor call.");
+      return AsExpr;
+    }
+  };
+
+  /// ParserImpl - Parser implementation.
+  class ParserImpl : public Parser {
+    typedef std::map<const std::string, const Identifier*> IdentifierTabTy;
+    typedef std::map<const Identifier*, ExprHandle> ExprSymTabTy;
+    typedef std::map<const Identifier*, VersionHandle> VersionSymTabTy;
+
+    const std::string Filename;
+    const MemoryBuffer *TheMemoryBuffer;
+    Lexer TheLexer;
+    unsigned MaxErrors;
+    unsigned NumErrors;
+
+    // FIXME: Use LLVM symbol tables?
+    IdentifierTabTy IdentifierTab;
+
+    std::map<const Identifier*, const ArrayDecl*> ArraySymTab;
+    ExprSymTabTy ExprSymTab;
+    VersionSymTabTy VersionSymTab;
+
+    /// Tok - The currently lexed token.
+    Token Tok;
+
+    /// ParenLevel - The current depth of matched '(' tokens. 
+    unsigned ParenLevel;
+    /// SquareLevel - The current depth of matched '[' tokens.
+    unsigned SquareLevel;
+
+    /* Core parsing functionality */
+    
+    const Identifier *GetOrCreateIdentifier(const Token &Tok);
+
+    void GetNextNonCommentToken() {
+      do {
+        TheLexer.Lex(Tok);
+      } while (Tok.kind == Token::Comment);
+    }
+
+    /// ConsumeToken - Consume the current 'peek token' and lex the next one.
+    void ConsumeToken() {
+      assert(Tok.kind != Token::LParen && Tok.kind != Token::RParen);
+      GetNextNonCommentToken();
+    }
+
+    /// ConsumeExpectedToken - Check that the current token is of the
+    /// expected kind and consume it.
+    void ConsumeExpectedToken(Token::Kind k) {
+      assert(Tok.kind == k && "Unexpected token!");
+      GetNextNonCommentToken();
+    }
+
+    void ConsumeLParen() {
+      ++ParenLevel;
+      ConsumeExpectedToken(Token::LParen);
+    }
+
+    void ConsumeRParen() {
+      if (ParenLevel) // Cannot go below zero.
+        --ParenLevel;
+      ConsumeExpectedToken(Token::RParen);
+    }
+
+    void ConsumeLSquare() {
+      ++SquareLevel;
+      ConsumeExpectedToken(Token::LSquare);
+    }
+
+    void ConsumeRSquare() {
+      if (SquareLevel) // Cannot go below zero.
+        --SquareLevel;
+      ConsumeExpectedToken(Token::RSquare);
+    }
+
+    void ConsumeAnyToken() {
+      switch (Tok.kind) {
+      case Token::LParen: return ConsumeLParen();
+      case Token::RParen: return ConsumeRParen();
+      case Token::LSquare: return ConsumeLSquare();
+      case Token::RSquare: return ConsumeRSquare();
+      default: 
+        return ConsumeToken();
+      }
+    }
+
+    /* Utility functions */
+
+    /// SkipUntilRParen - Scan forward to the next token following an
+    /// rparen at the given level, or EOF, whichever is first.
+    void SkipUntilRParen(unsigned Level) {
+      // FIXME: I keep wavering on whether it is an error to call this
+      // with the current token an rparen. In most cases this should
+      // have been handled differently (error reported,
+      // whatever). Audit & resolve.
+      assert(Level <= ParenLevel && 
+             "Refusing to skip until rparen at higher level.");
+      while (Tok.kind != Token::EndOfFile) {
+        if (Tok.kind == Token::RParen && ParenLevel == Level) {
+          ConsumeRParen();
+          break;
+        }
+        ConsumeAnyToken();
+      }
+    }
+
+    /// SkipUntilRParen - Scan forward until reaching an rparen token
+    /// at the current level (or EOF).
+    void SkipUntilRParen() {
+      SkipUntilRParen(ParenLevel);
+    }
+    
+    /// ExpectRParen - Utility method to close an sexp. This expects to
+    /// eat an rparen, and emits a diagnostic and skips to the next one
+    /// (or EOF) if it cannot.
+    void ExpectRParen(const char *Msg) {
+      if (Tok.kind == Token::EndOfFile) {
+        // FIXME: Combine with Msg
+        Error("expected ')' but found end-of-file.", Tok);
+      } else if (Tok.kind != Token::RParen) {
+        Error(Msg, Tok);
+        SkipUntilRParen();
+      } else {
+        ConsumeRParen();
+      }
+    }
+
+    /// SkipUntilRSquare - Scan forward to the next token following an
+    /// rsquare at the given level, or EOF, whichever is first.
+    void SkipUntilRSquare(unsigned Level) {
+      // FIXME: I keep wavering on whether it is an error to call this
+      // with the current token an rparen. In most cases this should
+      // have been handled differently (error reported,
+      // whatever). Audit & resolve.
+      assert(Level <= ParenLevel && 
+             "Refusing to skip until rparen at higher level.");
+      while (Tok.kind != Token::EndOfFile) {
+        if (Tok.kind == Token::RSquare && ParenLevel == Level) {
+          ConsumeRSquare();
+          break;
+        }
+        ConsumeAnyToken();
+      }
+    }
+
+    /// SkipUntilRSquare - Scan forward until reaching an rsquare token
+    /// at the current level (or EOF).
+    void SkipUntilRSquare() {
+      SkipUntilRSquare(ParenLevel);
+    }
+    
+    /// ExpectRSquare - Utility method to close an array. This expects
+    /// to eat an rparen, and emits a diagnostic and skips to the next
+    /// one (or EOF) if it cannot.
+    void ExpectRSquare(const char *Msg) {
+      if (Tok.kind == Token::EndOfFile) {
+        // FIXME: Combine with Msg
+        Error("expected ']' but found end-of-file.", Tok);
+      } else if (Tok.kind != Token::RSquare) {
+        Error(Msg, Tok);
+        SkipUntilRSquare();
+      } else {
+        ConsumeRSquare();
+      }
+    }
+
+    /*** Grammar productions ****/
+
+    /* Top level decls */
+
+    DeclResult ParseArrayDecl();
+    DeclResult ParseExprVarDecl();
+    DeclResult ParseVersionVarDecl();
+    DeclResult ParseCommandDecl();
+
+    /* Commands */
+
+    DeclResult ParseQueryCommand();
+
+    /* Etc. */
+
+    NumberOrExprResult ParseNumberOrExpr();
+
+    ExprResult ParseExpr(TypeResult ExpectedType);
+    ExprResult ParseParenExpr(TypeResult ExpectedType);
+    ExprResult ParseUnaryParenExpr(const Token &Name,
+                                   unsigned Kind, bool IsFixed,
+                                   Expr::Width ResTy);
+    ExprResult ParseBinaryParenExpr(const Token &Name,
+                                    unsigned Kind, bool IsFixed,
+                                    Expr::Width ResTy);
+    ExprResult ParseSelectParenExpr(const Token &Name, Expr::Width ResTy);
+    ExprResult ParseConcatParenExpr(const Token &Name, Expr::Width ResTy);
+    ExprResult ParseExtractParenExpr(const Token &Name, Expr::Width ResTy);
+    ExprResult ParseAnyReadParenExpr(const Token &Name,
+                                     unsigned Kind,
+                                     Expr::Width ResTy);
+    void ParseMatchedBinaryArgs(const Token &Name, 
+                                TypeResult ExpectType,
+                                ExprResult &LHS, ExprResult &RHS);
+    ExprResult ParseNumber(Expr::Width Width);
+    ExprResult ParseNumberToken(Expr::Width Width, const Token &Tok);
+
+    VersionResult ParseVersionSpecifier();
+    VersionResult ParseVersion();
+
+    TypeResult ParseTypeSpecifier();
+
+    /*** Diagnostics ***/
+    
+    void Error(const char *Message, const Token &At);
+    void Error(const char *Message) { Error(Message, Tok); }
+
+  public:
+    ParserImpl(const std::string _Filename,
+               const MemoryBuffer *MB) : Filename(_Filename),
+                                         TheMemoryBuffer(MB),
+                                         TheLexer(MB),
+                                         MaxErrors(~0u),
+                                         NumErrors(0) {}
+
+    /// Initialize - Initialize the parsing state. This must be called
+    /// prior to the start of parsing.
+    void Initialize() {
+      ParenLevel = SquareLevel = 0;
+
+      ConsumeAnyToken();
+    }
+
+    /* Parser interface implementation */
+
+    virtual Decl *ParseTopLevelDecl();
+
+    virtual void SetMaxErrors(unsigned N) {
+      MaxErrors = N;
+    }
+
+    virtual unsigned GetNumErrors() const {
+      return NumErrors; 
+    }
+  };
+}
+
+const Identifier *ParserImpl::GetOrCreateIdentifier(const Token &Tok) {
+  // FIXME: Make not horribly inefficient please.
+  assert(Tok.kind == Token::Identifier && "Expected only identifier tokens.");
+  std::string Name(Tok.start, Tok.length);
+  IdentifierTabTy::iterator it = IdentifierTab.find(Name);
+  if (it != IdentifierTab.end())
+    return it->second;
+
+  Identifier *I = new Identifier(Name);
+  IdentifierTab.insert(std::make_pair(Name, I));
+
+  return I;
+}
+
+Decl *ParserImpl::ParseTopLevelDecl() {
+  // Repeat until success or EOF.
+  while (Tok.kind != Token::EndOfFile) {
+    // Only handle commands for now.
+    if (Tok.kind == Token::LParen) {
+      DeclResult Res = ParseCommandDecl();
+      if (Res.isValid())
+        return Res.get();
+    } else {
+      Error("expected '(' token.");
+      ConsumeAnyToken();
+    }
+  }
+
+  return 0;
+}
+
+/// ParseCommandDecl - Parse a command declaration. The lexer should
+/// be positioned at the opening '('.
+///
+/// command = '(' name ... ')'
+DeclResult ParserImpl::ParseCommandDecl() {
+  ConsumeLParen();
+
+  if (!Tok.isKeyword()) {
+    Error("malformed command.");
+    SkipUntilRParen();
+    return DeclResult();
+  }
+
+  switch (Tok.kind) {
+  case Token::KWQuery:
+    return ParseQueryCommand();
+
+  default:
+    Error("malformed command (unexpected keyword).");
+    SkipUntilRParen();
+    return DeclResult();
+  }
+}
+
+/// ParseQueryCommand - Parse query command. The lexer should be
+/// positioned at the 'query' keyword.
+/// 
+/// 'query' expressions-list expression [expression-list [array-list]]
+DeclResult ParserImpl::ParseQueryCommand() {
+  // FIXME: We need a command for this. Or something.
+  ExprSymTab.clear();
+  VersionSymTab.clear();
+
+  std::vector<ExprHandle> Constraints;
+  ConsumeExpectedToken(Token::KWQuery);
+  if (Tok.kind != Token::LSquare) {
+    Error("malformed query, expected constraint list.");
+    SkipUntilRParen();
+    return DeclResult();
+  }
+
+  ConsumeExpectedToken(Token::LSquare);
+  // FIXME: Should avoid reading past unbalanced parens here.
+  while (Tok.kind != Token::RSquare) {
+    if (Tok.kind == Token::EndOfFile) {
+      Error("unexpected end of file.");
+      return new QueryCommand(Constraints.begin(), Constraints.end(),
+                              ref<Expr>(false, Expr::Bool));
+    }
+
+    ExprResult Res = ParseExpr(TypeResult(Expr::Bool));
+    if (Res.isValid())
+      Constraints.push_back(Res.get());
+  }
+
+  ConsumeRSquare();
+
+  ExprResult Res = ParseExpr(TypeResult());
+  if (!Res.isValid()) // Error emitted by ParseExpr.
+    Res = ExprResult(ref<Expr>(0, Expr::Bool));
+
+  ExpectRParen("unexpected argument to 'query'.");  
+  return new QueryCommand(Constraints.begin(), Constraints.end(),
+                          Res.get());
+}
+
+/// ParseNumberOrExpr - Parse an expression whose type cannot be
+/// predicted.
+NumberOrExprResult ParserImpl::ParseNumberOrExpr() {
+  if (Tok.kind == Token::Number){ 
+    Token Num = Tok;
+    ConsumeToken();
+    return NumberOrExprResult(Num);
+  } else {
+    return NumberOrExprResult(ParseExpr(TypeResult()));
+  }
+}
+
+/// ParseExpr - Parse an expression with the given \arg
+/// ExpectedType. \arg ExpectedType can be invalid if the type cannot
+/// be inferred from the context.
+///
+/// expr = false | true
+/// expr = <constant>
+/// expr = <identifier>
+/// expr = [<identifier>:] paren-expr
+ExprResult ParserImpl::ParseExpr(TypeResult ExpectedType) {
+  // FIXME: Is it right to need to do this here?
+  if (Tok.kind == Token::EndOfFile) {
+    Error("unexpected end of file.");
+    return ExprResult();
+  }
+
+  if (Tok.kind == Token::KWFalse || Tok.kind == Token::KWTrue) {
+    bool Value = Tok.kind == Token::KWTrue;
+    ConsumeToken();
+    return ExprResult(ref<Expr>(Value, Expr::Bool));
+  }
+  
+  if (Tok.kind == Token::Number) {
+    if (!ExpectedType.isValid()) {
+      Error("cannot infer type of number.");
+      ConsumeToken();
+      return ExprResult();
+    }
+    
+    return ParseNumber(ExpectedType.get());
+  }
+
+  const Identifier *Label = 0;
+  if (Tok.kind == Token::Identifier) {
+    Token LTok = Tok;
+    Label = GetOrCreateIdentifier(Tok);
+    ConsumeToken();
+
+    if (Tok.kind != Token::Colon) {
+      ExprSymTabTy::iterator it = ExprSymTab.find(Label);
+
+      if (it == ExprSymTab.end()) {
+        Error("invalid expression label reference.", LTok);
+        return ExprResult();
+      }
+
+      return it->second;
+    }
+
+    ConsumeToken();
+    if (ExprSymTab.count(Label)) {
+      Error("duplicate expression label definition.", LTok);
+      Label = 0;
+    }
+  }
+
+  Token Start = Tok;
+  ExprResult Res = ParseParenExpr(ExpectedType);
+  if (!Res.isValid()) {
+    // If we know the type, define the identifier just so we don't get
+    // use-of-undef errors. 
+    // FIXME: Maybe we should let the symbol table map to invalid
+    // entries?
+    if (Label && ExpectedType.isValid())
+      ExprSymTab.insert(std::make_pair(Label, 
+                                       ref<Expr>(0, ExpectedType.get())));
+    return Res;
+  } else if (ExpectedType.isValid()) {
+    // Type check result.    
+    if (Res.get().getWidth() != ExpectedType.get()) {
+      // FIXME: Need more info, and range
+      Error("expression has incorrect type.", Start);
+      return ExprResult();
+    }
+  }
+
+  if (Label)
+    ExprSymTab.insert(std::make_pair(Label, Res.get()));
+  return Res;
+}
+
+// Additional kinds for macro forms.
+enum MacroKind {
+  eMacroKind_Not = Expr::LastKind + 1,     // false == x
+  eMacroKind_Neg,                          // 0 - x
+  eMacroKind_ReadLSB,                      // Multibyte read
+  eMacroKind_ReadMSB,                      // Multibyte write
+  eMacroKind_Concat,                       // Magic concatenation syntax
+  eMacroKind_LastMacroKind = eMacroKind_ReadMSB
+};
+
+/// LookupExprInfo - Return information on the named token, if it is
+/// recognized.
+///
+/// \param Kind [out] - The Expr::Kind or MacroKind of the identifier.
+/// \param IsFixed [out] - True if the given kinds result and
+/// (expression) arguments are all of the same width.
+/// \param NumArgs [out] - The number of expression arguments for this
+/// kind. -1 indicates the kind is variadic or has non-expression
+/// arguments.
+/// \return True if the token is a valid kind or macro name.
+static bool LookupExprInfo(const Token &Tok, unsigned &Kind, 
+                           bool &IsFixed, int &NumArgs) {
+#define SetOK(kind, isfixed, numargs) (Kind=kind, IsFixed=isfixed,\
+                                       NumArgs=numargs, true)
+  assert(Tok.kind == Token::Identifier && "Unexpected token.");
+  
+  switch (Tok.length) {
+  case 2:
+    if (memcmp(Tok.start, "Eq", 2) == 0)
+      return SetOK(Expr::Eq, false, 2);
+    if (memcmp(Tok.start, "Ne", 2) == 0)
+      return SetOK(Expr::Ne, false, 2);
+
+    if (memcmp(Tok.start, "Or", 2) == 0)
+      return SetOK(Expr::Or, true, 2);
+    break;
+
+  case 3:
+    if (memcmp(Tok.start, "Add", 3) == 0)
+      return SetOK(Expr::Add, true, 2);
+    if (memcmp(Tok.start, "Sub", 3) == 0)
+      return SetOK(Expr::Sub, true, 2);
+    if (memcmp(Tok.start, "Mul", 3) == 0)
+      return SetOK(Expr::Mul, true, 2);
+
+    if (memcmp(Tok.start, "And", 3) == 0)
+      return SetOK(Expr::And, true, 2);
+    if (memcmp(Tok.start, "Shl", 3) == 0)
+      return SetOK(Expr::Shl, true, 2);
+    if (memcmp(Tok.start, "Xor", 3) == 0)
+      return SetOK(Expr::Xor, true, 2);
+
+    if (memcmp(Tok.start, "Not", 3) == 0)
+      return SetOK(eMacroKind_Not, true, 1);
+    if (memcmp(Tok.start, "Neg", 3) == 0)
+      return SetOK(eMacroKind_Neg, true, 1);
+    if (memcmp(Tok.start, "Ult", 3) == 0)
+      return SetOK(Expr::Ult, false, 2);
+    if (memcmp(Tok.start, "Ule", 3) == 0)
+      return SetOK(Expr::Ule, false, 2);
+    if (memcmp(Tok.start, "Ugt", 3) == 0)
+      return SetOK(Expr::Ugt, false, 2);
+    if (memcmp(Tok.start, "Uge", 3) == 0)
+      return SetOK(Expr::Uge, false, 2);
+    if (memcmp(Tok.start, "Slt", 3) == 0)
+      return SetOK(Expr::Slt, false, 2);
+    if (memcmp(Tok.start, "Sle", 3) == 0)
+      return SetOK(Expr::Sle, false, 2);
+    if (memcmp(Tok.start, "Sgt", 3) == 0)
+      return SetOK(Expr::Sgt, false, 2);
+    if (memcmp(Tok.start, "Sge", 3) == 0)
+      return SetOK(Expr::Sge, false, 2);
+    break;
+
+  case 4:
+    if (memcmp(Tok.start, "Read", 4) == 0)
+      return SetOK(Expr::Read, true, -1);
+    if (memcmp(Tok.start, "AShr", 4) == 0)
+      return SetOK(Expr::AShr, true, 2);
+    if (memcmp(Tok.start, "LShr", 4) == 0)
+      return SetOK(Expr::LShr, true, 2);
+
+    if (memcmp(Tok.start, "UDiv", 4) == 0)
+      return SetOK(Expr::UDiv, true, 2);
+    if (memcmp(Tok.start, "SDiv", 4) == 0)
+      return SetOK(Expr::SDiv, true, 2);
+    if (memcmp(Tok.start, "URem", 4) == 0)
+      return SetOK(Expr::URem, true, 2);
+    if (memcmp(Tok.start, "SRem", 4) == 0)
+      return SetOK(Expr::SRem, true, 2);
+    
+    if (memcmp(Tok.start, "SExt", 4) == 0)
+      return SetOK(Expr::SExt, false, 1);
+    if (memcmp(Tok.start, "ZExt", 4) == 0)
+      return SetOK(Expr::ZExt, false, 1);
+    break;
+    
+  case 6:
+    if (memcmp(Tok.start, "Concat", 6) == 0)
+      return SetOK(eMacroKind_Concat, false, -1); 
+    if (memcmp(Tok.start, "Select", 6) == 0)
+      return SetOK(Expr::Select, false, 3);
+    break;
+    
+  case 7:
+    if (memcmp(Tok.start, "Extract", 7) == 0)
+      return SetOK(Expr::Extract, false, -1);
+    if (memcmp(Tok.start, "ReadLSB", 7) == 0)
+      return SetOK(eMacroKind_ReadLSB, true, -1);
+    if (memcmp(Tok.start, "ReadMSB", 7) == 0)
+      return SetOK(eMacroKind_ReadMSB, true, -1);
+    break;
+  }
+
+  return false;
+#undef SetOK
+}
+
+/// ParseParenExpr - Parse a parenthesized expression with the given
+/// \arg ExpectedType. \arg ExpectedType can be invalid if the type
+/// cannot be inferred from the context.
+///
+/// paren-expr = '(' type number ')'
+/// paren-expr = '(' identifier [type] expr+ ')
+/// paren-expr = '(' ('Read' | 'ReadMSB' | 'ReadLSB') type expr update-list ')'
+ExprResult ParserImpl::ParseParenExpr(TypeResult FIXME_UNUSED) {
+  if (Tok.kind != Token::LParen) {
+    Error("unexpected token.");
+    ConsumeAnyToken();
+    return ExprResult();
+  }
+
+  ConsumeLParen();
+  
+  // Check for coercion case (w32 11).
+  if (Tok.kind == Token::KWWidth) {
+    TypeResult ExpectedType = ParseTypeSpecifier();
+
+    if (Tok.kind != Token::Number) {
+      Error("coercion can only apply to a number.");
+      SkipUntilRParen();
+      return ExprResult();
+    }
+    
+    // Make sure this was a type specifier we support.
+    ExprResult Res;
+    if (ExpectedType.isValid()) 
+      Res = ParseNumber(ExpectedType.get());
+    else
+      ConsumeToken();
+
+    ExpectRParen("unexpected argument in coercion.");  
+    return Res;
+  }
+  
+  if (Tok.kind != Token::Identifier) {
+    Error("unexpected token, expected expression.");
+    SkipUntilRParen();
+    return ExprResult();
+  }
+
+  Token Name = Tok;
+  ConsumeToken();
+
+  // FIXME: Use invalid type (i.e. width==0)?
+  Token TypeTok = Tok;
+  bool HasType = TypeTok.kind == Token::KWWidth;
+  TypeResult Type = HasType ? ParseTypeSpecifier() : Expr::Bool;
+
+  // FIXME: For now just skip to rparen on error. It might be nice
+  // to try and actually parse the child nodes though for error
+  // messages & better recovery?
+  if (!Type.isValid()) {
+    SkipUntilRParen();
+    return ExprResult();
+  }
+  Expr::Width ResTy = Type.get();
+
+  unsigned ExprKind;
+  bool IsFixed;
+  int NumArgs;
+  if (!LookupExprInfo(Name, ExprKind, IsFixed, NumArgs)) {
+    // FIXME: For now just skip to rparen on error. It might be nice
+    // to try and actually parse the child nodes though for error
+    // messages & better recovery?
+    Error("unknown expression kind.", Name);
+    SkipUntilRParen();
+    return ExprResult();
+  }
+
+  // See if we have to parse this form specially.
+  if (NumArgs == -1) {
+    switch (ExprKind) {
+    case eMacroKind_Concat:
+      return ParseConcatParenExpr(Name, ResTy);
+
+    case Expr::Extract:
+      return ParseExtractParenExpr(Name, ResTy);
+
+    case eMacroKind_ReadLSB:
+    case eMacroKind_ReadMSB:
+    case Expr::Read:
+      return ParseAnyReadParenExpr(Name, ExprKind, ResTy);
+
+    default:
+      Error("internal error, unimplemented special form.", Name);
+      SkipUntilRParen();
+      return ExprResult(ref<Expr>(0, ResTy));
+    }
+  }
+
+  switch (NumArgs) {
+  case 1:
+    return ParseUnaryParenExpr(Name, ExprKind, IsFixed, ResTy);
+  case 2:
+    return ParseBinaryParenExpr(Name, ExprKind, IsFixed, ResTy);
+  case 3:
+    if (ExprKind == Expr::Select)
+      return ParseSelectParenExpr(Name, ResTy);
+  default:
+    assert(0 && "Invalid argument kind (number of args).");
+    return ExprResult();
+  }
+}
+
+ExprResult ParserImpl::ParseUnaryParenExpr(const Token &Name,
+                                           unsigned Kind, bool IsFixed,
+                                           Expr::Width ResTy) {
+  if (Tok.kind == Token::RParen) {
+    Error("unexpected end of arguments.", Name);
+    ConsumeRParen();
+    return ref<Expr>(0, ResTy);
+  }
+
+  ExprResult Arg = ParseExpr(IsFixed ? ResTy : TypeResult());
+  if (!Arg.isValid())
+    Arg = ref<Expr>(0, ResTy);
+
+  ExpectRParen("unexpected argument in unary expression.");  
+  ExprHandle E = Arg.get();
+  switch (Kind) {
+  case eMacroKind_Not:
+    return EqExpr::alloc(ref<Expr>(0, E.getWidth()), E);
+  case eMacroKind_Neg:
+    return SubExpr::alloc(ref<Expr>(0, E.getWidth()), E);
+  case Expr::SExt:
+    // FIXME: Type check arguments.
+    return SExtExpr::alloc(E, ResTy);
+  case Expr::ZExt:
+    // FIXME: Type check arguments.
+    return ZExtExpr::alloc(E, ResTy);
+  default:
+    Error("internal error, unhandled kind.", Name);
+    return ref<Expr>(0, ResTy);
+  }
+}
+
+/// ParseMatchedBinaryArgs - Parse a pair of arguments who are
+/// expected to be of the same type. Upon return, if both LHS and RHS
+/// are valid then they are guaranteed to have the same type.
+///
+/// Name - The name token of the expression, for diagnostics.
+/// ExpectType - The expected type of the arguments, if known.
+void ParserImpl::ParseMatchedBinaryArgs(const Token &Name, 
+                                        TypeResult ExpectType,
+                                        ExprResult &LHS, ExprResult &RHS) {
+  if (Tok.kind == Token::RParen) {
+    Error("unexpected end of arguments.", Name);
+    ConsumeRParen();
+    return;
+  }
+
+  // Avoid NumberOrExprResult overhead and give more precise
+  // diagnostics when we know the type.
+  if (ExpectType.isValid()) {
+    LHS = ParseExpr(ExpectType);
+    if (Tok.kind == Token::RParen) {
+      Error("unexpected end of arguments.", Name);
+      ConsumeRParen();
+      return;
+    }
+    RHS = ParseExpr(ExpectType);
+  } else {
+    NumberOrExprResult LHS_NOE = ParseNumberOrExpr();
+
+    if (Tok.kind == Token::RParen) {
+      Error("unexpected end of arguments.", Name);
+      ConsumeRParen();
+      return;
+    }
+
+    if (LHS_NOE.isNumber()) {
+      NumberOrExprResult RHS_NOE = ParseNumberOrExpr();
+      
+      if (RHS_NOE.isNumber()) {
+        Error("ambiguous arguments to expression.", Name);
+      } else {
+        RHS = RHS_NOE.getExpr();
+        if (RHS.isValid())
+          LHS = ParseNumberToken(RHS.get().getWidth(), LHS_NOE.getNumber());
+      }
+    } else {
+      LHS = LHS_NOE.getExpr();
+      if (!LHS.isValid()) {
+        // FIXME: Should suppress ambiguity warnings here.
+        RHS = ParseExpr(TypeResult());
+      } else {
+        RHS = ParseExpr(LHS.get().getWidth());
+      }
+    }
+  }
+
+  ExpectRParen("unexpected argument to expression.");
+}
+
+ExprResult ParserImpl::ParseBinaryParenExpr(const Token &Name,
+                                           unsigned Kind, bool IsFixed,
+                                           Expr::Width ResTy) {
+  ExprResult LHS, RHS;
+  ParseMatchedBinaryArgs(Name, IsFixed ? TypeResult(ResTy) : TypeResult(), 
+                         LHS, RHS);
+  if (!LHS.isValid() || !RHS.isValid())
+    return ref<Expr>(0, ResTy);
+
+  ref<Expr> LHS_E = LHS.get(), RHS_E = RHS.get();
+  assert(LHS_E.getWidth() == RHS_E.getWidth() && "Mismatched types!");
+
+  switch (Kind) {    
+  case Expr::Add: return AddExpr::alloc(LHS_E, RHS_E);
+  case Expr::Sub: return SubExpr::alloc(LHS_E, RHS_E);
+  case Expr::Mul: return MulExpr::alloc(LHS_E, RHS_E);
+  case Expr::UDiv: return UDivExpr::alloc(LHS_E, RHS_E);
+  case Expr::SDiv: return SDivExpr::alloc(LHS_E, RHS_E);
+  case Expr::URem: return URemExpr::alloc(LHS_E, RHS_E);
+  case Expr::SRem: return SRemExpr::alloc(LHS_E, RHS_E);
+
+  case Expr::AShr: return AShrExpr::alloc(LHS_E, RHS_E);
+  case Expr::LShr: return LShrExpr::alloc(LHS_E, RHS_E);
+  case Expr::Shl: return AndExpr::alloc(LHS_E, RHS_E);
+
+  case Expr::And: return AndExpr::alloc(LHS_E, RHS_E);
+  case Expr::Or:  return OrExpr::alloc(LHS_E, RHS_E);
+  case Expr::Xor: return XorExpr::alloc(LHS_E, RHS_E);
+
+  case Expr::Eq:  return EqExpr::alloc(LHS_E, RHS_E);
+  case Expr::Ne:  return NeExpr::alloc(LHS_E, RHS_E);
+  case Expr::Ult: return UltExpr::alloc(LHS_E, RHS_E);
+  case Expr::Ule: return UleExpr::alloc(LHS_E, RHS_E);
+  case Expr::Ugt: return UgtExpr::alloc(LHS_E, RHS_E);
+  case Expr::Uge: return UgeExpr::alloc(LHS_E, RHS_E);
+  case Expr::Slt: return SltExpr::alloc(LHS_E, RHS_E);
+  case Expr::Sle: return SleExpr::alloc(LHS_E, RHS_E);
+  case Expr::Sgt: return SgtExpr::alloc(LHS_E, RHS_E);
+  case Expr::Sge: return SgeExpr::alloc(LHS_E, RHS_E);
+  default:
+    Error("FIXME: unhandled kind.", Name);
+    return ref<Expr>(0, ResTy);
+  }  
+}
+
+ExprResult ParserImpl::ParseSelectParenExpr(const Token &Name, 
+                                            Expr::Width ResTy) {
+  // FIXME: Why does this need to be here?
+  if (Tok.kind == Token::RParen) {
+    Error("unexpected end of arguments.", Name);
+    ConsumeRParen();
+    return ref<Expr>(0, ResTy);
+  }
+
+  ExprResult Cond = ParseExpr(Expr::Bool);
+  ExprResult LHS, RHS;
+  ParseMatchedBinaryArgs(Name, ResTy, LHS, RHS);
+  if (!Cond.isValid() || !LHS.isValid() || !RHS.isValid())
+    return ref<Expr>(0, ResTy);
+  return SelectExpr::alloc(Cond.get(), LHS.get(), RHS.get());
+}
+
+
+// need to decide if we want to allow n-ary Concat expressions in the
+// language
+ExprResult ParserImpl::ParseConcatParenExpr(const Token &Name,
+                                            Expr::Width ResTy) {
+  std::vector<ExprHandle> Kids;
+  
+  unsigned Width = 0;
+  while (Tok.kind != Token::RParen) {
+    ExprResult E = ParseExpr(TypeResult());
+
+    // Skip to end of expr on error.
+    if (!E.isValid()) {
+      SkipUntilRParen();
+      return ref<Expr>(0, ResTy);
+    }
+    
+    Kids.push_back(E.get());
+    Width += E.get().getWidth();
+  }
+  
+  ConsumeRParen();
+
+  if (Width != ResTy) {
+    Error("concat does not match expected result size.");
+    return ref<Expr>(0, ResTy);
+  }
+
+  return ConcatExpr::createN(Kids.size(), &Kids[0]);
+}
+
+ExprResult ParserImpl::ParseExtractParenExpr(const Token &Name,
+                                             Expr::Width ResTy) {
+  // FIXME: Pull out parse constant integer expression.
+  ExprResult OffsetExpr = ParseNumber(Expr::Int32);
+  ExprResult Child = ParseExpr(TypeResult());
+
+  ExpectRParen("unexpected argument to expression.");
+
+  if (!OffsetExpr.isValid() || !Child.isValid())
+    return ref<Expr>(0, ResTy);
+
+  assert(OffsetExpr.get().isConstant() && "ParseNumber returned non-constant.");
+  unsigned Offset = (unsigned) OffsetExpr.get().getConstantValue();
+
+  if (Offset + ResTy > Child.get().getWidth()) {
+    Error("extract out-of-range of child expression.", Name);
+    return ref<Expr>(0, ResTy);
+  }
+
+  return ExtractExpr::alloc(Child.get(), Offset, ResTy);
+}
+
+ExprResult ParserImpl::ParseAnyReadParenExpr(const Token &Name,
+                                             unsigned Kind,
+                                             Expr::Width ResTy) {
+  NumberOrExprResult Index = ParseNumberOrExpr();
+  VersionResult Array = ParseVersionSpecifier();
+  ExpectRParen("unexpected argument in read expression.");
+  
+  if (!Array.isValid())
+    return ref<Expr>(0, ResTy);
+
+  // FIXME: Need generic way to get array width. Needs to work with
+  // anonymous arrays.
+  Expr::Width ArrayDomainType = Expr::Int32;
+  Expr::Width ArrayRangeType = Expr::Int8;
+
+  // Coerce number to correct type.
+  ExprResult IndexExpr;
+  if (Index.isNumber())
+    IndexExpr = ParseNumberToken(ArrayDomainType, Index.getNumber());
+  else
+    IndexExpr = Index.getExpr();
+  
+  if (!IndexExpr.isValid())
+    return ref<Expr>(0, ResTy);
+  else if (IndexExpr.get().getWidth() != ArrayDomainType) {
+    Error("index width does not match array domain.");
+    return ref<Expr>(0, ResTy);
+  }
+
+  // FIXME: Check range width.
+
+  switch (Kind) {
+  default:
+    assert(0 && "Invalid kind.");
+    return ref<Expr>(0, ResTy);
+  case eMacroKind_ReadLSB:
+  case eMacroKind_ReadMSB: {
+    unsigned NumReads = ResTy / ArrayRangeType;
+    if (ResTy != NumReads*ArrayRangeType) {
+      Error("invalid ordered read (not multiple of range type).", Name);
+      return ref<Expr>(0, ResTy);
+    }
+    std::vector<ExprHandle> Kids;
+    Kids.reserve(NumReads);
+    ExprHandle Index = IndexExpr.get();
+    for (unsigned i=0; i<NumReads; ++i) {
+      // FIXME: using folding here
+      ExprHandle OffsetIndex = AddExpr::create(IndexExpr.get(),
+                                               ref<Expr>(i, ArrayDomainType));
+      Kids.push_back(ReadExpr::alloc(Array.get(), OffsetIndex));
+    }
+    if (Kind == eMacroKind_ReadLSB)
+      std::reverse(Kids.begin(), Kids.end());
+    return ConcatExpr::createN(NumReads, &Kids[0]);
+  }
+  case Expr::Read:
+    return ReadExpr::alloc(Array.get(), IndexExpr.get());
+  }
+}
+
+/// version-specifier = <identifier>
+/// version-specifier = [<identifier>:] [ version ]
+VersionResult ParserImpl::ParseVersionSpecifier() {
+  const Identifier *Label = 0;
+  if (Tok.kind == Token::Identifier) {
+    Token LTok = Tok;
+    Label = GetOrCreateIdentifier(Tok);
+    ConsumeToken();
+
+    // FIXME: hack: add array declarations and ditch this.
+    if (memcmp(Label->Name.c_str(), "arr", 3) == 0) {
+      // Declare or create array.
+      const ArrayDecl *&A = ArraySymTab[Label];
+      if (!A) {
+        //        Array = new ArrayDecl(Label, 0, 32, 8);
+        unsigned id = atoi(&Label->Name.c_str()[3]);
+        Array *root = new Array(0, id, 0);
+        // Create update list mapping of name -> array.
+        VersionSymTab.insert(std::make_pair(Label,
+                                            UpdateList(root, true, NULL)));
+      }
+    }
+
+    if (Tok.kind != Token::Colon) {
+      VersionSymTabTy::iterator it = VersionSymTab.find(Label);
+      
+      if (it == VersionSymTab.end()) {
+        Error("invalid update list label reference.", LTok);
+        return VersionResult(false,
+                             UpdateList(0, true, NULL));
+      }
+
+      return it->second;
+    }
+
+    ConsumeToken();
+    if (VersionSymTab.count(Label)) {
+      Error("duplicate update list label definition.", LTok);
+      Label = 0;
+    }
+  }
+
+  Token Start = Tok;
+  VersionResult Res = ParseVersion();
+  // Define update list to avoid use-of-undef errors.
+  if (!Res.isValid())
+    Res = VersionResult(false,
+                        UpdateList(0, true, NULL));
+  
+  if (Label)
+    VersionSymTab.insert(std::make_pair(Label, Res.get()));
+  return Res;
+}
+
+/// version - '[' update-list? ']' ['@' version-specifier]
+/// update-list - empty
+/// update-list - lhs '=' rhs [',' update-list]
+VersionResult ParserImpl::ParseVersion() {
+  if (Tok.kind != Token::LSquare)
+    return VersionResult(false, UpdateList(0, false, NULL));
+  
+  std::vector< std::pair<NumberOrExprResult, NumberOrExprResult> > Writes;
+  ConsumeLSquare();
+  for (;;) {
+    // FIXME: Type check exprs.
+
+    // FIXME: We need to do this (the above) anyway just to handle
+    // implicit constants correctly.
+    NumberOrExprResult LHS = ParseNumberOrExpr();
+    
+    if (Tok.kind != Token::Equals) {
+      Error("expected '='.", Tok);
+      break;
+    }
+    
+    ConsumeToken();
+    NumberOrExprResult RHS = ParseNumberOrExpr();
+
+    Writes.push_back(std::make_pair(LHS, RHS));
+    
+    if (Tok.kind == Token::Comma)
+      ConsumeToken();
+    else
+      break;
+  }
+  ExpectRSquare("expected close of update list");
+
+  VersionHandle Base(0, false, NULL);
+
+  // Anonymous array case.
+  if (Tok.kind != Token::At) { 
+    Array *root = new Array(0, 0, 0);
+    Base = UpdateList(root, false, NULL);
+  } else {
+    ConsumeToken();
+
+    VersionResult BaseRes = ParseVersionSpecifier();
+    if (!BaseRes.isValid())
+      return BaseRes;
+
+    Base = BaseRes.get();
+  }
+
+  Expr::Width ArrayDomainType = Expr::Int32;
+  Expr::Width ArrayRangeType = Expr::Int8;
+
+  for (std::vector< std::pair<NumberOrExprResult, NumberOrExprResult> >::reverse_iterator
+         it = Writes.rbegin(), ie = Writes.rend(); it != ie; ++it) {
+    ExprResult LHS, RHS;
+    // FIXME: This can be factored into common helper for coercing a
+    // NumberOrExpr into an Expr.
+    if (it->first.isNumber()) {
+      LHS = ParseNumberToken(ArrayDomainType, it->first.getNumber());
+    } else {
+      LHS = it->first.getExpr(); 
+      if (LHS.isValid() && LHS.get().getWidth() != ArrayDomainType) {
+        // FIXME: bad token location. We should maybe try and know the
+        // array up-front?
+        Error("invalid value in write index (doesn't match domain).", Tok);
+        LHS = ExprResult();
+      }
+    }
+
+    if (it->second.isNumber()) {
+      RHS = ParseNumberToken(ArrayRangeType, it->second.getNumber());
+    } else {
+      RHS = it->second.getExpr();
+      if (RHS.isValid() && RHS.get().getWidth() != ArrayRangeType) {
+        // FIXME: bad token location. We should maybe try and know the
+        // array up-front?
+        Error("invalid value in write assignment (doesn't match range).", Tok);
+        RHS = ExprResult();
+      }
+    }
+    
+    if (LHS.isValid() && RHS.isValid())
+      Base.extend(LHS.get(), RHS.get());
+  }
+
+  return Base;
+}
+
+/// ParseNumber - Parse a number of the given type.
+ExprResult ParserImpl::ParseNumber(Expr::Width Type) {
+  ExprResult Res = ParseNumberToken(Type, Tok);
+  ConsumeExpectedToken(Token::Number);
+  return Res;
+}
+
+/// ParseNumberToken - Parse a number of the given type from the given
+/// token.
+ExprResult ParserImpl::ParseNumberToken(Expr::Width Type, const Token &Tok) {
+  const char *S = Tok.start;
+  unsigned N = Tok.length;
+  unsigned Radix = 10, RadixBits = 4;
+  bool HasMinus = false;
+
+  // Detect +/- (a number token cannot have both).
+  if (S[0] == '+') {
+    ++S;
+    --N;
+  } else if (S[0] == '-') {
+    HasMinus = true;
+    ++S;
+    --N;
+  }
+
+  // Detect 0[box].
+  if ((Tok.length >= 2 && S[0] == '0') &&
+      (S[1] == 'b' || S[1] == 'o' || S[1] == 'x')) {
+    if (S[1] == 'b') {
+      Radix = 2; 
+      RadixBits = 1;
+    } else if (S[1] == 'o') {
+      Radix = 8;
+      RadixBits = 3;
+    } else {
+      Radix = 16;
+      RadixBits = 4;
+    }
+    S += 2;
+    N -= 2;
+
+    // Diagnose 0[box] with no trailing digits.
+    if (!N) {
+      Error("invalid numeric token (no digits).", Tok);
+      return ref<Expr>(0, Type);
+    }
+  }
+
+  // This is a simple but slow way to handle overflow.
+  APInt Val(std::max(64U, RadixBits * N), 0);
+  APInt RadixVal(Val.getBitWidth(), Radix);
+  APInt DigitVal(Val.getBitWidth(), 0);
+  for (unsigned i=0; i<N; ++i) {
+    unsigned Digit, Char = S[i];
+    
+    if (Char == '_')
+      continue;
+    
+    if ('0' <= Char && Char <= '9')
+      Digit = Char - '0';
+    else if ('a' <= Char && Char <= 'z')
+      Digit = Char - 'a' + 10;
+    else if ('A' <= Char && Char <= 'Z')
+      Digit = Char - 'A' + 10;
+    else {
+      Error("invalid character in numeric token.", Tok);
+      return ref<Expr>(0, Type);
+    }
+
+    if (Digit >= Radix) {
+      Error("invalid character in numeric token (out of range).", Tok);
+      return ref<Expr>(0, Type);
+    }
+
+    DigitVal = Digit;
+    Val = Val * RadixVal + DigitVal;
+  }
+
+  // FIXME: Actually do the check for overflow.
+  if (HasMinus)
+    Val = -Val;
+
+  return ExprResult(ref<Expr>(Val.trunc(Type).getZExtValue(), Type));
+}
+
+/// ParseTypeSpecifier - Parse a type specifier.
+///
+/// type = w[0-9]+
+TypeResult ParserImpl::ParseTypeSpecifier() {
+  assert(Tok.kind == Token::KWWidth && "Unexpected token.");
+
+  // FIXME: Need APInt technically.
+  Token TypeTok = Tok;
+  int width = atoi(std::string(Tok.start+1,Tok.length-1).c_str());
+  ConsumeToken();
+
+  // FIXME: We should impose some sort of maximum just for sanity?
+  return TypeResult(width);
+}
+
+void ParserImpl::Error(const char *Message, const Token &At) {
+  ++NumErrors;
+  if (MaxErrors && NumErrors >= MaxErrors)
+    return;
+
+  llvm::cerr << Filename 
+             << ":" << At.line << ":" << At.column 
+             << ": error: " << Message << "\n";
+
+  // Skip carat diagnostics on EOF token.
+  if (At.kind == Token::EndOfFile)
+    return;
+  
+  // Simple caret style diagnostics.
+  const char *LineBegin = At.start, *LineEnd = At.start,
+    *BufferBegin = TheMemoryBuffer->getBufferStart(),
+    *BufferEnd = TheMemoryBuffer->getBufferEnd();
+
+  // Run line pointers forward and back.
+  while (LineBegin > BufferBegin && 
+         LineBegin[-1] != '\r' && LineBegin[-1] != '\n')
+    --LineBegin;
+  while (LineEnd < BufferEnd && 
+         LineEnd[0] != '\r' && LineEnd[0] != '\n')
+    ++LineEnd;
+
+  // Show the line.
+  llvm::cerr << std::string(LineBegin, LineEnd) << "\n";
+
+  // Show the caret or squiggly, making sure to print back spaces the
+  // same.
+  for (const char *S=LineBegin; S != At.start; ++S)
+    llvm::cerr << (isspace(*S) ? *S : ' ');
+  if (At.length > 1) {
+    for (unsigned i=0; i<At.length; ++i)
+      llvm::cerr << '~';
+  } else
+    llvm::cerr << '^';
+  llvm::cerr << '\n';
+}
+
+// AST API
+// FIXME: Move out of parser.
+
+Decl::Decl() {}
+
+void QueryCommand::dump() {
+  // FIXME: This is masking the difference between an actual query and
+  // a query decl.
+  ExprPPrinter::printQuery(std::cerr, 
+                           ConstraintManager(Constraints), 
+                           Query);
+}
+
+// Public parser API
+
+Parser::Parser() {
+}
+
+Parser::~Parser() {
+}
+
+Parser *Parser::Create(const std::string Filename,
+                       const MemoryBuffer *MB) {
+  ParserImpl *P = new ParserImpl(Filename, MB);
+  P->Initialize();
+  return P;
+}

Added: klee/trunk/lib/Expr/Updates.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Expr/Updates.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Expr/Updates.cpp (added)
+++ klee/trunk/lib/Expr/Updates.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,126 @@
+//===-- Updates.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/Expr.h"
+
+#include <cassert>
+
+using namespace klee;
+
+///
+
+UpdateNode::UpdateNode(const UpdateNode *_next, 
+                       const ref<Expr> &_index, 
+                       const ref<Expr> &_value) 
+  : refCount(0),
+    stpArray(0),
+    next(_next),
+    index(_index),
+    value(_value) {
+  assert(_value.getWidth() == Expr::Int8 && "Update value should be 8-bit wide.");
+  computeHash();
+  if (next) {
+    ++next->refCount;
+    size = 1 + next->size;
+  }
+  else size = 1;
+}
+
+extern "C" void vc_DeleteExpr(void*);
+
+UpdateNode::~UpdateNode() {
+  // XXX gross
+  if (stpArray)
+    ::vc_DeleteExpr(stpArray);
+}
+
+int UpdateNode::compare(const UpdateNode &b) const {
+  if (int i = index.compare(b.index)) 
+    return i;
+  return value.compare(b.value);
+}
+
+unsigned UpdateNode::computeHash() {
+  hashValue = index.hash() ^ value.hash();
+  if (next)
+    hashValue ^= next->hash();
+  return hashValue;
+}
+
+///
+
+UpdateList::UpdateList(const Array *_root, bool _isRooted,
+                       const UpdateNode *_head)
+  : root(_root),
+    head(_head),
+    isRooted(_isRooted) {
+  if (head) ++head->refCount;
+}
+
+UpdateList::UpdateList(const UpdateList &b)
+  : root(b.root),
+    head(b.head),
+    isRooted(b.isRooted) {
+  if (head) ++head->refCount;
+}
+
+UpdateList::~UpdateList() {
+  // We need to be careful and avoid recursion here. We do this in
+  // cooperation with the private dtor of UpdateNode which does not
+  // recursively free its tail.
+  while (head && --head->refCount==0) {
+    const UpdateNode *n = head->next;
+    delete head;
+    head = n;
+  }
+}
+
+UpdateList &UpdateList::operator=(const UpdateList &b) {
+  if (b.head) ++b.head->refCount;
+  if (head && --head->refCount==0) delete head;
+  root = b.root;
+  head = b.head;
+  isRooted = b.isRooted;
+  return *this;
+}
+
+void UpdateList::extend(const ref<Expr> &index, const ref<Expr> &value) {
+  if (head) --head->refCount;
+  head = new UpdateNode(head, index, value);
+  ++head->refCount;
+}
+
+int UpdateList::compare(const UpdateList &b) const {
+  // use object id to increase determinism
+  if (root->id != b.root->id) 
+    return root->id < b.root->id ? -1 : 1;
+  
+  if (getSize() < b.getSize()) return -1;
+  else if (getSize() > b.getSize()) return 1;    
+
+  // XXX build comparison into update, make fast
+  const UpdateNode *an=head, *bn=b.head;
+  for (; an && bn; an=an->next,bn=bn->next) {
+    if (an==bn) { // exploit shared list structure
+      return 0;
+    } else {
+      if (int res = an->compare(*bn))
+        return res;
+    }
+  }
+  assert(!an && !bn);
+  return 0;
+}
+
+unsigned UpdateList::hash() const {
+  unsigned res = root->id * Expr::MAGIC_HASH_CONSTANT;
+  if (head)
+    res ^= head->hash();
+  return res;
+}

Added: klee/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Makefile (added)
+++ klee/trunk/lib/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+#===-- lib/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=..
+
+PARALLEL_DIRS=Basic Support Expr Solver Module Core
+
+include $(LEVEL)/Makefile.common
+

Added: klee/trunk/lib/Module/Checks.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/Checks.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/Checks.cpp (added)
+++ klee/trunk/lib/Module/Checks.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,68 @@
+//===-- Checks.cpp --------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Passes.h"
+
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/InstrTypes.h"
+#include "llvm/Instruction.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Type.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Target/TargetData.h"
+
+using namespace llvm;
+using namespace klee;
+
+char DivCheckPass::ID;
+
+bool DivCheckPass::runOnModule(Module &M) { 
+  Function *divZeroCheckFunction = 0;
+
+  bool moduleChanged = false;
+  
+  for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) {
+    for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b) {
+      for (BasicBlock::iterator i = b->begin(), ie = b->end(); i != ie; ++i) {     
+          if (BinaryOperator* binOp = dyn_cast<BinaryOperator>(i)) {
+          // find all [s|u][div|mod] instructions
+          Instruction::BinaryOps opcode = binOp->getOpcode();
+          if (opcode == Instruction::SDiv || opcode == Instruction::UDiv ||
+              opcode == Instruction::SRem || opcode == Instruction::URem) {
+            
+            CastInst *denominator =
+              CastInst::CreateIntegerCast(i->getOperand(1),
+                                          (Type*)Type::Int64Ty,
+                                          false,  /* sign doesn't matter */
+                                          "int_cast_to_i64",
+                                          i);
+            
+            // Lazily bind the function to avoid always importing it.
+            if (!divZeroCheckFunction) {
+              Constant *fc = M.getOrInsertFunction("klee_div_zero_check", 
+                                                   Type::VoidTy, 
+                                                   Type::Int64Ty, NULL);
+              divZeroCheckFunction = cast<Function>(fc);
+            }
+
+	    CallInst::Create(divZeroCheckFunction, denominator, "", &*i);
+            moduleChanged = true;
+          }
+        }
+      }
+    }
+  }
+  return moduleChanged;
+}

Added: klee/trunk/lib/Module/InstructionInfoTable.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/InstructionInfoTable.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/InstructionInfoTable.cpp (added)
+++ klee/trunk/lib/Module/InstructionInfoTable.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,196 @@
+//===-- InstructionInfoTable.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/Internal/Module/InstructionInfoTable.h"
+
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Linker.h"
+#include "llvm/Module.h"
+#include "llvm/Assembly/AsmAnnotationWriter.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Analysis/ValueTracking.h"
+
+#include <map>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+using namespace llvm;
+using namespace klee;
+
+class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter {
+public:
+  void emitInstructionAnnot(const Instruction *i, llvm::raw_ostream &os) {
+    os << "%%%" << (uintptr_t) i;
+  }
+};
+        
+static void buildInstructionToLineMap(Module *m,
+                                      std::map<const Instruction*, unsigned> &out) {  
+  InstructionToLineAnnotator a;
+  std::ostringstream buffer;
+  m->print(buffer, &a);
+  std::string str = buffer.str();
+  const char *s;
+
+  unsigned line = 1;
+  for (s=str.c_str(); *s; s++) {
+    if (*s=='\n') {
+      line++;
+      if (s[1]=='%' && s[2]=='%' && s[3]=='%') {
+        s += 4;
+        char *end;
+        unsigned long long value = strtoull(s, &end, 10);
+        if (end!=s) {
+          out.insert(std::make_pair((const Instruction*) value, line));
+        }
+        s = end;
+      }
+    }
+  }
+}
+
+static std::string getDSPIPath(DbgStopPointInst *dspi) {
+  std::string dir, file;
+  bool res = GetConstantStringInfo(dspi->getDirectory(), dir);
+  assert(res && "GetConstantStringInfo failed");
+  res = GetConstantStringInfo(dspi->getFileName(), file);
+  assert(res && "GetConstantStringInfo failed");
+  if (dir.empty()) {
+    return file;
+  } else if (*dir.rbegin() == '/') {
+    return dir + file;
+  } else {
+    return dir + "/" + file;
+  }
+}
+
+InstructionInfoTable::InstructionInfoTable(Module *m) 
+  : dummyString(""), dummyInfo(0, dummyString, 0, 0) {
+  unsigned id = 0;
+  std::map<const Instruction*, unsigned> lineTable;
+  buildInstructionToLineMap(m, lineTable);
+
+  for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); 
+       fnIt != fn_ie; ++fnIt) {
+    const std::string *initialFile = &dummyString;
+    unsigned initialLine = 0;
+
+    // It may be better to look for the closest stoppoint to the entry
+    // following the CFG, but it is not clear that it ever matters in
+    // practice.
+    for (inst_iterator it = inst_begin(fnIt), ie = inst_end(fnIt);
+         it != ie; ++it) {
+      if (DbgStopPointInst *dspi = dyn_cast<DbgStopPointInst>(&*it)) {
+        initialFile = internString(getDSPIPath(dspi));
+        initialLine = dspi->getLine();
+        break;
+      }
+    }
+    
+    typedef std::map<BasicBlock*, std::pair<const std::string*,unsigned> > 
+      sourceinfo_ty;
+    sourceinfo_ty sourceInfo;
+    for (llvm::Function::iterator bbIt = fnIt->begin(), bbie = fnIt->end(); 
+         bbIt != bbie; ++bbIt) {
+      std::pair<sourceinfo_ty::iterator, bool>
+        res = sourceInfo.insert(std::make_pair(bbIt,
+                                               std::make_pair(initialFile,
+                                                              initialLine)));
+      if (!res.second)
+        continue;
+
+      std::vector<BasicBlock*> worklist;
+      worklist.push_back(bbIt);
+
+      do {
+        BasicBlock *bb = worklist.back();
+        worklist.pop_back();
+
+        sourceinfo_ty::iterator si = sourceInfo.find(bb);
+        assert(si != sourceInfo.end());
+        const std::string *file = si->second.first;
+        unsigned line = si->second.second;
+        
+        for (BasicBlock::iterator it = bb->begin(), ie = bb->end();
+             it != ie; ++it) {
+          Instruction *instr = it;
+          unsigned assemblyLine = 0;
+          std::map<const Instruction*, unsigned>::const_iterator ltit = 
+            lineTable.find(instr);
+          if (ltit!=lineTable.end())
+            assemblyLine = ltit->second;
+          if (DbgStopPointInst *dspi = dyn_cast<DbgStopPointInst>(instr)) {
+            file = internString(getDSPIPath(dspi));
+            line = dspi->getLine();
+          }
+          infos.insert(std::make_pair(instr,
+                                      InstructionInfo(id++,
+                                                      *file,
+                                                      line,
+                                                      assemblyLine)));        
+        }
+        
+        for (succ_iterator it = succ_begin(bb), ie = succ_end(bb); 
+             it != ie; ++it) {
+          if (sourceInfo.insert(std::make_pair(*it,
+                                               std::make_pair(file, line))).second)
+            worklist.push_back(*it);
+        }
+      } while (!worklist.empty());
+    }
+  }
+}
+
+InstructionInfoTable::~InstructionInfoTable() {
+  for (std::set<const std::string *, ltstr>::iterator
+         it = internedStrings.begin(), ie = internedStrings.end();
+       it != ie; ++it)
+    delete *it;
+}
+
+const std::string *InstructionInfoTable::internString(std::string s) {
+  std::set<const std::string *, ltstr>::iterator it = internedStrings.find(&s);
+  if (it==internedStrings.end()) {
+    std::string *interned = new std::string(s);
+    internedStrings.insert(interned);
+    return interned;
+  } else {
+    return *it;
+  }
+}
+
+unsigned InstructionInfoTable::getMaxID() const {
+  return infos.size();
+}
+
+const InstructionInfo &
+InstructionInfoTable::getInfo(const Instruction *inst) const {
+  std::map<const llvm::Instruction*, InstructionInfo>::const_iterator it = 
+    infos.find(inst);
+  if (it==infos.end()) {
+    return dummyInfo;
+  } else {
+    return it->second;
+  }
+}
+
+const InstructionInfo &
+InstructionInfoTable::getFunctionInfo(const Function *f) const {
+  if (f->isDeclaration()) {
+    return dummyInfo;
+  } else {
+    return getInfo(f->begin()->begin());
+  }
+}

Added: klee/trunk/lib/Module/IntrinsicCleaner.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/IntrinsicCleaner.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/IntrinsicCleaner.cpp (added)
+++ klee/trunk/lib/Module/IntrinsicCleaner.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,119 @@
+//===-- IntrinsicCleaner.cpp ----------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Passes.h"
+
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/InstrTypes.h"
+#include "llvm/Instruction.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Type.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Target/TargetData.h"
+
+using namespace llvm;
+
+namespace klee {
+
+char IntrinsicCleanerPass::ID;
+
+bool IntrinsicCleanerPass::runOnModule(Module &M) {
+  bool dirty = false;
+  for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f)
+    for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b)
+        dirty |= runOnBasicBlock(*b);
+  return dirty;
+}
+
+bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { 
+  bool dirty = false;
+
+  for (BasicBlock::iterator i = b.begin(), ie = b.end(); i != ie;) {     
+    IntrinsicInst *ii = dyn_cast<IntrinsicInst>(&*i);
+    // increment now since LowerIntrinsic deletion makes iterator invalid.
+    ++i;  
+    if(ii) {
+      switch (ii->getIntrinsicID()) {
+      case Intrinsic::vastart:
+      case Intrinsic::vaend:
+        break;
+        
+        // Lower vacopy so that object resolution etc is handled by
+        // normal instructions.  FIXME: This is broken for non-x86_32.
+      case Intrinsic::vacopy: { // (dst, src) -> *((i8**) dst) = *((i8**) src)
+        Value *dst = ii->getOperand(1);
+        Value *src = ii->getOperand(2);
+        Type *i8pp = PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty));
+        Value *castedDst = CastInst::CreatePointerCast(dst, i8pp, "vacopy.cast.dst", ii);
+        Value *castedSrc = CastInst::CreatePointerCast(src, i8pp, "vacopy.cast.src", ii);
+        Value *load = new LoadInst(castedSrc, "vacopy.read", ii);
+        new StoreInst(load, castedDst, false, ii);
+        ii->removeFromParent();
+        delete ii;
+        break;
+      }
+
+      case Intrinsic::dbg_stoppoint: {
+        // We can remove this stoppoint if the next instruction is
+        // sure to be another stoppoint. This is nice for cleanliness
+        // but also important for switch statements where it can allow
+        // the targets to be joined.
+        bool erase = false;
+        if (isa<DbgStopPointInst>(i) ||
+            isa<UnreachableInst>(i)) {
+          erase = true;
+        } else if (isa<BranchInst>(i) ||
+                   isa<SwitchInst>(i)) {
+          BasicBlock *bb = i->getParent();
+          erase = true;
+          for (succ_iterator it=succ_begin(bb), ie=succ_end(bb);
+               it!=ie; ++it) {
+            if (!isa<DbgStopPointInst>(it->getFirstNonPHI())) {
+              erase = false;
+              break;
+            }
+          }
+        }
+
+        if (erase) {
+          ii->eraseFromParent();
+          dirty = true;
+        }
+        break;
+      }
+
+      case Intrinsic::dbg_region_start:
+      case Intrinsic::dbg_region_end:
+      case Intrinsic::dbg_func_start:
+      case Intrinsic::dbg_declare:
+        // Remove these regardless of lower intrinsics flag. This can
+        // be removed once IntrinsicLowering is fixed to not have bad
+        // caches.
+        ii->eraseFromParent();
+        dirty = true;
+        break;
+                    
+      default:
+        if (LowerIntrinsics)
+          IL->LowerIntrinsicCall(ii);
+        dirty = true;
+        break;
+      }
+    }
+  }
+
+  return dirty;
+}
+}

Added: klee/trunk/lib/Module/KInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/KInstruction.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/KInstruction.cpp (added)
+++ klee/trunk/lib/Module/KInstruction.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+//===-- KInstruction.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/Internal/Module/KInstruction.h"
+
+using namespace llvm;
+using namespace klee;
+
+/***/
+
+KInstruction::~KInstruction() {
+  delete[] operands;
+}

Added: klee/trunk/lib/Module/KModule.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/KModule.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/KModule.cpp (added)
+++ klee/trunk/lib/Module/KModule.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,506 @@
+//===-- KModule.cpp -------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: This does not belong here.
+#include "../Core/Common.h"
+
+#include "klee/Internal/Module/KModule.h"
+
+#include "Passes.h"
+
+#include "klee/Interpreter.h"
+#include "klee/Internal/Module/Cell.h"
+#include "klee/Internal/Module/KInstruction.h"
+#include "klee/Internal/Module/InstructionInfoTable.h"
+#include "klee/Internal/Support/ModuleUtil.h"
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/ValueSymbolTable.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/System/Path.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/Scalar.h"
+
+#include <sstream>
+
+using namespace llvm;
+using namespace klee;
+
+namespace {
+  enum SwitchImplType {
+    eSwitchTypeSimple,
+    eSwitchTypeLLVM,
+    eSwitchTypeInternal
+  };
+
+  cl::list<std::string>
+  MergeAtExit("merge-at-exit");
+    
+  cl::opt<bool>
+  NoTruncateSourceLines("no-truncate-source-lines",
+                        cl::desc("Don't truncate long lines in the output source"));
+
+  cl::opt<bool>
+  OutputSource("output-source",
+               cl::desc("Write the assembly for the final transformed source"),
+               cl::init(true));
+
+  cl::opt<bool>
+  OutputModule("output-module",
+               cl::desc("Write the bitcode for the final transformed module"),
+               cl::init(false));
+
+  cl::opt<SwitchImplType>
+  SwitchType("switch-type", cl::desc("Select the implementation of switch"),
+             cl::values(clEnumValN(eSwitchTypeSimple, "simple", 
+                                   "lower to ordered branches"),
+                        clEnumValN(eSwitchTypeLLVM, "llvm", 
+                                   "lower using LLVM"),
+                        clEnumValN(eSwitchTypeInternal, "internal", 
+                                   "execute switch internally"),
+                        clEnumValEnd),
+             cl::init(eSwitchTypeInternal));
+  
+  cl::opt<bool>
+  DebugPrintEscapingFunctions("debug-print-escaping-functions", 
+                              cl::desc("Print functions whose address is taken."));
+}
+
+KModule::KModule(Module *_module) 
+  : module(_module),
+    targetData(new TargetData(module)),
+    dbgStopPointFn(0),
+    kleeMergeFn(0),
+    infos(0),
+    constantTable(0) {
+}
+
+KModule::~KModule() {
+  delete[] constantTable;
+  delete infos;
+
+  for (std::vector<KFunction*>::iterator it = functions.begin(), 
+         ie = functions.end(); it != ie; ++it)
+    delete *it;
+
+  delete targetData;
+  delete module;
+}
+
+/***/
+
+namespace llvm {
+extern void Optimize(Module*);
+}
+
+// what a hack
+static Function *getStubFunctionForCtorList(Module *m,
+                                            GlobalVariable *gv, 
+                                            std::string name) {
+  assert(!gv->isDeclaration() && !gv->hasInternalLinkage() &&
+         "do not support old LLVM style constructor/destructor lists");
+  
+  std::vector<const Type*> nullary;
+
+  Function *fn = Function::Create(FunctionType::get(Type::VoidTy, 
+						    nullary, false),
+				  GlobalVariable::InternalLinkage, 
+				  name,
+                              m);
+  BasicBlock *bb = BasicBlock::Create("entry", fn);
+  
+  // From lli:
+  // Should be an array of '{ int, void ()* }' structs.  The first value is
+  // the init priority, which we ignore.
+  ConstantArray *arr = dyn_cast<ConstantArray>(gv->getInitializer());
+  if (arr) {
+    for (unsigned i=0; i<arr->getNumOperands(); i++) {
+      ConstantStruct *cs = cast<ConstantStruct>(arr->getOperand(i));
+      assert(cs->getNumOperands()==2 && "unexpected element in ctor initializer list");
+      
+      Constant *fp = cs->getOperand(1);      
+      if (!fp->isNullValue()) {
+        if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp))
+          fp = ce->getOperand(0);
+
+        if (Function *f = dyn_cast<Function>(fp)) {
+	  CallInst::Create(f, "", bb);
+        } else {
+          assert(0 && "unable to get function pointer from ctor initializer list");
+        }
+      }
+    }
+  }
+  
+  ReturnInst::Create(bb);
+
+  return fn;
+}
+
+static void injectStaticConstructorsAndDestructors(Module *m) {
+  GlobalVariable *ctors = m->getNamedGlobal("llvm.global_ctors");
+  GlobalVariable *dtors = m->getNamedGlobal("llvm.global_dtors");
+  
+  if (ctors || dtors) {
+    Function *mainFn = m->getFunction("main");
+    assert(mainFn && "unable to find main function");
+
+    if (ctors)
+    CallInst::Create(getStubFunctionForCtorList(m, ctors, "klee.ctor_stub"),
+		     "", mainFn->begin()->begin());
+    if (dtors) {
+      Function *dtorStub = getStubFunctionForCtorList(m, dtors, "klee.dtor_stub");
+      for (Function::iterator it = mainFn->begin(), ie = mainFn->end();
+           it != ie; ++it) {
+        if (isa<ReturnInst>(it->getTerminator()))
+	  CallInst::Create(dtorStub, "", it->getTerminator());
+      }
+    }
+  }
+}
+
+static void forceImport(Module *m, const char *name, const Type *retType, ...) {
+  // If module lacks an externally visible symbol for the name then we
+  // need to create one. We have to look in the symbol table because
+  // we want to check everything (global variables, functions, and
+  // aliases).
+
+  Value *v = m->getValueSymbolTable().lookup(name);
+  GlobalValue *gv = dyn_cast_or_null<GlobalValue>(v);
+
+  if (!gv || gv->hasInternalLinkage()) {
+    va_list ap;
+
+    va_start(ap, retType);
+    std::vector<const Type *> argTypes;
+    while (const Type *t = va_arg(ap, const Type*))
+      argTypes.push_back(t);
+    va_end(ap);
+
+    m->getOrInsertFunction(name, FunctionType::get(retType, argTypes, false));
+  }
+}
+
+void KModule::prepare(const Interpreter::ModuleOptions &opts,
+                      InterpreterHandler *ih) {
+  if (!MergeAtExit.empty()) {
+    Function *mergeFn = module->getFunction("klee_merge");
+    if (!mergeFn) {
+      const llvm::FunctionType *Ty = 
+        FunctionType::get(Type::VoidTy, std::vector<const Type*>(), false);
+      mergeFn = Function::Create(Ty, GlobalVariable::ExternalLinkage,
+				 "klee_merge",
+				 module);
+    }
+
+    for (cl::list<std::string>::iterator it = MergeAtExit.begin(), 
+           ie = MergeAtExit.end(); it != ie; ++it) {
+      std::string &name = *it;
+      Function *f = module->getFunction(name);
+      if (!f) {
+        klee_error("cannot insert merge-at-exit for: %s (cannot find)",
+                   name.c_str());
+      } else if (f->isDeclaration()) {
+        klee_error("cannot insert merge-at-exit for: %s (external)",
+                   name.c_str());
+      }
+
+      BasicBlock *exit = BasicBlock::Create("exit", f);
+      PHINode *result = 0;
+      if (f->getReturnType() != Type::VoidTy)
+        result = PHINode::Create(f->getReturnType(), "retval", exit);
+      CallInst::Create(mergeFn, "", exit);
+      ReturnInst::Create(result, exit);
+
+      llvm::cerr << "KLEE: adding klee_merge at exit of: " << name << "\n";
+      for (llvm::Function::iterator bbit = f->begin(), bbie = f->end(); 
+           bbit != bbie; ++bbit) {
+        if (&*bbit != exit) {
+          Instruction *i = bbit->getTerminator();
+          if (i->getOpcode()==Instruction::Ret) {
+            if (result) {
+              result->addIncoming(i->getOperand(0), bbit);
+            }
+            i->eraseFromParent();
+	    BranchInst::Create(exit, bbit);
+          }
+        }
+      }
+    }
+  }
+
+  // Inject checks prior to optimization... we also perform the
+  // invariant transformations that we will end up doing later so that
+  // optimize is seeing what is as close as possible to the final
+  // module.
+  PassManager pm;
+  pm.add(new RaiseAsmPass());
+  if (opts.CheckDivZero) pm.add(new DivCheckPass());
+  // FIXME: This false here is to work around a bug in
+  // IntrinsicLowering which caches values which may eventually be
+  // deleted (via RAUW). This can be removed once LLVM fixes this
+  // issue.
+  pm.add(new IntrinsicCleanerPass(*targetData, false));
+  pm.run(*module);
+
+  if (opts.Optimize)
+    Optimize(module);
+
+  // Force importing functions required by intrinsic lowering. Kind of
+  // unfortunate clutter when we don't need them but we won't know
+  // that until after all linking and intrinsic lowering is
+  // done. After linking and passes we just try to manually trim these
+  // by name. We only add them if such a function doesn't exist to
+  // avoid creating stale uses.
+
+  forceImport(module, "memcpy", PointerType::getUnqual(Type::Int8Ty),
+              PointerType::getUnqual(Type::Int8Ty),
+              PointerType::getUnqual(Type::Int8Ty),
+              targetData->getIntPtrType(), (Type*) 0);
+  forceImport(module, "memmove", PointerType::getUnqual(Type::Int8Ty),
+              PointerType::getUnqual(Type::Int8Ty),
+              PointerType::getUnqual(Type::Int8Ty),
+              targetData->getIntPtrType(), (Type*) 0);
+  forceImport(module, "memset", PointerType::getUnqual(Type::Int8Ty),
+              PointerType::getUnqual(Type::Int8Ty),
+              Type::Int32Ty,
+              targetData->getIntPtrType(), (Type*) 0);
+
+  // FIXME: Missing force import for various math functions.
+
+  // FIXME: Find a way that we can test programs without requiring
+  // this to be linked in, it makes low level debugging much more
+  // annoying.
+  llvm::sys::Path path(opts.LibraryDir);
+  path.appendComponent("libintrinsic.bca");
+  module = linkWithLibrary(module, path.c_str());
+
+  // Needs to happen after linking (since ctors/dtors can be modified)
+  // and optimization (since global optimization can rewrite lists).
+  injectStaticConstructorsAndDestructors(module);
+
+  // Finally, run the passes that maintain invariants we expect during
+  // interpretation. We run the intrinsic cleaner just in case we
+  // linked in something with intrinsics but any external calls are
+  // going to be unresolved. We really need to handle the intrinsics
+  // directly I think?
+  PassManager pm3;
+  pm3.add(createCFGSimplificationPass());
+  switch(SwitchType) {
+  case eSwitchTypeInternal: break;
+  case eSwitchTypeSimple: pm3.add(new LowerSwitchPass()); break;
+  case eSwitchTypeLLVM:  pm3.add(createLowerSwitchPass()); break;
+  default: klee_error("invalid --switch-type");
+  }
+  pm3.add(new IntrinsicCleanerPass(*targetData));
+  pm3.add(new PhiCleanerPass());
+  pm3.run(*module);
+
+  // For cleanliness see if we can discard any of the functions we
+  // forced to import.
+  Function *f;
+  f = module->getFunction("memcpy");
+  if (f && f->use_empty()) f->eraseFromParent();
+  f = module->getFunction("memmove");
+  if (f && f->use_empty()) f->eraseFromParent();
+  f = module->getFunction("memset");
+  if (f && f->use_empty()) f->eraseFromParent();
+
+
+  // Write out the .ll assembly file. We truncate long lines to work
+  // around a kcachegrind parsing bug (it puts them on new lines), so
+  // that source browsing works.
+  if (OutputSource) {
+    std::ostream *os = ih->openOutputFile("assembly.ll");
+    assert(os && os->good() && "unable to open source output");
+
+    // We have an option for this in case the user wants a .ll they
+    // can compile.
+    if (NoTruncateSourceLines) {
+      *os << *module;
+    } else {
+      bool truncated = false;
+      std::stringstream buffer;
+      buffer << *module;
+      std::string string = buffer.str();
+      const char *position = string.c_str();
+
+      for (;;) {
+        const char *end = index(position, '\n');
+        if (!end) {
+          *os << position;
+          break;
+        } else {
+          unsigned count = (end - position) + 1;
+          if (count<255) {
+            os->write(position, count);
+          } else {
+            os->write(position, 254);
+            *os << "\n";
+            truncated = true;
+          }
+          position = end+1;
+        }
+      }
+    }
+
+    delete os;
+  }
+
+  if (OutputModule) {
+    std::ostream *f = ih->openOutputFile("final.bc");
+    WriteBitcodeToFile(module, *f);
+    delete f;
+  }
+
+  dbgStopPointFn = module->getFunction("llvm.dbg.stoppoint");
+  kleeMergeFn = module->getFunction("klee_merge");
+
+  /* Build shadow structures */
+
+  infos = new InstructionInfoTable(module);  
+  
+  for (Module::iterator it = module->begin(), ie = module->end();
+       it != ie; ++it) {
+    if (it->isDeclaration())
+      continue;
+
+    KFunction *kf = new KFunction(it, this);
+    
+    for (unsigned i=0; i<kf->numInstructions; ++i) {
+      KInstruction *ki = kf->instructions[i];
+      ki->info = &infos->getInfo(ki->inst);
+    }
+
+    functions.push_back(kf);
+    functionMap.insert(std::make_pair(it, kf));
+  }
+
+  /* Compute various interesting properties */
+
+  for (std::vector<KFunction*>::iterator it = functions.begin(), 
+         ie = functions.end(); it != ie; ++it) {
+    KFunction *kf = *it;
+    if (functionEscapes(kf->function))
+      escapingFunctions.insert(kf->function);
+  }
+
+  if (DebugPrintEscapingFunctions && !escapingFunctions.empty()) {
+    llvm::cerr << "KLEE: escaping functions: [";
+    for (std::set<Function*>::iterator it = escapingFunctions.begin(), 
+         ie = escapingFunctions.end(); it != ie; ++it) {
+      llvm::cerr << (*it)->getName() << ", ";
+    }
+    llvm::cerr << "]\n";
+  }
+}
+
+KConstant* KModule::getKConstant(Constant *c) {
+  std::map<llvm::Constant*, KConstant*>::iterator it = constantMap.find(c);
+  if (it != constantMap.end())
+    return it->second;
+  return NULL;
+}
+
+unsigned KModule::getConstantID(Constant *c, KInstruction* ki) {
+  KConstant *kc = getKConstant(c);
+  if (kc)
+    return kc->id;  
+
+  unsigned id = constants.size();
+  kc = new KConstant(c, id, ki);
+  constantMap.insert(std::make_pair(c, kc));
+  constants.push_back(c);
+  return id;
+}
+
+/***/
+
+KConstant::KConstant(llvm::Constant* _ct, unsigned _id, KInstruction* _ki) {
+  ct = _ct;
+  id = _id;
+  ki = _ki;
+}
+
+/***/
+
+KFunction::KFunction(llvm::Function *_function,
+                     KModule *km) 
+  : function(_function),
+    numArgs(function->arg_size()),
+    numInstructions(0),
+    trackCoverage(true) {
+  for (llvm::Function::iterator bbit = function->begin(), 
+         bbie = function->end(); bbit != bbie; ++bbit) {
+    BasicBlock *bb = bbit;
+    basicBlockEntry[bb] = numInstructions;
+    numInstructions += bb->size();
+  }
+
+  instructions = new KInstruction*[numInstructions];
+
+  std::map<Instruction*, unsigned> registerMap;
+
+  // The first arg_size() registers are reserved for formals.
+  unsigned rnum = numArgs;
+  for (llvm::Function::iterator bbit = function->begin(), 
+         bbie = function->end(); bbit != bbie; ++bbit) {
+    for (llvm::BasicBlock::iterator it = bbit->begin(), ie = bbit->end();
+         it != ie; ++it)
+      registerMap[it] = rnum++;
+  }
+  numRegisters = rnum;
+  
+  unsigned i = 0;
+  for (llvm::Function::iterator bbit = function->begin(), 
+         bbie = function->end(); bbit != bbie; ++bbit) {
+    for (llvm::BasicBlock::iterator it = bbit->begin(), ie = bbit->end();
+         it != ie; ++it) {
+      KInstruction *ki;
+
+      switch(it->getOpcode()) {
+      case Instruction::GetElementPtr:
+        ki = new KGEPInstruction(); break;
+      default:
+        ki = new KInstruction(); break;
+      }
+
+      unsigned numOperands = it->getNumOperands();
+      ki->inst = it;      
+      ki->operands = new int[numOperands];
+      ki->dest = registerMap[it];
+      for (unsigned j=0; j<numOperands; j++) {
+        Value *v = it->getOperand(j);
+        
+        if (Instruction *inst = dyn_cast<Instruction>(v)) {
+          ki->operands[j] = registerMap[inst];
+        } else if (Argument *a = dyn_cast<Argument>(v)) {
+          ki->operands[j] = a->getArgNo();
+        } else if (isa<BasicBlock>(v) || isa<InlineAsm>(v)) {
+          ki->operands[j] = -1;
+        } else {
+          assert(isa<Constant>(v));
+          Constant *c = cast<Constant>(v);
+          ki->operands[j] = -(km->getConstantID(c, ki) + 2);
+        }
+      }
+
+      instructions[i++] = ki;
+    }
+  }
+}
+
+KFunction::~KFunction() {
+  for (unsigned i=0; i<numInstructions; ++i)
+    delete instructions[i];
+  delete[] instructions;
+}

Added: klee/trunk/lib/Module/LowerSwitch.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/LowerSwitch.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/LowerSwitch.cpp (added)
+++ klee/trunk/lib/Module/LowerSwitch.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,134 @@
+//===-- LowerSwitch.cpp - Eliminate Switch instructions -------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Derived from LowerSwitch.cpp in LLVM, heavily modified by piotrek
+// to get rid of the binary search transform, as it was creating
+// multiple paths through the program (i.e., extra paths that didn't
+// exist in the original program).
+//
+//===----------------------------------------------------------------------===//
+
+#include "Passes.h"
+#include <algorithm>
+
+using namespace llvm;
+
+namespace klee {
+
+char LowerSwitchPass::ID = 0;
+
+// The comparison function for sorting the switch case values in the vector.
+struct SwitchCaseCmp {
+  bool operator () (const LowerSwitchPass::SwitchCase& C1,
+                    const LowerSwitchPass::SwitchCase& C2) {
+    
+    const ConstantInt* CI1 = cast<const ConstantInt>(C1.value);
+    const ConstantInt* CI2 = cast<const ConstantInt>(C2.value);
+    return CI1->getValue().slt(CI2->getValue());
+  }
+};
+
+bool LowerSwitchPass::runOnFunction(Function &F) {
+  bool changed = false;
+
+  for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
+    BasicBlock *cur = I++; // Advance over block so we don't traverse new blocks
+
+    if (SwitchInst *SI = dyn_cast<SwitchInst>(cur->getTerminator())) {
+      changed = true;
+      processSwitchInst(SI);
+    }
+  }
+
+  return changed;
+}
+
+// switchConvert - Convert the switch statement into a linear scan
+// through all the case values
+void LowerSwitchPass::switchConvert(CaseItr begin, CaseItr end,
+                                    Value* value, BasicBlock* origBlock,
+                                    BasicBlock* defaultBlock)
+{
+  BasicBlock *curHead = defaultBlock;
+  Function *F = origBlock->getParent();
+  
+  // iterate through all the cases, creating a new BasicBlock for each
+  for (CaseItr it = begin; it < end; ++it) {
+    BasicBlock *newBlock = BasicBlock::Create("NodeBlock");
+    Function::iterator FI = origBlock;
+    F->getBasicBlockList().insert(++FI, newBlock);
+    
+    ICmpInst *cmpInst = new ICmpInst(ICmpInst::ICMP_EQ,
+                                     value,
+                                     it->value,
+                                     "Case Comparison");
+    
+    newBlock->getInstList().push_back(cmpInst);
+    BranchInst::Create(it->block, curHead, cmpInst, newBlock);
+
+    // If there were any PHI nodes in this successor, rewrite one entry
+    // from origBlock to come from newBlock.
+    for (BasicBlock::iterator bi = it->block->begin(); isa<PHINode>(bi); ++bi) {
+      PHINode* PN = cast<PHINode>(bi);
+
+      int blockIndex = PN->getBasicBlockIndex(origBlock);
+      assert(blockIndex != -1 && "Switch didn't go to this successor??");
+      PN->setIncomingBlock((unsigned)blockIndex, newBlock);
+    }
+    
+    curHead = newBlock;
+  }
+
+  // Branch to our shiny new if-then stuff...
+  BranchInst::Create(curHead, origBlock);
+}
+
+// processSwitchInst - Replace the specified switch instruction with a sequence
+// of chained if-then instructions.
+//
+void LowerSwitchPass::processSwitchInst(SwitchInst *SI) {
+  BasicBlock *origBlock = SI->getParent();
+  BasicBlock *defaultBlock = SI->getDefaultDest();
+  Function *F = origBlock->getParent();
+  Value *switchValue = SI->getOperand(0);
+
+  // Create a new, empty default block so that the new hierarchy of
+  // if-then statements go to this and the PHI nodes are happy.
+  BasicBlock* newDefault = BasicBlock::Create("newDefault");
+
+  F->getBasicBlockList().insert(defaultBlock, newDefault);
+  BranchInst::Create(defaultBlock, newDefault);
+
+  // If there is an entry in any PHI nodes for the default edge, make sure
+  // to update them as well.
+  for (BasicBlock::iterator I = defaultBlock->begin(); isa<PHINode>(I); ++I) {
+    PHINode *PN = cast<PHINode>(I);
+    int BlockIdx = PN->getBasicBlockIndex(origBlock);
+    assert(BlockIdx != -1 && "Switch didn't go to this successor??");
+    PN->setIncomingBlock((unsigned)BlockIdx, newDefault);
+  }
+  
+  CaseVector cases;
+  for (unsigned i = 1; i < SI->getNumSuccessors(); ++i)
+    cases.push_back(SwitchCase(SI->getSuccessorValue(i),
+                               SI->getSuccessor(i)));
+  
+  // reverse cases, as switchConvert constructs a chain of
+  //   basic blocks by appending to the front. if we reverse,
+  //   the if comparisons will happen in the same order
+  //   as the cases appear in the switch
+  std::reverse(cases.begin(), cases.end());
+  
+  switchConvert(cases.begin(), cases.end(), switchValue, origBlock, newDefault);
+
+  // We are now done with the switch instruction, so delete it
+  origBlock->getInstList().erase(SI);
+}
+
+}

Added: klee/trunk/lib/Module/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/Makefile (added)
+++ klee/trunk/lib/Module/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+#===-- lib/Module/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=kleeModule
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+
+include $(LEVEL)/Makefile.common

Propchange: klee/trunk/lib/Module/Makefile

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/lib/Module/ModuleUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/ModuleUtil.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/ModuleUtil.cpp (added)
+++ klee/trunk/lib/Module/ModuleUtil.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,101 @@
+//===-- ModuleUtil.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/Internal/Support/ModuleUtil.h"
+
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Linker.h"
+#include "llvm/Module.h"
+#include "llvm/Assembly/AsmAnnotationWriter.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Analysis/ValueTracking.h"
+
+#include <map>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+using namespace llvm;
+using namespace klee;
+
+Module *klee::linkWithLibrary(Module *module, 
+                              const std::string &libraryName) {
+  try {
+    Linker linker("klee", module, false);
+
+    llvm::sys::Path libraryPath(libraryName);
+    bool native = false;
+    
+    if (linker.LinkInFile(libraryPath, native)) {
+      assert(0 && "linking in library failed!");
+    }
+    
+    return linker.releaseModule();
+  } catch (...) {
+    assert(0 && "error during linking");
+  }
+}
+
+Function *klee::getDirectCallTarget(const Instruction *i) {
+  assert(isa<CallInst>(i) || isa<InvokeInst>(i));
+
+  Value *v = i->getOperand(0);
+  if (Function *f = dyn_cast<Function>(v)) {
+    return f;
+  } else if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(v)) {
+    if (ce->getOpcode()==Instruction::BitCast)
+      if (Function *f = dyn_cast<Function>(ce->getOperand(0)))
+        return f;
+
+    // NOTE: This assert may fire, it isn't necessarily a problem and
+    // can be disabled, I just wanted to know when and if it happened.
+    assert(0 && "FIXME: Unresolved direct target for a constant expression.");
+  }
+  
+  return 0;
+}
+
+static bool valueIsOnlyCalled(const Value *v) {
+  for (Value::use_const_iterator it = v->use_begin(), ie = v->use_end();
+       it != ie; ++it) {
+    if (const Instruction *instr = dyn_cast<Instruction>(*it)) {
+      if (instr->getOpcode()==0) continue; // XXX function numbering inst
+      if (!isa<CallInst>(instr) && !isa<InvokeInst>(instr)) return false;
+      
+      // Make sure that the value is only the target of this call and
+      // not an argument.
+      for (unsigned i=1,e=instr->getNumOperands(); i!=e; ++i)
+        if (instr->getOperand(i)==v)
+          return false;
+    } else if (const llvm::ConstantExpr *ce = 
+               dyn_cast<llvm::ConstantExpr>(*it)) {
+      if (ce->getOpcode()==Instruction::BitCast)
+        if (valueIsOnlyCalled(ce))
+          continue;
+      return false;
+    } else if (const GlobalAlias *ga = dyn_cast<GlobalAlias>(*it)) {
+      // XXX what about v is bitcast of aliasee?
+      if (v==ga->getAliasee() && !valueIsOnlyCalled(ga))
+        return false;
+    } else {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool klee::functionEscapes(const Function *f) {
+  return !valueIsOnlyCalled(f);
+}

Added: klee/trunk/lib/Module/Optimize.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/Optimize.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/Optimize.cpp (added)
+++ klee/trunk/lib/Module/Optimize.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,272 @@
+// FIXME: This file is a bastard child of opt.cpp and llvm-ld's
+// Optimize.cpp. This stuff should live in common code.
+
+
+//===- Optimize.cpp - Optimize a complete program -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements all optimization of the linked module for llvm-ld.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/System/DynamicLibrary.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/PassNameParser.h"
+#include "llvm/Support/PluginLoader.h"
+#include <iostream>
+using namespace llvm;
+
+#if 0
+// Pass Name Options as generated by the PassNameParser
+static cl::list<const PassInfo*, bool, PassNameParser>
+  OptimizationList(cl::desc("Optimizations available:"));
+#endif
+
+// Don't verify at the end
+static cl::opt<bool> DontVerify("disable-verify", cl::ReallyHidden);
+
+static cl::opt<bool> DisableInline("disable-inlining",
+  cl::desc("Do not run the inliner pass"));
+
+static cl::opt<bool>
+DisableOptimizations("disable-opt",
+  cl::desc("Do not run any optimization passes"));
+
+static cl::opt<bool> DisableInternalize("disable-internalize",
+  cl::desc("Do not mark all symbols as internal"));
+
+static cl::opt<bool> VerifyEach("verify-each",
+ cl::desc("Verify intermediate results of all passes"));
+
+static cl::alias ExportDynamic("export-dynamic",
+  cl::aliasopt(DisableInternalize),
+  cl::desc("Alias for -disable-internalize"));
+
+static cl::opt<bool> Strip("strip-all", 
+  cl::desc("Strip all symbol info from executable"));
+
+static cl::alias A0("s", cl::desc("Alias for --strip-all"), 
+  cl::aliasopt(Strip));
+
+static cl::opt<bool> StripDebug("strip-debug",
+  cl::desc("Strip debugger symbol info from executable"));
+
+static cl::alias A1("S", cl::desc("Alias for --strip-debug"),
+  cl::aliasopt(StripDebug));
+
+// A utility function that adds a pass to the pass manager but will also add
+// a verifier pass after if we're supposed to verify.
+static inline void addPass(PassManager &PM, Pass *P) {
+  // Add the pass to the pass manager...
+  PM.add(P);
+
+  // If we are verifying all of the intermediate steps, add the verifier...
+  if (VerifyEach)
+    PM.add(createVerifierPass());
+}
+
+namespace llvm {
+
+
+static void AddStandardCompilePasses(PassManager &PM) {
+  PM.add(createVerifierPass());                  // Verify that input is correct
+
+  addPass(PM, createLowerSetJmpPass());          // Lower llvm.setjmp/.longjmp
+
+  // If the -strip-debug command line option was specified, do it.
+  if (StripDebug)
+    addPass(PM, createStripSymbolsPass(true));
+
+  if (DisableOptimizations) return;
+
+  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
+  addPass(PM, createCFGSimplificationPass());    // Clean up disgusting code
+  addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas
+  addPass(PM, createGlobalOptimizerPass());      // Optimize out global vars
+  addPass(PM, createGlobalDCEPass());            // Remove unused fns and globs
+  addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation
+  addPass(PM, createDeadArgEliminationPass());   // Dead argument elimination
+  addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
+  addPass(PM, createCFGSimplificationPass());    // Clean up after IPCP & DAE
+
+  addPass(PM, createPruneEHPass());              // Remove dead EH info
+  addPass(PM, createFunctionAttrsPass());        // Deduce function attrs
+
+  if (!DisableInline)
+    addPass(PM, createFunctionInliningPass());   // Inline small functions
+  addPass(PM, createArgumentPromotionPass());    // Scalarize uninlined fn args
+
+  addPass(PM, createSimplifyLibCallsPass());     // Library Call Optimizations
+  addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl.
+  addPass(PM, createJumpThreadingPass());        // Thread jumps.
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
+  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
+  addPass(PM, createCondPropagationPass());      // Propagate conditionals
+
+  addPass(PM, createTailCallEliminationPass());  // Eliminate tail calls
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  addPass(PM, createReassociatePass());          // Reassociate expressions
+  addPass(PM, createLoopRotatePass());
+  addPass(PM, createLICMPass());                 // Hoist loop invariants
+  addPass(PM, createLoopUnswitchPass());         // Unswitch loops.
+  addPass(PM, createLoopIndexSplitPass());       // Index split loops.
+  // FIXME : Removing instcombine causes nestedloop regression.
+  addPass(PM, createInstructionCombiningPass());
+  addPass(PM, createIndVarSimplifyPass());       // Canonicalize indvars
+  addPass(PM, createLoopDeletionPass());         // Delete dead loops
+  addPass(PM, createLoopUnrollPass());           // Unroll small loops
+  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
+  addPass(PM, createGVNPass());                  // Remove redundancies
+  addPass(PM, createMemCpyOptPass());            // Remove memcpy / form memset
+  addPass(PM, createSCCPPass());                 // Constant prop with SCCP
+
+  // Run instcombine after redundancy elimination to exploit opportunities
+  // opened up by them.
+  addPass(PM, createInstructionCombiningPass());
+  addPass(PM, createCondPropagationPass());      // Propagate conditionals
+
+  addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
+  addPass(PM, createAggressiveDCEPass());        // Delete dead instructions
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  addPass(PM, createStripDeadPrototypesPass());  // Get rid of dead prototypes
+  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
+  addPass(PM, createConstantMergePass());        // Merge dup global constants
+}
+
+/// Optimize - Perform link time optimizations. This will run the scalar
+/// optimizations, any loaded plugin-optimization modules, and then the
+/// inter-procedural optimizations if applicable.
+void Optimize(Module* M) {
+
+  // Instantiate the pass manager to organize the passes.
+  PassManager Passes;
+
+  // If we're verifying, start off with a verification pass.
+  if (VerifyEach)
+    Passes.add(createVerifierPass());
+
+  // Add an appropriate TargetData instance for this module...
+  addPass(Passes, new TargetData(M));
+
+  // DWD - Run the opt standard pass list as well.
+  AddStandardCompilePasses(Passes);
+
+  if (!DisableOptimizations) {
+    // Now that composite has been compiled, scan through the module, looking
+    // for a main function.  If main is defined, mark all other functions
+    // internal.
+    if (!DisableInternalize)
+      addPass(Passes, createInternalizePass(true));
+
+    // Propagate constants at call sites into the functions they call.  This
+    // opens opportunities for globalopt (and inlining) by substituting function
+    // pointers passed as arguments to direct uses of functions.  
+    addPass(Passes, createIPSCCPPass());
+
+    // Now that we internalized some globals, see if we can hack on them!
+    addPass(Passes, createGlobalOptimizerPass());
+
+    // Linking modules together can lead to duplicated global constants, only
+    // keep one copy of each constant...
+    addPass(Passes, createConstantMergePass());
+
+    // Remove unused arguments from functions...
+    addPass(Passes, createDeadArgEliminationPass());
+
+    // Reduce the code after globalopt and ipsccp.  Both can open up significant
+    // simplification opportunities, and both can propagate functions through
+    // function pointers.  When this happens, we often have to resolve varargs
+    // calls, etc, so let instcombine do this.
+    addPass(Passes, createInstructionCombiningPass());
+
+    if (!DisableInline)
+      addPass(Passes, createFunctionInliningPass()); // Inline small functions
+
+    addPass(Passes, createPruneEHPass());            // Remove dead EH info
+    addPass(Passes, createGlobalOptimizerPass());    // Optimize globals again.
+    addPass(Passes, createGlobalDCEPass());          // Remove dead functions
+
+    // If we didn't decide to inline a function, check to see if we can
+    // transform it to pass arguments by value instead of by reference.
+    addPass(Passes, createArgumentPromotionPass());
+
+    // The IPO passes may leave cruft around.  Clean up after them.
+    addPass(Passes, createInstructionCombiningPass());
+    addPass(Passes, createJumpThreadingPass());        // Thread jumps.
+    addPass(Passes, createScalarReplAggregatesPass()); // Break up allocas
+
+    // Run a few AA driven optimizations here and now, to cleanup the code.
+    addPass(Passes, createFunctionAttrsPass());      // Add nocapture
+    addPass(Passes, createGlobalsModRefPass());      // IP alias analysis
+
+    addPass(Passes, createLICMPass());               // Hoist loop invariants
+    addPass(Passes, createGVNPass());                // Remove redundancies
+    addPass(Passes, createMemCpyOptPass());          // Remove dead memcpy's
+    addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores
+
+    // Cleanup and simplify the code after the scalar optimizations.
+    addPass(Passes, createInstructionCombiningPass());
+
+    addPass(Passes, createJumpThreadingPass());        // Thread jumps.
+    addPass(Passes, createPromoteMemoryToRegisterPass()); // Cleanup jumpthread.
+    
+    // Delete basic blocks, which optimization passes may have killed...
+    addPass(Passes, createCFGSimplificationPass());
+
+    // Now that we have optimized the program, discard unreachable functions...
+    addPass(Passes, createGlobalDCEPass());
+  }
+
+  // If the -s or -S command line options were specified, strip the symbols out
+  // of the resulting program to make it smaller.  -s and -S are GNU ld options
+  // that we are supporting; they alias -strip-all and -strip-debug.
+  if (Strip || StripDebug)
+    addPass(Passes, createStripSymbolsPass(StripDebug && !Strip));
+
+#if 0
+  // Create a new optimization pass for each one specified on the command line
+  std::auto_ptr<TargetMachine> target;
+  for (unsigned i = 0; i < OptimizationList.size(); ++i) {
+    const PassInfo *Opt = OptimizationList[i];
+    if (Opt->getNormalCtor())
+      addPass(Passes, Opt->getNormalCtor()());
+    else
+      std::cerr << "llvm-ld: cannot create pass: " << Opt->getPassName() 
+                << "\n";
+  }
+#endif
+
+  // The user's passes may leave cruft around. Clean up after them them but
+  // only if we haven't got DisableOptimizations set
+  if (!DisableOptimizations) {
+    addPass(Passes, createInstructionCombiningPass());
+    addPass(Passes, createCFGSimplificationPass());
+    addPass(Passes, createAggressiveDCEPass());
+    addPass(Passes, createGlobalDCEPass());
+  }
+
+  // Make sure everything is still good.
+  if (!DontVerify)
+    Passes.add(createVerifierPass());
+
+  // Run our queue of passes all at once now, efficiently.
+  Passes.run(*M);
+}
+
+}

Added: klee/trunk/lib/Module/Passes.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/Passes.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/Passes.h (added)
+++ klee/trunk/lib/Module/Passes.h Wed May 20 23:36:41 2009
@@ -0,0 +1,132 @@
+//===-- Passes.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_PASSES_H
+#define KLEE_PASSES_H
+
+#include "llvm/Constants.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+
+namespace llvm {
+  class Function;
+  class Instruction;
+  class Module;
+  class TargetData;
+  class Type;
+}
+
+namespace klee {
+
+  /// RaiseAsmPass - This pass raises some common occurences of inline
+  /// asm which are used by glibc into normal LLVM IR.
+class RaiseAsmPass : public llvm::ModulePass {
+  static char ID;
+
+  llvm::Function *getIntrinsic(llvm::Module &M,
+                               unsigned IID,
+                               const llvm::Type **Tys,
+                               unsigned NumTys);
+  llvm::Function *getIntrinsic(llvm::Module &M,
+                               unsigned IID, 
+                               const llvm::Type *Ty0) {
+    return getIntrinsic(M, IID, &Ty0, 1);
+  }
+
+  bool runOnInstruction(llvm::Module &M, llvm::Instruction *I);
+
+public:
+  RaiseAsmPass() : llvm::ModulePass((intptr_t) &ID) {}
+  
+  virtual bool runOnModule(llvm::Module &M);
+};
+
+  // This is a module pass because it can add and delete module
+  // variables (via intrinsic lowering).
+class IntrinsicCleanerPass : public llvm::ModulePass {
+  static char ID;
+  llvm::IntrinsicLowering *IL;
+  bool LowerIntrinsics;
+
+  bool runOnBasicBlock(llvm::BasicBlock &b);
+public:
+  IntrinsicCleanerPass(const llvm::TargetData &TD,
+                       bool LI=true)
+    : llvm::ModulePass((intptr_t) &ID),
+      IL(new llvm::IntrinsicLowering(TD)),
+      LowerIntrinsics(LI) {}
+  ~IntrinsicCleanerPass() { delete IL; } 
+  
+  virtual bool runOnModule(llvm::Module &M);
+};
+  
+  // performs two transformations which make interpretation
+  // easier and faster.
+  //
+  // 1) Ensure that all the PHI nodes in a basic block have
+  //    the incoming block list in the same order. Thus the
+  //    incoming block index only needs to be computed once
+  //    for each transfer.
+  // 
+  // 2) Ensure that no PHI node result is used as an argument to
+  //    a subsequent PHI node in the same basic block. This allows
+  //    the transfer to execute the instructions in order instead
+  //    of in two passes.
+class PhiCleanerPass : public llvm::FunctionPass {
+  static char ID;
+
+public:
+  PhiCleanerPass() : llvm::FunctionPass((intptr_t) &ID) {}
+  
+  virtual bool runOnFunction(llvm::Function &f);
+};
+  
+class DivCheckPass : public llvm::ModulePass {
+  static char ID;
+public:
+  DivCheckPass(): ModulePass((intptr_t) &ID) {}
+  virtual bool runOnModule(llvm::Module &M);
+};
+
+/// LowerSwitchPass - Replace all SwitchInst instructions with chained branch
+/// instructions.  Note that this cannot be a BasicBlock pass because it
+/// modifies the CFG!
+class LowerSwitchPass : public llvm::FunctionPass {
+public:
+  static char ID; // Pass identification, replacement for typeid
+  LowerSwitchPass() : FunctionPass((intptr_t) &ID) {} 
+  
+  virtual bool runOnFunction(llvm::Function &F);
+  
+  struct SwitchCase {
+    llvm ::Constant *value;
+    llvm::BasicBlock *block;
+    
+    SwitchCase() : value(0), block(0) { }
+    SwitchCase(llvm::Constant *v, llvm::BasicBlock *b) :
+      value(v), block(b) { }
+  };
+  
+  typedef std::vector<SwitchCase>           CaseVector;
+  typedef std::vector<SwitchCase>::iterator CaseItr;
+  
+private:
+  void processSwitchInst(llvm::SwitchInst *SI);
+  void switchConvert(CaseItr begin,
+                     CaseItr end,
+                     llvm::Value *value,
+                     llvm::BasicBlock *origBlock,
+                     llvm::BasicBlock *defaultBlock);
+};
+
+}
+
+#endif

Added: klee/trunk/lib/Module/PhiCleaner.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/PhiCleaner.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/PhiCleaner.cpp (added)
+++ klee/trunk/lib/Module/PhiCleaner.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,83 @@
+//===-- PhiCleaner.cpp ----------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Passes.h"
+
+#include <set>
+
+using namespace llvm;
+
+char klee::PhiCleanerPass::ID = 0;
+
+bool klee::PhiCleanerPass::runOnFunction(Function &f) {
+  bool changed = false;
+  
+  for (Function::iterator b = f.begin(), be = f.end(); b != be; ++b) {
+    BasicBlock::iterator it = b->begin();
+
+    if (it->getOpcode() == Instruction::PHI) {
+      PHINode *reference = cast<PHINode>(it);
+      
+      std::set<Value*> phis;
+      phis.insert(reference);
+
+      unsigned numBlocks = reference->getNumIncomingValues();
+      for (++it; isa<PHINode>(*it); ++it) {
+        PHINode *pi = cast<PHINode>(it);
+
+        assert(numBlocks == pi->getNumIncomingValues());
+
+        // see if it is out of order
+        unsigned i;
+        for (i=0; i<numBlocks; i++)
+          if (pi->getIncomingBlock(i) != reference->getIncomingBlock(i))
+            break;
+
+        if (i!=numBlocks) {
+          std::vector<Value*> values;
+          values.reserve(numBlocks);
+          for (unsigned i=0; i<numBlocks; i++)
+            values[i] = pi->getIncomingValueForBlock(reference->getIncomingBlock(i));
+          for (unsigned i=0; i<numBlocks; i++) {
+            pi->setIncomingBlock(i, reference->getIncomingBlock(i));
+            pi->setIncomingValue(i, values[i]);
+          }
+          changed = true;
+        }
+
+        // see if it uses any previously defined phi nodes
+        for (i=0; i<numBlocks; i++) {
+          Value *value = pi->getIncomingValue(i);
+
+          if (phis.find(value) != phis.end()) {
+            // fix by making a "move" at the end of the incoming block
+            // to a new temporary, which is thus known not to be a phi
+            // result. we could be somewhat more efficient about this
+            // by sharing temps and by reordering phi instructions so
+            // this isn't completely necessary, but in the end this is
+            // just a pathological case which does not occur very
+            // often.
+            Instruction *tmp = 
+              new BitCastInst(value, 
+                              value->getType(),
+                              value->getName() + ".phiclean",
+                              pi->getIncomingBlock(i)->getTerminator());
+            pi->setIncomingValue(i, tmp);
+          }
+
+          changed = true;
+        }
+        
+        phis.insert(pi);
+      }
+    }
+  }
+
+  return changed;
+}

Added: klee/trunk/lib/Module/RaiseAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Module/RaiseAsm.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Module/RaiseAsm.cpp (added)
+++ klee/trunk/lib/Module/RaiseAsm.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,69 @@
+//===-- RaiseAsm.cpp ------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Passes.h"
+
+#include "llvm/InlineAsm.h"
+
+using namespace llvm;
+using namespace klee;
+
+char RaiseAsmPass::ID = 0;
+
+Function *RaiseAsmPass::getIntrinsic(llvm::Module &M,
+                                     unsigned IID,
+                                     const Type **Tys,
+                                     unsigned NumTys) {  
+  return Intrinsic::getDeclaration(&M, (llvm::Intrinsic::ID) IID, Tys, NumTys);
+}
+
+// FIXME: This should just be implemented as a patch to
+// X86TargetAsmInfo.cpp, then everyone will benefit.
+bool RaiseAsmPass::runOnInstruction(Module &M, Instruction *I) {
+  if (CallInst *ci = dyn_cast<CallInst>(I)) {
+    if (InlineAsm *ia = dyn_cast<InlineAsm>(ci->getCalledValue())) {
+      const std::string &as = ia->getAsmString();
+      const std::string &cs = ia->getConstraintString();
+      const llvm::Type *T = ci->getType();
+
+      // bswaps
+      if (ci->getNumOperands() == 2 && 
+          T == ci->getOperand(1)->getType() &&
+          ((T == llvm::Type::Int16Ty && 
+            as == "rorw $$8, ${0:w}" &&
+            cs == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") ||
+           (T == llvm::Type::Int32Ty &&
+            as == "rorw $$8, ${0:w};rorl $$16, $0;rorw $$8, ${0:w}" &&
+            cs == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}"))) {
+        llvm::Value *Arg0 = ci->getOperand(1);
+        Function *F = getIntrinsic(M, Intrinsic::bswap, Arg0->getType());
+        ci->setOperand(0, F);
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+bool RaiseAsmPass::runOnModule(Module &M) {
+  bool changed = false;
+  
+  for (Module::iterator fi = M.begin(), fe = M.end(); fi != fe; ++fi) {
+    for (Function::iterator bi = fi->begin(), be = fi->end(); bi != be; ++bi) {
+      for (BasicBlock::iterator ii = bi->begin(), ie = bi->end(); ii != ie;) {
+        Instruction *i = ii;
+        ++ii;  
+        changed |= runOnInstruction(M, i);
+      }
+    }
+  }
+
+  return changed;
+}

Added: klee/trunk/lib/README.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/README.txt?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/README.txt (added)
+++ klee/trunk/lib/README.txt Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+The klee and kleaver code is organized as follows:
+
+lib/Basic   - Low level support for both klee and kleaver which should
+              be independent of LLVM.
+
+lib/Support - Higher level support, but only used by klee. This can
+              use LLVM facilities.
+
+lib/Expr    - The core kleaver expression library.
+
+lib/Solver  - The kleaver solver library.
+
+lib/Module  - klee facilities for working with LLVM modules, including
+              the shadow module/instruction structures we use during
+              execution.
+
+lib/Core    - The core symbolic virtual machine.
+

Added: klee/trunk/lib/Solver/CachingSolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/CachingSolver.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/CachingSolver.cpp (added)
+++ klee/trunk/lib/Solver/CachingSolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,241 @@
+//===-- CachingSolver.cpp - Caching expression solver ---------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "klee/Solver.h"
+
+#include "klee/Constraints.h"
+#include "klee/Expr.h"
+#include "klee/IncompleteSolver.h"
+#include "klee/SolverImpl.h"
+
+#include "SolverStats.h"
+
+#include <tr1/unordered_map>
+
+using namespace klee;
+
+class CachingSolver : public SolverImpl {
+private:
+  ref<Expr> canonicalizeQuery(ref<Expr> originalQuery,
+                              bool &negationUsed);
+
+  void cacheInsert(const Query& query,
+                   IncompleteSolver::PartialValidity result);
+
+  bool cacheLookup(const Query& query,
+                   IncompleteSolver::PartialValidity &result);
+  
+  struct CacheEntry {
+    CacheEntry(const ConstraintManager &c, ref<Expr> q)
+      : constraints(c), query(q) {}
+
+    CacheEntry(const CacheEntry &ce)
+      : constraints(ce.constraints), query(ce.query) {}
+    
+    ConstraintManager constraints;
+    ref<Expr> query;
+
+    bool operator==(const CacheEntry &b) const {
+      return constraints==b.constraints && *query.get()==*b.query.get();
+    }
+  };
+  
+  struct CacheEntryHash {
+    unsigned operator()(const CacheEntry &ce) const {
+      unsigned result = ce.query.hash();
+      
+      for (ConstraintManager::constraint_iterator it = ce.constraints.begin();
+           it != ce.constraints.end(); ++it)
+        result ^= it->hash();
+      
+      return result;
+    }
+  };
+
+  typedef std::tr1::unordered_map<CacheEntry, 
+                                  IncompleteSolver::PartialValidity, 
+                                  CacheEntryHash> cache_map;
+  
+  Solver *solver;
+  cache_map cache;
+
+public:
+  CachingSolver(Solver *s) : solver(s) {}
+  ~CachingSolver() { cache.clear(); delete solver; }
+
+  bool computeValidity(const Query&, Solver::Validity &result);
+  bool computeTruth(const Query&, bool &isValid);
+  bool computeValue(const Query& query, ref<Expr> &result) {
+    return solver->impl->computeValue(query, result);
+  }
+  bool computeInitialValues(const Query& query,
+                            const std::vector<const Array*> &objects,
+                            std::vector< std::vector<unsigned char> > &values,
+                            bool &hasSolution) {
+    return solver->impl->computeInitialValues(query, objects, values, 
+                                              hasSolution);
+  }
+};
+
+/** @returns the canonical version of the given query.  The reference
+    negationUsed is set to true if the original query was negated in
+    the canonicalization process. */
+ref<Expr> CachingSolver::canonicalizeQuery(ref<Expr> originalQuery,
+                                           bool &negationUsed) {
+  ref<Expr> negatedQuery = Expr::createNot(originalQuery);
+
+  // select the "smaller" query to the be canonical representation
+  if (originalQuery.compare(negatedQuery) < 0) {
+    negationUsed = false;
+    return originalQuery;
+  } else {
+    negationUsed = true;
+    return negatedQuery;
+  }
+}
+
+/** @returns true on a cache hit, false of a cache miss.  Reference
+    value result only valid on a cache hit. */
+bool CachingSolver::cacheLookup(const Query& query,
+                                IncompleteSolver::PartialValidity &result) {
+  bool negationUsed;
+  ref<Expr> canonicalQuery = canonicalizeQuery(query.expr, negationUsed);
+
+  CacheEntry ce(query.constraints, canonicalQuery);
+  cache_map::iterator it = cache.find(ce);
+  
+  if (it != cache.end()) {
+    result = (negationUsed ?
+              IncompleteSolver::negatePartialValidity(it->second) :
+              it->second);
+    return true;
+  }
+  
+  return false;
+}
+
+/// Inserts the given query, result pair into the cache.
+void CachingSolver::cacheInsert(const Query& query,
+                                IncompleteSolver::PartialValidity result) {
+  bool negationUsed;
+  ref<Expr> canonicalQuery = canonicalizeQuery(query.expr, negationUsed);
+
+  CacheEntry ce(query.constraints, canonicalQuery);
+  IncompleteSolver::PartialValidity cachedResult = 
+    (negationUsed ? IncompleteSolver::negatePartialValidity(result) : result);
+  
+  cache.insert(std::make_pair(ce, cachedResult));
+}
+
+bool CachingSolver::computeValidity(const Query& query,
+                                    Solver::Validity &result) {
+  IncompleteSolver::PartialValidity cachedResult;
+  bool tmp, cacheHit = cacheLookup(query, cachedResult);
+  
+  if (cacheHit) {
+    ++stats::queryCacheHits;
+
+    switch(cachedResult) {
+    case IncompleteSolver::MustBeTrue:   
+      result = Solver::True;
+      return true;
+    case IncompleteSolver::MustBeFalse:  
+      result = Solver::False;
+      return true;
+    case IncompleteSolver::TrueOrFalse:  
+      result = Solver::Unknown;
+      return true;
+    case IncompleteSolver::MayBeTrue: {
+      if (!solver->impl->computeTruth(query, tmp))
+        return false;
+      if (tmp) {
+        cacheInsert(query, IncompleteSolver::MustBeTrue);
+        result = Solver::True;
+        return true;
+      } else {
+        cacheInsert(query, IncompleteSolver::TrueOrFalse);
+        result = Solver::Unknown;
+        return true;
+      }
+    }
+    case IncompleteSolver::MayBeFalse: {
+      if (!solver->impl->computeTruth(query.negateExpr(), tmp))
+        return false;
+      if (tmp) {
+        cacheInsert(query, IncompleteSolver::MustBeFalse);
+        result = Solver::False;
+        return true;
+      } else {
+        cacheInsert(query, IncompleteSolver::TrueOrFalse);
+        result = Solver::Unknown;
+        return true;
+      }
+    }
+    default: assert(0 && "unreachable");
+    }
+  }
+
+  ++stats::queryCacheMisses;
+  
+  if (!solver->impl->computeValidity(query, result))
+    return false;
+
+  switch (result) {
+  case Solver::True: 
+    cachedResult = IncompleteSolver::MustBeTrue; break;
+  case Solver::False: 
+    cachedResult = IncompleteSolver::MustBeFalse; break;
+  default: 
+    cachedResult = IncompleteSolver::TrueOrFalse; break;
+  }
+  
+  cacheInsert(query, cachedResult);
+  return true;
+}
+
+bool CachingSolver::computeTruth(const Query& query,
+                                 bool &isValid) {
+  IncompleteSolver::PartialValidity cachedResult;
+  bool cacheHit = cacheLookup(query, cachedResult);
+
+  // a cached result of MayBeTrue forces us to check whether
+  // a False assignment exists.
+  if (cacheHit && cachedResult != IncompleteSolver::MayBeTrue) {
+    ++stats::queryCacheHits;
+    isValid = (cachedResult == IncompleteSolver::MustBeTrue);
+    return true;
+  }
+
+  ++stats::queryCacheMisses;
+  
+  // cache miss: query solver
+  if (!solver->impl->computeTruth(query, isValid))
+    return false;
+
+  if (isValid) {
+    cachedResult = IncompleteSolver::MustBeTrue;
+  } else if (cacheHit) {
+    // We know a true assignment exists, and query isn't valid, so
+    // must be TrueOrFalse.
+    assert(cachedResult == IncompleteSolver::MayBeTrue);
+    cachedResult = IncompleteSolver::TrueOrFalse;
+  } else {
+    cachedResult = IncompleteSolver::MayBeFalse;
+  }
+  
+  cacheInsert(query, cachedResult);
+  return true;
+}
+
+///
+
+Solver *klee::createCachingSolver(Solver *_solver) {
+  return new Solver(new CachingSolver(_solver));
+}

Added: klee/trunk/lib/Solver/CexCachingSolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/CexCachingSolver.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/CexCachingSolver.cpp (added)
+++ klee/trunk/lib/Solver/CexCachingSolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,313 @@
+//===-- CexCachingSolver.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/Solver.h"
+
+#include "klee/Constraints.h"
+#include "klee/Expr.h"
+#include "klee/SolverImpl.h"
+#include "klee/TimerStatIncrementer.h"
+#include "klee/util/Assignment.h"
+#include "klee/util/ExprUtil.h"
+#include "klee/util/ExprVisitor.h"
+#include "klee/Internal/ADT/MapOfSets.h"
+
+#include "SolverStats.h"
+
+#include "llvm/Support/CommandLine.h"
+
+using namespace klee;
+using namespace llvm;
+
+namespace {
+  cl::opt<bool>
+  DebugCexCacheCheckBinding("debug-cex-cache-check-binding");
+
+  cl::opt<bool>
+  CexCacheTryAll("cex-cache-try-all",
+                 cl::desc("try substituting all counterexamples before asking STP"),
+                 cl::init(false));
+
+  cl::opt<bool>
+  CexCacheExperimental("cex-cache-exp", cl::init(false));
+
+}
+
+///
+
+typedef std::set< ref<Expr> > KeyType;
+
+struct AssignmentLessThan {
+  bool operator()(const Assignment *a, const Assignment *b) {
+    return a->bindings < b->bindings;
+  }
+};
+
+
+class CexCachingSolver : public SolverImpl {
+  typedef std::set<Assignment*, AssignmentLessThan> assignmentsTable_ty;
+
+  Solver *solver;
+  
+  MapOfSets<ref<Expr>, Assignment*> cache;
+  // memo table
+  assignmentsTable_ty assignmentsTable;
+
+  bool searchForAssignment(KeyType &key, 
+                           Assignment *&result);
+  
+  bool lookupAssignment(const Query& query, Assignment *&result);
+
+  bool getAssignment(const Query& query, Assignment *&result);
+  
+public:
+  CexCachingSolver(Solver *_solver) : solver(_solver) {}
+  ~CexCachingSolver();
+  
+  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);
+};
+
+///
+
+struct NullAssignment {
+  bool operator()(Assignment *a) const { return !a; }
+};
+
+struct NonNullAssignment {
+  bool operator()(Assignment *a) const { return a!=0; }
+};
+
+struct NullOrSatisfyingAssignment {
+  KeyType &key;
+  
+  NullOrSatisfyingAssignment(KeyType &_key) : key(_key) {}
+
+  bool operator()(Assignment *a) const { 
+    return !a || a->satisfies(key.begin(), key.end()); 
+  }
+};
+
+bool CexCachingSolver::searchForAssignment(KeyType &key, Assignment *&result) {
+  Assignment * const *lookup = cache.lookup(key);
+  if (lookup) {
+    result = *lookup;
+    return true;
+  }
+
+  if (CexCacheTryAll) {
+    Assignment **lookup = cache.findSuperset(key, NonNullAssignment());
+    if (!lookup) lookup = cache.findSubset(key, NullAssignment());
+    if (lookup) {
+      result = *lookup;
+      return true;
+    }
+    for (assignmentsTable_ty::iterator it = assignmentsTable.begin(), 
+           ie = assignmentsTable.end(); it != ie; ++it) {
+      Assignment *a = *it;
+      if (a->satisfies(key.begin(), key.end())) {
+        result = a;
+        return true;
+      }
+    }
+  } else {
+    // XXX which order? one is sure to be better
+    Assignment **lookup = cache.findSuperset(key, NonNullAssignment());
+    if (!lookup) lookup = cache.findSubset(key, NullOrSatisfyingAssignment(key));
+    if (lookup) {
+      result = *lookup;
+      return true;
+    }
+  }
+  
+  return false;
+}
+
+bool CexCachingSolver::lookupAssignment(const Query &query, 
+                                        Assignment *&result) {
+  KeyType key(query.constraints.begin(), query.constraints.end());
+  ref<Expr> neg = Expr::createNot(query.expr);
+  if (neg.isConstant()) {
+    if (!neg.getConstantValue()) {
+      result = (Assignment*) 0;
+      return true;
+    }
+  } else {
+    key.insert(neg);
+  }
+
+  return searchForAssignment(key, result);
+}
+
+bool CexCachingSolver::getAssignment(const Query& query, Assignment *&result) {
+  KeyType key(query.constraints.begin(), query.constraints.end());
+  ref<Expr> neg = Expr::createNot(query.expr);
+  if (neg.isConstant()) {
+    if (!neg.getConstantValue()) {
+      result = (Assignment*) 0;
+      return true;
+    }
+  } else {
+    key.insert(neg);
+  }
+
+  if (!searchForAssignment(key, result)) {
+    // need to solve
+    
+    std::vector<const Array*> objects;
+    findSymbolicObjects(key.begin(), key.end(), objects);
+
+    std::vector< std::vector<unsigned char> > values;
+    bool hasSolution;
+    if (!solver->impl->computeInitialValues(query, objects, values, 
+                                            hasSolution))
+      return false;
+    
+    Assignment *binding;
+    if (hasSolution) {
+      binding = new Assignment(objects, values);
+
+      // memoization
+      std::pair<assignmentsTable_ty::iterator, bool>
+        res = assignmentsTable.insert(binding);
+      if (!res.second) {
+        delete binding;
+        binding = *res.first;
+      }
+
+      if (DebugCexCacheCheckBinding)
+        assert(binding->satisfies(key.begin(), key.end()));
+    } else {
+      binding = (Assignment*) 0;
+    }
+
+    result = binding;
+    cache.insert(key, binding);
+  }
+
+  return true;
+}
+
+///
+
+CexCachingSolver::~CexCachingSolver() {
+  cache.clear();
+  delete solver;
+  for (assignmentsTable_ty::iterator it = assignmentsTable.begin(), 
+         ie = assignmentsTable.end(); it != ie; ++it)
+    delete *it;
+}
+
+bool CexCachingSolver::computeValidity(const Query& query,
+                                       Solver::Validity &result) {
+  TimerStatIncrementer t(stats::cexCacheTime);
+  Assignment *a;
+  if (!getAssignment(query.withFalse(), a))
+    return false;
+  assert(a && "computeValidity() must have assignment");
+  ref<Expr> q = a->evaluate(query.expr);
+  assert(q.isConstant() && "assignment evaluation did not result in constant");
+
+  if (q.getConstantValue()) {
+    if (!getAssignment(query, a))
+      return false;
+    result = !a ? Solver::True : Solver::Unknown;
+  } else {
+    if (!getAssignment(query.negateExpr(), a))
+      return false;
+    result = !a ? Solver::False : Solver::Unknown;
+  }
+  
+  return true;
+}
+
+bool CexCachingSolver::computeTruth(const Query& query,
+                                    bool &isValid) {
+  TimerStatIncrementer t(stats::cexCacheTime);
+
+  // There is a small amount of redundancy here. We only need to know
+  // truth and do not really need to compute an assignment. This means
+  // that we could check the cache to see if we already know that
+  // state ^ query has no assignment. In that case, by the validity of
+  // state, we know that state ^ !query must have an assignment, and
+  // so query cannot be true (valid). This does get hits, but doesn't
+  // really seem to be worth the overhead.
+
+  if (CexCacheExperimental) {
+    Assignment *a;
+    if (lookupAssignment(query.negateExpr(), a) && !a)
+      return false;
+  }
+
+  Assignment *a;
+  if (!getAssignment(query, a))
+    return false;
+
+  isValid = !a;
+
+  return true;
+}
+
+bool CexCachingSolver::computeValue(const Query& query,
+                                    ref<Expr> &result) {
+  TimerStatIncrementer t(stats::cexCacheTime);
+
+  Assignment *a;
+  if (!getAssignment(query.withFalse(), a))
+    return false;
+  assert(a && "computeValue() must have assignment");
+  result = a->evaluate(query.expr);  
+  assert(result.isConstant() && 
+         "assignment evaluation did not result in constant");
+  return true;
+}
+
+bool 
+CexCachingSolver::computeInitialValues(const Query& query,
+                                       const std::vector<const Array*> 
+                                         &objects,
+                                       std::vector< std::vector<unsigned char> >
+                                         &values,
+                                       bool &hasSolution) {
+  TimerStatIncrementer t(stats::cexCacheTime);
+  Assignment *a;
+  if (!getAssignment(query, a))
+    return false;
+  hasSolution = !!a;
+  
+  if (!a)
+    return true;
+
+  // FIXME: We should use smarter assignment for result so we don't
+  // need redundant copy.
+  values = std::vector< std::vector<unsigned char> >(objects.size());
+  for (unsigned i=0; i < objects.size(); ++i) {
+    const Array *os = objects[i];
+    Assignment::bindings_ty::iterator it = a->bindings.find(os);
+    
+    if (it == a->bindings.end()) {
+      values[i] = std::vector<unsigned char>(os->size, 0);
+    } else {
+      values[i] = it->second;
+    }
+  }
+  
+  return true;
+}
+
+///
+
+Solver *klee::createCexCachingSolver(Solver *_solver) {
+  return new Solver(new CexCachingSolver(_solver));
+}

Added: klee/trunk/lib/Solver/ConstantDivision.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/ConstantDivision.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/ConstantDivision.cpp (added)
+++ klee/trunk/lib/Solver/ConstantDivision.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,146 @@
+//===-- ConstantDivision.cpp ----------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ConstantDivision.h"
+
+#include "klee/util/Bits.h"
+
+#include <algorithm>
+#include <cassert>
+
+namespace klee {
+
+/* Macros and functions which define the basic bit-level operations 
+ * needed to implement quick division operations.
+ *
+ * Based on Hacker's Delight (2003) by Henry S. Warren, Jr.
+ */
+
+/* 32 -- number of bits in the integer type on this architecture */
+
+/* 2^32 -- NUM_BITS=32 requires 64 bits to represent this unsigned value */
+#define TWO_TO_THE_32_U64 (1ULL << 32)
+
+/* 2e31 -- NUM_BITS=32 requires 64 bits to represent this signed value */
+#define TWO_TO_THE_31_S64 (1LL << 31)
+
+/* ABS(x) -- positive x */
+#define ABS(x) ( ((x)>0)?x:-(x) ) /* fails if x is the min value of its type */
+
+/* XSIGN(x) -- -1 if x<0 and 0 otherwise */
+#define XSIGN(x) ( (x) >> 31 )
+
+/* LOG2_CEIL(x) -- logarithm base 2 of x, rounded up */
+#define LOG2_CEIL(x) ( 32 - ldz(x - 1) )
+
+/* ones(x) -- counts the number of bits in x with the value 1 */
+static uint32_t ones( register uint32_t x ) {
+  x -= ((x >> 1) & 0x55555555);
+  x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
+  x = (((x >> 4) + x) & 0x0f0f0f0f);
+  x += (x >> 8);
+  x += (x >> 16);
+
+  return( x & 0x0000003f );
+}
+
+/* ldz(x) -- counts the number of leading zeroes in a 32-bit word */
+static uint32_t ldz( register uint32_t x ) {
+  x |= (x >> 1);
+  x |= (x >> 2);
+  x |= (x >> 4);
+  x |= (x >> 8);
+  x |= (x >> 16);
+
+  return 32 - ones(x);
+}
+
+/* exp_base_2(n) -- 2^n computed as an integer */
+static uint32_t exp_base_2( register int32_t n ) {
+  register uint32_t x = ~n & (n - 32);
+  x = x >> 31;
+  return( x << n );
+}
+
+// A simple algorithm: Iterate over all contiguous regions of 1 bits
+// in x starting with the lowest bits.
+//
+// For a particular range where x is 1 for bits [low,high) then:
+//   1) if the range is just one bit, simple add it
+//   2) if the range is more than one bit, replace with an add
+//      of the high bit and a subtract of the low bit. we apply
+//      one useful optimization: if we were going to add the bit
+//      below the one we wish to subtract, we simply change that
+//      add to a subtract instead of subtracting the low bit itself.
+// Obviously we must take care when high==64.
+void ComputeMultConstants64(uint64_t multiplicand, 
+                            uint64_t &add, uint64_t &sub) {
+  uint64_t x = multiplicand;
+  add = sub = 0;
+
+  while (x) {
+    // Determine rightmost contiguous region of 1s.
+    unsigned low = bits64::indexOfRightmostBit(x);
+    uint64_t lowbit = 1LL << low;
+    uint64_t p = x + lowbit;
+    uint64_t q = bits64::isolateRightmostBit(p);
+    unsigned high = q ? bits64::indexOfSingleBit(q) : 64;
+
+    if (high==low+1) { // Just one bit...
+      add |= lowbit;
+    } else {
+      // Rewrite as +(1<<high) - (1<<low).
+
+      // Optimize +(1<<x) - (1<<(x+1)) to -(1<<x).
+      if (low && (add & (lowbit>>1))) {
+        add ^= lowbit>>1;
+        sub ^= lowbit>>1;
+      } else {
+        sub |= lowbit;
+      }
+
+      if (high!=64)
+        add |= 1LL << high;
+    }
+
+    x = p ^ q;
+  }
+
+  assert(multiplicand == add - sub);
+}
+
+void ComputeUDivConstants32(uint32_t d, uint32_t &mprime, uint32_t &sh1, 
+                            uint32_t &sh2) {
+  int32_t l = LOG2_CEIL( d ); /* signed so l-1 => -1 when l=0 (see sh2) */
+  uint32_t mid = exp_base_2(l) - d;
+
+  mprime = (TWO_TO_THE_32_U64 * mid / d) + 1;
+  sh1    = std::min( l,   1 );
+  sh2    = std::max( l-1, 0 );
+}
+
+void ComputeSDivConstants32(int32_t d, int32_t &mprime, int32_t &dsign, 
+                            int32_t &shpost ) {
+  uint64_t abs_d = ABS( (int64_t)d ); /* use 64-bits in case d is INT32_MIN */
+
+  /* LOG2_CEIL works on 32-bits, so we cast abs_d.  The only possible value
+   * outside the 32-bit rep. is 2^31.  This is special cased to save computer 
+   * time since 64-bit routines would be overkill. */
+  int32_t l = std::max( 1U, LOG2_CEIL((uint32_t)abs_d) );
+  if( abs_d == TWO_TO_THE_31_S64 ) l = 31;
+
+  uint32_t mid = exp_base_2( l - 1 );
+  uint64_t m = TWO_TO_THE_32_U64 * mid / abs_d + 1ULL;
+
+  mprime = m - TWO_TO_THE_32_U64; /* implicit cast to 32-bits signed */
+  dsign  = XSIGN( d );
+  shpost = l - 1;
+}
+
+}

Added: klee/trunk/lib/Solver/ConstantDivision.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/ConstantDivision.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/ConstantDivision.h (added)
+++ klee/trunk/lib/Solver/ConstantDivision.h Wed May 20 23:36:41 2009
@@ -0,0 +1,51 @@
+//===-- ConstantDivision.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_CONSTANTDIVISION_H__
+#define __UTIL_CONSTANTDIVISION_H__
+
+#include <stdint.h>
+
+namespace klee {
+
+/// ComputeMultConstants64 - Compute add and sub such that add-sub==x,
+/// while attempting to minimize the number of bits in add and sub
+/// combined.
+void ComputeMultConstants64(uint64_t x, uint64_t &add_out, 
+                            uint64_t &sub_out);
+
+/// Compute the constants to perform a quicker equivalent of a division of some 
+/// 32-bit unsigned integer n by a known constant d (also a 32-bit unsigned 
+/// integer).  The constants to compute n/d without explicit division will be 
+/// stored in mprime, sh1, and sh2 (unsigned 32-bit integers).
+/// 
+/// @param d - denominator (divisor)
+/// 
+/// @param [out] mprime
+/// @param [out] sh1
+/// @param [out] sh2
+void ComputeUDivConstants32(uint32_t d, uint32_t &mprime, uint32_t &sh1, 
+                            uint32_t &sh2);
+
+/// Compute the constants to perform a quicker equivalent of a division of some 
+/// 32-bit signed integer n by a known constant d (also a 32-bit signed 
+/// integer).  The constants to compute n/d without explicit division will be 
+/// stored in mprime, dsign, and shpost (signed 32-bit integers).
+/// 
+/// @param d - denominator (divisor)
+/// 
+/// @param [out] mprime
+/// @param [out] dsign
+/// @param [out] shpost
+void ComputeSDivConstants32(int32_t d, int32_t &mprime, int32_t &dsign, 
+                            int32_t &shpost);
+
+}
+
+#endif

Added: klee/trunk/lib/Solver/FastCexSolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/FastCexSolver.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/FastCexSolver.cpp (added)
+++ klee/trunk/lib/Solver/FastCexSolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,959 @@
+//===-- FastCexSolver.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/Solver.h"
+
+#include "klee/Constraints.h"
+#include "klee/Expr.h"
+#include "klee/IncompleteSolver.h"
+#include "klee/util/ExprEvaluator.h"
+#include "klee/util/ExprRangeEvaluator.h"
+#include "klee/util/ExprVisitor.h"
+// FIXME: Use APInt.
+#include "klee/Internal/Support/IntEvaluation.h"
+
+#include <iostream>
+#include <sstream>
+#include <cassert>
+#include <map>
+#include <vector>
+
+using namespace klee;
+
+/***/
+
+//#define LOG
+#ifdef LOG
+std::ostream *theLog;
+#endif
+
+      // Hacker's Delight, pgs 58-63
+static uint64_t minOR(uint64_t a, uint64_t b,
+                      uint64_t c, uint64_t d) {
+  uint64_t temp, m = ((uint64_t) 1)<<63;
+  while (m) {
+    if (~a & c & m) {
+      temp = (a | m) & -m;
+      if (temp <= b) { a = temp; break; }
+    } else if (a & ~c & m) {
+      temp = (c | m) & -m;
+      if (temp <= d) { c = temp; break; }
+    }
+    m >>= 1;
+  }
+  
+  return a | c;
+}
+static uint64_t maxOR(uint64_t a, uint64_t b,
+                      uint64_t c, uint64_t d) {
+  uint64_t temp, m = ((uint64_t) 1)<<63;
+
+  while (m) {
+    if (b & d & m) {
+      temp = (b - m) | (m - 1);
+      if (temp >= a) { b = temp; break; }
+      temp = (d - m) | (m -1);
+      if (temp >= c) { d = temp; break; }
+    }
+    m >>= 1;
+  }
+
+  return b | d;
+}
+static uint64_t minAND(uint64_t a, uint64_t b,
+                       uint64_t c, uint64_t d) {
+  uint64_t temp, m = ((uint64_t) 1)<<63;
+  while (m) {
+    if (~a & ~c & m) {
+      temp = (a | m) & -m;
+      if (temp <= b) { a = temp; break; }
+      temp = (c | m) & -m;
+      if (temp <= d) { c = temp; break; }
+    }
+    m >>= 1;
+  }
+  
+  return a & c;
+}
+static uint64_t maxAND(uint64_t a, uint64_t b,
+                       uint64_t c, uint64_t d) {
+  uint64_t temp, m = ((uint64_t) 1)<<63;
+  while (m) {
+    if (b & ~d & m) {
+      temp = (b & ~m) | (m - 1);
+      if (temp >= a) { b = temp; break; }
+    } else if (~b & d & m) {
+      temp = (d & ~m) | (m - 1);
+      if (temp >= c) { d = temp; break; }
+    }
+    m >>= 1;
+  }
+  
+  return b & d;
+}
+
+///
+
+class ValueRange {
+private:
+  uint64_t m_min, m_max;
+
+public:
+  ValueRange() : m_min(1),m_max(0) {}
+  ValueRange(uint64_t value) : m_min(value), m_max(value) {}
+  ValueRange(uint64_t _min, uint64_t _max) : m_min(_min), m_max(_max) {}
+  ValueRange(const ValueRange &b) : m_min(b.m_min), m_max(b.m_max) {}
+
+  void print(std::ostream &os) const {
+    if (isFixed()) {
+      os << m_min;
+    } else {
+      os << "[" << m_min << "," << m_max << "]";
+    }
+  }
+
+  bool isEmpty() const { 
+    return m_min>m_max; 
+  }
+  bool contains(uint64_t value) const { 
+    return this->intersects(ValueRange(value)); 
+  }
+  bool intersects(const ValueRange &b) const { 
+    return !this->set_intersection(b).isEmpty(); 
+  }
+
+  bool isFullRange(unsigned bits) {
+    return m_min==0 && m_max==bits64::maxValueOfNBits(bits);
+  }
+
+  ValueRange set_intersection(const ValueRange &b) const {
+    return ValueRange(std::max(m_min,b.m_min), std::min(m_max,b.m_max));
+  }
+  ValueRange set_union(const ValueRange &b) const {
+    return ValueRange(std::min(m_min,b.m_min), std::max(m_max,b.m_max));
+  }
+  ValueRange set_difference(const ValueRange &b) const {
+    if (b.isEmpty() || b.m_min > m_max || b.m_max < m_min) { // no intersection
+      return *this;
+    } else if (b.m_min <= m_min && b.m_max >= m_max) { // empty
+      return ValueRange(1,0); 
+    } else if (b.m_min <= m_min) { // one range out
+      // cannot overflow because b.m_max < m_max
+      return ValueRange(b.m_max+1, m_max);
+    } else if (b.m_max >= m_max) {
+      // cannot overflow because b.min > m_min
+      return ValueRange(m_min, b.m_min-1);
+    } else {
+      // two ranges, take bottom
+      return ValueRange(m_min, b.m_min-1);
+    }
+  }
+  ValueRange binaryAnd(const ValueRange &b) const {
+    // XXX
+    assert(!isEmpty() && !b.isEmpty() && "XXX");
+    if (isFixed() && b.isFixed()) {
+      return ValueRange(m_min & b.m_min);
+    } else {
+      return ValueRange(minAND(m_min, m_max, b.m_min, b.m_max),
+                        maxAND(m_min, m_max, b.m_min, b.m_max));
+    }
+  }
+  ValueRange binaryAnd(uint64_t b) const { return binaryAnd(ValueRange(b)); }
+  ValueRange binaryOr(ValueRange b) const {
+    // XXX
+    assert(!isEmpty() && !b.isEmpty() && "XXX");
+    if (isFixed() && b.isFixed()) {
+      return ValueRange(m_min | b.m_min);
+    } else {
+      return ValueRange(minOR(m_min, m_max, b.m_min, b.m_max),
+                        maxOR(m_min, m_max, b.m_min, b.m_max));
+    }
+  }
+  ValueRange binaryOr(uint64_t b) const { return binaryOr(ValueRange(b)); }
+  ValueRange binaryXor(ValueRange b) const {
+    if (isFixed() && b.isFixed()) {
+      return ValueRange(m_min ^ b.m_min);
+    } else {
+      uint64_t t = m_max | b.m_max;
+      while (!bits64::isPowerOfTwo(t))
+        t = bits64::withoutRightmostBit(t);
+      return ValueRange(0, (t<<1)-1);
+    }
+  }
+
+  ValueRange binaryShiftLeft(unsigned bits) const {
+    return ValueRange(m_min<<bits, m_max<<bits);
+  }
+  ValueRange binaryShiftRight(unsigned bits) const {
+    return ValueRange(m_min>>bits, m_max>>bits);
+  }
+
+  ValueRange concat(const ValueRange &b, unsigned bits) const {
+    return binaryShiftLeft(bits).binaryOr(b);
+  }
+  ValueRange extract(uint64_t lowBit, uint64_t maxBit) const {
+    return binaryShiftRight(lowBit).binaryAnd(bits64::maxValueOfNBits(maxBit-lowBit));
+  }
+
+  ValueRange add(const ValueRange &b, unsigned width) const {
+    return ValueRange(0, bits64::maxValueOfNBits(width));
+  }
+  ValueRange sub(const ValueRange &b, unsigned width) const {
+    return ValueRange(0, bits64::maxValueOfNBits(width));
+  }
+  ValueRange mul(const ValueRange &b, unsigned width) const {
+    return ValueRange(0, bits64::maxValueOfNBits(width));
+  }
+  ValueRange udiv(const ValueRange &b, unsigned width) const {
+    return ValueRange(0, bits64::maxValueOfNBits(width));
+  }
+  ValueRange sdiv(const ValueRange &b, unsigned width) const {
+    return ValueRange(0, bits64::maxValueOfNBits(width));
+  }
+  ValueRange urem(const ValueRange &b, unsigned width) const {
+    return ValueRange(0, bits64::maxValueOfNBits(width));
+  }
+  ValueRange srem(const ValueRange &b, unsigned width) const {
+    return ValueRange(0, bits64::maxValueOfNBits(width));
+  }
+
+  // use min() to get value if true (XXX should we add a method to
+  // make code clearer?)
+  bool isFixed() const { return m_min==m_max; }
+
+  bool operator==(const ValueRange &b) const { return m_min==b.m_min && m_max==b.m_max; }
+  bool operator!=(const ValueRange &b) const { return !(*this==b); }
+
+  bool mustEqual(const uint64_t b) const { return m_min==m_max && m_min==b; }
+  bool mayEqual(const uint64_t b) const { return m_min<=b && m_max>=b; }
+  
+  bool mustEqual(const ValueRange &b) const { return isFixed() && b.isFixed() && m_min==b.m_min; }
+  bool mayEqual(const ValueRange &b) const { return this->intersects(b); }
+
+  uint64_t min() const { 
+    assert(!isEmpty() && "cannot get minimum of empty range");
+    return m_min; 
+  }
+
+  uint64_t max() const { 
+    assert(!isEmpty() && "cannot get maximum of empty range");
+    return m_max; 
+  }
+  
+  int64_t minSigned(unsigned bits) const {
+    assert((m_min>>bits)==0 && (m_max>>bits)==0 &&
+           "range is outside given number of bits");
+
+    // if max allows sign bit to be set then it can be smallest value,
+    // otherwise since the range is not empty, min cannot have a sign
+    // bit
+
+    uint64_t smallest = ((uint64_t) 1 << (bits-1));
+    if (m_max >= smallest) {
+      return ints::sext(smallest, 64, bits);
+    } else {
+      return m_min;
+    }
+  }
+
+  int64_t maxSigned(unsigned bits) const {
+    assert((m_min>>bits)==0 && (m_max>>bits)==0 &&
+           "range is outside given number of bits");
+
+    uint64_t smallest = ((uint64_t) 1 << (bits-1));
+
+    // if max and min have sign bit then max is max, otherwise if only
+    // max has sign bit then max is largest signed integer, otherwise
+    // max is max
+
+    if (m_min < smallest && m_max >= smallest) {
+      return smallest - 1;
+    } else {
+      return ints::sext(m_max, 64, bits);
+    }
+  }
+};
+
+inline std::ostream &operator<<(std::ostream &os, const ValueRange &vr) {
+  vr.print(os);
+  return os;
+}
+
+// used to find all memory object ids and the maximum size of any
+// object state that references them (for symbolic size).
+class ObjectFinder : public ExprVisitor {
+protected:
+  Action visitRead(const ReadExpr &re) {
+    addUpdates(re.updates);
+    return Action::doChildren();
+  }
+
+  // XXX nice if this information was cached somewhere, used by
+  // independence as well right?
+  void addUpdates(const UpdateList &ul) {
+    for (const UpdateNode *un=ul.head; un; un=un->next) {
+      visit(un->index);
+      visit(un->value);
+    }
+
+    addObject(*ul.root);
+  }
+
+public:
+  void addObject(const Array& array) {
+    unsigned id = array.id;
+    std::map<unsigned,unsigned>::iterator it = results.find(id);
+
+    // FIXME: Not 64-bit size clean.
+    if (it == results.end()) {
+      results[id] = (unsigned) array.size;      
+    } else {
+      it->second = std::max(it->second, (unsigned) array.size);
+    }
+  }
+
+public:
+  std::map<unsigned, unsigned> results;
+};
+
+// XXX waste of space, rather have ByteValueRange
+typedef ValueRange CexValueData;
+
+class CexObjectData {
+public:
+  unsigned size;
+  CexValueData *values;
+
+public:
+  CexObjectData(unsigned _size) : size(_size), values(new CexValueData[size]) {
+    for (unsigned i=0; i<size; i++)
+      values[i] = ValueRange(0, 255);
+  }
+};
+
+class CexRangeEvaluator : public ExprRangeEvaluator<ValueRange> {
+public:
+  std::map<unsigned, CexObjectData> &objectValues;
+  CexRangeEvaluator(std::map<unsigned, CexObjectData> &_objectValues) 
+    : objectValues(_objectValues) {}
+
+  ValueRange getInitialReadRange(const Array &os, ValueRange index) {
+    return ValueRange(0, 255);
+  }
+};
+
+class CexConstifier : public ExprEvaluator {
+protected:
+  ref<Expr> getInitialValue(const Array& array, unsigned index) {
+    std::map<unsigned, CexObjectData>::iterator it = 
+      objectValues.find(array.id);
+    assert(it != objectValues.end() && "missing object?");
+    CexObjectData &cod = it->second;
+    
+    if (index >= cod.size) {
+      return ReadExpr::create(UpdateList(&array, true, 0), 
+                              ref<Expr>(index, Expr::Int32));
+    } else {
+      CexValueData &cvd = cod.values[index];
+      assert(cvd.min() == cvd.max() && "value is not fixed");
+      return ref<Expr>(cvd.min(), Expr::Int8);
+    }
+  }
+
+public:
+  std::map<unsigned, CexObjectData> &objectValues;
+  CexConstifier(std::map<unsigned, CexObjectData> &_objectValues) 
+    : objectValues(_objectValues) {}
+};
+
+class CexData {
+public:
+  std::map<unsigned, CexObjectData> objectValues;
+
+public:
+  CexData(ObjectFinder &finder) {
+    for (std::map<unsigned,unsigned>::iterator it = finder.results.begin(),
+           ie = finder.results.end(); it != ie; ++it) {
+      objectValues.insert(std::pair<unsigned, CexObjectData>(it->first, 
+                                                             CexObjectData(it->second)));
+    }
+  }  
+  ~CexData() {
+    for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
+           ie = objectValues.end(); it != ie; ++it)
+      delete[] it->second.values;
+  }
+
+  void forceExprToValue(ref<Expr> e, uint64_t value) {
+    forceExprToRange(e, CexValueData(value,value));
+  }
+
+  void forceExprToRange(ref<Expr> e, CexValueData range) {
+#ifdef LOG
+    //    *theLog << "force: " << e << " to " << range << "\n";
+#endif
+    switch (e.getKind()) {
+    case Expr::Constant: {
+      // rather a pity if the constant isn't in the range, but how can
+      // we use this?
+      break;
+    }
+
+      // Special
+
+    case Expr::NotOptimized: break;
+
+    case Expr::Read: {
+      ReadExpr *re = static_ref_cast<ReadExpr>(e);
+      const Array *array = re->updates.root;
+      CexObjectData &cod = objectValues.find(array->id)->second;
+
+      // XXX we need to respect the version here and object state chain
+
+      if (re->index.isConstant() && 
+          re->index.getConstantValue() < array->size) {
+        CexValueData &cvd = cod.values[re->index.getConstantValue()];
+        CexValueData tmp = cvd.set_intersection(range);
+        
+        if (tmp.isEmpty()) {
+          if (range.isFixed()) // ranges conflict, if new one is fixed use that
+            cvd = range;
+        } else {
+          cvd = tmp;
+        }
+      } else {
+        // XXX        fatal("XXX not implemented");
+      }
+      
+      break;
+    }
+
+    case Expr::Select: {
+      SelectExpr *se = static_ref_cast<SelectExpr>(e);
+      ValueRange cond = evalRangeForExpr(se->cond);
+      if (cond.isFixed()) {
+        if (cond.min()) {
+          forceExprToRange(se->trueExpr, range);
+        } else {
+          forceExprToRange(se->falseExpr, range);
+        }
+      } else {
+        // XXX imprecise... we have a choice here. One method is to
+        // simply force both sides into the specified range (since the
+        // condition is indetermined). This may lose in two ways, the
+        // first is that the condition chosen may limit further
+        // restrict the range in each of the children, however this is
+        // less of a problem as the range will be a superset of legal
+        // values. The other is if the condition ends up being forced
+        // by some other constraints, then we needlessly forced one
+        // side into the given range.
+        //
+        // The other method would be to force the condition to one
+        // side and force that side into the given range. This loses
+        // when we force the condition to an unsatisfiable value
+        // (either because the condition cannot be that, or the
+        // resulting range given that condition is not in the required
+        // range).
+        // 
+        // Currently we just force both into the range. A hybrid would
+        // be to evaluate the ranges for each of the children... if
+        // one of the ranges happens to already be a subset of the
+        // required range then it may be preferable to force the
+        // condition to that side.
+        forceExprToRange(se->trueExpr, range);
+        forceExprToRange(se->falseExpr, range);
+      }
+      break;
+    }
+
+      // XXX imprecise... the problem here is that extracting bits
+      // loses information about what bits are connected across the
+      // bytes. if a value can be 1 or 256 then either the top or
+      // lower byte is 0, but just extraction loses this information
+      // and will allow neither,one,or both to be 1.
+      //
+      // we can protect against this in a limited fashion by writing
+      // the extraction a byte at a time, then checking the evaluated
+      // value, isolating for that range, and continuing.
+    case Expr::Concat: {
+      ConcatExpr *ce = static_ref_cast<ConcatExpr>(e);
+      if (ce->is2ByteConcat()) {
+	forceExprToRange(ce->getKid(0), range.extract( 8, 16));
+	forceExprToRange(ce->getKid(1), range.extract( 0,  8));
+      }
+      else if (ce->is4ByteConcat()) {
+	forceExprToRange(ce->getKid(0), range.extract(24, 32));
+	forceExprToRange(ce->getKid(1), range.extract(16, 24));
+	forceExprToRange(ce->getKid(2), range.extract( 8, 16));
+	forceExprToRange(ce->getKid(3), range.extract( 0,  8));
+      }
+      else if (ce->is8ByteConcat()) {
+	forceExprToRange(ce->getKid(0), range.extract(56, 64));
+	forceExprToRange(ce->getKid(1), range.extract(48, 56));
+	forceExprToRange(ce->getKid(2), range.extract(40, 48));
+	forceExprToRange(ce->getKid(3), range.extract(32, 40));
+	forceExprToRange(ce->getKid(4), range.extract(24, 32));
+	forceExprToRange(ce->getKid(5), range.extract(16, 24));
+	forceExprToRange(ce->getKid(6), range.extract( 8, 16));
+	forceExprToRange(ce->getKid(7), range.extract( 0,  8));
+      }
+      
+      break;
+    }
+
+    case Expr::Extract: {
+      // XXX
+      break;
+    }
+
+      // Casting
+
+      // Simply intersect the output range with the range of all
+      // possible outputs and then truncate to the desired number of
+      // bits. 
+
+      // For ZExt this simplifies to just intersection with the
+      // possible input range.
+    case Expr::ZExt: {
+      CastExpr *ce = static_ref_cast<CastExpr>(e);
+      unsigned inBits = ce->src.getWidth();
+      ValueRange input = range.set_intersection(ValueRange(0, bits64::maxValueOfNBits(inBits)));
+      forceExprToRange(ce->src, input);
+      break;
+    }
+      // For SExt instead of doing the intersection we just take the output range
+      // minus the impossible values. This is nicer since it is a single interval.
+    case Expr::SExt: {
+      CastExpr *ce = static_ref_cast<CastExpr>(e);
+      unsigned inBits = ce->src.getWidth();
+      unsigned outBits = ce->width;
+      ValueRange output = range.set_difference(ValueRange(1<<(inBits-1),
+                                                          (bits64::maxValueOfNBits(outBits)-
+                                                           bits64::maxValueOfNBits(inBits-1)-1)));
+      ValueRange input = output.binaryAnd(bits64::maxValueOfNBits(inBits));
+      forceExprToRange(ce->src, input);
+      break;
+    }
+
+      // Binary
+
+    case Expr::And: {
+      BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+      if (be->getWidth()==Expr::Bool) {
+        if (range.isFixed()) {
+          ValueRange left = evalRangeForExpr(be->left);
+          ValueRange right = evalRangeForExpr(be->right);
+
+          if (!range.min()) {
+            if (left.mustEqual(0) || right.mustEqual(0)) {
+              // all is well
+            } else {
+              // XXX heuristic, which order
+
+              forceExprToValue(be->left, 0);
+              left = evalRangeForExpr(be->left);
+
+              // see if that worked
+              if (!left.mustEqual(1))
+                forceExprToValue(be->right, 0);
+            }
+          } else {
+            if (!left.mustEqual(1)) forceExprToValue(be->left, 1);
+            if (!right.mustEqual(1)) forceExprToValue(be->right, 1);
+          }
+        }
+      } else {
+        // XXX
+      }
+      break;
+    }
+
+    case Expr::Or: {
+      BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+      if (be->getWidth()==Expr::Bool) {
+        if (range.isFixed()) {
+          ValueRange left = evalRangeForExpr(be->left);
+          ValueRange right = evalRangeForExpr(be->right);
+
+          if (range.min()) {
+            if (left.mustEqual(1) || right.mustEqual(1)) {
+              // all is well
+            } else {
+              // XXX heuristic, which order?
+              
+              // force left to value we need
+              forceExprToValue(be->left, 1);
+              left = evalRangeForExpr(be->left);
+
+              // see if that worked
+              if (!left.mustEqual(1))
+                forceExprToValue(be->right, 1);
+            }
+          } else {
+            if (!left.mustEqual(0)) forceExprToValue(be->left, 0);
+            if (!right.mustEqual(0)) forceExprToValue(be->right, 0);
+          }
+        }
+      } else {
+        // XXX
+      }
+      break;
+    }
+
+    case Expr::Xor: break;
+
+      // Comparison
+
+    case Expr::Eq: {
+      BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+      if (range.isFixed()) {
+        if (be->left.isConstant()) {
+          uint64_t value = be->left.getConstantValue();
+          if (range.min()) {
+            forceExprToValue(be->right, value);
+          } else {
+            if (value==0) {
+              forceExprToRange(be->right, 
+                               CexValueData(1,
+                                            ints::sext(1, 
+                                                       be->right.getWidth(),
+                                                       1)));
+            } else {
+              // XXX heuristic / lossy, could be better to pick larger range?
+              forceExprToRange(be->right, CexValueData(0, value-1));
+            }
+          }
+        } else {
+          // XXX what now
+        }
+      }
+      break;
+    }
+
+    case Expr::Ult: {
+      BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+      
+      // XXX heuristic / lossy, what order if conflict
+
+      if (range.isFixed()) {
+        ValueRange left = evalRangeForExpr(be->left);
+        ValueRange right = evalRangeForExpr(be->right);
+
+        uint64_t maxValue = bits64::maxValueOfNBits(be->right.getWidth());
+
+        // XXX should deal with overflow (can lead to empty range)
+
+        if (left.isFixed()) {
+          if (range.min()) {
+            forceExprToRange(be->right, CexValueData(left.min()+1, maxValue));
+          } else {
+            forceExprToRange(be->right, CexValueData(0, left.min()));
+          }
+        } else if (right.isFixed()) {
+          if (range.min()) {
+            forceExprToRange(be->left, CexValueData(0, right.min()-1));
+          } else {
+            forceExprToRange(be->left, CexValueData(right.min(), maxValue));
+          }
+        } else {
+          // XXX ???
+        }
+      }
+      break;
+    }
+    case Expr::Ule: {
+      BinaryExpr *be = static_ref_cast<BinaryExpr>(e);
+      
+      // XXX heuristic / lossy, what order if conflict
+
+      if (range.isFixed()) {
+        ValueRange left = evalRangeForExpr(be->left);
+        ValueRange right = evalRangeForExpr(be->right);
+
+        // XXX should deal with overflow (can lead to empty range)
+
+        uint64_t maxValue = bits64::maxValueOfNBits(be->right.getWidth());
+        if (left.isFixed()) {
+          if (range.min()) {
+            forceExprToRange(be->right, CexValueData(left.min(), maxValue));
+          } else {
+            forceExprToRange(be->right, CexValueData(0, left.min()-1));
+          }
+        } else if (right.isFixed()) {
+          if (range.min()) {
+            forceExprToRange(be->left, CexValueData(0, right.min()));
+          } else {
+            forceExprToRange(be->left, CexValueData(right.min()+1, maxValue));
+          }
+        } else {
+          // XXX ???
+        }
+      }
+      break;
+    }
+
+    case Expr::Ne:
+    case Expr::Ugt:
+    case Expr::Uge:
+    case Expr::Sgt:
+    case Expr::Sge:
+      assert(0 && "invalid expressions (uncanonicalized");
+
+    default:
+      break;
+    }
+  }
+
+  void fixValues() {
+    for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
+           ie = objectValues.end(); it != ie; ++it) {
+      CexObjectData &cod = it->second;
+      for (unsigned i=0; i<cod.size; i++) {
+        CexValueData &cvd = cod.values[i];
+        cvd = CexValueData(cvd.min() + (cvd.max()-cvd.min())/2);
+      }
+    }
+  }
+
+  ValueRange evalRangeForExpr(ref<Expr> &e) {
+    CexRangeEvaluator ce(objectValues);
+    return ce.evaluate(e);
+  }
+
+  bool exprMustBeValue(ref<Expr> e, uint64_t value) {
+    CexConstifier cc(objectValues);
+    ref<Expr> v = cc.visit(e);
+    if (!v.isConstant()) return false;
+    // XXX reenable once all reads and vars are fixed
+    //    assert(v.isConstant() && "not all values have been fixed");
+    return v.getConstantValue()==value;
+  }
+};
+
+/* *** */
+
+
+class FastCexSolver : public IncompleteSolver {
+public:
+  FastCexSolver();
+  ~FastCexSolver();
+
+  IncompleteSolver::PartialValidity computeTruth(const Query&);  
+  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);
+};
+
+FastCexSolver::FastCexSolver() { }
+
+FastCexSolver::~FastCexSolver() { }
+
+IncompleteSolver::PartialValidity 
+FastCexSolver::computeTruth(const Query& query) {
+#ifdef LOG
+  std::ostringstream log;
+  theLog = &log;
+  //  log << "------ start FastCexSolver::mustBeTrue ------\n";
+  log << "-- QUERY --\n";
+  unsigned i=0;
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    log << "    C" << i++ << ": " << *it << ", \n";
+  log << "    Q : " << query.expr << "\n";
+#endif
+
+  ObjectFinder of;
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    of.visit(*it);
+  of.visit(query.expr);
+  CexData cd(of);
+
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    cd.forceExprToValue(*it, 1);
+  cd.forceExprToValue(query.expr, 0);
+
+#ifdef LOG
+  log << " -- ranges --\n";
+  for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
+         ie = objectValues.end(); it != ie; ++it) {
+    CexObjectData &cod = it->second;
+    log << "    arr" << it->first << "[" << cod.size << "] = [";
+    unsigned continueFrom=cod.size-1;
+    for (; continueFrom>0; continueFrom--)
+      if (cod.values[continueFrom-1]!=cod.values[continueFrom])
+        break;
+    for (unsigned i=0; i<cod.size; i++) {
+      log << cod.values[i];
+      if (i<cod.size-1) {
+        log << ", ";
+        if (i==continueFrom) {
+          log << "...";
+          break;
+        }
+      }
+    }
+    log << "]\n";
+  }
+#endif
+
+  // this could be done lazily of course
+  cd.fixValues();
+
+#ifdef LOG
+  log << " -- fixed values --\n";
+  for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
+         ie = objectValues.end(); it != ie; ++it) {
+    CexObjectData &cod = it->second;
+    log << "    arr" << it->first << "[" << cod.size << "] = [";
+    unsigned continueFrom=cod.size-1;
+    for (; continueFrom>0; continueFrom--)
+      if (cod.values[continueFrom-1]!=cod.values[continueFrom])
+        break;
+    for (unsigned i=0; i<cod.size; i++) {
+      log << cod.values[i];
+      if (i<cod.size-1) {
+        log << ", ";
+        if (i==continueFrom) {
+          log << "...";
+          break;
+        }
+      }
+    }
+    log << "]\n";
+  }
+#endif
+
+  // check the result
+
+  bool isGood = true;
+
+  if (!cd.exprMustBeValue(query.expr, 0)) isGood = false;
+
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    if (!cd.exprMustBeValue(*it, 1)) 
+      isGood = false;
+
+#ifdef LOG
+  log << " -- evaluating result --\n";
+  
+  i=0;
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it) {
+    bool res = cd.exprMustBeValue(*it, 1);
+    log << "    C" << i++ << ": " << (res?"true":"false") << "\n";
+  }
+  log << "    Q : " 
+      << (cd.exprMustBeValue(query.expr, 0)?"true":"false") << "\n";
+  
+  log << "\n\n";
+#endif
+
+  return isGood ? IncompleteSolver::MayBeFalse : IncompleteSolver::None;
+}
+
+bool FastCexSolver::computeValue(const Query& query, ref<Expr> &result) {
+  ObjectFinder of;
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    of.visit(*it);
+  of.visit(query.expr);
+  CexData cd(of);
+
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    cd.forceExprToValue(*it, 1);
+
+  // this could be done lazily of course
+  cd.fixValues();
+
+  // check the result
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    if (!cd.exprMustBeValue(*it, 1))
+      return false;
+
+  CexConstifier cc(cd.objectValues);
+  ref<Expr> value = cc.visit(query.expr);
+
+  if (value.isConstant()) {
+    result = value;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool
+FastCexSolver::computeInitialValues(const Query& query,
+                                    const std::vector<const Array*>
+                                      &objects,
+                                    std::vector< std::vector<unsigned char> >
+                                      &values,
+                                    bool &hasSolution) {
+  ObjectFinder of;
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    of.visit(*it);
+  of.visit(query.expr);
+  for (unsigned i = 0; i != objects.size(); ++i)
+    of.addObject(*objects[i]);
+  CexData cd(of);
+
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    cd.forceExprToValue(*it, 1);
+  cd.forceExprToValue(query.expr, 0);
+
+  // this could be done lazily of course
+  cd.fixValues();
+
+  // check the result
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    if (!cd.exprMustBeValue(*it, 1))
+      return false;
+  if (!cd.exprMustBeValue(query.expr, 0))
+    return false;
+
+  hasSolution = true;
+  CexConstifier cc(cd.objectValues);
+  for (unsigned i = 0; i != objects.size(); ++i) {
+    const Array *array = objects[i];
+    std::vector<unsigned char> data;
+    data.reserve(array->size);
+
+    for (unsigned i=0; i < array->size; i++) {
+      ref<Expr> value =
+        cc.visit(ReadExpr::create(UpdateList(array, true, 0),
+                                  ConstantExpr::create(i,
+                                                       kMachinePointerType)));
+      
+      if (value.isConstant()) {
+        data.push_back(value.getConstantValue());
+      } else {
+        // FIXME: When does this happen?
+        return false;
+      }
+    }
+
+    values.push_back(data);
+  }
+
+  return true;
+}
+
+
+Solver *klee::createFastCexSolver(Solver *s) {
+  return new Solver(new StagedSolverImpl(new FastCexSolver(), s));
+}

Added: klee/trunk/lib/Solver/IncompleteSolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/IncompleteSolver.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/IncompleteSolver.cpp (added)
+++ klee/trunk/lib/Solver/IncompleteSolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,136 @@
+//===-- IncompleteSolver.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/IncompleteSolver.h"
+
+#include "klee/Constraints.h"
+
+using namespace klee;
+using namespace llvm;
+
+/***/
+
+IncompleteSolver::PartialValidity 
+IncompleteSolver::negatePartialValidity(PartialValidity pv) {
+  switch(pv) {
+    case MustBeTrue:  return MustBeFalse;
+    case MustBeFalse: return MustBeTrue;
+    case MayBeTrue:   return MayBeFalse;
+    case MayBeFalse:  return MayBeTrue;
+    case TrueOrFalse: return TrueOrFalse;
+    default: assert(0 && "invalid partial validity");  
+  }
+}
+
+IncompleteSolver::PartialValidity 
+IncompleteSolver::computeValidity(const Query& query) {
+  PartialValidity trueResult = computeTruth(query);
+
+  if (trueResult == MustBeTrue) {
+    return MustBeTrue;
+  } else {
+    PartialValidity falseResult = computeTruth(query.negateExpr());
+
+    if (falseResult == MustBeTrue) {
+      return MustBeFalse;
+    } else {
+      bool trueCorrect = trueResult != None,
+        falseCorrect = falseResult != None;
+      
+      if (trueCorrect && falseCorrect) {
+        return TrueOrFalse;
+      } else if (trueCorrect) { // ==> trueResult == MayBeFalse
+        return MayBeFalse;
+      } else if (falseCorrect) { // ==> falseResult == MayBeFalse
+        return MayBeTrue;
+      } else {
+        return None;
+      }
+    }
+  }
+}
+
+/***/
+
+StagedSolverImpl::StagedSolverImpl(IncompleteSolver *_primary, 
+                                   Solver *_secondary) 
+  : primary(_primary),
+    secondary(_secondary) {
+}
+
+StagedSolverImpl::~StagedSolverImpl() {
+  delete primary;
+  delete secondary;
+}
+
+bool StagedSolverImpl::computeTruth(const Query& query, bool &isValid) {
+  IncompleteSolver::PartialValidity trueResult = primary->computeTruth(query); 
+  
+  if (trueResult != IncompleteSolver::None) {
+    isValid = (trueResult == IncompleteSolver::MustBeTrue);
+    return true;
+  } 
+
+  return secondary->impl->computeTruth(query, isValid);
+}
+
+bool StagedSolverImpl::computeValidity(const Query& query,
+                                       Solver::Validity &result) {
+  bool tmp;
+
+  switch(primary->computeValidity(query)) {
+  case IncompleteSolver::MustBeTrue: 
+    result = Solver::True;
+    break;
+  case IncompleteSolver::MustBeFalse: 
+    result = Solver::False;
+    break;
+  case IncompleteSolver::TrueOrFalse: 
+    result = Solver::Unknown;
+    break;
+  case IncompleteSolver::MayBeTrue:
+    if (!secondary->impl->computeTruth(query, tmp))
+      return false;
+    result = tmp ? Solver::True : Solver::Unknown;
+    break;
+  case IncompleteSolver::MayBeFalse:
+    if (!secondary->impl->computeTruth(query.negateExpr(), tmp))
+      return false;
+    result = tmp ? Solver::False : Solver::Unknown;
+    break;
+  default:
+    if (!secondary->impl->computeValidity(query, result))
+      return false;
+    break;
+  }
+
+  return true;
+}
+
+bool StagedSolverImpl::computeValue(const Query& query,
+                                    ref<Expr> &result) {
+  if (primary->computeValue(query, result))
+    return true;
+
+  return secondary->impl->computeValue(query, result);
+}
+
+bool 
+StagedSolverImpl::computeInitialValues(const Query& query,
+                                       const std::vector<const Array*> 
+                                         &objects,
+                                       std::vector< std::vector<unsigned char> >
+                                         &values,
+                                       bool &hasSolution) {
+  if (primary->computeInitialValues(query, objects, values, hasSolution))
+    return true;
+  
+  return secondary->impl->computeInitialValues(query, objects, values,
+                                               hasSolution);
+}

Added: klee/trunk/lib/Solver/IndependentSolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/IndependentSolver.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/IndependentSolver.cpp (added)
+++ klee/trunk/lib/Solver/IndependentSolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,314 @@
+//===-- IndependentSolver.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/Solver.h"
+
+#include "klee/Expr.h"
+#include "klee/Constraints.h"
+#include "klee/SolverImpl.h"
+
+#include "klee/util/ExprUtil.h"
+
+#include "llvm/Support/Streams.h"
+
+#include <map>
+#include <vector>
+
+using namespace klee;
+using namespace llvm;
+
+template<class T>
+class DenseSet {
+  typedef std::set<T> set_ty;
+  set_ty s;
+
+public:
+  DenseSet() {}
+
+  void add(T x) {
+    s.insert(x);
+  }
+  void add(T start, T end) {
+    for (; start<end; start++)
+      s.insert(start);
+  }
+
+  // returns true iff set is changed by addition
+  bool add(const DenseSet &b) {
+    bool modified = false;
+    for (typename set_ty::const_iterator it = b.s.begin(), ie = b.s.end(); 
+         it != ie; ++it) {
+      if (modified || !s.count(*it)) {
+        modified = true;
+        s.insert(*it);
+      }
+    }
+    return modified;
+  }
+
+  bool intersects(const DenseSet &b) {
+    for (typename set_ty::iterator it = s.begin(), ie = s.end(); 
+         it != ie; ++it)
+      if (b.s.count(*it))
+        return true;
+    return false;
+  }
+
+  void print(std::ostream &os) const {
+    bool first = true;
+    os << "{";
+    for (typename set_ty::iterator it = s.begin(), ie = s.end(); 
+         it != ie; ++it) {
+      if (first) {
+        first = false;
+      } else {
+        os << ",";
+      }
+      os << *it;
+    }
+    os << "}";
+  }
+};
+
+template<class T>
+inline std::ostream &operator<<(std::ostream &os, const DenseSet<T> &dis) {
+  dis.print(os);
+  return os;
+}
+
+class IndependentElementSet {
+  typedef std::map<const Array*, DenseSet<unsigned> > elements_ty;
+  elements_ty elements;
+  std::set<const Array*> wholeObjects;
+
+public:
+  IndependentElementSet() {}
+  IndependentElementSet(ref<Expr> e) {
+    std::vector< ref<ReadExpr> > reads;
+    findReads(e, /* visitUpdates= */ true, reads);
+    for (unsigned i = 0; i != reads.size(); ++i) {
+      ReadExpr *re = reads[i].get();
+      if (re->updates.isRooted) {
+        const Array *array = re->updates.root;
+        if (!wholeObjects.count(array)) {
+          if (re->index.isConstant()) {
+            DenseSet<unsigned> &dis = elements[array];
+            dis.add((unsigned) re->index.getConstantValue());
+          } else {
+            elements_ty::iterator it2 = elements.find(array);
+            if (it2!=elements.end())
+              elements.erase(it2);
+            wholeObjects.insert(array);
+          }
+        }
+      }
+    }
+  }
+  IndependentElementSet(const IndependentElementSet &ies) : 
+    elements(ies.elements),
+    wholeObjects(ies.wholeObjects) {}    
+
+  IndependentElementSet &operator=(const IndependentElementSet &ies) {
+    elements = ies.elements;
+    wholeObjects = ies.wholeObjects;
+    return *this;
+  }
+
+  void print(std::ostream &os) const {
+    os << "{";
+    bool first = true;
+    for (std::set<const Array*>::iterator it = wholeObjects.begin(), 
+           ie = wholeObjects.end(); it != ie; ++it) {
+      const Array *array = *it;
+
+      if (first) {
+        first = false;
+      } else {
+        os << ", ";
+      }
+
+      os << "MO" << array->id;
+    }
+    for (elements_ty::const_iterator it = elements.begin(), ie = elements.end();
+         it != ie; ++it) {
+      const Array *array = it->first;
+      const DenseSet<unsigned> &dis = it->second;
+
+      if (first) {
+        first = false;
+      } else {
+        os << ", ";
+      }
+
+      os << "MO" << array->id << " : " << dis;
+    }
+    os << "}";
+  }
+
+  // more efficient when this is the smaller set
+  bool intersects(const IndependentElementSet &b) {
+    for (std::set<const Array*>::iterator it = wholeObjects.begin(), 
+           ie = wholeObjects.end(); it != ie; ++it) {
+      const Array *array = *it;
+      if (b.wholeObjects.count(array) || 
+          b.elements.find(array) != b.elements.end())
+        return true;
+    }
+    for (elements_ty::iterator it = elements.begin(), ie = elements.end();
+         it != ie; ++it) {
+      const Array *array = it->first;
+      if (b.wholeObjects.count(array))
+        return true;
+      elements_ty::const_iterator it2 = b.elements.find(array);
+      if (it2 != b.elements.end()) {
+        if (it->second.intersects(it2->second))
+          return true;
+      }
+    }
+    return false;
+  }
+
+  // returns true iff set is changed by addition
+  bool add(const IndependentElementSet &b) {
+    bool modified = false;
+    for (std::set<const Array*>::const_iterator it = b.wholeObjects.begin(), 
+           ie = b.wholeObjects.end(); it != ie; ++it) {
+      const Array *array = *it;
+      elements_ty::iterator it2 = elements.find(array);
+      if (it2!=elements.end()) {
+        modified = true;
+        elements.erase(it2);
+        wholeObjects.insert(array);
+      } else {
+        if (!wholeObjects.count(array)) {
+          modified = true;
+          wholeObjects.insert(array);
+        }
+      }
+    }
+    for (elements_ty::const_iterator it = b.elements.begin(), 
+           ie = b.elements.end(); it != ie; ++it) {
+      const Array *array = it->first;
+      if (!wholeObjects.count(array)) {
+        elements_ty::iterator it2 = elements.find(array);
+        if (it2==elements.end()) {
+          modified = true;
+          elements.insert(*it);
+        } else {
+          if (it2->second.add(it->second))
+            modified = true;
+        }
+      }
+    }
+    return modified;
+  }
+};
+
+inline std::ostream &operator<<(std::ostream &os, const IndependentElementSet &ies) {
+  ies.print(os);
+  return os;
+}
+
+static 
+IndependentElementSet getIndependentConstraints(const Query& query,
+                                                std::vector< ref<Expr> > &result) {
+  IndependentElementSet eltsClosure(query.expr);
+  std::vector< std::pair<ref<Expr>, IndependentElementSet> > worklist;
+
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    worklist.push_back(std::make_pair(*it, IndependentElementSet(*it)));
+
+  // XXX This should be more efficient (in terms of low level copy stuff).
+  bool done = false;
+  do {
+    done = true;
+    std::vector< std::pair<ref<Expr>, IndependentElementSet> > newWorklist;
+    for (std::vector< std::pair<ref<Expr>, IndependentElementSet> >::iterator
+           it = worklist.begin(), ie = worklist.end(); it != ie; ++it) {
+      if (it->second.intersects(eltsClosure)) {
+        if (eltsClosure.add(it->second))
+          done = false;
+        result.push_back(it->first);
+      } else {
+        newWorklist.push_back(*it);
+      }
+    }
+    worklist.swap(newWorklist);
+  } while (!done);
+
+  if (0) {
+    std::set< ref<Expr> > reqset(result.begin(), result.end());
+    llvm::cerr << "--\n";
+    llvm::cerr << "Q: " << query.expr << "\n";
+    llvm::cerr << "\telts: " << IndependentElementSet(query.expr) << "\n";
+    int i = 0;
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it) {
+      llvm::cerr << "C" << i++ << ": " << *it;
+      llvm::cerr << " " << (reqset.count(*it) ? "(required)" : "(independent)") << "\n";
+      llvm::cerr << "\telts: " << IndependentElementSet(*it) << "\n";
+    }
+    llvm::cerr << "elts closure: " << eltsClosure << "\n";
+  }
+
+  return eltsClosure;
+}
+
+class IndependentSolver : public SolverImpl {
+private:
+  Solver *solver;
+
+public:
+  IndependentSolver(Solver *_solver) 
+    : solver(_solver) {}
+  ~IndependentSolver() { delete solver; }
+
+  bool computeTruth(const Query&, bool &isValid);
+  bool computeValidity(const Query&, Solver::Validity &result);
+  bool computeValue(const Query&, ref<Expr> &result);
+  bool computeInitialValues(const Query& query,
+                            const std::vector<const Array*> &objects,
+                            std::vector< std::vector<unsigned char> > &values,
+                            bool &hasSolution) {
+    return solver->impl->computeInitialValues(query, objects, values,
+                                              hasSolution);
+  }
+};
+  
+bool IndependentSolver::computeValidity(const Query& query,
+                                        Solver::Validity &result) {
+  std::vector< ref<Expr> > required;
+  IndependentElementSet eltsClosure =
+    getIndependentConstraints(query, required);
+  ConstraintManager tmp(required);
+  return solver->impl->computeValidity(Query(tmp, query.expr), 
+                                       result);
+}
+
+bool IndependentSolver::computeTruth(const Query& query, bool &isValid) {
+  std::vector< ref<Expr> > required;
+  IndependentElementSet eltsClosure = 
+    getIndependentConstraints(query, required);
+  ConstraintManager tmp(required);
+  return solver->impl->computeTruth(Query(tmp, query.expr), 
+                                    isValid);
+}
+
+bool IndependentSolver::computeValue(const Query& query, ref<Expr> &result) {
+  std::vector< ref<Expr> > required;
+  IndependentElementSet eltsClosure = 
+    getIndependentConstraints(query, required);
+  ConstraintManager tmp(required);
+  return solver->impl->computeValue(Query(tmp, query.expr), result);
+}
+
+Solver *klee::createIndependentSolver(Solver *s) {
+  return new Solver(new IndependentSolver(s));
+}

Added: klee/trunk/lib/Solver/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/Makefile (added)
+++ klee/trunk/lib/Solver/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+#===-- lib/Solver/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=kleaverSolver
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+
+include $(LEVEL)/Makefile.common

Propchange: klee/trunk/lib/Solver/Makefile

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/lib/Solver/PCLoggingSolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/PCLoggingSolver.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/PCLoggingSolver.cpp (added)
+++ klee/trunk/lib/Solver/PCLoggingSolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,134 @@
+//===-- PCLoggingSolver.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/Solver.h"
+
+// FIXME: This should not be here.
+#include "klee/ExecutionState.h"
+#include "klee/Expr.h"
+#include "klee/SolverImpl.h"
+#include "klee/Statistics.h"
+#include "klee/util/ExprPPrinter.h"
+#include "klee/Internal/Support/QueryLog.h"
+#include "klee/Internal/System/Time.h"
+
+#include "llvm/Support/CommandLine.h"
+
+#include <fstream>
+
+using namespace klee;
+using namespace llvm;
+using namespace klee::util;
+
+///
+
+class PCLoggingSolver : public SolverImpl {
+  Solver *solver;
+  std::ofstream os;
+  ExprPPrinter *printer;
+  unsigned queryCount;
+  double startTime;
+
+  void startQuery(const Query& query, const char *typeName) {
+    Statistic *S = theStatisticManager->getStatisticByName("Instructions");
+    uint64_t instructions = S ? S->getValue() : 0;
+    os << "# Query " << queryCount++ << " -- "
+       << "Type: " << typeName << ", "
+       << "Instructions: " << instructions << "\n";
+    printer->printQuery(os, query.constraints, query.expr);
+    
+    startTime = getWallTime();
+  }
+
+  void finishQuery(bool success) {
+    double delta = getWallTime() - startTime;
+    os << "#   " << (success ? "OK" : "FAIL") << " -- "
+       << "Elapsed: " << delta << "\n";
+  }
+  
+public:
+  PCLoggingSolver(Solver *_solver, std::string path) 
+  : solver(_solver),
+    os(path.c_str(), std::ios::trunc),
+    printer(ExprPPrinter::create(os)),
+    queryCount(0) {
+  }                                                      
+  ~PCLoggingSolver() {
+    delete printer;
+    delete solver;
+  }
+  
+  bool computeTruth(const Query& query, bool &isValid) {
+    startQuery(query, "Truth");
+    bool success = solver->impl->computeTruth(query, isValid);
+    finishQuery(success);
+    if (success)
+      os << "#   Is Valid: " << (isValid ? "true" : "false") << "\n";
+    os << "\n";
+    return success;
+  }
+
+  bool computeValidity(const Query& query, Solver::Validity &result) {
+    startQuery(query, "Validity");
+    bool success = solver->impl->computeValidity(query, result);
+    finishQuery(success);
+    if (success)
+      os << "#   Validity: " << result << "\n";
+    os << "\n";
+    return success;
+  }
+
+  bool computeValue(const Query& query, ref<Expr> &result) {
+    startQuery(query, "Value");
+    bool success = solver->impl->computeValue(query, result);
+    finishQuery(success);
+    if (success)
+      os << "#   Result: " << result << "\n";
+    os << "\n";
+    return success;
+  }
+
+  bool computeInitialValues(const Query& query,
+                            const std::vector<const Array*> &objects,
+                            std::vector< std::vector<unsigned char> > &values,
+                            bool &hasSolution) {
+    // FIXME: Add objects to output.
+    startQuery(query, "InitialValues");
+    bool success = solver->impl->computeInitialValues(query, objects, 
+                                                      values, hasSolution);
+    finishQuery(success);
+    if (success) {
+      os << "#   Solvable: " << (hasSolution ? "true" : "false") << "\n";
+      if (hasSolution) {
+        std::vector< std::vector<unsigned char> >::iterator
+          values_it = values.begin();
+        for (std::vector<const Array*>::const_iterator i = objects.begin(),
+               e = objects.end(); i != e; ++i, ++values_it) {
+          const Array *array = *i;
+          std::vector<unsigned char> &data = *values_it;
+          os << "#     arr" << array->id << " = [";
+          for (unsigned j = 0; j < array->size; j++) {
+            os << (int) data[j];
+            if (j+1 < array->size)
+              os << ",";
+          }
+          os << "]\n";
+        }
+      }
+    }
+    os << "\n";
+    return success;
+  }
+};
+
+///
+
+Solver *klee::createPCLoggingSolver(Solver *_solver, std::string path) {
+  return new Solver(new PCLoggingSolver(_solver, path));
+}

Added: klee/trunk/lib/Solver/STPBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/STPBuilder.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/STPBuilder.cpp (added)
+++ klee/trunk/lib/Solver/STPBuilder.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,819 @@
+//===-- STPBuilder.cpp ----------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "STPBuilder.h"
+
+#include "klee/Expr.h"
+#include "klee/Solver.h"
+#include "klee/util/Bits.h"
+
+#include "ConstantDivision.h"
+#include "SolverStats.h"
+
+#include "llvm/Support/CommandLine.h"
+
+#define vc_bvBoolExtract IAMTHESPAWNOFSATAN
+// unclear return
+#define vc_bvLeftShiftExpr IAMTHESPAWNOFSATAN
+#define vc_bvRightShiftExpr IAMTHESPAWNOFSATAN
+// bad refcnt'ng
+#define vc_bvVar32LeftShiftExpr IAMTHESPAWNOFSATAN
+#define vc_bvVar32RightShiftExpr IAMTHESPAWNOFSATAN
+#define vc_bvVar32DivByPowOfTwoExpr IAMTHESPAWNOFSATAN
+#define vc_bvCreateMemoryArray IAMTHESPAWNOFSATAN
+#define vc_bvReadMemoryArray IAMTHESPAWNOFSATAN
+#define vc_bvWriteToMemoryArray IAMTHESPAWNOFSATAN
+
+#include <algorithm> // max, min
+#include <cassert>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <vector>
+
+using namespace klee;
+
+namespace {
+  llvm::cl::opt<bool>
+  UseConstructHash("use-construct-hash", 
+                   llvm::cl::desc("Use hash-consing during STP query construction."),
+                   llvm::cl::init(true));
+}
+
+///
+
+/***/
+
+STPBuilder::STPBuilder(::VC _vc, bool _optimizeDivides) 
+  : vc(_vc), optimizeDivides(_optimizeDivides)
+{
+  tempVars[0] = buildVar("__tmpInt8", 8);
+  tempVars[1] = buildVar("__tmpInt16", 16);
+  tempVars[2] = buildVar("__tmpInt32", 32);
+  tempVars[3] = buildVar("__tmpInt64", 64);
+}
+
+STPBuilder::~STPBuilder() {
+}
+
+///
+
+/* Warning: be careful about what c_interface functions you use. Some of
+   them look like they cons memory but in fact don't, which is bad when
+   you call vc_DeleteExpr on them. */
+
+::VCExpr STPBuilder::buildVar(const char *name, unsigned width) {
+  // XXX don't rebuild if this stuff cons's
+  ::Type t = (width==1) ? vc_boolType(vc) : vc_bvType(vc, width);
+  ::VCExpr res = vc_varExpr(vc, (char*) name, t);
+  vc_DeleteExpr(t);
+  return res;
+}
+
+::VCExpr STPBuilder::buildArray(const char *name, unsigned indexWidth, unsigned valueWidth) {
+  // XXX don't rebuild if this stuff cons's
+  ::Type t1 = vc_bvType(vc, indexWidth);
+  ::Type t2 = vc_bvType(vc, valueWidth);
+  ::Type t = vc_arrayType(vc, t1, t2);
+  ::VCExpr res = vc_varExpr(vc, (char*) name, t);
+  vc_DeleteExpr(t);
+  vc_DeleteExpr(t2);
+  vc_DeleteExpr(t1);
+  return res;
+}
+
+ExprHandle STPBuilder::getTempVar(Expr::Width w) {
+  switch (w) {
+  case Expr::Int8: return tempVars[0];
+  case Expr::Int16: return tempVars[1];
+  case Expr::Int32: return tempVars[2];
+  case Expr::Int64: return tempVars[3];
+  default:
+    assert(0 && "invalid type");
+  }
+}
+
+ExprHandle STPBuilder::getTrue() {
+  return vc_trueExpr(vc);
+}
+ExprHandle STPBuilder::getFalse() {
+  return vc_falseExpr(vc);
+}
+ExprHandle STPBuilder::bvOne(unsigned width) {
+  return bvConst32(width, 1);
+}
+ExprHandle STPBuilder::bvZero(unsigned width) {
+  return bvConst32(width, 0);
+}
+ExprHandle STPBuilder::bvMinusOne(unsigned width) {
+  return bvConst64(width, (int64_t) -1);
+}
+ExprHandle STPBuilder::bvConst32(unsigned width, uint32_t value) {
+  return vc_bvConstExprFromInt(vc, width, value);
+}
+ExprHandle STPBuilder::bvConst64(unsigned width, uint64_t value) {
+  return vc_bvConstExprFromLL(vc, width, value);
+}
+
+ExprHandle STPBuilder::bvBoolExtract(ExprHandle expr, int bit) {
+  return vc_eqExpr(vc, bvExtract(expr, bit, bit), bvOne(1));
+}
+ExprHandle STPBuilder::bvExtract(ExprHandle expr, unsigned top, unsigned bottom) {
+  return vc_bvExtract(vc, expr, top, bottom);
+}
+ExprHandle STPBuilder::eqExpr(ExprHandle a, ExprHandle b) {
+  return vc_eqExpr(vc, a, b);
+}
+
+// logical right shift
+ExprHandle STPBuilder::bvRightShift(ExprHandle expr, unsigned amount, unsigned shiftBits) {
+  unsigned width = vc_getBVLength(vc, expr);
+  unsigned shift = amount & ((1<<shiftBits) - 1);
+
+  if (shift==0) {
+    return expr;
+  } else if (shift>=width) {
+    return bvZero(width);
+  } else {
+    return vc_bvConcatExpr(vc,
+                           bvZero(shift),
+                           bvExtract(expr, width - 1, shift));
+  }
+}
+
+// logical left shift
+ExprHandle STPBuilder::bvLeftShift(ExprHandle expr, unsigned amount, unsigned shiftBits) {
+  unsigned width = vc_getBVLength(vc, expr);
+  unsigned shift = amount & ((1<<shiftBits) - 1);
+
+  if (shift==0) {
+    return expr;
+  } else if (shift>=width) {
+    return bvZero(width);
+  } else {
+    // stp shift does "expr @ [0 x s]" which we then have to extract,
+    // rolling our own gives slightly smaller exprs
+    return vc_bvConcatExpr(vc, 
+                           bvExtract(expr, width - shift - 1, 0),
+                           bvZero(shift));
+  }
+}
+
+// left shift by a variable amount on an expression of the specified width
+ExprHandle STPBuilder::bvVarLeftShift(ExprHandle expr, ExprHandle amount, unsigned width) {
+  ExprHandle res = bvZero(width);
+
+  int shiftBits = getShiftBits( width );
+
+  //get the shift amount (looking only at the bits appropriate for the given width)
+  ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 ); 
+
+  //construct a big if-then-elif-elif-... with one case per possible shift amount
+  for( int i=width-1; i>=0; i-- ) {
+    res = vc_iteExpr(vc,
+                     eqExpr(shift, bvConst32(shiftBits, i)),
+                     bvLeftShift(expr, i, shiftBits),
+                     res);
+  }
+  return res;
+}
+
+// logical right shift by a variable amount on an expression of the specified width
+ExprHandle STPBuilder::bvVarRightShift(ExprHandle expr, ExprHandle amount, unsigned width) {
+  ExprHandle res = bvZero(width);
+
+  int shiftBits = getShiftBits( width );
+
+  //get the shift amount (looking only at the bits appropriate for the given width)
+  ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 ); 
+
+  //construct a big if-then-elif-elif-... with one case per possible shift amount
+  for( int i=width-1; i>=0; i-- ) {
+    res = vc_iteExpr(vc,
+                     eqExpr(shift, bvConst32(shiftBits, i)),
+                     bvRightShift(expr, i, shiftBits),
+                     res);
+  }
+
+  return res;
+}
+
+// arithmetic right shift by a variable amount on an expression of the specified width
+ExprHandle STPBuilder::bvVarArithRightShift(ExprHandle expr, ExprHandle amount, unsigned width) {
+  int shiftBits = getShiftBits( width );
+
+  //get the shift amount (looking only at the bits appropriate for the given width)
+  ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 );
+
+  //get the sign bit to fill with
+  ExprHandle signedBool = bvBoolExtract(expr, width-1);
+
+  //start with the result if shifting by width-1
+  ExprHandle res = constructAShrByConstant(expr, width-1, signedBool, shiftBits);
+
+  //construct a big if-then-elif-elif-... with one case per possible shift amount
+  // XXX more efficient to move the ite on the sign outside all exprs?
+  // XXX more efficient to sign extend, right shift, then extract lower bits?
+  for( int i=width-2; i>=0; i-- ) {
+    res = vc_iteExpr(vc,
+                     eqExpr(shift, bvConst32(shiftBits,i)),
+                     constructAShrByConstant(expr, 
+                                             i, 
+                                             signedBool, 
+                                             shiftBits),
+                     res);
+  }
+
+  return res;
+}
+
+ExprHandle STPBuilder::constructAShrByConstant(ExprHandle expr,
+                                               unsigned amount,
+                                               ExprHandle isSigned, 
+                                               unsigned shiftBits) {
+  unsigned width = vc_getBVLength(vc, expr);
+  unsigned shift = amount & ((1<<shiftBits) - 1);
+
+  if (shift==0) {
+    return expr;
+  } else if (shift>=width-1) {
+    return vc_iteExpr(vc, isSigned, bvMinusOne(width), bvZero(width));
+  } else {
+    return vc_iteExpr(vc,
+                      isSigned,
+                      ExprHandle(vc_bvConcatExpr(vc,
+                                                 bvMinusOne(shift),
+                                                 bvExtract(expr, width - 1, shift))),
+                      bvRightShift(expr, shift, shiftBits));
+  }
+}
+
+ExprHandle STPBuilder::constructMulByConstant(ExprHandle expr, unsigned width, uint64_t x) {
+  unsigned shiftBits = getShiftBits(width);
+  uint64_t add, sub;
+  ExprHandle res = 0;
+
+  // expr*x == expr*(add-sub) == expr*add - expr*sub
+  ComputeMultConstants64(x, add, sub);
+
+  // legal, these would overflow completely
+  add = bits64::truncateToNBits(add, width);
+  sub = bits64::truncateToNBits(sub, width);
+
+  for (int j=63; j>=0; j--) {
+    uint64_t bit = 1LL << j;
+
+    if ((add&bit) || (sub&bit)) {
+      assert(!((add&bit) && (sub&bit)) && "invalid mult constants");
+      ExprHandle op = bvLeftShift(expr, j, shiftBits);
+      
+      if (add&bit) {
+        if (res) {
+          res = vc_bvPlusExpr(vc, width, res, op);
+        } else {
+          res = op;
+        }
+      } else {
+        if (res) {
+          res = vc_bvMinusExpr(vc, width, res, op);
+        } else {
+          res = vc_bvUMinusExpr(vc, op);
+        }
+      }
+    }
+  }
+
+  if (!res) 
+    res = bvZero(width);
+
+  return res;
+}
+
+/* 
+ * Compute the 32-bit unsigned integer division of n by a divisor d based on 
+ * the constants derived from the constant divisor d.
+ *
+ * Returns n/d without doing explicit division.  The cost is 2 adds, 3 shifts, 
+ * and a (64-bit) multiply.
+ *
+ * @param n      numerator (dividend) as an expression
+ * @param width  number of bits used to represent the value
+ * @param d      the divisor
+ *
+ * @return n/d without doing explicit division
+ */
+ExprHandle STPBuilder::constructUDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d) {
+  assert(width==32 && "can only compute udiv constants for 32-bit division");
+
+  // Compute the constants needed to compute n/d for constant d w/o
+  // division by d.
+  uint32_t mprime, sh1, sh2;
+  ComputeUDivConstants32(d, mprime, sh1, sh2);
+  ExprHandle expr_sh1    = bvConst32( 32, sh1);
+  ExprHandle expr_sh2    = bvConst32( 32, sh2);
+
+  // t1  = MULUH(mprime, n) = ( (uint64_t)mprime * (uint64_t)n ) >> 32
+  ExprHandle expr_n_64   = vc_bvConcatExpr( vc, bvZero(32), expr_n ); //extend to 64 bits
+  ExprHandle t1_64bits   = constructMulByConstant( expr_n_64, 64, (uint64_t)mprime );
+  ExprHandle t1          = vc_bvExtract( vc, t1_64bits, 63, 32 ); //upper 32 bits
+
+  // n/d = (((n - t1) >> sh1) + t1) >> sh2;
+  ExprHandle n_minus_t1  = vc_bvMinusExpr( vc, width, expr_n, t1 );
+  ExprHandle shift_sh1   = bvVarRightShift( n_minus_t1, expr_sh1, 32 );
+  ExprHandle plus_t1     = vc_bvPlusExpr( vc, width, shift_sh1, t1 );
+  ExprHandle res         = bvVarRightShift( plus_t1, expr_sh2, 32 );
+
+  return res;
+}
+
+/* 
+ * Compute the 32-bitnsigned integer division of n by a divisor d based on 
+ * the constants derived from the constant divisor d.
+ *
+ * Returns n/d without doing explicit division.  The cost is 3 adds, 3 shifts, 
+ * a (64-bit) multiply, and an XOR.
+ *
+ * @param n      numerator (dividend) as an expression
+ * @param width  number of bits used to represent the value
+ * @param d      the divisor
+ *
+ * @return n/d without doing explicit division
+ */
+ExprHandle STPBuilder::constructSDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d) {
+  assert(width==32 && "can only compute udiv constants for 32-bit division");
+
+  // Compute the constants needed to compute n/d for constant d w/o division by d.
+  int32_t mprime, dsign, shpost;
+  ComputeSDivConstants32(d, mprime, dsign, shpost);
+  ExprHandle expr_dsign   = bvConst32( 32, dsign);
+  ExprHandle expr_shpost  = bvConst32( 32, shpost);
+
+  // q0 = n + MULSH( mprime, n ) = n + (( (int64_t)mprime * (int64_t)n ) >> 32)
+  int64_t mprime_64     = (int64_t)mprime;
+
+  ExprHandle expr_n_64    = vc_bvSignExtend( vc, expr_n, 64 );
+  ExprHandle mult_64      = constructMulByConstant( expr_n_64, 64, mprime_64 );
+  ExprHandle mulsh        = vc_bvExtract( vc, mult_64, 63, 32 ); //upper 32-bits
+  ExprHandle n_plus_mulsh = vc_bvPlusExpr( vc, width, expr_n, mulsh );
+
+  // Improved variable arithmetic right shift: sign extend, shift,
+  // extract.
+  ExprHandle extend_npm   = vc_bvSignExtend( vc, n_plus_mulsh, 64 );
+  ExprHandle shift_npm    = bvVarRightShift( extend_npm, expr_shpost, 64 );
+  ExprHandle shift_shpost = vc_bvExtract( vc, shift_npm, 31, 0 ); //lower 32-bits
+
+  // XSIGN(n) is -1 if n is negative, positive one otherwise
+  ExprHandle is_signed    = bvBoolExtract( expr_n, 31 );
+  ExprHandle neg_one      = bvMinusOne(32);
+  ExprHandle xsign_of_n   = vc_iteExpr( vc, is_signed, neg_one, bvZero(32) );
+
+  // q0 = (n_plus_mulsh >> shpost) - XSIGN(n)
+  ExprHandle q0           = vc_bvMinusExpr( vc, width, shift_shpost, xsign_of_n );
+  
+  // n/d = (q0 ^ dsign) - dsign
+  ExprHandle q0_xor_dsign = vc_bvXorExpr( vc, q0, expr_dsign );
+  ExprHandle res          = vc_bvMinusExpr( vc, width, q0_xor_dsign, expr_dsign );
+
+  return res;
+}
+
+::VCExpr STPBuilder::getInitialArray(const Array *root) {
+  if (root->stpInitialArray) {
+    return root->stpInitialArray;
+  } else {
+    char buf[32];
+    sprintf(buf, "arr%d", root->id);
+    root->stpInitialArray = buildArray(buf, 32, 8);
+    return root->stpInitialArray;
+  }
+}
+
+ExprHandle STPBuilder::getInitialRead(const Array *root, unsigned index) {
+  return vc_readExpr(vc, getInitialArray(root), bvConst32(32, index));
+}
+
+::VCExpr STPBuilder::getArrayForUpdate(const Array *root, 
+                                       const UpdateNode *un) {
+  if (!un) {
+    return getInitialArray(root);
+  } else {
+    // FIXME: This really needs to be non-recursive.
+    if (!un->stpArray)
+      un->stpArray = vc_writeExpr(vc,
+                                  getArrayForUpdate(root, un->next),
+                                  construct(un->index, 0),
+                                  construct(un->value, 0));
+
+    return un->stpArray;
+  }
+}
+
+/** if *width_out!=1 then result is a bitvector,
+    otherwise it is a bool */
+ExprHandle STPBuilder::construct(ref<Expr> e, int *width_out) {
+  if (!UseConstructHash || e.isConstant()) {
+    return constructActual(e, width_out);
+  } else {
+    ExprHashMap< std::pair<ExprHandle, unsigned> >::iterator it = 
+      constructed.find(e);
+    if (it!=constructed.end()) {
+      if (width_out)
+        *width_out = it->second.second;
+      return it->second.first;
+    } else {
+      int width;
+      if (!width_out) width_out = &width;
+      ExprHandle res = constructActual(e, width_out);
+      constructed.insert(std::make_pair(e, std::make_pair(res, *width_out)));
+      return res;
+    }
+  }
+}
+
+
+/** if *width_out!=1 then result is a bitvector,
+    otherwise it is a bool */
+ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out) {
+  int width;
+  if (!width_out) width_out = &width;
+
+  ++stats::queryConstructs;
+
+  switch(e.getKind()) {
+
+  case Expr::Constant: {
+    uint64_t asUInt64 = e.getConstantValue();
+    *width_out = e.getWidth();
+
+    if (*width_out > 64)
+      assert(0 && "constructActual: width > 64");
+
+    if (*width_out == 1)
+      return asUInt64 ? getTrue() : getFalse();
+    else if (*width_out <= 32) 
+      return bvConst32(*width_out, asUInt64);
+    else return bvConst64(*width_out, asUInt64);
+  }
+    
+  // Special
+  case Expr::NotOptimized: {
+    NotOptimizedExpr *noe = static_ref_cast<NotOptimizedExpr>(e);
+    return construct(noe->src, width_out);
+  }
+
+  case Expr::Read: {
+    ReadExpr *re = static_ref_cast<ReadExpr>(e);
+    *width_out = 8;
+    return vc_readExpr(vc,
+                       getArrayForUpdate(re->updates.root, re->updates.head),
+                       construct(re->index, 0));
+  }
+    
+  case Expr::Select: {
+    SelectExpr *se = static_ref_cast<SelectExpr>(e);
+    ExprHandle cond = construct(se->cond, 0);
+    ExprHandle tExpr = construct(se->trueExpr, width_out);
+    ExprHandle fExpr = construct(se->falseExpr, width_out);
+    return vc_iteExpr(vc, cond, tExpr, fExpr);
+  }
+
+  case Expr::Concat: {
+    ConcatExpr *ce = static_ref_cast<ConcatExpr>(e);
+    unsigned numKids = ce->getNumKids();
+    ExprHandle res = construct(ce->getKid(numKids-1), 0);
+    for (int i=numKids-2; i>=0; i--) {
+      res = vc_bvConcatExpr(vc, construct(ce->getKid(i), 0), res);
+    }
+    *width_out = ce->getWidth();
+    return res;
+  }
+
+  case Expr::Extract: {
+    ExtractExpr *ee = static_ref_cast<ExtractExpr>(e);
+    ExprHandle src = construct(ee->expr, width_out);    
+    *width_out = ee->getWidth();
+    if (*width_out==1) {
+      return bvBoolExtract(src, 0);
+    } else {
+      return vc_bvExtract(vc, src, ee->offset + *width_out - 1, ee->offset);
+    }
+  }
+
+    // Casting
+
+  case Expr::ZExt: {
+    int srcWidth;
+    CastExpr *ce = static_ref_cast<CastExpr>(e);
+    ExprHandle src = construct(ce->src, &srcWidth);
+    *width_out = ce->getWidth();
+    if (srcWidth==1) {
+      return vc_iteExpr(vc, src, bvOne(*width_out), bvZero(*width_out));
+    } else {
+      return vc_bvConcatExpr(vc, bvZero(*width_out-srcWidth), src);
+    }
+  }
+
+  case Expr::SExt: {
+    int srcWidth;
+    CastExpr *ce = static_ref_cast<CastExpr>(e);
+    ExprHandle src = construct(ce->src, &srcWidth);
+    *width_out = ce->getWidth();
+    if (srcWidth==1) {
+      return vc_iteExpr(vc, src, bvMinusOne(*width_out), bvZero(*width_out));
+    } else {
+      return vc_bvSignExtend(vc, src, *width_out);
+    }
+  }
+
+    // Arithmetic
+
+  case Expr::Add: {
+    AddExpr *ae = static_ref_cast<AddExpr>(e);
+    ExprHandle left = construct(ae->left, width_out);
+    ExprHandle right = construct(ae->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized add");
+    return vc_bvPlusExpr(vc, *width_out, left, right);
+  }
+
+  case Expr::Sub: {
+    SubExpr *se = static_ref_cast<SubExpr>(e);
+    ExprHandle left = construct(se->left, width_out);
+    ExprHandle right = construct(se->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized sub");
+    return vc_bvMinusExpr(vc, *width_out, left, right);
+  } 
+
+  case Expr::Mul: {
+    MulExpr *me = static_ref_cast<MulExpr>(e);
+    ExprHandle right = construct(me->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized mul");
+
+    if (me->left.isConstant()) {
+      return constructMulByConstant(right, *width_out, me->left.getConstantValue());
+    } else {
+      ExprHandle left = construct(me->left, width_out);
+      return vc_bvMultExpr(vc, *width_out, left, right);
+    }
+  }
+
+  case Expr::UDiv: {
+    UDivExpr *de = static_ref_cast<UDivExpr>(e);
+    ExprHandle left = construct(de->left, width_out);
+    assert(*width_out!=1 && "uncanonicalized udiv");
+    
+    if (de->right.isConstant()) {
+      uint64_t divisor = de->right.getConstantValue();
+      
+      if (bits64::isPowerOfTwo(divisor)) {
+        return bvRightShift(left,
+                            bits64::indexOfSingleBit(divisor),
+                            getShiftBits(*width_out));
+      } else if (optimizeDivides) {
+        if (*width_out == 32) //only works for 32-bit division
+          return constructUDivByConstant( left, *width_out, (uint32_t)divisor );
+      }
+    } 
+
+    ExprHandle right = construct(de->right, width_out);
+    return vc_bvDivExpr(vc, *width_out, left, right);
+  }
+
+  case Expr::SDiv: {
+    SDivExpr *de = static_ref_cast<SDivExpr>(e);
+    ExprHandle left = construct(de->left, width_out);
+    assert(*width_out!=1 && "uncanonicalized sdiv");
+
+    if (de->right.isConstant()) {
+      uint64_t divisor = de->right.getConstantValue();
+ 
+      if (optimizeDivides) {
+	if (*width_out == 32) //only works for 32-bit division
+	  return constructSDivByConstant( left, *width_out, divisor);
+      }
+    } 
+
+    // XXX need to test for proper handling of sign, not sure I
+    // trust STP
+    ExprHandle right = construct(de->right, width_out);
+    return vc_sbvDivExpr(vc, *width_out, left, right);
+  }
+
+  case Expr::URem: {
+    URemExpr *de = static_ref_cast<URemExpr>(e);
+    ExprHandle left = construct(de->left, width_out);
+    assert(*width_out!=1 && "uncanonicalized urem");
+    
+    if (de->right.isConstant()) {
+      uint64_t divisor = de->right.getConstantValue();
+
+      if (bits64::isPowerOfTwo(divisor)) {
+        unsigned bits = bits64::indexOfSingleBit(divisor);
+
+        // special case for modding by 1 or else we bvExtract -1:0
+        if (bits == 0) {
+          return bvZero(*width_out);
+        } else {
+          return vc_bvConcatExpr(vc,
+                                 bvZero(*width_out - bits),
+                                 bvExtract(left, bits - 1, 0));
+        }
+      }
+
+      //use fast division to compute modulo without explicit division for constant divisor
+      if (optimizeDivides) {
+	if (*width_out == 32) { //only works for 32-bit division
+	  ExprHandle quotient = constructUDivByConstant( left, *width_out, (uint32_t)divisor );
+	  ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
+          ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
+	  return rem;
+	}
+      }
+    }
+    
+    ExprHandle right = construct(de->right, width_out);
+    return vc_bvModExpr(vc, *width_out, left, right);
+  }
+
+  case Expr::SRem: {
+    SRemExpr *de = static_ref_cast<SRemExpr>(e);
+    ExprHandle left = construct(de->left, width_out);
+    ExprHandle right = construct(de->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized srem");
+
+#if 0 //not faster per first benchmark
+    if (optimizeDivides) {
+      if (ConstantExpr *cre = de->right->asConstant()) {
+	uint64_t divisor = cre->asUInt64;
+
+	//use fast division to compute modulo without explicit division for constant divisor
+      	if( *width_out == 32 ) { //only works for 32-bit division
+	  ExprHandle quotient = constructSDivByConstant( left, *width_out, divisor );
+	  ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
+	  ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
+	  return rem;
+	}
+      }
+    }
+#endif
+
+    // XXX implement my fast path and test for proper handling of sign
+    return vc_sbvModExpr(vc, *width_out, left, right);
+  }
+
+    // Binary
+
+  case Expr::And: {
+    AndExpr *ae = static_ref_cast<AndExpr>(e);
+    ExprHandle left = construct(ae->left, width_out);
+    ExprHandle right = construct(ae->right, width_out);
+    if (*width_out==1) {
+      return vc_andExpr(vc, left, right);
+    } else {
+      return vc_bvAndExpr(vc, left, right);
+    }
+  }
+  case Expr::Or: {
+    OrExpr *oe = static_ref_cast<OrExpr>(e);
+    ExprHandle left = construct(oe->left, width_out);
+    ExprHandle right = construct(oe->right, width_out);
+    if (*width_out==1) {
+      return vc_orExpr(vc, left, right);
+    } else {
+      return vc_bvOrExpr(vc, left, right);
+    }
+  }
+
+  case Expr::Xor: {
+    XorExpr *xe = static_ref_cast<XorExpr>(e);
+    ExprHandle left = construct(xe->left, width_out);
+    ExprHandle right = construct(xe->right, width_out);
+    
+    if (*width_out==1) {
+      // XXX check for most efficient?
+      return vc_iteExpr(vc, left, 
+                        ExprHandle(vc_notExpr(vc, right)), right);
+    } else {
+      return vc_bvXorExpr(vc, left, right);
+    }
+  }
+
+  case Expr::Shl: {
+    ShlExpr *se = static_ref_cast<ShlExpr>(e);
+    ExprHandle left = construct(se->left, width_out);
+    assert(*width_out!=1 && "uncanonicalized shl");
+
+    if (se->right.isConstant()) {
+      return bvLeftShift(left, se->right.getConstantValue(), getShiftBits(*width_out));
+    } else {
+      int shiftWidth;
+      ExprHandle amount = construct(se->right, &shiftWidth);
+      return bvVarLeftShift( left, amount, *width_out );
+    }
+  }
+
+  case Expr::LShr: {
+    LShrExpr *lse = static_ref_cast<LShrExpr>(e);
+    ExprHandle left = construct(lse->left, width_out);
+    unsigned shiftBits = getShiftBits(*width_out);
+    assert(*width_out!=1 && "uncanonicalized lshr");
+
+    if (lse->right.isConstant()) {
+      return bvRightShift(left, (unsigned) lse->right.getConstantValue(), shiftBits);
+    } else {
+      int shiftWidth;
+      ExprHandle amount = construct(lse->right, &shiftWidth);
+      return bvVarRightShift( left, amount, *width_out );
+    }
+  }
+
+  case Expr::AShr: {
+    AShrExpr *ase = static_ref_cast<AShrExpr>(e);
+    ExprHandle left = construct(ase->left, width_out);
+    assert(*width_out!=1 && "uncanonicalized ashr");
+    
+    if (ase->right.isConstant()) {
+      unsigned shift = (unsigned) ase->right.getConstantValue();
+      ExprHandle signedBool = bvBoolExtract(left, *width_out-1);
+      return constructAShrByConstant(left, shift, signedBool, getShiftBits(*width_out));
+    } else {
+      int shiftWidth;
+      ExprHandle amount = construct(ase->right, &shiftWidth);
+      return bvVarArithRightShift( left, amount, *width_out );
+    }
+  }
+
+    // Comparison
+
+  case Expr::Eq: {
+    EqExpr *ee = static_ref_cast<EqExpr>(e);
+    ExprHandle left = construct(ee->left, width_out);
+    ExprHandle right = construct(ee->right, width_out);
+    if (*width_out==1) {
+      if (ee->left.isConstant()) {
+        assert(!ee->left.getConstantValue() && "uncanonicalized eq");
+        return vc_notExpr(vc, right);
+      } else {
+        return vc_iffExpr(vc, left, right);
+      }
+    } else {
+      *width_out = 1;
+      return vc_eqExpr(vc, left, right);
+    }
+  }
+
+  case Expr::Ult: {
+    UltExpr *ue = static_ref_cast<UltExpr>(e);
+    ExprHandle left = construct(ue->left, width_out);
+    ExprHandle right = construct(ue->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized ult");
+    *width_out = 1;
+    return vc_bvLtExpr(vc, left, right);
+  }
+
+  case Expr::Ule: {
+    UleExpr *ue = static_ref_cast<UleExpr>(e);
+    ExprHandle left = construct(ue->left, width_out);
+    ExprHandle right = construct(ue->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized ule");
+    *width_out = 1;
+    return vc_bvLeExpr(vc, left, right);
+  }
+
+  case Expr::Slt: {
+    SltExpr *se = static_ref_cast<SltExpr>(e);
+    ExprHandle left = construct(se->left, width_out);
+    ExprHandle right = construct(se->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized slt");
+    *width_out = 1;
+    return vc_sbvLtExpr(vc, left, right);
+  }
+
+  case Expr::Sle: {
+    SleExpr *se = static_ref_cast<SleExpr>(e);
+    ExprHandle left = construct(se->left, width_out);
+    ExprHandle right = construct(se->right, width_out);
+    assert(*width_out!=1 && "uncanonicalized sle");
+    *width_out = 1;
+    return vc_sbvLeExpr(vc, left, right);
+  }
+
+    // unused due to canonicalization
+#if 0
+  case Expr::Ne:
+  case Expr::Ugt:
+  case Expr::Uge:
+  case Expr::Sgt:
+  case Expr::Sge:
+#endif
+
+  default: 
+    assert(0 && "unhandled Expr type");
+    return vc_trueExpr(vc);
+  }
+}

Added: klee/trunk/lib/Solver/STPBuilder.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/STPBuilder.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/STPBuilder.h (added)
+++ klee/trunk/lib/Solver/STPBuilder.h Wed May 20 23:36:41 2009
@@ -0,0 +1,125 @@
+//===-- STPBuilder.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_STPBUILDER_H__
+#define __UTIL_STPBUILDER_H__
+
+#include "klee/util/ExprHashMap.h"
+#include "klee/Config/config.h"
+
+#include <vector>
+#include <map>
+
+#define Expr VCExpr
+#include "stp/c_interface.h"
+
+#if ENABLE_STPLOG == 1
+#include "stp/stplog.h"
+#endif
+#undef Expr
+
+namespace klee {
+  class ExprHolder {
+    friend class ExprHandle;
+    ::VCExpr expr;
+    unsigned count;
+    
+  public:
+    ExprHolder(const ::VCExpr _expr) : expr(_expr), count(0) {}
+    ~ExprHolder() { 
+      if (expr) vc_DeleteExpr(expr); 
+    }
+  };
+
+  class ExprHandle {
+    ExprHolder *H;
+    
+  public:
+    ExprHandle() : H(new ExprHolder(0)) { H->count++; }
+    ExprHandle(::VCExpr _expr) : H(new ExprHolder(_expr)) { H->count++; }
+    ExprHandle(const ExprHandle &b) : H(b.H) { H->count++; }
+    ~ExprHandle() { if (--H->count == 0) delete H; }
+    
+    ExprHandle &operator=(const ExprHandle &b) {
+      if (--H->count == 0) delete H;
+      H = b.H;
+      H->count++;
+      return *this;
+    }
+
+    operator bool () { return H->expr; }
+    operator ::VCExpr () { return H->expr; }
+  };
+
+class STPBuilder {
+  ::VC vc;
+  ExprHandle tempVars[4];
+  ExprHashMap< std::pair<ExprHandle, unsigned> > constructed;
+
+  /// optimizeDivides - Rewrite division and reminders by constants
+  /// into multiplies and shifts. STP should probably handle this for
+  /// use.
+  bool optimizeDivides;
+
+private:
+  unsigned getShiftBits(unsigned amount) {
+    return (amount == 64) ? 6 : 5;
+  }
+
+  ExprHandle bvOne(unsigned width);
+  ExprHandle bvZero(unsigned width);
+  ExprHandle bvMinusOne(unsigned width);
+  ExprHandle bvConst32(unsigned width, uint32_t value);
+  ExprHandle bvConst64(unsigned width, uint64_t value);
+
+  ExprHandle bvBoolExtract(ExprHandle expr, int bit);
+  ExprHandle bvExtract(ExprHandle expr, unsigned top, unsigned bottom);
+  ExprHandle eqExpr(ExprHandle a, ExprHandle b);
+
+  //logical left and right shift (not arithmetic)
+  ExprHandle bvLeftShift(ExprHandle expr, unsigned shift, unsigned shiftBits);
+  ExprHandle bvRightShift(ExprHandle expr, unsigned amount, unsigned shiftBits);
+  ExprHandle bvVarLeftShift(ExprHandle expr, ExprHandle amount, unsigned width);
+  ExprHandle bvVarRightShift(ExprHandle expr, ExprHandle amount, unsigned width);
+  ExprHandle bvVarArithRightShift(ExprHandle expr, ExprHandle amount, unsigned width);
+
+  ExprHandle constructAShrByConstant(ExprHandle expr, unsigned shift, 
+                                     ExprHandle isSigned, unsigned shiftBits);
+  ExprHandle constructMulByConstant(ExprHandle expr, unsigned width, uint64_t x);
+  ExprHandle constructUDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d);
+  ExprHandle constructSDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d);
+
+  ::VCExpr getInitialArray(const Array *os);
+  ::VCExpr getArrayForUpdate(const Array *root, const UpdateNode *un);
+
+  ExprHandle constructActual(ref<Expr> e, int *width_out);
+  ExprHandle construct(ref<Expr> e, int *width_out);
+  
+  ::VCExpr buildVar(const char *name, unsigned width);
+  ::VCExpr buildArray(const char *name, unsigned indexWidth, unsigned valueWidth);
+
+public:
+  STPBuilder(::VC _vc, bool _optimizeDivides=true);
+  ~STPBuilder();
+
+  ExprHandle getTrue();
+  ExprHandle getFalse();
+  ExprHandle getTempVar(Expr::Width w);
+  ExprHandle getInitialRead(const Array *os, unsigned index);
+
+  ExprHandle construct(ref<Expr> e) { 
+    ExprHandle res = construct(e, 0);
+    constructed.clear();
+    return res;
+  }
+};
+
+}
+
+#endif

Added: klee/trunk/lib/Solver/Solver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/Solver.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/Solver.cpp (added)
+++ klee/trunk/lib/Solver/Solver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,643 @@
+//===-- Solver.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/Solver.h"
+#include "klee/SolverImpl.h"
+
+#include "SolverStats.h"
+#include "STPBuilder.h"
+
+#include "klee/Constraints.h"
+#include "klee/Expr.h"
+#include "klee/TimerStatIncrementer.h"
+#include "klee/util/Assignment.h"
+#include "klee/util/ExprPPrinter.h"
+#include "klee/util/ExprUtil.h"
+#include "klee/Internal/Support/Timer.h"
+
+#define vc_bvBoolExtract IAMTHESPAWNOFSATAN
+
+#include <cassert>
+#include <map>
+#include <vector>
+
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+using namespace klee;
+
+/***/
+
+const char *Solver::validity_to_str(Validity v) {
+  switch (v) {
+  default:    return "Unknown";
+  case True:  return "True";
+  case False: return "False";
+  }
+}
+
+Solver::~Solver() { 
+  delete impl; 
+}
+
+SolverImpl::~SolverImpl() {
+}
+
+bool Solver::evaluate(const Query& query, Validity &result) {
+  assert(query.expr.getWidth() == Expr::Bool && "Invalid expression type!");
+
+  // Maintain invariants implementation expect.
+  if (query.expr.isConstant()) {
+    result = query.expr.getConstantValue() ? True : False;
+    return true;
+  }
+
+  return impl->computeValidity(query, result);
+}
+
+bool SolverImpl::computeValidity(const Query& query, Solver::Validity &result) {
+  bool isTrue, isFalse;
+  if (!computeTruth(query, isTrue))
+    return false;
+  if (isTrue) {
+    result = Solver::True;
+  } else {
+    if (!computeTruth(query.negateExpr(), isFalse))
+      return false;
+    result = isFalse ? Solver::False : Solver::Unknown;
+  }
+  return true;
+}
+
+bool Solver::mustBeTrue(const Query& query, bool &result) {
+  assert(query.expr.getWidth() == Expr::Bool && "Invalid expression type!");
+
+  // Maintain invariants implementation expect.
+  if (query.expr.isConstant()) {
+    result = query.expr.getConstantValue() ? true : false;
+    return true;
+  }
+
+  return impl->computeTruth(query, result);
+}
+
+bool Solver::mustBeFalse(const Query& query, bool &result) {
+  return mustBeTrue(query.negateExpr(), result);
+}
+
+bool Solver::mayBeTrue(const Query& query, bool &result) {
+  bool res;
+  if (!mustBeFalse(query, res))
+    return false;
+  result = !res;
+  return true;
+}
+
+bool Solver::mayBeFalse(const Query& query, bool &result) {
+  bool res;
+  if (!mustBeTrue(query, res))
+    return false;
+  result = !res;
+  return true;
+}
+
+bool Solver::getValue(const Query& query, ref<Expr> &result) {
+  // Maintain invariants implementation expect.
+  if (query.expr.isConstant()) {
+    result = query.expr;
+    return true;
+  }
+
+  return impl->computeValue(query, result);
+}
+
+bool 
+Solver::getInitialValues(const Query& query,
+                         const std::vector<const Array*> &objects,
+                         std::vector< std::vector<unsigned char> > &values) {
+  bool hasSolution;
+  bool success =
+    impl->computeInitialValues(query, objects, values, hasSolution);
+  // FIXME: Propogate this out.
+  if (!hasSolution)
+    return false;
+    
+  return success;
+}
+
+std::pair< ref<Expr>, ref<Expr> > Solver::getRange(const Query& query) {
+  ref<Expr> e = query.expr;
+  Expr::Width width = e.getWidth();
+  uint64_t min, max;
+
+  if (width==1) {
+    Solver::Validity result;
+    if (!evaluate(query, result))
+      assert(0 && "computeValidity failed");
+    switch (result) {
+    case Solver::True: 
+      min = max = 1; break;
+    case Solver::False: 
+      min = max = 0; break;
+    default:
+      min = 0, max = 1; break;
+    }
+  } else if (e.isConstant()) {
+    min = max = e.getConstantValue();
+  } else {
+    // binary search for # of useful bits
+    uint64_t lo=0, hi=width, mid, bits=0;
+    while (lo<hi) {
+      mid = (lo+hi)/2;
+      bool res;
+      bool success = 
+        mustBeTrue(query.withExpr(
+                     EqExpr::create(LShrExpr::create(e,
+                                                     ConstantExpr::create(mid, 
+                                                                          width)),
+                                    ConstantExpr::create(0, width))),
+                   res);
+      assert(success && "FIXME: Unhandled solver failure");
+      if (res) {
+        hi = mid;
+      } else {
+        lo = mid+1;
+      }
+
+      bits = lo;
+    }
+    
+    // could binary search for training zeros and offset
+    // min max but unlikely to be very useful
+
+    // check common case
+    bool res = false;
+    bool success = 
+      mayBeTrue(query.withExpr(EqExpr::create(e, ConstantExpr::create(0, 
+                                                                      width))), 
+                res);
+    assert(success && "FIXME: Unhandled solver failure");      
+    if (res) {
+      min = 0;
+    } else {
+      // binary search for min
+      lo=0, hi=bits64::maxValueOfNBits(bits);
+      while (lo<hi) {
+        mid = (lo+hi)/2;
+        bool res = false;
+        bool success = 
+          mayBeTrue(query.withExpr(UleExpr::create(e, 
+                                                   ConstantExpr::create(mid, 
+                                                                        width))),
+                    res);
+        assert(success && "FIXME: Unhandled solver failure");      
+        if (res) {
+          hi = mid;
+        } else {
+          lo = mid+1;
+        }
+      }
+
+      min = lo;
+    }
+
+    // binary search for max
+    lo=min, hi=bits64::maxValueOfNBits(bits);
+    while (lo<hi) {
+      mid = (lo+hi)/2;
+      bool res;
+      bool success = 
+        mustBeTrue(query.withExpr(UleExpr::create(e, 
+                                                  ConstantExpr::create(mid, 
+                                                                       width))),
+                   res);
+      assert(success && "FIXME: Unhandled solver failure");      
+      if (res) {
+        hi = mid;
+      } else {
+        lo = mid+1;
+      }
+    }
+
+    max = lo;
+  }
+
+  return std::make_pair(ConstantExpr::create(min, width),
+                        ConstantExpr::create(max, width));
+}
+
+/***/
+
+class ValidatingSolver : public SolverImpl {
+private:
+  Solver *solver, *oracle;
+
+public: 
+  ValidatingSolver(Solver *_solver, Solver *_oracle) 
+    : solver(_solver), oracle(_oracle) {}
+  ~ValidatingSolver() { delete solver; }
+  
+  bool computeValidity(const Query&, Solver::Validity &result);
+  bool computeTruth(const Query&, bool &isValid);
+  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);
+};
+
+bool ValidatingSolver::computeTruth(const Query& query,
+                                    bool &isValid) {
+  bool answer;
+  
+  if (!solver->impl->computeTruth(query, isValid))
+    return false;
+  if (!oracle->impl->computeTruth(query, answer))
+    return false;
+  
+  if (isValid != answer)
+    assert(0 && "invalid solver result (computeTruth)");
+  
+  return true;
+}
+
+bool ValidatingSolver::computeValidity(const Query& query,
+                                       Solver::Validity &result) {
+  Solver::Validity answer;
+  
+  if (!solver->impl->computeValidity(query, result))
+    return false;
+  if (!oracle->impl->computeValidity(query, answer))
+    return false;
+  
+  if (result != answer)
+    assert(0 && "invalid solver result (computeValidity)");
+  
+  return true;
+}
+
+bool ValidatingSolver::computeValue(const Query& query,
+                                    ref<Expr> &result) {  
+  bool answer;
+
+  if (!solver->impl->computeValue(query, result))
+    return false;
+  // We don't want to compare, but just make sure this is a legal
+  // solution.
+  if (!oracle->impl->computeTruth(query.withExpr(NeExpr::create(query.expr, 
+                                                                result)),
+                                  answer))
+    return false;
+
+  if (answer)
+    assert(0 && "invalid solver result (computeValue)");
+
+  return true;
+}
+
+bool 
+ValidatingSolver::computeInitialValues(const Query& query,
+                                       const std::vector<const Array*>
+                                         &objects,
+                                       std::vector< std::vector<unsigned char> >
+                                         &values,
+                                       bool &hasSolution) {
+  bool answer;
+
+  if (!solver->impl->computeInitialValues(query, objects, values, 
+                                          hasSolution))
+    return false;
+
+  if (hasSolution) {
+    // Assert the bindings as constraints, and verify that the
+    // conjunction of the actual constraints is satisfiable.
+    std::vector< ref<Expr> > bindings;
+    for (unsigned i = 0; i != values.size(); ++i) {
+      const Array *array = objects[i];
+      for (unsigned j=0; j<array->size; j++) {
+        unsigned char value = values[i][j];
+        bindings.push_back(EqExpr::create(ReadExpr::create(UpdateList(array,
+                                                                      true, 0),
+                                                           ref<Expr>(j, Expr::Int32)),
+                                          ref<Expr>(value, Expr::Int8)));
+      }
+    }
+    ConstraintManager tmp(bindings);
+    ref<Expr> constraints = Expr::createNot(query.expr);
+    for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+           ie = query.constraints.end(); it != ie; ++it)
+      constraints = AndExpr::create(constraints, *it);
+    
+    if (!oracle->impl->computeTruth(Query(tmp, constraints), answer))
+      return false;
+    if (!answer)
+      assert(0 && "invalid solver result (computeInitialValues)");
+  } else {
+    if (!oracle->impl->computeTruth(query, answer))
+      return false;
+    if (!answer)
+      assert(0 && "invalid solver result (computeInitialValues)");    
+  }
+
+  return true;
+}
+
+Solver *klee::createValidatingSolver(Solver *s, Solver *oracle) {
+  return new Solver(new ValidatingSolver(s, oracle));
+}
+
+/***/
+
+class STPSolverImpl : public SolverImpl {
+private:
+  /// The solver we are part of, for access to public information.
+  STPSolver *solver;
+  VC vc;
+  STPBuilder *builder;
+  double timeout;
+  bool useForkedSTP;
+
+public:
+  STPSolverImpl(STPSolver *_solver, bool _useForkedSTP);
+  ~STPSolverImpl();
+
+  char *getConstraintLog(const Query&);
+  void setTimeout(double _timeout) { timeout = _timeout; }
+
+  bool computeTruth(const Query&, bool &isValid);
+  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);
+};
+
+static unsigned char *shared_memory_ptr;
+static const unsigned shared_memory_size = 1<<20;
+static int shared_memory_id;
+
+static void stp_error_handler(const char* err_msg) {
+  fprintf(stderr, "error: STP Error: %s\n", err_msg);
+  abort();
+}
+
+STPSolverImpl::STPSolverImpl(STPSolver *_solver, bool _useForkedSTP) 
+  : solver(_solver),
+    vc(vc_createValidityChecker()),
+    builder(new STPBuilder(vc)),
+    timeout(0.0),
+    useForkedSTP(_useForkedSTP)
+{
+  assert(vc && "unable to create validity checker");
+  assert(builder && "unable to create STPBuilder");
+
+  vc_registerErrorHandler(::stp_error_handler);
+
+  if (useForkedSTP) {
+    shared_memory_id = shmget(IPC_PRIVATE, shared_memory_size, IPC_CREAT | 0700);
+    assert(shared_memory_id>=0 && "shmget failed");
+    shared_memory_ptr = (unsigned char*) shmat(shared_memory_id, NULL, 0);
+    assert(shared_memory_ptr!=(void*)-1 && "shmat failed");
+    shmctl(shared_memory_id, IPC_RMID, NULL);
+  }
+}
+
+STPSolverImpl::~STPSolverImpl() {
+  delete builder;
+
+  vc_Destroy(vc);
+}
+
+/***/
+
+STPSolver::STPSolver(bool useForkedSTP) 
+  : Solver(new STPSolverImpl(this, useForkedSTP))
+{
+}
+
+char *STPSolver::getConstraintLog(const Query &query) {
+  return static_cast<STPSolverImpl*>(impl)->getConstraintLog(query);  
+}
+
+void STPSolver::setTimeout(double timeout) {
+  static_cast<STPSolverImpl*>(impl)->setTimeout(timeout);
+}
+
+/***/
+
+char *STPSolverImpl::getConstraintLog(const Query &query) {
+  vc_push(vc);
+  for (std::vector< ref<Expr> >::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    vc_assertFormula(vc, builder->construct(*it));
+  assert(query.expr == ref<Expr>(0, Expr::Bool) &&
+         "Unexpected expression in query!");
+
+  char *buffer;
+  unsigned long length;
+  vc_printQueryStateToBuffer(vc, builder->getFalse(), 
+                             &buffer, &length, false);
+  vc_pop(vc);
+
+  return buffer;
+}
+
+bool STPSolverImpl::computeTruth(const Query& query,
+                                 bool &isValid) {
+  std::vector<const Array*> objects;
+  std::vector< std::vector<unsigned char> > values;
+  bool hasSolution;
+
+  if (!computeInitialValues(query, objects, values, hasSolution))
+    return false;
+
+  isValid = !hasSolution;
+  return true;
+}
+
+bool STPSolverImpl::computeValue(const Query& query,
+                                 ref<Expr> &result) {
+  std::vector<const Array*> objects;
+  std::vector< std::vector<unsigned char> > values;
+  bool hasSolution;
+
+  // Find the object used in the expression, and compute an assignment
+  // for them.
+  findSymbolicObjects(query.expr, objects);
+  if (!computeInitialValues(query.withFalse(), objects, values, hasSolution))
+    return false;
+  assert(hasSolution && "state has invalid constraint set");
+  
+  // Evaluate the expression with the computed assignment.
+  Assignment a(objects, values);
+  result = a.evaluate(query.expr);
+
+  return true;
+}
+
+static void runAndGetCex(::VC vc, STPBuilder *builder, ::VCExpr q,
+                   const std::vector<const Array*> &objects,
+                   std::vector< std::vector<unsigned char> > &values,
+                   bool &hasSolution) {
+  // XXX I want to be able to timeout here, safely
+  hasSolution = !vc_query(vc, q);
+
+  if (hasSolution) {
+    values.reserve(objects.size());
+    for (std::vector<const Array*>::const_iterator
+           it = objects.begin(), ie = objects.end(); it != ie; ++it) {
+      const Array *array = *it;
+      std::vector<unsigned char> data;
+      
+      data.reserve(array->size);
+      for (unsigned offset = 0; offset < array->size; offset++) {
+        ExprHandle counter = 
+          vc_getCounterExample(vc, builder->getInitialRead(array, offset));
+        unsigned char val = getBVUnsigned(counter);
+        data.push_back(val);
+      }
+      
+      values.push_back(data);
+    }
+  }
+}
+
+static void stpTimeoutHandler(int x) {
+  _exit(52);
+}
+
+static bool runAndGetCexForked(::VC vc, 
+                               STPBuilder *builder,
+                               ::VCExpr q,
+                               const std::vector<const Array*> &objects,
+                               std::vector< std::vector<unsigned char> >
+                                 &values,
+                               bool &hasSolution,
+                               double timeout) {
+  unsigned char *pos = shared_memory_ptr;
+  unsigned sum = 0;
+  for (std::vector<const Array*>::const_iterator
+         it = objects.begin(), ie = objects.end(); it != ie; ++it)
+    sum += (*it)->size;
+  assert(sum<shared_memory_size && "not enough shared memory for counterexample");
+
+  fflush(stdout);
+  fflush(stderr);
+  int pid = fork();
+  if (pid==-1) {
+    fprintf(stderr, "error: fork failed (for STP)");
+    return false;
+  }
+
+  if (pid == 0) {
+    if (timeout) {
+      ::alarm(0); /* Turn off alarm so we can safely set signal handler */
+      ::signal(SIGALRM, stpTimeoutHandler);
+      ::alarm(std::max(1, (int)timeout));
+    }    
+    unsigned res = vc_query(vc, q);
+    if (!res) {
+      for (std::vector<const Array*>::const_iterator
+             it = objects.begin(), ie = objects.end(); it != ie; ++it) {
+        const Array *array = *it;
+        for (unsigned offset = 0; offset < array->size; offset++) {
+          ExprHandle counter = 
+            vc_getCounterExample(vc, builder->getInitialRead(array, offset));
+          *pos++ = getBVUnsigned(counter);
+        }
+      }
+    }
+    _exit(res);
+  } else {
+    int status;
+    int res = waitpid(pid, &status, 0);
+    
+    if (res<0) {
+      fprintf(stderr, "error: waitpid() for STP failed");
+      return false;
+    }
+    
+    // From timed_run.py: It appears that linux at least will on
+    // "occasion" return a status when the process was terminated by a
+    // signal, so test signal first.
+    if (WIFSIGNALED(status) || !WIFEXITED(status)) {
+      fprintf(stderr, "error: STP did not return successfully");
+      return false;
+    }
+
+    int exitcode = WEXITSTATUS(status);
+    if (exitcode==0) {
+      hasSolution = true;
+    } else if (exitcode==1) {
+      hasSolution = false;
+    } else if (exitcode==52) {
+      fprintf(stderr, "error: STP timed out");
+      return false;
+    } else {
+      fprintf(stderr, "error: STP did not return a recognized code");
+      return false;
+    }
+    
+    if (hasSolution) {
+      values = std::vector< std::vector<unsigned char> >(objects.size());
+      unsigned i=0;
+      for (std::vector<const Array*>::const_iterator
+             it = objects.begin(), ie = objects.end(); it != ie; ++it) {
+        const Array *array = *it;
+        std::vector<unsigned char> &data = values[i++];
+        data.insert(data.begin(), pos, pos + array->size);
+        pos += array->size;
+      }
+    }
+
+    return true;
+  }
+}
+
+bool
+STPSolverImpl::computeInitialValues(const Query &query,
+                                    const std::vector<const Array*> 
+                                      &objects,
+                                    std::vector< std::vector<unsigned char> > 
+                                      &values,
+                                    bool &hasSolution) {
+  TimerStatIncrementer t(stats::queryTime);
+
+  vc_push(vc);
+
+  for (ConstraintManager::const_iterator it = query.constraints.begin(), 
+         ie = query.constraints.end(); it != ie; ++it)
+    vc_assertFormula(vc, builder->construct(*it));
+  
+  ++stats::queries;
+  ++stats::queryCounterexamples;
+
+  ExprHandle stp_e = builder->construct(query.expr);
+     
+  bool success;
+  if (useForkedSTP) {
+    success = runAndGetCexForked(vc, builder, stp_e, objects, values, 
+                                 hasSolution, timeout);
+  } else {
+    runAndGetCex(vc, builder, stp_e, objects, values, hasSolution);
+    success = true;
+  }
+  
+  if (success) {
+    if (hasSolution)
+      ++stats::queriesInvalid;
+    else
+      ++stats::queriesValid;
+  }
+  
+  vc_pop(vc);
+  
+  return success;
+}

Added: klee/trunk/lib/Solver/SolverStats.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/SolverStats.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/SolverStats.cpp (added)
+++ klee/trunk/lib/Solver/SolverStats.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,23 @@
+//===-- SolverStats.cpp ---------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SolverStats.h"
+
+using namespace klee;
+
+Statistic stats::cexCacheTime("CexCacheTime", "CCtime");
+Statistic stats::queries("Queries", "Q");
+Statistic stats::queriesInvalid("QueriesInvalid", "Qiv");
+Statistic stats::queriesValid("QueriesValid", "Qv");
+Statistic stats::queryCacheHits("QueryCacheHits", "QChits") ;
+Statistic stats::queryCacheMisses("QueryCacheMisses", "QCmisses");
+Statistic stats::queryConstructTime("QueryConstructTime", "QBtime") ;
+Statistic stats::queryConstructs("QueriesConstructs", "QB");
+Statistic stats::queryCounterexamples("QueriesCEX", "Qcex");
+Statistic stats::queryTime("QueryTime", "Qtime");

Added: klee/trunk/lib/Solver/SolverStats.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Solver/SolverStats.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Solver/SolverStats.h (added)
+++ klee/trunk/lib/Solver/SolverStats.h Wed May 20 23:36:41 2009
@@ -0,0 +1,32 @@
+//===-- SolverStats.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_SOLVERSTATS_H
+#define KLEE_SOLVERSTATS_H
+
+#include "klee/Statistic.h"
+
+namespace klee {
+namespace stats {
+
+  extern Statistic cexCacheTime;
+  extern Statistic queries;
+  extern Statistic queriesInvalid;
+  extern Statistic queriesValid;
+  extern Statistic queryCacheHits;
+  extern Statistic queryCacheMisses;
+  extern Statistic queryConstructTime;
+  extern Statistic queryConstructs;
+  extern Statistic queryCounterexamples;
+  extern Statistic queryTime;
+
+}
+}
+
+#endif

Added: klee/trunk/lib/Support/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Support/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Support/Makefile (added)
+++ klee/trunk/lib/Support/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+#===-- lib/Support/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=kleeSupport
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+
+include $(LEVEL)/Makefile.common

Added: klee/trunk/lib/Support/README.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Support/README.txt?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Support/README.txt (added)
+++ klee/trunk/lib/Support/README.txt Wed May 20 23:36:41 2009
@@ -0,0 +1,2 @@
+This directory holds basic support facilities (data structures,
+utilities, etc.) used by klee.

Added: klee/trunk/lib/Support/RNG.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Support/RNG.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Support/RNG.cpp (added)
+++ klee/trunk/lib/Support/RNG.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,146 @@
+/* 
+   A C-program for MT19937, with initialization improved 2002/1/26.
+   Coded by Takuji Nishimura and Makoto Matsumoto.
+   Modified to be a C++ class by Daniel Dunbar.
+
+   Before using, initialize the state by using init_genrand(seed)  
+   or init_by_array(init_key, key_length).
+
+   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+   All rights reserved.                          
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+     3. The names of its contributors may not be used to endorse or promote 
+        products derived from this software without specific prior written 
+        permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+   Any feedback is very welcome.
+   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+
+#include "klee/Internal/ADT/RNG.h"
+
+using namespace klee;
+
+/* initializes mt[N] with a seed */
+RNG::RNG(unsigned int s) {
+  seed(s);
+}
+
+void RNG::seed(unsigned int s) {
+  mt[0]= s & 0xffffffffUL;
+  for (mti=1; mti<N; mti++) {
+    mt[mti] = 
+      (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
+    /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+    /* In the previous versions, MSBs of the seed affect   */
+    /* only MSBs of the array mt[].                        */
+    /* 2002/01/09 modified by Makoto Matsumoto             */
+    mt[mti] &= 0xffffffffUL;
+    /* for >32 bit machines */
+  }
+}
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned int RNG::getInt32() {
+  unsigned int y;
+  static unsigned int mag01[2]={0x0UL, MATRIX_A};
+  /* mag01[x] = x * MATRIX_A  for x=0,1 */
+  
+  if (mti >= N) { /* generate N words at one time */
+    int kk;
+    
+    for (kk=0;kk<N-M;kk++) {
+      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+      mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+    }
+    for (;kk<N-1;kk++) {
+      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+      mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+    }
+    y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+    mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+    
+    mti = 0;
+  }
+  
+  y = mt[mti++];
+
+  /* Tempering */
+  y ^= (y >> 11);
+  y ^= (y << 7) & 0x9d2c5680UL;
+  y ^= (y << 15) & 0xefc60000UL;
+  y ^= (y >> 18);
+  
+  return y;
+}
+
+/* generates a random number on [0,0x7fffffff]-interval */
+int RNG::getInt31() {
+  return (int)(getInt32()>>1);
+}
+
+/* generates a random number on [0,1]-real-interval */
+double RNG::getDoubleLR() {
+  return getInt32()*(1.0/4294967295.0); 
+  /* divided by 2^32-1 */ 
+}
+
+/* generates a random number on [0,1)-real-interval */
+double RNG::getDoubleL() {
+  return getInt32()*(1.0/4294967296.0); 
+  /* divided by 2^32 */
+}
+
+/* generates a random number on (0,1)-real-interval */
+double RNG::getDouble() {
+  return (((double)getInt32()) + 0.5)*(1.0/4294967296.0); 
+  /* divided by 2^32 */
+}
+
+float RNG::getFloatLR() {
+  return getInt32()*(1.0f/4294967295.0f); 
+  /* divided by 2^32-1 */ 
+}
+float RNG::getFloatL() {
+  return getInt32()*(1.0f/4294967296.0f); 
+  /* divided by 2^32 */
+}
+float RNG::getFloat() {
+  return (getInt32() + 0.5f)*(1.0f/4294967296.0f); 
+  /* divided by 2^32 */
+}
+
+bool RNG::getBool() {
+  unsigned bits = getInt32();
+  bits ^= bits >> 16;
+  bits ^= bits >> 8;
+  bits ^= bits >> 4;
+  bits ^= bits >> 2;
+  bits ^= bits >> 1;
+  return bits&1;
+}

Added: klee/trunk/lib/Support/Time.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Support/Time.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Support/Time.cpp (added)
+++ klee/trunk/lib/Support/Time.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,27 @@
+//===-- Time.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/Internal/System/Time.h"
+
+#include "llvm/System/Process.h"
+
+using namespace llvm;
+using namespace klee;
+
+double util::getUserTime() {
+  sys::TimeValue now(0,0),user(0,0),sys(0,0);
+  sys::Process::GetTimeUsage(now,user,sys);
+  return (user.seconds() + (double) user.nanoseconds() * 1e-9);
+}
+
+double util::getWallTime() {
+  sys::TimeValue now(0,0),user(0,0),sys(0,0);
+  sys::Process::GetTimeUsage(now,user,sys);
+  return (now.seconds() + (double) now.nanoseconds() * 1e-9);
+}

Added: klee/trunk/lib/Support/Timer.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Support/Timer.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Support/Timer.cpp (added)
+++ klee/trunk/lib/Support/Timer.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,27 @@
+//===-- Timer.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/Internal/Support/Timer.h"
+
+#include "llvm/System/Process.h"
+
+using namespace klee;
+using namespace llvm;
+
+WallTimer::WallTimer() {
+  sys::TimeValue now(0,0),user(0,0),sys(0,0);
+  sys::Process::GetTimeUsage(now,user,sys);
+  startMicroseconds = now.usec();
+}
+
+uint64_t WallTimer::check() {
+  sys::TimeValue now(0,0),user(0,0),sys(0,0);
+  sys::Process::GetTimeUsage(now,user,sys);
+  return now.usec() - startMicroseconds;
+}

Added: klee/trunk/lib/Support/TreeStream.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/lib/Support/TreeStream.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/lib/Support/TreeStream.cpp (added)
+++ klee/trunk/lib/Support/TreeStream.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,201 @@
+//===-- TreeStream.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/Internal/ADT/TreeStream.h"
+
+#include <cassert>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <iterator>
+#include <map>
+
+#include <string.h>
+
+using namespace klee;
+
+///
+
+TreeStreamWriter::TreeStreamWriter(const std::string &_path) 
+  : lastID(0),
+    bufferCount(0),
+    path(_path),
+    output(new std::ofstream(path.c_str(), 
+                             std::ios::out | std::ios::binary)),
+    ids(1) {
+  if (!output->good()) {
+    delete output;
+    output = 0;
+  }
+}
+
+TreeStreamWriter::~TreeStreamWriter() {
+  flush();
+  if (output)
+    delete output;
+}
+
+bool TreeStreamWriter::good() {
+  return !!output;
+}
+
+TreeOStream TreeStreamWriter::open() {
+  return open(TreeOStream(*this, 0));
+}
+
+TreeOStream TreeStreamWriter::open(const TreeOStream &os) {
+  assert(output && os.writer==this);
+  flushBuffer();
+  unsigned id = ids++;
+  output->write(reinterpret_cast<const char*>(&os.id), 4);
+  unsigned tag = id | (1<<31);
+  output->write(reinterpret_cast<const char*>(&tag), 4);
+  return TreeOStream(*this, id);
+}
+
+void TreeStreamWriter::write(TreeOStream &os, const char *s, unsigned size) {
+#if 1
+  if (bufferCount && 
+      (os.id!=lastID || size+bufferCount>bufferSize))
+    flushBuffer();
+  if (bufferCount) { // (os.id==lastID && size+bufferCount<=bufferSize)
+    memcpy(&buffer[bufferCount], s, size);
+    bufferCount += size;
+  } else if (size<bufferSize) {
+    lastID = os.id;
+    memcpy(buffer, s, size);
+    bufferCount = size;
+  } else {
+    output->write(reinterpret_cast<const char*>(&os.id), 4);
+    output->write(reinterpret_cast<const char*>(&size), 4);
+    output->write(buffer, size);
+  }
+#else
+  output->write(reinterpret_cast<const char*>(&os.id), 4);
+  output->write(reinterpret_cast<const char*>(&size), 4);
+  output->write(s, size);
+#endif
+}
+
+void TreeStreamWriter::flushBuffer() {
+  if (bufferCount) {    
+    output->write(reinterpret_cast<const char*>(&lastID), 4);
+    output->write(reinterpret_cast<const char*>(&bufferCount), 4);
+    output->write(buffer, bufferCount);
+    bufferCount = 0;
+  }
+}
+
+void TreeStreamWriter::flush() {
+  flushBuffer();
+  output->flush();
+}
+
+void TreeStreamWriter::readStream(TreeStreamID streamID,
+                                  std::vector<unsigned char> &out) {
+  assert(streamID>0 && streamID<ids);
+  flush();
+  
+  std::ifstream is(path.c_str(),
+                   std::ios::in | std::ios::binary);
+  assert(is.good());
+#if 0
+  std::cout << "finding chain for: " << streamID << "\n";
+#endif
+  
+  std::map<unsigned,unsigned> parents;
+  std::vector<unsigned> roots;
+  for (;;) {
+    assert(is.good());
+    unsigned id;
+    unsigned tag;
+    is.read(reinterpret_cast<char*>(&id), 4);
+    is.read(reinterpret_cast<char*>(&tag), 4);
+    if (tag&(1<<31)) { // fork
+      unsigned child = tag ^ (1<<31);
+
+      if (child==streamID) {
+        roots.push_back(child);
+        while (id) {
+          roots.push_back(id);
+          std::map<unsigned, unsigned>::iterator it = parents.find(id);
+          assert(it!=parents.end());
+          id = it->second;
+        } 
+        break;
+      } else {
+        parents.insert(std::make_pair(child,id));
+      }
+    } else {
+      unsigned size = tag;
+      while (size--) is.get();
+    }
+  }
+#if 0
+  std::cout << "roots: ";
+  std::copy(roots.begin(), roots.end(), std::ostream_iterator<unsigned>(std::cout, " "));
+  std::cout << "\n"; 
+#endif
+  is.seekg(0, std::ios::beg);
+  for (;;) {
+    unsigned id;
+    unsigned tag;
+    is.read(reinterpret_cast<char*>(&id), 4);
+    is.read(reinterpret_cast<char*>(&tag), 4);
+    if (!is.good()) break;
+    if (tag&(1<<31)) { // fork
+      unsigned child = tag ^ (1<<31);
+      if (id==roots.back() && roots.size()>1 && child==roots[roots.size()-2])
+        roots.pop_back();
+    } else {
+      unsigned size = tag;
+      if (id==roots.back()) {
+        while (size--) out.push_back(is.get());
+      } else {
+        while (size--) is.get();
+      }
+    }
+  }  
+}
+
+///
+
+TreeOStream::TreeOStream()
+  : writer(0),
+    id(0) {
+}
+
+TreeOStream::TreeOStream(TreeStreamWriter &_writer, unsigned _id)
+  : writer(&_writer),
+    id(_id) {
+}
+
+TreeOStream::~TreeOStream() {
+}
+
+unsigned TreeOStream::getID() const {
+  assert(writer);
+  return id;
+}
+
+void TreeOStream::write(const char *buffer, unsigned size) {
+  assert(writer);
+  writer->write(*this, buffer, size);
+}
+
+TreeOStream &TreeOStream::operator<<(const std::string &s) {
+  assert(writer);
+  write(s.c_str(), s.size());
+  return *this;
+}
+
+void TreeOStream::flush() {
+  assert(writer);
+  writer->flush();
+}

Added: klee/trunk/runtime/Intrinsic/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/Makefile (added)
+++ klee/trunk/runtime/Intrinsic/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+#===-- runtime/Intrinsic/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=intrinsic
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+BYTECODE_LIBRARY=1
+# Don't strip debug info from the module.
+DEBUG_RUNTIME=1
+NO_PEDANTIC=1
+
+include $(LEVEL)/Makefile.common

Added: klee/trunk/runtime/Intrinsic/klee_div_zero_check.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/klee_div_zero_check.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/klee_div_zero_check.c (added)
+++ klee/trunk/runtime/Intrinsic/klee_div_zero_check.c Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+//===-- klee_div_zero_check.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/klee.h>
+
+void klee_div_zero_check(long long z) {
+  if (z == 0)
+    klee_report_error(__FILE__, __LINE__, "divide by zero", "div.err");
+}

Added: klee/trunk/runtime/Intrinsic/klee_int.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/klee_int.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/klee_int.c (added)
+++ klee/trunk/runtime/Intrinsic/klee_int.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+//===-- klee_int.c --------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <klee/klee.h>
+
+int klee_int(const char *name) {
+  int x;
+  klee_make_symbolic_name(&x, sizeof x, name);
+  return x;
+}

Added: klee/trunk/runtime/Intrinsic/klee_make_symbolic.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/klee_make_symbolic.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/klee_make_symbolic.c (added)
+++ klee/trunk/runtime/Intrinsic/klee_make_symbolic.c Wed May 20 23:36:41 2009
@@ -0,0 +1,14 @@
+//===-- klee_make_symbolic.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/klee.h>
+
+void klee_make_symbolic(void *addr, unsigned nbytes) {
+  klee_make_symbolic_name(addr, nbytes, "unnamed");
+}

Added: klee/trunk/runtime/Intrinsic/klee_range.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/klee_range.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/klee_range.c (added)
+++ klee/trunk/runtime/Intrinsic/klee_range.c Wed May 20 23:36:41 2009
@@ -0,0 +1,33 @@
+//===-- klee_range.c ------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <klee/klee.h>
+
+int klee_range(int start, int end, const char* name) {
+  int x;
+
+  assert(start < end);
+
+  if (start+1==end) {
+    return start;
+  } else {
+    klee_make_symbolic_name(&x, sizeof x, name); 
+
+    /* Make nicer constraint when simple... */
+    if (start==0) {
+      klee_assume((unsigned) x < (unsigned) end);
+    } else {
+      klee_assume(start <= x);
+      klee_assume(x < end);
+    }
+
+    return x;
+  }
+}

Added: klee/trunk/runtime/Intrinsic/memcpy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/memcpy.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/memcpy.c (added)
+++ klee/trunk/runtime/Intrinsic/memcpy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+//===-- memcpy.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *memcpy(void *destaddr, void const *srcaddr, unsigned int len) {
+  char *dest = destaddr;
+  char const *src = srcaddr;
+
+  while (len-- > 0)
+    *dest++ = *src++;
+  return destaddr;
+}

Added: klee/trunk/runtime/Intrinsic/memmove.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/memmove.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/memmove.c (added)
+++ klee/trunk/runtime/Intrinsic/memmove.c Wed May 20 23:36:41 2009
@@ -0,0 +1,28 @@
+//===-- memmove.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *memmove(void *dst, const void *src, size_t count) {
+  char *a = dst;
+  const char *b = src;
+
+  if (src == dst)
+    return dst;
+
+  if (src>dst) {
+    while (count--) *a++ = *b++;
+  } else {
+    a+=count-1;
+    b+=count-1;
+    while (count--) *a-- = *b--;
+  }
+
+  return dst;
+}

Added: klee/trunk/runtime/Intrinsic/mempcpy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/mempcpy.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/mempcpy.c (added)
+++ klee/trunk/runtime/Intrinsic/mempcpy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+//===-- mempcpy.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *mempcpy(void *destaddr, void const *srcaddr, unsigned int len) {
+  char *dest = destaddr;
+  char const *src = srcaddr;
+
+  while (len-- > 0)
+    *dest++ = *src++;
+  return dest;
+}

Added: klee/trunk/runtime/Intrinsic/memset.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Intrinsic/memset.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Intrinsic/memset.c (added)
+++ klee/trunk/runtime/Intrinsic/memset.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+//===-- memset.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *memset(void * dst, int s, size_t count) {
+    char * a = dst;
+    while (count-- > 0)
+      *a++ = s;
+    return dst;
+}

Added: klee/trunk/runtime/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Makefile (added)
+++ klee/trunk/runtime/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,26 @@
+#===-- runtime/Makefile ------------------------------------*- Makefile -*--===#
+#
+#                     The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+#
+# Relative path to the top of the source tree.
+#
+LEVEL=..
+
+#
+# List all of the subdirectories that we will compile.
+#
+PARALLEL_DIRS=Intrinsic klee-libc Runtest
+
+include $(LEVEL)/Makefile.config
+
+ifeq ($(ENABLE_POSIX_RUNTIME),1)
+PARALLEL_DIRS += POSIX
+endif
+
+include $(LEVEL)/Makefile.common

Propchange: klee/trunk/runtime/Makefile

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/runtime/POSIX/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/Makefile (added)
+++ klee/trunk/runtime/POSIX/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+#===-- runtime/POSIX/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=kleeRuntimePOSIX
+DONT_BUILD_RELINKED=1
+BUILD_ARCHIVE=1
+BYTECODE_LIBRARY=1
+# Don't strip debug info from the module.
+DEBUG_RUNTIME=1
+NO_PEDANTIC=1
+
+include $(LEVEL)/Makefile.common

Added: klee/trunk/runtime/POSIX/fd.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/fd.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/fd.c (added)
+++ klee/trunk/runtime/POSIX/fd.c Wed May 20 23:36:41 2009
@@ -0,0 +1,1287 @@
+//===-- fd.c --------------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define _LARGEFILE64_SOURCE
+#include "fd.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <termios.h>
+#include <sys/select.h>
+#include <klee/klee.h>
+
+/* #define DEBUG */
+
+void klee_warning(const char*);
+void klee_warning_once(const char*);
+int klee_get_errno(void);
+
+/* Returns pointer to the symbolic file structure is the pathname is symbolic */
+static exe_disk_file_t *__get_sym_file(const char *pathname) {
+  char c = pathname[0];
+  unsigned i;
+
+  if (c == 0 || pathname[1] != 0)
+    return NULL;
+
+  for (i=0; i<__exe_fs.n_sym_files; ++i) {
+    if (c == 'A' + (char) i) {
+      exe_disk_file_t *df = &__exe_fs.sym_files[i];
+      if (df->stat->st_ino == 0)
+        return NULL;
+      return df;
+    }
+  }
+  
+  return NULL;
+}
+
+static void *__concretize_ptr(const void *p);
+static size_t __concretize_size(size_t s);
+static const char *__concretize_string(const char *s);
+
+/* Returns pointer to the file entry for a valid fd */
+static exe_file_t *__get_file(int fd) {
+  if (fd>=0 && fd<MAX_FDS) {
+    exe_file_t *f = &__exe_env.fds[fd];
+    if (f->flags & eOpen)
+      return f;
+  }
+
+  return 0;
+}
+
+int access(const char *pathname, int mode) {
+  exe_disk_file_t *dfile = __get_sym_file(pathname);
+  
+  if (dfile) {
+    /* XXX we should check against stat values but we also need to
+       enforce in open and friends then. */
+    return 0;
+  } else {
+    int r = syscall(__NR_access, __concretize_string(pathname), mode);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  } 
+}
+
+mode_t umask(mode_t mask) {  
+  mode_t r = __exe_env.umask;
+  __exe_env.umask = mask & 0777;
+  return r;
+}
+
+
+/* Returns 1 if the process has the access rights specified by 'flags'
+   to the file with stat 's'.  Returns 0 otherwise*/
+static int has_permission(int flags, struct stat64 *s) {
+  int write_access, read_access;
+  mode_t mode = s->st_mode;
+  
+  if (flags & O_RDONLY || flags & O_RDWR)
+    read_access = 1;
+  else read_access = 0;
+
+  if (flags & O_WRONLY || flags & O_RDWR)
+    write_access = 1;
+  else write_access = 0;
+
+  /* XXX: We don't worry about process uid and gid for now. 
+     We allow access if any user has access to the file. */
+#if 0
+  uid_t uid = s->st_uid;
+  uid_t euid = geteuid();
+  gid_t gid = s->st_gid;
+  gid_t egid = getegid();
+#endif  
+
+  if (read_access && ((mode & S_IRUSR) | (mode & S_IRGRP) | (mode & S_IROTH)))
+    return 0;
+
+  if (write_access && !((mode & S_IWUSR) | (mode & S_IWGRP) | (mode & S_IWOTH)))
+    return 0;
+
+  return 1;
+}
+
+
+int __fd_open(const char *pathname, int flags, mode_t mode) {
+  exe_disk_file_t *df;
+  exe_file_t *f;
+  int fd;
+
+  for (fd = 0; fd < MAX_FDS; ++fd)
+    if (!(__exe_env.fds[fd].flags & eOpen))
+      break;
+  if (fd == MAX_FDS) {
+    errno = EMFILE;
+    return -1;
+  }
+  
+  f = &__exe_env.fds[fd];
+
+  /* Should be the case if file was available, but just in case. */
+  memset(f, 0, sizeof *f);
+
+  df = __get_sym_file(pathname); 
+  if (df) {    
+    /* XXX Should check access against mode / stat / possible
+       deletion. */
+    f->dfile = df;
+    
+    if ((flags & O_CREAT) && (flags & O_EXCL)) {
+      errno = EEXIST;
+      return -1;
+    }
+    
+    if ((flags & O_TRUNC) && (flags & O_RDONLY)) {
+      /* The result of using O_TRUNC with O_RDONLY is undefined, so we
+	 return error */
+      fprintf(stderr, "Undefined call to open(): O_TRUNC | O_RDONLY\n");
+      errno = EACCES;
+      return -1;
+    }
+
+    if ((flags & O_EXCL) && !(flags & O_CREAT)) {
+      /* The result of using O_EXCL without O_CREAT is undefined, so
+	 we return error */
+      fprintf(stderr, "Undefined call to open(): O_EXCL w/o O_RDONLY\n");
+      errno = EACCES;
+      return -1;
+    }
+
+    if (!has_permission(flags, df->stat)) {
+	errno = EACCES;
+	return -1;
+    }
+    else
+      f->dfile->stat->st_mode = ((f->dfile->stat->st_mode & ~0777) |
+				 (mode & ~__exe_env.umask));
+  } else {    
+    int os_fd = syscall(__NR_open, __concretize_string(pathname), flags, mode);
+    if (os_fd == -1) {
+      errno = klee_get_errno();
+      return -1;
+    }
+    f->fd = os_fd;
+  }
+  
+  f->flags = eOpen;
+  if ((flags & O_ACCMODE) == O_RDONLY) {
+    f->flags |= eReadable;
+  } else if ((flags & O_ACCMODE) == O_WRONLY) {
+    f->flags |= eWriteable;
+  } else { /* XXX What actually happens here if != O_RDWR. */
+    f->flags |= eReadable | eWriteable;
+  }
+  
+  return fd;
+}
+
+int close(int fd) {
+  static int n_calls = 0;
+  exe_file_t *f;
+  int r = 0;
+  
+  n_calls++;  
+
+  f = __get_file(fd);
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  } 
+
+  if (__exe_fs.max_failures && *__exe_fs.close_fail == n_calls) {
+    __exe_fs.max_failures--;
+    errno = EIO;
+    return -1;
+  }
+
+#if 0
+  if (!f->dfile) {
+    /* if a concrete fd */
+    r = syscall(__NR_close, f->fd);
+  }
+  else r = 0;
+#endif
+
+  memset(f, 0, sizeof *f);
+  
+  return r;
+}
+
+ssize_t read(int fd, void *buf, size_t count) {
+  static int n_calls = 0;
+  exe_file_t *f;
+
+  n_calls++;
+
+  if (count == 0) 
+    return 0;
+
+  if (buf == NULL) {
+    errno = EFAULT;
+    return -1;
+  }
+  
+  f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }  
+
+  if (__exe_fs.max_failures && *__exe_fs.read_fail == n_calls) {
+    __exe_fs.max_failures--;
+    errno = EIO;
+    return -1;
+  }
+  
+  if (!f->dfile) {
+    /* concrete file */
+    int r;
+    buf = __concretize_ptr(buf);
+    count = __concretize_size(count);
+    /* XXX In terms of looking for bugs we really should do this check
+       before concretization, at least once the routine has been fixed
+       to properly work with symbolics. */
+    klee_check_memory_access(buf, count);
+    if (f->fd == 0)
+      r = syscall(__NR_read, f->fd, buf, count);
+    else
+      r = syscall(__NR_pread64, f->fd, buf, count, (off64_t) f->off);
+
+    if (r == -1) {
+      errno = klee_get_errno();
+      return -1;
+    }
+    
+    if (f->fd != 0)
+      f->off += r;
+    return r;
+  }
+  else {
+    assert(f->off >= 0);
+    if (f->dfile->size < f->off)
+      return 0;
+
+    /* symbolic file */
+    if (f->off + count > f->dfile->size) {
+      count = f->dfile->size - f->off;
+    }
+    
+    memcpy(buf, f->dfile->contents + f->off, count);
+    f->off += count;
+    
+    return count;
+  }
+}
+
+
+ssize_t write(int fd, const void *buf, size_t count) {
+  static int n_calls = 0;
+  exe_file_t *f;
+
+  n_calls++;
+
+  f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+
+  if (__exe_fs.max_failures && *__exe_fs.write_fail == n_calls) {
+    __exe_fs.max_failures--;
+    errno = EIO;
+    return -1;
+  }
+
+  if (!f->dfile) {
+    int r;
+
+    buf = __concretize_ptr(buf);
+    count = __concretize_size(count);
+    /* XXX In terms of looking for bugs we really should do this check
+       before concretization, at least once the routine has been fixed
+       to properly work with symbolics. */
+    klee_check_memory_access(buf, count);
+    if (f->fd == 1 || f->fd == 2)
+      r = syscall(__NR_write, f->fd, buf, count);
+    else r = syscall(__NR_pwrite64, f->fd, buf, count, (off64_t) f->off);
+    
+    if (r == -1) {
+      errno = klee_get_errno();
+      return -1;
+    }
+    
+    assert(r >= 0);
+    if (f->fd != 1 && f->fd != 2)
+      f->off += r;
+
+    return r;
+  }
+  else {
+    /* symbolic file */    
+    size_t actual_count = 0;
+    if (f->off + count <= f->dfile->size)
+      actual_count = count;
+    else {
+      if (__exe_env.save_all_writes)
+	assert(0);
+      else {
+	if (f->off < f->dfile->size)
+	  actual_count = f->dfile->size - f->off;	
+      }
+    }
+    
+    if (actual_count)
+      memcpy(f->dfile->contents + f->off, buf, actual_count);
+    
+    if (count != actual_count)
+      fprintf(stderr, "WARNING: write() ignores bytes.\n");
+
+    if (f->dfile == __exe_fs.sym_stdout)
+      __exe_fs.stdout_writes += actual_count;
+
+    f->off += count;
+    return count;
+  }
+}
+
+
+off64_t __fd_lseek(int fd, off64_t offset, int whence) {
+  off64_t new_off;
+  exe_file_t *f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+
+  if (!f->dfile) {
+    /* We could always do SEEK_SET then whence, but this causes
+       troubles with directories since we play nasty tricks with the
+       offset, and the OS doesn't want us to randomly seek
+       directories. We could detect if it is a directory and correct
+       the offset, but really directories should only be SEEK_SET, so
+       this solves the problem. */
+    if (whence == SEEK_SET) {
+      new_off = syscall(__NR_lseek, f->fd, (int) offset, SEEK_SET);
+    } else {
+      new_off = syscall(__NR_lseek, f->fd, (int) f->off, SEEK_SET);
+
+      /* If we can't seek to start off, just return same error.
+         Probably ESPIPE. */
+      if (new_off != -1) {
+        assert(new_off == f->off);
+        new_off = syscall(__NR_lseek, f->fd, (int) offset, whence);
+      }
+    }
+
+    if (new_off == -1) {
+      errno = klee_get_errno();
+      return -1;
+    }
+
+    f->off = new_off;
+    return new_off;
+  }
+  
+  switch (whence) {
+  case SEEK_SET: new_off = offset; break;
+  case SEEK_CUR: new_off = f->off + offset; break;
+  case SEEK_END: new_off = f->dfile->size + offset; break;
+  default: {
+    errno = EINVAL;
+    return (off64_t) -1;
+  }
+  }
+
+  if (new_off < 0) {
+    errno = EINVAL;
+    return (off64_t) -1;
+  }
+    
+  f->off = new_off;
+  return f->off;
+}
+
+int __fd_stat(const char *path, struct stat64 *buf) {  
+  exe_disk_file_t *dfile = __get_sym_file(path);
+  if (dfile) {
+    memcpy(buf, dfile->stat, sizeof(*dfile->stat));
+    return 0;
+  } 
+
+  {
+    int r = syscall(__NR_stat64, __concretize_string(path), buf);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int __fd_lstat(const char *path, struct stat64 *buf) {
+  exe_disk_file_t *dfile = __get_sym_file(path);
+  if (dfile) {
+    memcpy(buf, dfile->stat, sizeof(*dfile->stat));
+    return 0;
+  } 
+
+  {    
+    int r = syscall(__NR_lstat64, __concretize_string(path), buf);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int chdir(const char *path) {
+  exe_disk_file_t *dfile = __get_sym_file(path);
+
+  if (dfile) {
+    /* XXX incorrect */
+    klee_warning("symbolic file, ignoring (ENOENT)");
+    errno = ENOENT;
+    return -1;
+  }
+
+  {
+    int r = syscall(__NR_chdir, __concretize_string(path));
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int fchdir(int fd) {
+  exe_file_t *f = __get_file(fd);
+  
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+
+  if (f->dfile) {
+    klee_warning("symbolic file, ignoring (ENOENT)");
+    errno = ENOENT;
+    return -1;
+  } else {
+    int r = syscall(__NR_fchdir, f->fd);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+/* Sets mode and or errno and return appropriate result. */
+static int __df_chmod(exe_disk_file_t *df, mode_t mode) {
+  if (geteuid() == df->stat->st_uid) {
+    if (getgid() != df->stat->st_gid)
+      mode &= ~ S_ISGID;
+    df->stat->st_mode = ((df->stat->st_mode & ~07777) | 
+                         (mode & 07777));
+    return 0;
+  } else {
+    errno = EPERM;
+    return -1;
+  }
+}
+
+int chmod(const char *path, mode_t mode) {
+  static int n_calls = 0;
+
+  exe_disk_file_t *dfile = __get_sym_file(path);
+
+  n_calls++;
+  if (__exe_fs.max_failures && *__exe_fs.chmod_fail == n_calls) {
+    __exe_fs.max_failures--;
+    errno = EIO;
+    return -1;
+  }
+
+  if (dfile) {
+    return __df_chmod(dfile, mode);
+  } else {
+    int r = syscall(__NR_chmod, __concretize_string(path), mode);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int fchmod(int fd, mode_t mode) {
+  static int n_calls = 0;
+
+  exe_file_t *f = __get_file(fd);
+  
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+
+  n_calls++;
+  if (__exe_fs.max_failures && *__exe_fs.fchmod_fail == n_calls) {
+    __exe_fs.max_failures--;
+    errno = EIO;
+    return -1;
+  }
+
+  if (f->dfile) {
+    return __df_chmod(f->dfile, mode);
+  } else {
+    int r = syscall(__NR_fchmod, f->fd, mode);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }  
+}
+
+static int __df_chown(exe_disk_file_t *df, uid_t owner, gid_t group) {
+  klee_warning("symbolic file, ignoring (EPERM)");
+  errno = EPERM;
+  return -1;  
+}
+
+int chown(const char *path, uid_t owner, gid_t group) {
+  exe_disk_file_t *df = __get_sym_file(path);
+
+  if (df) {
+    return __df_chown(df, owner, group);
+  } else {
+    int r = syscall(__NR_chown, __concretize_string(path), owner, group);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int fchown(int fd, uid_t owner, gid_t group) {
+  exe_file_t *f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+
+  if (f->dfile) {
+    return __df_chown(f->dfile, owner, group);
+  } else {
+    int r = syscall(__NR_fchown, fd, owner, group);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int lchown(const char *path, uid_t owner, gid_t group) {
+  /* XXX Ignores 'l' part */
+  exe_disk_file_t *df = __get_sym_file(path);
+
+  if (df) {
+    return __df_chown(df, owner, group);
+  } else {
+    int r = syscall(__NR_chown, __concretize_string(path), owner, group);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int __fd_fstat(int fd, struct stat64 *buf) {
+  exe_file_t *f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+  
+  if (!f->dfile) {
+    int r = syscall(__NR_fstat64, f->fd, buf);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+  
+  memcpy(buf, f->dfile->stat, sizeof(*f->dfile->stat));
+  return 0;
+}
+
+int __fd_ftruncate(int fd, off64_t length) {
+  static int n_calls = 0;
+  exe_file_t *f = __get_file(fd);
+
+  n_calls++;
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+
+  if (__exe_fs.max_failures && *__exe_fs.ftruncate_fail == n_calls) {
+    __exe_fs.max_failures--;
+    errno = EIO;
+    return -1;
+  }
+  
+  if (f->dfile) {
+    klee_warning("symbolic file, ignoring (EIO)");
+    errno = EIO;
+    return -1;
+  } else {
+    int r = syscall(__NR_ftruncate64, f->fd, length);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }  
+}
+
+int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) {
+  exe_file_t *f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+  
+  if (f->dfile) {
+    klee_warning("symbolic file, ignoring (EINVAL)");
+    errno = EINVAL;
+    return -1;
+  } else {
+    if ((unsigned) f->off < 4096u) {
+      /* Return our dirents */
+      unsigned i, pad, bytes=0;
+
+      /* What happens for bad offsets? */
+      i = f->off / sizeof(*dirp);
+      if ((i * sizeof(*dirp) != f->off) ||
+          i > __exe_fs.n_sym_files) {
+        errno = EINVAL;
+        return -1;
+      } 
+      for (; i<__exe_fs.n_sym_files; ++i) {
+        exe_disk_file_t *df = &__exe_fs.sym_files[i];
+        dirp->d_ino = df->stat->st_ino;
+        dirp->d_reclen = sizeof(*dirp);
+        dirp->d_type = IFTODT(df->stat->st_mode);
+        dirp->d_name[0] = 'A' + i;
+        dirp->d_name[1] = '\0';
+        dirp->d_off = (i+1) * sizeof(*dirp);
+        bytes += dirp->d_reclen;
+        ++dirp;
+      }
+      
+      /* Fake jump to OS records by a "deleted" file. */
+      pad = count>=4096 ? 4096 : count;
+      dirp->d_ino = 0;
+      dirp->d_reclen = pad - bytes;
+      dirp->d_type = DT_UNKNOWN;
+      dirp->d_name[0] = '\0';
+      dirp->d_off = 4096;
+      bytes += dirp->d_reclen;
+      f->off = pad;
+      return bytes;
+    } else {
+      unsigned os_pos = f->off - 4096;
+      int res, s;
+
+      /* For reasons which I really don't understand, if I don't
+         memset this then sometimes the kernel returns d_ino==0 for
+         some valid entries? Am I crazy? Can writeback possibly be
+         failing? 
+      
+         Even more bizarre, interchanging the memset and the seek also
+         case strange behavior. Really should be debugged properly. */
+      memset(dirp, 0, count);
+      s = syscall(__NR_lseek, f->fd, (int) os_pos, SEEK_SET);
+      assert(s != (off64_t) -1);
+      res = syscall(__NR_getdents64, f->fd, dirp, count);
+      if (res == -1) {
+        errno = klee_get_errno();
+      } else {
+        int pos = 0;
+
+        f->off = syscall(__NR_lseek, f->fd, 0, SEEK_CUR) + 4096;
+
+        /* Patch offsets */
+        
+        while (pos < res) {
+          struct dirent64 *dp = (struct dirent64*) ((char*) dirp + pos);
+          dp->d_off += 4096;
+          pos += dp->d_reclen;
+        }
+      }
+      return res;
+    }
+  }
+}
+
+int ioctl(int fd, unsigned long request, ...) {
+  exe_file_t *f = __get_file(fd);
+  va_list ap;
+  void *buf;
+
+#if 0
+  printf("In ioctl(%d, ...)\n", fd);
+#endif
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+  
+  va_start(ap, request);
+  buf = va_arg(ap, void*);
+  va_end(ap);
+  
+  if (f->dfile) {
+    struct stat *stat = (struct stat*) f->dfile->stat;
+
+    switch (request) {
+    case TCGETS: {      
+      struct termios *ts = buf;
+
+      klee_warning_once("(TCGETS) symbolic file, incomplete model");
+
+      /* XXX need more data, this is ok but still not good enough */
+      if (S_ISCHR(stat->st_mode)) {
+        /* Just copied from my system, munged to match what fields
+           uclibc thinks are there. */
+        ts->c_iflag = 27906;
+        ts->c_oflag = 5;
+        ts->c_cflag = 1215;
+        ts->c_lflag = 35287;
+        ts->c_line = 0;
+        ts->c_cc[0] = '\x03';
+        ts->c_cc[1] = '\x1c';
+        ts->c_cc[2] = '\x7f';
+        ts->c_cc[3] = '\x15';
+        ts->c_cc[4] = '\x04';
+        ts->c_cc[5] = '\x00';
+        ts->c_cc[6] = '\x01';
+        ts->c_cc[7] = '\xff';
+        ts->c_cc[8] = '\x11';
+        ts->c_cc[9] = '\x13';
+        ts->c_cc[10] = '\x1a';
+        ts->c_cc[11] = '\xff';
+        ts->c_cc[12] = '\x12';
+        ts->c_cc[13] = '\x0f';
+        ts->c_cc[14] = '\x17';
+        ts->c_cc[15] = '\x16';
+        ts->c_cc[16] = '\xff';
+        ts->c_cc[17] = '\x0';
+        ts->c_cc[18] = '\x0';
+        return 0;
+      } else {
+        errno = ENOTTY;
+        return -1;
+      }
+    }
+    case TCSETS: {
+      /* const struct termios *ts = buf; */
+      klee_warning_once("(TCSETS) symbolic file, silently ignoring");
+      if (S_ISCHR(stat->st_mode)) {
+        return 0;
+      } else {
+        errno = ENOTTY;
+        return -1;
+      }
+    }
+    case TCSETSW: {
+      /* const struct termios *ts = buf; */
+      klee_warning_once("(TCSETSW) symbolic file, silently ignoring");
+      if (fd==0) {
+        return 0;
+      } else {
+        errno = ENOTTY;
+        return -1;
+      }
+    }
+    case TCSETSF: {
+      /* const struct termios *ts = buf; */
+      klee_warning_once("(TCSETSF) symbolic file, silently ignoring");
+      if (S_ISCHR(stat->st_mode)) {        
+        return 0;
+      } else {
+        errno = ENOTTY;
+        return -1;
+      }
+    }
+    case TIOCGWINSZ: {
+      struct winsize *ws = buf;
+      ws->ws_row = 24;
+      ws->ws_col = 80;
+      klee_warning_once("(TIOCGWINSZ) symbolic file, incomplete model");
+      if (S_ISCHR(stat->st_mode)) {
+        return 0;
+      } else {
+        errno = ENOTTY;
+        return -1;
+      }
+    }
+    case TIOCSWINSZ: {
+      /* const struct winsize *ws = buf; */
+      klee_warning_once("(TIOCSWINSZ) symbolic file, ignoring (EINVAL)");
+      if (S_ISCHR(stat->st_mode)) {
+        errno = EINVAL;
+        return -1;
+      } else {
+        errno = ENOTTY;
+        return -1;
+      }
+    }
+    case FIONREAD: {
+      int *res = buf;
+      klee_warning_once("(FIONREAD) symbolic file, incomplete model");
+      if (S_ISCHR(stat->st_mode)) {
+        if (f->off < f->dfile->size) {
+          *res = f->dfile->size - f->off;
+        } else {
+          *res = 0;
+        }
+        return 0;
+      } else {
+        errno = ENOTTY;
+        return -1;
+      }
+    }
+    case MTIOCGET: {
+      klee_warning("(MTIOCGET) symbolic file, ignoring (EINVAL)");
+      errno = EINVAL;
+      return -1;
+    }
+    default:
+      klee_warning("symbolic file, ignoring (EINVAL)");
+      errno = EINVAL;
+      return -1;
+    }
+  } else {
+    int r = syscall(__NR_ioctl, f->fd, request, buf );
+    if (r == -1) 
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int fcntl(int fd, int cmd, ...) {
+  exe_file_t *f = __get_file(fd);
+  va_list ap;
+  unsigned arg; /* 32 bit assumption (int/ptr) */
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+  
+  if (cmd==F_GETFD || cmd==F_GETFL || cmd==F_GETOWN || cmd==F_GETSIG ||
+      cmd==F_GETLEASE || cmd==F_NOTIFY) {
+    arg = 0;
+  } else {
+    va_start(ap, cmd);
+    arg = va_arg(ap, int);
+    va_end(ap);
+  }
+
+  if (f->dfile) {
+    switch(cmd) {
+    case F_GETFD: {
+      int flags = 0;
+      if (f->flags & eCloseOnExec)
+        flags |= FD_CLOEXEC;
+      return flags;
+    } 
+    case F_SETFD: {
+      f->flags &= ~eCloseOnExec;
+      if (arg & FD_CLOEXEC)
+        f->flags |= eCloseOnExec;
+      return 0;
+    }
+    case F_GETFL: {
+      /* XXX (CrC): This should return the status flags: O_APPEND,
+	 O_ASYNC, O_DIRECT, O_NOATIME, O_NONBLOCK.  As of now, we
+	 discard these flags during open().  We should save them and
+	 return them here.  These same flags can be set by F_SETFL,
+	 which we could also handle properly. 
+      */
+      return 0;
+    }
+    default:
+      klee_warning("symbolic file, ignoring (EINVAL)");
+      errno = EINVAL;
+      return -1;
+    }
+  } else {
+    int r = syscall(__NR_fcntl, f->fd, cmd, arg );
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int __fd_statfs(const char *path, struct statfs *buf) {
+  exe_disk_file_t *dfile = __get_sym_file(path);
+  if (dfile) {
+    /* XXX incorrect */
+    klee_warning("symbolic file, ignoring (ENOENT)");
+    errno = ENOENT;
+    return -1;
+  }
+
+  {
+    int r = syscall(__NR_statfs, __concretize_string(path), buf);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int fstatfs(int fd, struct statfs *buf) {
+  exe_file_t *f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  }
+  
+  if (f->dfile) {
+    klee_warning("symbolic file, ignoring (EBADF)");
+    errno = EBADF;
+    return -1;
+  } else {
+    int r = syscall(__NR_fstatfs, f->fd, buf);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int fsync(int fd) {
+  exe_file_t *f = __get_file(fd);
+
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  } else if (f->dfile) {
+    return 0;
+  } else {
+    int r = syscall(__NR_fsync, f->fd);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+int dup2(int oldfd, int newfd) {
+  exe_file_t *f = __get_file(oldfd);
+
+  if (!f || !(newfd>=0 && newfd<MAX_FDS)) {
+    errno = EBADF;
+    return -1;
+  } else {
+    exe_file_t *f2 = &__exe_env.fds[newfd];
+    if (f2->flags & eOpen) close(newfd);
+
+    /* XXX Incorrect, really we need another data structure for open
+       files */
+    *f2 = *f;
+
+    f2->flags &= ~eCloseOnExec;
+      
+    /* I'm not sure it is wise, but we can get away with not dup'ng
+       the OS fd, since actually that will in many cases effect the
+       sharing of the open file (and the process should never have
+       access to it). */
+
+    return newfd;
+  }
+}
+
+int dup(int oldfd) {
+  exe_file_t *f = __get_file(oldfd);
+  if (!f) {
+    errno = EBADF;
+    return -1;
+  } else {
+    int fd;
+    for (fd = 0; fd < MAX_FDS; ++fd)
+      if (!(__exe_env.fds[fd].flags & eOpen))
+        break;
+    if (fd == MAX_FDS) {
+      errno = EMFILE;
+      return -1;
+    } else {
+      return dup2(oldfd, fd);
+    }
+  }
+}
+
+int rmdir(const char *pathname) {
+  exe_disk_file_t *dfile = __get_sym_file(pathname);
+  if (dfile) {
+    /* XXX check access */ 
+    if (S_ISDIR(dfile->stat->st_mode)) {
+      dfile->stat->st_ino = 0;
+      return 0;
+    } else {
+      errno = ENOTDIR;
+      return -1;
+    }
+  }
+
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int unlink(const char *pathname) {
+  exe_disk_file_t *dfile = __get_sym_file(pathname);
+  if (dfile) {
+    /* XXX check access */ 
+    if (S_ISREG(dfile->stat->st_mode)) {
+      dfile->stat->st_ino = 0;
+      return 0;
+    } else if (S_ISDIR(dfile->stat->st_mode)) {
+      errno = EISDIR;
+      return -1;
+    } else {
+      errno = EPERM;
+      return -1;
+    }
+  }
+
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+ssize_t readlink(const char *path, char *buf, size_t bufsize) {
+  exe_disk_file_t *dfile = __get_sym_file(path);
+  if (dfile) {
+    /* XXX We need to get the sym file name really, but since we don't
+       handle paths anyway... */
+    if (S_ISLNK(dfile->stat->st_mode)) {
+      buf[0] = path[0];
+      if (bufsize>1) buf[1] = '.';
+      if (bufsize>2) buf[2] = 'l';
+      if (bufsize>3) buf[3] = 'n';
+      if (bufsize>4) buf[4] = 'k';
+      return (bufsize>5) ? 5 : bufsize;
+    } else {
+      errno = EINVAL;
+      return -1;
+    }
+  } else {
+    int r = syscall(__NR_readlink, path, buf, bufsize);
+    if (r == -1)
+      errno = klee_get_errno();
+    return r;
+  }
+}
+
+#undef FD_SET
+#undef FD_CLR
+#undef FD_ISSET
+#undef FD_ZERO
+#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p)	memset((char *)(p), '\0', sizeof(*(p)))
+int select(int nfds, fd_set *read, fd_set *write,
+           fd_set *except, struct timeval *timeout) {
+  fd_set in_read, in_write, in_except, os_read, os_write, os_except;
+  int i, count = 0, os_nfds = 0;
+
+  if (read) {
+    in_read = *read;
+    FD_ZERO(read);
+  } else {
+    FD_ZERO(&in_read);
+  }
+
+  if (write) {
+    in_write = *write;
+    FD_ZERO(write);
+  } else {
+    FD_ZERO(&in_write);
+  }
+   
+  if (except) {
+    in_except = *except;
+    FD_ZERO(except);
+  } else {
+    FD_ZERO(&in_except);
+  }
+
+  FD_ZERO(&os_read);
+  FD_ZERO(&os_write);
+  FD_ZERO(&os_except);
+
+  /* Check for symbolic stuff */
+  for (i=0; i<nfds; i++) {    
+    if (FD_ISSET(i, &in_read) || FD_ISSET(i, &in_write) || FD_ISSET(i, &in_except)) {
+      exe_file_t *f = __get_file(i);
+      if (!f) {
+        errno = EBADF;
+        return -1;
+      } else if (f->dfile) {
+        /* Operations on this fd will never block... */
+        if (FD_ISSET(i, &in_read)) FD_SET(i, read);
+        if (FD_ISSET(i, &in_write)) FD_SET(i, write);
+        if (FD_ISSET(i, &in_except)) FD_SET(i, except);
+        ++count;
+      } else {
+        if (FD_ISSET(i, &in_read)) FD_SET(f->fd, &os_read);
+        if (FD_ISSET(i, &in_write)) FD_SET(f->fd, &os_write);
+        if (FD_ISSET(i, &in_except)) FD_SET(f->fd, &os_except);
+        if (f->fd >= os_nfds) os_nfds = f->fd + 1;
+      }
+    }
+  }
+
+  if (os_nfds > 0) {
+    /* Never allow blocking select. This is broken but what else can
+       we do. */
+    struct timeval tv = { 0, 0 };    
+    int r = syscall(__NR_select, os_nfds, 
+                    &os_read, &os_write, &os_except, &tv);
+    
+    if (r == -1) {
+      /* If no symbolic results, return error. Otherwise we will
+         silently ignore the OS error. */
+      if (!count) {
+        errno = klee_get_errno();
+        return -1;
+      }
+    } else {
+      count += r;
+
+      /* Translate resulting sets back */
+      for (i=0; i<nfds; i++) {
+        exe_file_t *f = __get_file(i);
+        if (f && !f->dfile) {
+          if (read && FD_ISSET(f->fd, &os_read)) FD_SET(i, read);
+          if (write && FD_ISSET(f->fd, &os_write)) FD_SET(i, write);
+          if (except && FD_ISSET(f->fd, &os_except)) FD_SET(i, except);
+        }
+      }
+    }
+  }
+
+  return count;
+}
+
+/*** Library functions ***/
+
+char *getcwd(char *buf, size_t size) {
+  static int n_calls = 0;
+  int r;
+
+  n_calls++;
+
+  if (__exe_fs.max_failures && *__exe_fs.getcwd_fail == n_calls) {
+    __exe_fs.max_failures--;
+    errno = ERANGE;
+    return NULL;
+  }
+
+  if (!buf) {
+    if (!size)
+      size = 1024;
+    buf = malloc(size);
+  }
+  
+  buf = __concretize_ptr(buf);
+  size = __concretize_size(size);
+  /* XXX In terms of looking for bugs we really should do this check
+     before concretization, at least once the routine has been fixed
+     to properly work with symbolics. */
+  klee_check_memory_access(buf, size);
+  r = syscall(__NR_getcwd, buf, size);
+  if (r == -1) {
+    errno = klee_get_errno();
+    return NULL;
+  }
+    
+  return buf;
+}
+
+/*** Helper functions ***/
+
+static void *__concretize_ptr(const void *p) {
+  /* XXX 32-bit assumption */
+  char *pc = (char*) klee_get_value((unsigned) (long) p);
+  klee_assume(pc == p);
+  return pc;
+}
+
+static size_t __concretize_size(size_t s) {
+  size_t sc = klee_get_value(s);
+  klee_assume(sc == s);
+  return sc;
+}
+
+static const char *__concretize_string(const char *s) {
+  char *sc = __concretize_ptr(s);
+  unsigned i;
+
+  for (i=0; ; ++i) {
+    char c = *sc;
+    if (!(i&(i-1))) {
+      if (!c) {
+        *sc++ = 0;
+        break;
+      } else if (c=='/') {
+        *sc++ = '/';
+      } 
+    } else {
+      char cc = (char) klee_get_value(c);
+      klee_assume(cc == c);
+      *sc++ = cc;
+      if (!cc) break;
+    }
+  }
+
+  return s;
+}
+
+
+
+/* Trivial model:
+   if path is "/" (basically no change) accept, otherwise reject
+*/
+int chroot(const char *path) {
+  if (path[0] == '\0') {
+    errno = ENOENT;
+    return -1;
+  }
+    
+  if (path[0] == '/' && path[1] == '\0') {
+    return 0;
+  }
+  
+  klee_warning("ignoring (ENOENT)");
+  errno = ENOENT;
+  return -1;
+}

Added: klee/trunk/runtime/POSIX/fd.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/fd.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/fd.h (added)
+++ klee/trunk/runtime/POSIX/fd.h Wed May 20 23:36:41 2009
@@ -0,0 +1,90 @@
+//===-- fd.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 __EXE_FD__
+#define __EXE_FD__
+
+#ifndef _LARGEFILE64_SOURCE
+#error "_LARGEFILE64_SOURCE should be defined"
+#endif
+#include <sys/types.h>
+#include <sys/statfs.h>
+#include <dirent.h>
+
+typedef struct {  
+  unsigned size;  /* in bytes */
+  char* contents;
+  struct stat64* stat;
+} exe_disk_file_t;
+
+typedef enum {
+  eOpen         = (1 << 0),
+  eCloseOnExec  = (1 << 1),
+  eReadable     = (1 << 2),
+  eWriteable    = (1 << 3)
+} exe_file_flag_t;
+
+typedef struct {      
+  int fd;                   /* actual fd if not symbolic */
+  unsigned flags;           /* set of exe_file_flag_t values. fields
+                               are only defined when flags at least
+                               has eOpen. */
+  off64_t off;              /* offset */
+  exe_disk_file_t* dfile;   /* ptr to file on disk, if symbolic */
+} exe_file_t;
+
+typedef struct {
+  unsigned n_sym_files; /* number of symbolic input files, excluding stdin */
+  exe_disk_file_t *sym_stdin, *sym_stdout;
+  unsigned stdout_writes; /* how many chars were written to stdout */
+  exe_disk_file_t *sym_files;
+  /* --- */
+  /* the maximum number of failures on one path; gets decremented after each failure */
+  unsigned max_failures; 
+
+  /* Which read, write etc. call should fail */
+  int *read_fail, *write_fail, *close_fail, *ftruncate_fail, *getcwd_fail;
+  int *chmod_fail, *fchmod_fail;
+} exe_file_system_t;
+
+#define MAX_FDS 32
+
+/* Note, if you change this structure be sure to update the
+   initialization code if necessary. New fields should almost
+   certainly be at the end. */
+typedef struct {
+  exe_file_t fds[MAX_FDS];
+  mode_t umask; /* process umask */
+  unsigned version;
+  /* If set, writes execute as expected.  Otherwise, writes extending
+     the file size only change the contents up to the initial
+     size. The file offset is always incremented correctly. */
+  int save_all_writes; 
+} exe_sym_env_t;
+
+extern exe_file_system_t __exe_fs;
+extern exe_sym_env_t __exe_env;
+
+void klee_init_fds(unsigned n_files, unsigned file_length, 
+		   int sym_stdout_flag, int do_all_writes_flag, 
+		   unsigned max_failures);
+void klee_init_env(int *argcPtr, char ***argvPtr);
+
+/* *** */
+
+int __fd_open(const char *pathname, int flags, mode_t mode);
+off64_t __fd_lseek(int fd, off64_t offset, int whence);
+int __fd_stat(const char *path, struct stat64 *buf);
+int __fd_lstat(const char *path, struct stat64 *buf);
+int __fd_fstat(int fd, struct stat64 *buf);
+int __fd_ftruncate(int fd, off64_t length);
+int __fd_statfs(const char *path, struct statfs *buf);
+int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count);
+
+#endif /* __EXE_FD__ */

Added: klee/trunk/runtime/POSIX/fd_32.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/fd_32.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/fd_32.c (added)
+++ klee/trunk/runtime/POSIX/fd_32.c Wed May 20 23:36:41 2009
@@ -0,0 +1,196 @@
+//===-- fd_32.c -----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define _LARGEFILE64_SOURCE
+#include "fd.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/vfs.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <unistd.h>
+#include <dirent.h>
+
+/***/
+
+static void __stat64_to_stat(struct stat64 *a, struct stat *b) {
+  b->st_dev = a->st_dev;
+  b->st_ino = a->st_ino;
+  b->st_mode = a->st_mode;
+  b->st_nlink = a->st_nlink;
+  b->st_uid = a->st_uid;
+  b->st_gid = a->st_gid;
+  b->st_rdev = a->st_rdev;
+  b->st_size = a->st_size;
+  b->st_atime = a->st_atime;
+  b->st_mtime = a->st_mtime;
+  b->st_ctime = a->st_ctime;
+  b->st_blksize = a->st_blksize;
+  b->st_blocks = a->st_blocks;
+}
+
+/***/
+
+int open(const char *pathname, int flags, ...) {
+  mode_t mode = 0;
+
+  if (flags & O_CREAT) {
+    /* get mode */
+    va_list ap;
+    va_start(ap, flags);
+    mode = va_arg(ap, mode_t);
+    va_end(ap);
+  }
+
+  return __fd_open(pathname, flags, mode);
+}
+
+off_t lseek(int fd, off_t off, int whence) {
+  return (off_t) __fd_lseek(fd, off, whence);
+}
+
+int __xstat(int vers, const char *path, struct stat *buf) {
+  struct stat64 tmp;
+  int res = __fd_stat(path, &tmp);
+  __stat64_to_stat(&tmp, buf);
+  return res;
+}
+
+int stat(const char *path, struct stat *buf) {
+  struct stat64 tmp;
+  int res = __fd_stat(path, &tmp);
+  __stat64_to_stat(&tmp, buf);
+  return res;
+}
+
+int __lxstat(int vers, const char *path, struct stat *buf) {
+  struct stat64 tmp;
+  int res = __fd_lstat(path, &tmp);
+  __stat64_to_stat(&tmp, buf);
+  return res;
+}
+
+int lstat(const char *path, struct stat *buf) {
+  struct stat64 tmp;
+  int res = __fd_lstat(path, &tmp);
+  __stat64_to_stat(&tmp, buf);
+  return res;
+}
+
+int __fxstat(int vers, int fd, struct stat *buf) {
+  struct stat64 tmp;
+  int res = __fd_fstat(fd, &tmp);
+  __stat64_to_stat(&tmp, buf);
+  return res;
+}
+
+int fstat(int fd, struct stat *buf) {
+  struct stat64 tmp;
+  int res = __fd_fstat(fd, &tmp);
+  __stat64_to_stat(&tmp, buf);
+  return res;
+}
+
+int ftruncate(int fd, off_t length) {
+  return __fd_ftruncate(fd, length);
+}
+
+int statfs(const char *path, struct statfs *buf32) {
+#if 0
+    struct statfs64 buf;
+
+    if (__fd_statfs(path, &buf) < 0)
+	return -1;
+
+    buf32->f_type = buf.f_type;
+    buf32->f_bsize = buf.f_bsize;
+    buf32->f_blocks = buf.f_blocks;
+    buf32->f_bfree = buf.f_bfree;
+    buf32->f_bavail = buf.f_bavail;
+    buf32->f_files = buf.f_files;
+    buf32->f_ffree = buf.f_ffree;
+    buf32->f_fsid = buf.f_fsid;
+    buf32->f_namelen = buf.f_namelen;
+
+    return 0;
+#else
+    return __fd_statfs(path, buf32);
+#endif
+}
+
+/* Based on uclibc version. We use getdents64 and then rewrite the
+   results over themselves, as dirent32s. */
+ssize_t getdents(int fd, struct dirent *dirp, size_t nbytes) {
+  struct dirent64 *dp64 = (struct dirent64*) dirp;
+  ssize_t res = __fd_getdents(fd, dp64, nbytes);
+
+  if (res>0) {
+    struct dirent64 *end = (struct dirent64*) ((char*) dp64 + res);
+    while (dp64 < end) {
+      struct dirent *dp = (struct dirent *) dp64;
+      unsigned name_len = (dp64->d_reclen - 
+                           (unsigned) &((struct dirent64*) 0)->d_name);
+      dp->d_ino = dp64->d_ino;
+      dp->d_off = dp64->d_off;
+      dp->d_reclen = dp64->d_reclen;
+      dp->d_type = dp64->d_type;
+      memmove(dp->d_name, dp64->d_name, name_len);
+      dp64 = (struct dirent64*) ((char*) dp64 + dp->d_reclen);
+    }
+  }
+
+  return res;
+}
+int __getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
+     __attribute__((alias("getdents")));
+
+/* Forward to 64 versions (uclibc expects versions w/o asm specifier) */
+
+int open64(const char *pathname, int flags, ...) __attribute__((weak));
+int open64(const char *pathname, int flags, ...) {
+  mode_t mode = 0;
+
+  if (flags & O_CREAT) {
+    /* get mode */
+    va_list ap;
+    va_start(ap, flags);
+    mode = va_arg(ap, mode_t);
+    va_end(ap);
+  }
+
+  return __fd_open(pathname, flags, mode);
+}
+
+off64_t lseek64(int fd, off64_t off, int whence) __attribute__((weak));
+off64_t lseek64(int fd, off64_t off, int whence) {
+  return __fd_lseek(fd, off, whence);
+}
+
+int stat64(const char *path, struct stat64 *buf) __attribute__((weak));
+int stat64(const char *path, struct stat64 *buf) {
+  return __fd_stat(path, buf);
+}
+
+int lstat64(const char *path, struct stat64 *buf) __attribute__((weak));
+int lstat64(const char *path, struct stat64 *buf) {
+  return __fd_lstat(path, buf);
+}
+
+int fstat64(int fd, struct stat64 *buf) __attribute__((weak));
+int fstat64(int fd, struct stat64 *buf) {
+  return __fd_fstat(fd, buf);
+}

Added: klee/trunk/runtime/POSIX/fd_64.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/fd_64.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/fd_64.c (added)
+++ klee/trunk/runtime/POSIX/fd_64.c Wed May 20 23:36:41 2009
@@ -0,0 +1,90 @@
+//===-- fd_64.c -----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
+#include "fd.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <termios.h>
+#include <sys/select.h>
+#include <klee/klee.h>
+
+/*** Forward to actual implementations ***/
+
+int open(const char *pathname, int flags, ...) {
+  mode_t mode = 0;
+  
+  if (flags & O_CREAT) {
+    /* get mode */
+    va_list ap;
+    va_start(ap, flags);
+    mode = va_arg(ap, mode_t);
+    va_end(ap);
+  }
+
+  return __fd_open(pathname, flags, mode);
+}
+
+off64_t lseek(int fd, off64_t offset, int whence) {
+  return __fd_lseek(fd, offset, whence);
+}
+
+int __xstat(int vers, const char *path, struct stat *buf) {
+  return __fd_stat(path, (struct stat64*) buf);
+}
+
+int stat(const char *path, struct stat *buf) {
+  return __fd_stat(path, (struct stat64*) buf);
+}
+
+int __lxstat(int vers, const char *path, struct stat *buf) {
+  return __fd_lstat(path, (struct stat64*) buf);
+}
+
+int lstat(const char *path, struct stat *buf) {
+  return __fd_lstat(path, (struct stat64*) buf);
+}
+
+int __fxstat(int vers, int fd, struct stat *buf) {
+  return __fd_fstat(fd, (struct stat64*) buf);
+}
+
+int fstat(int fd, struct stat *buf) {
+  return __fd_fstat(fd, (struct stat64*) buf);
+}
+
+int ftruncate64(int fd, off64_t length) {
+  return __fd_ftruncate(fd, length);
+}
+
+int statfs(const char *path, struct statfs *buf) __attribute__((weak));
+int statfs(const char *path, struct statfs *buf) {
+  return __fd_statfs(path, buf);
+}
+
+int getdents64(unsigned int fd, struct dirent *dirp, unsigned int count) {
+  return __fd_getdents(fd, (struct dirent64*) dirp, count);
+}
+int __getdents64(unsigned int fd, struct dirent *dirp, unsigned int count)
+     __attribute__((alias("getdents64")));

Added: klee/trunk/runtime/POSIX/fd_init.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/fd_init.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/fd_init.c (added)
+++ klee/trunk/runtime/POSIX/fd_init.c Wed May 20 23:36:41 2009
@@ -0,0 +1,161 @@
+//===-- fd_init.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
+#include "fd.h"
+#include <klee/klee.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+
+exe_file_system_t __exe_fs;
+
+/* NOTE: It is important that these are statically initialized
+   correctly, since things that run before main may hit them given the
+   current way things are linked. */
+
+/* XXX Technically these flags are initialized w.o.r. to the
+   environment we are actually running in. We could patch them in
+   klee_init_fds, but we still have the problem that uclibc calls
+   prior to main will get the wrong data. Not such a big deal since we
+   mostly care about sym case anyway. */
+
+
+exe_sym_env_t __exe_env = { 
+  {{ 0, eOpen | eReadable, 0, 0}, 
+   { 1, eOpen | eWriteable, 0, 0}, 
+   { 2, eOpen | eWriteable, 0, 0}},
+  022,
+  0,
+  0
+};
+
+static void __create_new_dfile(exe_disk_file_t *dfile, unsigned size, 
+                               const char *name, struct stat64 *defaults) {
+  struct stat64 *s = malloc(sizeof(*s));
+  const char *sp;
+  char sname[64];
+  for (sp=name; *sp; ++sp)
+    sname[sp-name] = *sp;
+  memcpy(&sname[sp-name], "-stat", 6);
+
+  assert(size);
+
+  dfile->size = size;
+  dfile->contents = malloc(dfile->size);
+  klee_make_symbolic_name(dfile->contents, dfile->size, name);
+  
+  klee_make_symbolic_name(s, sizeof(*s), sname);
+
+  /* For broken tests */
+  if (!klee_is_symbolic(s->st_ino) && 
+      (s->st_ino & 0x7FFFFFFF) == 0)
+    s->st_ino = defaults->st_ino;
+  
+  /* Important since we copy this out through getdents, and readdir
+     will otherwise skip this entry. For same reason need to make sure
+     it fits in low bits. */
+  klee_assume((s->st_ino & 0x7FFFFFFF) != 0);
+
+  /* uclibc opendir uses this as its buffer size, try to keep
+     reasonable. */
+  klee_assume((s->st_blksize & ~0xFFFF) == 0);
+
+  klee_prefer_cex(s, !(s->st_mode & ~(S_IFMT | 0777)));
+  klee_prefer_cex(s, s->st_dev == defaults->st_dev);
+  klee_prefer_cex(s, s->st_rdev == defaults->st_rdev);
+  klee_prefer_cex(s, (s->st_mode&0700) == 0600);
+  klee_prefer_cex(s, (s->st_mode&0070) == 0020);
+  klee_prefer_cex(s, (s->st_mode&0007) == 0002);
+  klee_prefer_cex(s, (s->st_mode&S_IFMT) == S_IFREG);
+  klee_prefer_cex(s, s->st_nlink == 1);
+  klee_prefer_cex(s, s->st_uid == defaults->st_uid);
+  klee_prefer_cex(s, s->st_gid == defaults->st_gid);
+  klee_prefer_cex(s, s->st_blksize == 4096);
+  klee_prefer_cex(s, s->st_atime == defaults->st_atime);
+  klee_prefer_cex(s, s->st_mtime == defaults->st_mtime);
+  klee_prefer_cex(s, s->st_ctime == defaults->st_ctime);
+
+  s->st_size = dfile->size;
+  s->st_blocks = 8;
+  dfile->stat = s;
+}
+
+static unsigned __sym_uint32(const char *name) {
+  unsigned x;
+  klee_make_symbolic_name(&x, sizeof x, name);
+  return x;
+}
+
+/* n_files: number of symbolic input files, excluding stdin
+   file_length: size in bytes of each symbolic file, including stdin
+   sym_stdout_flag: 1 if stdout should be symbolic, 0 otherwise
+   save_all_writes_flag: 1 if all writes are executed as expected, 0 if 
+                         writes past the initial file size are discarded 
+			 (file offset is always incremented)
+   max_failures: maximum number of system call failures */
+void klee_init_fds(unsigned n_files, unsigned file_length, 
+		   int sym_stdout_flag, int save_all_writes_flag,
+		   unsigned max_failures) {
+  unsigned k;
+  char name[7] = "?-data";
+  struct stat64 s;
+
+  stat64(".", &s);
+
+  __exe_fs.n_sym_files = n_files;
+  __exe_fs.sym_files = malloc(sizeof(*__exe_fs.sym_files) * n_files);
+  for (k=0; k < n_files; k++) {
+    name[0] = 'A' + k;
+    __create_new_dfile(&__exe_fs.sym_files[k], file_length, name, &s);
+  }
+  
+  /* setting symbolic stdin */
+  if (file_length) {
+    __exe_fs.sym_stdin = malloc(sizeof(*__exe_fs.sym_stdin));
+    __create_new_dfile(__exe_fs.sym_stdin, file_length, "stdin", &s);
+    __exe_env.fds[0].dfile = __exe_fs.sym_stdin;
+  }
+  else __exe_fs.sym_stdin = NULL;
+
+  __exe_fs.max_failures = max_failures;
+  if (__exe_fs.max_failures) {
+    __exe_fs.read_fail = malloc(sizeof(*__exe_fs.read_fail));
+    __exe_fs.write_fail = malloc(sizeof(*__exe_fs.write_fail));
+    __exe_fs.close_fail = malloc(sizeof(*__exe_fs.close_fail));
+    __exe_fs.ftruncate_fail = malloc(sizeof(*__exe_fs.ftruncate_fail));
+    __exe_fs.getcwd_fail = malloc(sizeof(*__exe_fs.getcwd_fail));
+
+    klee_make_symbolic_name(__exe_fs.read_fail, sizeof(*__exe_fs.read_fail), "read_fail");
+    klee_make_symbolic_name(__exe_fs.write_fail, sizeof(*__exe_fs.write_fail), "write_fail");
+    klee_make_symbolic_name(__exe_fs.close_fail, sizeof(*__exe_fs.close_fail), "close_fail");
+    klee_make_symbolic_name(__exe_fs.ftruncate_fail, sizeof(*__exe_fs.ftruncate_fail), "ftruncate_fail");
+    klee_make_symbolic_name(__exe_fs.getcwd_fail, sizeof(*__exe_fs.getcwd_fail), "getcwd_fail");
+  }
+
+  /* setting symbolic stdout */
+  if (sym_stdout_flag) {
+    __exe_fs.sym_stdout = malloc(sizeof(*__exe_fs.sym_stdout));
+    __create_new_dfile(__exe_fs.sym_stdout, 1024, "stdout", &s);
+    __exe_env.fds[1].dfile = __exe_fs.sym_stdout;
+    __exe_fs.stdout_writes = 0;
+  }
+  else __exe_fs.sym_stdout = NULL;
+  
+  __exe_env.save_all_writes = save_all_writes_flag;
+  __exe_env.version = __sym_uint32("model_version");
+  klee_assume(__exe_env.version == 1);
+}

Added: klee/trunk/runtime/POSIX/illegal.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/illegal.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/illegal.c (added)
+++ klee/trunk/runtime/POSIX/illegal.c Wed May 20 23:36:41 2009
@@ -0,0 +1,70 @@
+//===-- illegal.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+
+#include <klee/klee.h>
+
+void klee_warning(const char*);
+void klee_warning_once(const char*);
+
+int kill(pid_t pid, int sig) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int _setjmp (struct __jmp_buf_tag __env[1]) __attribute__((weak));
+int _setjmp (struct __jmp_buf_tag __env[1]) {
+  klee_warning_once("ignoring");
+  return 0;
+}
+
+void longjmp(jmp_buf env, int val) {
+  klee_report_error(__FILE__, __LINE__, "longjmp unsupported", "xxx.err");
+}
+
+/* Macro so function name from klee_warning comes out correct. */
+#define __bad_exec() \
+  (klee_warning("ignoring (EACCES)"),\
+   errno = EACCES,\
+   -1)
+
+/* This need to be weak because uclibc wants to define them as well,
+   but we will want to make sure a definition is around in case we
+   don't link with it. */
+
+int execl(const char *path, const char *arg, ...) __attribute__((weak));
+int execlp(const char *file, const char *arg, ...) __attribute__((weak));
+int execle(const char *path, const char *arg, ...) __attribute__((weak));
+int execv(const char *path, char *const argv[]) __attribute__((weak));
+int execvp(const char *file, char *const argv[]) __attribute__((weak));
+int execve(const char *file, char *const argv[], char *const envp[]) __attribute__((weak));
+
+int execl(const char *path, const char *arg, ...) { return __bad_exec(); }
+int execlp(const char *file, const char *arg, ...) { return __bad_exec(); }
+int execle(const char *path, const char *arg, ...)  { return __bad_exec(); }
+int execv(const char *path, char *const argv[]) { return __bad_exec(); }
+int execvp(const char *file, char *const argv[]) { return __bad_exec(); }
+int execve(const char *file, char *const argv[], char *const envp[]) { return __bad_exec(); }
+
+pid_t fork(void) {
+  klee_warning("ignoring (ENOMEM)");
+  errno = ENOMEM;
+  return -1;
+}
+
+pid_t vfork(void) {
+  return fork();
+}

Added: klee/trunk/runtime/POSIX/klee_init_env.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/klee_init_env.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/klee_init_env.c (added)
+++ klee/trunk/runtime/POSIX/klee_init_env.c Wed May 20 23:36:41 2009
@@ -0,0 +1,181 @@
+//===-- klee_init_env.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/klee.h"
+#define _LARGEFILE64_SOURCE
+#include "fd.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+static void __emit_error(const char *msg) {
+  klee_report_error(__FILE__, __LINE__, msg, "user.err");
+}
+
+/* Helper function that converts a string to an integer, and
+   terminates the program with an error message is the string is not a
+   proper number */   
+static long int __str_to_int(char *s, const char *error_msg) {
+  long int res = 0;
+  char c;
+
+  if (!*s) __emit_error(error_msg);
+
+  while ((c = *s++)) {
+    if (c == '\0') {
+      break;
+    } else if (c>='0' && c<='9') {
+      res = res*10 + (c - '0');
+    } else {
+      __emit_error(error_msg);
+    }
+  }
+  return res;
+}
+
+static int __isprint(const char c) {
+  /* Assume ASCII */
+  return (32 <= c && c <= 126);
+}
+
+static int __streq(const char *a, const char *b) {
+  while (*a == *b) {
+    if (!*a)
+      return 1;
+    a++;
+    b++;
+  }
+  return 0;
+}
+
+static char *__get_sym_str(int numChars, char *name) {
+  int i;
+  char *s = malloc(numChars+1);
+  klee_mark_global(s);
+  klee_make_symbolic_name(s, numChars+1, name);
+
+  for (i=0; i<numChars; i++)
+    klee_prefer_cex(s, __isprint(s[i]));
+  
+  s[numChars] = '\0';
+  return s;
+}
+
+static void __add_arg(int *argc, char **argv, char *arg, int argcMax) {
+  if (*argc==argcMax) {
+    __emit_error("too many arguments for klee_init_env");
+  } else {
+    argv[*argc] = arg;
+    (*argc)++;
+  }
+}
+
+void klee_init_env(int* argcPtr, char*** argvPtr) {
+  int argc = *argcPtr;
+  char** argv = *argvPtr;
+
+  int new_argc = 0, n_args;
+  char* new_argv[1024];
+  unsigned max_len, min_argvs, max_argvs;
+  unsigned sym_files = 0, sym_file_len = 0;
+  int sym_stdout_flag = 0;
+  int save_all_writes_flag = 0;
+  int fd_fail = 0;
+  char** final_argv;
+  char sym_arg_name[5] = "arg";
+  unsigned sym_arg_num = 0;
+  int k=0, i;
+
+  sym_arg_name[4] = '\0';
+
+  while (k < argc) {
+    if (__streq(argv[k], "--sym-arg") || __streq(argv[k], "-sym-arg")) {
+      const char *msg = "--sym-arg expects an integer argument <max-len>";
+      if (++k == argc)        
+	__emit_error(msg);
+		
+      max_len = __str_to_int(argv[k++], msg);
+      sym_arg_name[3] = '0' + sym_arg_num++;
+      __add_arg(&new_argc, new_argv, 
+                __get_sym_str(max_len, sym_arg_name),
+                1024);
+    }
+    else if (__streq(argv[k], "--sym-args") || __streq(argv[k], "-sym-args")) {
+      const char *msg = 
+        "--sym-args expects three integer arguments <min-argvs> <max-argvs> <max-len>";
+
+      if (k+3 >= argc)
+	__emit_error(msg);
+      
+      k++;
+      min_argvs = __str_to_int(argv[k++], msg);
+      max_argvs = __str_to_int(argv[k++], msg);
+      max_len = __str_to_int(argv[k++], msg);
+
+      n_args = klee_range(min_argvs, max_argvs+1, "n_args");
+      for (i=0; i < n_args; i++) {
+        sym_arg_name[3] = '0' + sym_arg_num++;
+        __add_arg(&new_argc, new_argv, 
+                  __get_sym_str(max_len, sym_arg_name),
+                  1024);
+      }
+    }
+    else if (__streq(argv[k], "--sym-files") || __streq(argv[k], "-sym-files")) {
+      const char* msg = "--sym-files expects two integer arguments <no-sym-files> <sym-file-len>";      
+
+      if (k+2 >= argc)
+	__emit_error(msg);
+      
+      k++;
+      sym_files = __str_to_int(argv[k++], msg);
+      sym_file_len = __str_to_int(argv[k++], msg);
+
+    }
+    else if (__streq(argv[k], "--sym-stdout") || __streq(argv[k], "-sym-stdout")) {
+      sym_stdout_flag = 1;
+      k++;
+    }
+    else if (__streq(argv[k], "--save-all-writes") || __streq(argv[k], "-save-all-writes")) {
+      save_all_writes_flag = 1;
+      k++;
+    }
+    else if (__streq(argv[k], "--fd-fail") || __streq(argv[k], "-fd-fail")) {
+      fd_fail = 1;
+      k++;
+    }
+    else if (__streq(argv[k], "--max-fail") || __streq(argv[k], "-max-fail")) {
+      const char *msg = "--max-fail expects an integer argument <max-failures>";
+      if (++k == argc)
+	__emit_error(msg);
+		
+      fd_fail = __str_to_int(argv[k++], msg);
+    }
+    else {
+      /* simply copy arguments */
+      __add_arg(&new_argc, new_argv, argv[k++], 1024);
+    }
+  }
+
+  final_argv = (char**) malloc((new_argc+1) * sizeof(*final_argv));
+  klee_mark_global(final_argv);
+  memcpy(final_argv, new_argv, new_argc * sizeof(*final_argv));
+  final_argv[new_argc] = 0;
+
+  *argcPtr = new_argc;
+  *argvPtr = final_argv;
+
+  klee_init_fds(sym_files, sym_file_len, 
+		sym_stdout_flag, save_all_writes_flag, 
+		fd_fail);
+}
+

Added: klee/trunk/runtime/POSIX/misc.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/misc.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/misc.c (added)
+++ klee/trunk/runtime/POSIX/misc.c Wed May 20 23:36:41 2009
@@ -0,0 +1,87 @@
+//===-- misc.c ------------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <klee/klee.h>
+#include <string.h>
+
+#if 0
+#define MAX_SYM_ENV_SIZE 32
+typedef struct {
+  char name[MAX_SYM_ENV_SIZE];
+  char *value;
+} sym_env_var;
+
+static sym_env_var *__klee_sym_env = 0;
+static unsigned __klee_sym_env_count = 0;
+static unsigned __klee_sym_env_nvars = 0;
+static unsigned __klee_sym_env_var_size = 0;
+void __klee_init_environ(unsigned nvars, 
+                         unsigned var_size) {
+  assert(var_size);
+  __klee_sym_env = malloc(sizeof(*__klee_sym_env) * nvars);
+  assert(__klee_sym_env);
+
+  __klee_sym_env_nvars = nvars;
+  __klee_sym_env_var_size = var_size;  
+}
+
+static unsigned __strlen(const char *s) {
+  const char *s2 = s;
+  while (*s2) ++s2;
+  return s2-s;
+}
+
+extern char *__getenv(const char *name);
+char *getenv(const char *name) {
+  char *res = __getenv(name);
+
+  if (!__klee_sym_env_nvars)
+    return res;
+
+  /* If it exists in the system environment fork and return the actual
+     result or 0. */
+  if (res) {
+    return klee_range(0, 2, name) ? res : 0;
+  } else {
+    unsigned i, len = __strlen(name);
+
+    if (len>=MAX_SYM_ENV_SIZE) {
+      /* Don't deal with strings to large to fit in our name. */
+      return 0;
+    } else {
+      /* Check for existing entry */
+      for (i=0; i<__klee_sym_env_count; ++i)
+        if (memcmp(__klee_sym_env[i].name, name, len+1)==0)
+          return __klee_sym_env[i].value;
+      
+      /* Otherwise create if room and we choose to */
+      if (__klee_sym_env_count < __klee_sym_env_nvars) {
+        if (klee_range(0, 2, name)) {
+          char *s = malloc(__klee_sym_env_var_size+1);
+          klee_make_symbolic(s, __klee_sym_env_var_size+1);
+          s[__klee_sym_env_var_size] = '\0';
+          
+          memcpy(__klee_sym_env[__klee_sym_env_count].name, name, len+1);
+          __klee_sym_env[__klee_sym_env_count].value = s;
+          ++__klee_sym_env_count;
+          
+          return s;
+        }
+      }
+      
+      return 0;
+    }
+  }
+}
+#endif

Added: klee/trunk/runtime/POSIX/selinux.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/selinux.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/selinux.c (added)
+++ klee/trunk/runtime/POSIX/selinux.c Wed May 20 23:36:41 2009
@@ -0,0 +1,80 @@
+//===-- selinux.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+/* Very basic SELinux support */
+
+#include "klee/Config/config.h"
+
+#ifdef HAVE_SELINUX_SELINUX_H
+
+#include "klee/klee.h"
+
+#include <selinux/selinux.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* for now, assume we run on an SELinux machine */
+int exe_selinux = 1;
+
+/* NULL is the default policy behavior */
+security_context_t create_con = NULL;
+
+
+int is_selinux_enabled() {
+  return exe_selinux;
+}
+
+
+/***/
+
+int getfscreatecon(security_context_t *context) {
+  *context = create_con;
+  return 0;
+}
+
+
+int setfscreatecon(security_context_t context) {
+  if (context == NULL) {
+    create_con = context;
+    return 0;
+  }
+
+  /* on my machine, setfscreatecon seems to incorrectly accept one
+     char strings.. Also, make sure mcstrans > 0.2.8 for replay 
+     (important bug fixed) */
+  if (context[0] != '\0' && context[1] == '\0')
+    klee_silent_exit(1);
+
+  return -1;
+}
+
+/***/
+
+int setfilecon(const char *path, security_context_t con) {
+  if (con)
+    return 0;
+  
+  errno = ENOSPC;
+  return -1;  
+}
+
+int lsetfilecon(const char *path, security_context_t con) {
+  return setfilecon(path, con);
+}
+
+int fsetfilecon(int fd, security_context_t con) {
+  return setfilecon("", con);
+}
+
+/***/
+
+void freecon(security_context_t con) {}
+void freeconary(security_context_t *con) {}
+
+#endif

Added: klee/trunk/runtime/POSIX/stubs.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/stubs.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/stubs.c (added)
+++ klee/trunk/runtime/POSIX/stubs.c Wed May 20 23:36:41 2009
@@ -0,0 +1,560 @@
+//===-- stubs.c -----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <utime.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "klee/Config/config.h"
+
+void klee_warning(const char*);
+void klee_warning_once(const char*);
+
+/* Silent ignore */
+
+int __syscall_rt_sigaction(int signum, const struct sigaction *act, 
+                           struct sigaction *oldact, size_t _something)
+     __attribute__((weak));
+
+int __syscall_rt_sigaction(int signum, const struct sigaction *act, 
+                           struct sigaction *oldact, size_t _something) {
+  klee_warning_once("silently ignoring");
+  return 0;
+}
+
+int sigaction(int signum, const struct sigaction *act, 
+              struct sigaction *oldact) __attribute__((weak));
+
+int sigaction(int signum, const struct sigaction *act, 
+              struct sigaction *oldact) {
+  klee_warning_once("silently ignoring");
+  return 0;
+}
+
+int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
+     __attribute__((weak));
+int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
+  klee_warning_once("silently ignoring");
+  return 0;
+}
+
+/* Not even worth warning about these */
+int fdatasync(int fd) __attribute__((weak));
+int fdatasync(int fd) {
+  return 0;
+}
+
+/* Not even worth warning about this */
+void sync(void) __attribute__((weak));
+void sync(void) {
+}
+
+/* Error ignore */
+
+extern int __fgetc_unlocked(FILE *f);
+extern int __fputc_unlocked(int c, FILE *f);
+
+int __socketcall(int type, int *args) __attribute__((weak));
+int __socketcall(int type, int *args) {
+  klee_warning("ignoring (EAFNOSUPPORT)");
+  errno = EAFNOSUPPORT;
+  return -1;
+}
+
+int _IO_getc(FILE *f) __attribute__((weak));
+int _IO_getc(FILE *f) {
+  return __fgetc_unlocked(f);
+}
+
+int _IO_putc(int c, FILE *f) __attribute__((weak));
+int _IO_putc(int c, FILE *f) {
+  return __fputc_unlocked(c, f);
+}
+
+int mkdir(const char *pathname, mode_t mode) __attribute__((weak));
+int mkdir(const char *pathname, mode_t mode) {
+  klee_warning("ignoring (EIO)");
+  errno = EIO;
+  return -1;
+}
+
+int mkfifo(const char *pathname, mode_t mode) __attribute__((weak));
+int mkfifo(const char *pathname, mode_t mode) {
+  klee_warning("ignoring (EIO)");
+  errno = EIO;
+  return -1;
+}
+
+int mknod(const char *pathname, mode_t mode, dev_t dev) __attribute__((weak));
+int mknod(const char *pathname, mode_t mode, dev_t dev) {
+  klee_warning("ignoring (EIO)");
+  errno = EIO;
+  return -1;
+}
+
+int pipe(int filedes[2]) __attribute__((weak));
+int pipe(int filedes[2]) {
+  klee_warning("ignoring (ENFILE)");
+  errno = ENFILE;
+  return -1;
+}
+
+int link(const char *oldpath, const char *newpath) __attribute__((weak));
+int link(const char *oldpath, const char *newpath) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;  
+}
+
+int symlink(const char *oldpath, const char *newpath) __attribute__((weak));
+int symlink(const char *oldpath, const char *newpath) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;  
+}
+
+int rename(const char *oldpath, const char *newpath) __attribute__((weak));
+int rename(const char *oldpath, const char *newpath) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;  
+}
+
+int nanosleep(const struct timespec *req, struct timespec *rem) __attribute__((weak));
+int nanosleep(const struct timespec *req, struct timespec *rem) {
+  return 0;
+}
+
+/* XXX why can't I call this internally? */
+int clock_gettime(clockid_t clk_id, struct timespec *res) __attribute__((weak));
+int clock_gettime(clockid_t clk_id, struct timespec *res) {
+  /* Fake */
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  res->tv_sec = tv.tv_sec;
+  res->tv_nsec = tv.tv_usec * 1000;
+  return 0;
+}
+
+int clock_settime(clockid_t clk_id, const struct timespec *res) __attribute__((weak));
+int clock_settime(clockid_t clk_id, const struct timespec *res) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+time_t time(time_t *t) {
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  if (t)
+    *t = tv.tv_sec;
+  return tv.tv_sec;
+}
+
+clock_t times(struct tms *buf) {
+  /* Fake */
+  buf->tms_utime = 0;
+  buf->tms_stime = 0;
+  buf->tms_cutime = 0;
+  buf->tms_cstime = 0;
+  return 0;
+}
+
+struct utmpx *getutxent(void) __attribute__((weak));
+struct utmpx *getutxent(void) {
+  return (struct utmpx*) getutent();
+}
+
+void setutxent(void) __attribute__((weak));
+void setutxent(void) {
+  setutent();
+}
+
+void endutxent(void) __attribute__((weak));
+void endutxent(void) {
+  endutent();
+}
+
+int utmpxname(const char *file) __attribute__((weak));
+int utmpxname(const char *file) {
+  utmpname(file);
+  return 0;
+}
+
+int euidaccess(const char *pathname, int mode) __attribute__((weak));
+int euidaccess(const char *pathname, int mode) {
+  return access(pathname, mode);
+}
+
+int eaccess(const char *pathname, int mode) __attribute__((weak));
+int eaccess(const char *pathname, int mode) {
+  return euidaccess(pathname, mode);
+}
+
+int group_member (gid_t __gid) __attribute__((weak));
+int group_member (gid_t __gid) {
+  return ((__gid == getgid ()) || (__gid == getegid ()));
+}
+
+int utime(const char *filename, const struct utimbuf *buf) __attribute__((weak));
+int utime(const char *filename, const struct utimbuf *buf) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int utimes(const char *filename, const struct timeval times[2]) __attribute__((weak));
+int utimes(const char *filename, const struct timeval times[2]) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int futimes(int fd, const struct timeval times[2]) __attribute__((weak));
+int futimes(int fd, const struct timeval times[2]) {
+  klee_warning("ignoring (EBADF)");
+  errno = EBADF;
+  return -1;
+}
+
+int strverscmp (__const char *__s1, __const char *__s2) {
+  return strcmp(__s1, __s2); /* XXX no doubt this is bad */
+}
+
+unsigned int gnu_dev_major(unsigned long long int __dev) __attribute__((weak));
+unsigned int gnu_dev_major(unsigned long long int __dev) {
+  return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff);
+}
+
+unsigned int gnu_dev_minor(unsigned long long int __dev) __attribute__((weak));
+unsigned int gnu_dev_minor(unsigned long long int __dev) {
+  return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff);
+}
+
+unsigned long long int gnu_dev_makedev(unsigned int __major, unsigned int __minor) __attribute__((weak));
+unsigned long long int gnu_dev_makedev(unsigned int __major, unsigned int __minor) {
+  return ((__minor & 0xff) | ((__major & 0xfff) << 8)
+	  | (((unsigned long long int) (__minor & ~0xff)) << 12)
+	  | (((unsigned long long int) (__major & ~0xfff)) << 32));
+}
+
+char *canonicalize_file_name (const char *name) __attribute__((weak));
+char *canonicalize_file_name (const char *name) {
+  char *res = malloc(PATH_MAX);
+  char *rp_res = realpath(name, res);
+  if (!rp_res)
+    free(res);
+  return rp_res;
+}
+
+int getloadavg(double loadavg[], int nelem) __attribute__((weak));
+int getloadavg(double loadavg[], int nelem) {
+  klee_warning("ignoring (-1 result)");
+  return -1;
+}
+
+pid_t wait(int *status) __attribute__((weak));
+pid_t wait(int *status) {
+  klee_warning("ignoring (ECHILD)");
+  errno = ECHILD;
+  return -1;
+}
+
+pid_t wait3(int *status, int options, struct rusage *rusage) __attribute__((weak));
+pid_t wait3(int *status, int options, struct rusage *rusage) {
+  klee_warning("ignoring (ECHILD)");
+  errno = ECHILD;
+  return -1;
+}
+
+pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) __attribute__((weak));
+pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) {
+  klee_warning("ignoring (ECHILD)");
+  errno = ECHILD;
+  return -1;
+}
+
+pid_t waitpid(pid_t pid, int *status, int options) __attribute__((weak));
+pid_t waitpid(pid_t pid, int *status, int options) {
+  klee_warning("ignoring (ECHILD)");
+  errno = ECHILD;
+  return -1;
+}
+
+pid_t waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) __attribute__((weak));
+pid_t waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) {
+  klee_warning("ignoring (ECHILD)");
+  errno = ECHILD;
+  return -1;
+}
+
+/* ACL */
+
+/* FIXME: We need autoconf magic for this. */
+
+#ifdef HAVE_SYS_ACL_H
+
+#include <sys/acl.h>
+
+int acl_delete_def_file(const char *path_p) __attribute__((weak));
+int acl_delete_def_file(const char *path_p) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int acl_extended_file(const char path_p) __attribute__((weak));
+int acl_extended_file(const char path_p) {
+  klee_warning("ignoring (ENOENT)");
+  errno = ENOENT;
+  return -1;
+}
+
+int acl_entries(acl_t acl) __attribute__((weak));
+int acl_entries(acl_t acl) {
+  klee_warning("ignoring (EINVAL)");
+  errno = EINVAL;
+  return -1;
+}
+
+acl_t acl_from_mode(mode_t mode) __attribute__((weak));
+acl_t acl_from_mode(mode_t mode) {
+  klee_warning("ignoring (ENOMEM)");
+  errno = ENOMEM;
+  return NULL;
+}
+
+acl_t acl_get_fd(int fd) __attribute__((weak));
+acl_t acl_get_fd(int fd) {
+  klee_warning("ignoring (ENOMEM)");
+  errno = ENOMEM;
+  return NULL;
+}
+
+acl_t acl_get_file(const char *pathname, acl_type_t type) __attribute__((weak));
+acl_t acl_get_file(const char *pathname, acl_type_t type) {
+  klee_warning("ignoring (ENONMEM)");
+  errno = ENOMEM;
+  return NULL;
+}
+
+int acl_set_fd(int fd, acl_t acl) __attribute__((weak));
+int acl_set_fd(int fd, acl_t acl) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int acl_set_file(const char *path_p, acl_type_t type, acl_t acl) __attribute__((weak));
+int acl_set_file(const char *path_p, acl_type_t type, acl_t acl) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int acl_free(void *obj_p) __attribute__((weak));
+int acl_free(void *obj_p) {
+  klee_warning("ignoring (EINVAL)");
+  errno = EINVAL;
+  return -1;
+}
+
+#endif
+
+int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) __attribute__((weak));
+int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int umount(const char *target) __attribute__((weak));
+int umount(const char *target) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int umount2(const char *target, int flags) __attribute__((weak));
+int umount2(const char *target, int flags) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int swapon(const char *path, int swapflags) __attribute__((weak));
+int swapon(const char *path, int swapflags) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int swapoff(const char *path) __attribute__((weak));
+int swapoff(const char *path) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setgid(gid_t gid) __attribute__((weak));
+int setgid(gid_t gid) {
+  klee_warning("silently ignoring (returning 0)");
+  return 0;
+}
+
+int setgroups(size_t size, const gid_t *list) __attribute__((weak));
+int setgroups(size_t size, const gid_t *list) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int sethostname(const char *name, size_t len) __attribute__((weak));
+int sethostname(const char *name, size_t len) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setpgid(pid_t pid, pid_t pgid) __attribute__((weak));
+int setpgid(pid_t pid, pid_t pgid) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setpgrp(void) __attribute__((weak));
+int setpgrp(void) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setpriority(__priority_which_t which, id_t who, int prio) __attribute__((weak));
+int setpriority(__priority_which_t which, id_t who, int prio) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setresgid(gid_t rgid, gid_t egid, gid_t sgid) __attribute__((weak));
+int setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setresuid(uid_t ruid, uid_t euid, uid_t suid) __attribute__((weak));
+int setresuid(uid_t ruid, uid_t euid, uid_t suid) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlim) __attribute__((weak));
+int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlim) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setrlimit64(__rlimit_resource_t resource, const struct rlimit64 *rlim) __attribute__((weak));
+int setrlimit64(__rlimit_resource_t resource, const struct rlimit64 *rlim) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+pid_t setsid(void) __attribute__((weak));
+pid_t setsid(void) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int settimeofday(const struct timeval *tv, const struct timezone *tz) __attribute__((weak));
+int settimeofday(const struct timeval *tv, const struct timezone *tz) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int setuid(uid_t uid) __attribute__((weak));
+int setuid(uid_t uid) {
+  klee_warning("silently ignoring (returning 0)");
+  return 0;
+}
+
+int reboot(int flag) __attribute__((weak));
+int reboot(int flag) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int mlock(const void *addr, size_t len) __attribute__((weak));
+int mlock(const void *addr, size_t len) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int munlock(const void *addr, size_t len) __attribute__((weak));
+int munlock(const void *addr, size_t len) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+int pause(void) __attribute__((weak));
+int pause(void) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+ssize_t readahead(int fd, off64_t *offset, size_t count) __attribute__((weak));
+ssize_t readahead(int fd, off64_t *offset, size_t count) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) __attribute__((weak));
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return (void*) -1;
+}
+
+void *mmap64(void *start, size_t length, int prot, int flags, int fd, off64_t offset) __attribute__((weak));
+void *mmap64(void *start, size_t length, int prot, int flags, int fd, off64_t offset) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return (void*) -1;
+}
+
+int munmap(void*start, size_t length) __attribute__((weak));
+int munmap(void*start, size_t length) {
+  klee_warning("ignoring (EPERM)");
+  errno = EPERM;
+  return -1;
+}

Added: klee/trunk/runtime/POSIX/testing-dir/a
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/testing-dir/a?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/testing-dir/a (added)
+++ klee/trunk/runtime/POSIX/testing-dir/a Wed May 20 23:36:41 2009
@@ -0,0 +1 @@
+link /dev/null
\ No newline at end of file

Propchange: klee/trunk/runtime/POSIX/testing-dir/a

------------------------------------------------------------------------------
    svn:special = *

Added: klee/trunk/runtime/POSIX/testing-dir/b
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/testing-dir/b?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/testing-dir/b (added)
+++ klee/trunk/runtime/POSIX/testing-dir/b Wed May 20 23:36:41 2009
@@ -0,0 +1 @@
+link /dev/random
\ No newline at end of file

Propchange: klee/trunk/runtime/POSIX/testing-dir/b

------------------------------------------------------------------------------
    svn:special = *

Added: klee/trunk/runtime/POSIX/testing-dir/c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/testing-dir/c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/testing-dir/c (added)
+++ klee/trunk/runtime/POSIX/testing-dir/c Wed May 20 23:36:41 2009
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo "Hello world!"

Propchange: klee/trunk/runtime/POSIX/testing-dir/c

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/runtime/POSIX/testing-dir/d
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/testing-dir/d?rev=72205&view=auto

==============================================================================
    (empty)

Added: klee/trunk/runtime/POSIX/testing-env
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/POSIX/testing-env?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/POSIX/testing-env (added)
+++ klee/trunk/runtime/POSIX/testing-env Wed May 20 23:36:41 2009
@@ -0,0 +1,27 @@
+# This file is sourced prior to running the testing environment, make
+# sure to quote things.
+
+export TERM="xterm"
+export SHELL="/bin/bash"
+export LS_COLORS="no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.flac=01;35:*.mp3=01;35:*.mpc=01;35:*.ogg=01;35:*.wav=01;35:"
+export PATH="/usr/local/bin:/usr/bin:/bin"
+export COLORTERM="gnome-terminal"
+export LC_ALL=C
+export TABSIZE=8
+export COLUMNS=80
+
+#       1 BLOCK_SIZE
+#       2 COLUMNS
+#       1 DF_BLOCK_SIZE
+#       1 DU_BLOCK_SIZE
+#       1 HOME
+#       1 LS_BLOCK_SIZE
+#       1 LS_COLORS
+#      11 POSIXLY_CORRECT
+#       1 QUOTING_STYLE
+#       3 SHELL
+#       4 SIMPLE_BACKUP_SUFFIX
+#       1 TABSIZE
+#       2 TERM
+#       2 TIME_STYLE
+#       4 TMPDIR

Added: klee/trunk/runtime/Runtest/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Runtest/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Runtest/Makefile (added)
+++ klee/trunk/runtime/Runtest/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+#===-- runtime/Runtest/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=../..
+
+USEDLIBS=kleeBasic.a
+LIBRARYNAME=kleeRuntest
+SHARED_LIBRARY=1
+LINK_LIBS_IN_SHARED = 1
+DONT_BUILD_RELINKED = 1
+NO_PEDANTIC=1
+
+include $(LEVEL)/Makefile.common

Added: klee/trunk/runtime/Runtest/intrinsics.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/Runtest/intrinsics.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/Runtest/intrinsics.c (added)
+++ klee/trunk/runtime/Runtest/intrinsics.c Wed May 20 23:36:41 2009
@@ -0,0 +1,154 @@
+//===-- intrinsics.c ------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+/* Straight C for linking simplicity */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "klee/klee.h"
+
+#include "klee/Internal/ADT/BOut.h"
+
+static BOut *testData = 0;
+static unsigned testPosition = 0;
+
+static unsigned char rand_byte(void) {
+  unsigned x = rand();
+  x ^= x>>16;
+  x ^= x>>8;
+  return x & 0xFF;
+}
+
+void klee_make_symbolic_name(void *array, unsigned nbytes, const char *name) {
+  static int rand_init = -1;
+
+  if (rand_init == -1) {
+    if (getenv("KLEE_RANDOM")) {
+      struct timeval tv;
+      gettimeofday(&tv, 0);
+      rand_init = 1;
+      srand(tv.tv_sec ^ tv.tv_usec);
+    } else {
+      rand_init = 0;
+    }
+  }
+
+  if (rand_init) {
+    if (!strcmp(name,"syscall_a0")) {
+      unsigned long long *v = array;
+      assert(nbytes == 8);
+      *v = rand() % 69;
+    } else {
+      char *c = array;
+      unsigned i;
+      for (i=0; i<nbytes; i++)
+        c[i] = rand_byte();
+    }
+    return;
+  }
+
+  if (!testData) {
+    char tmp[256];
+    char *name = getenv("KLEE_RUNTEST");
+
+    if (!name) {
+      fprintf(stdout, "KLEE-RUNTIME: KLEE_RUNTEST not set, please enter .bout path: ");
+      fflush(stdout);
+      name = tmp;
+      if (!fgets(tmp, sizeof tmp, stdin) || !strlen(tmp)) {
+        fprintf(stderr, "KLEE-RUNTIME: cannot replay, no KLEE_RUNTEST or user input\n");
+        exit(1);
+      }
+      tmp[strlen(tmp)-1] = '\0'; /* kill newline */
+    }
+    testData = bOut_fromFile(name);
+    if (!testData) {
+      fprintf(stderr, "KLEE-RUNTIME: unable to open .bout file\n");
+      exit(1);
+    }
+  }
+
+  if (testPosition >= testData->numObjects) {
+    fprintf(stderr, "ERROR: out of inputs, using zero\n");
+    memset(array, 0, nbytes);
+  } else {
+    BOutObject *o = &testData->objects[testPosition++];
+    memcpy(array, o->bytes, nbytes<o->numBytes ? nbytes : o->numBytes);
+    if (nbytes != o->numBytes) {
+      fprintf(stderr, "ERROR: object sizes differ\n");
+      if (o->numBytes < nbytes) 
+        memset((char*) array + o->numBytes, 0, nbytes - o->numBytes);
+    }
+  }
+}
+
+void klee_make_symbolic(void *array, unsigned nbytes) {
+  klee_make_symbolic_name(array, nbytes, "unnamed");
+}
+
+void *klee_malloc_n(unsigned nelems, unsigned size, unsigned alignment) {
+#if 1
+  return mmap((void*) 0x90000000, nelems*size, PROT_READ|PROT_WRITE, 
+              MAP_PRIVATE
+#ifdef MAP_ANONYMOUS
+              |MAP_ANONYMOUS
+#endif
+              , 0, 0);
+#else
+  char *buffer = malloc(nelems*size + alignment - 1);
+  buffer += (alignment - (long)buffer % alignment);
+  return buffer;
+#endif
+}
+
+void klee_silent_exit(int x) {
+  exit(x);
+}
+
+unsigned klee_choose(unsigned n) {
+  unsigned x;
+  klee_make_symbolic(&x, sizeof x);
+  if(x >= n)
+    fprintf(stderr, "ERROR: max = %d, got = %d\n", n, x);
+  assert(x < n);
+  return x;
+}
+
+void klee_assume(unsigned x) {
+  if (!x) {
+    fprintf(stderr, "ERROR: invalid klee_assume\n");
+  }
+}
+
+unsigned klee_get_value(unsigned x) {
+  return x;
+}
+
+int klee_range_name(int begin, int end, const char* name) {
+  int x;
+  klee_make_symbolic_name(&x, sizeof x, name);
+  if (x<begin || x>=end) {
+    fprintf(stderr, 
+            "KLEE: ERROR: invalid klee_range(%u,%u,%s) value, got: %u\n", 
+            begin, end, name, x);
+    abort();
+  }
+  return x;
+}
+
+/* not sure we should even define.  is for debugging. */
+void klee_print_expr(const char *msg, ...) { }
+
+void klee_set_forking(unsigned enable) { }

Added: klee/trunk/runtime/klee-libc/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/Makefile (added)
+++ klee/trunk/runtime/klee-libc/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+#===-- runtime/klee-libc/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=klee-libc
+DONT_BUILD_RELINKED=1
+BYTECODE_LIBRARY=1
+# Don't strip debug info from the module.
+DEBUG_RUNTIME=1
+NO_PEDANTIC=1
+
+include $(LEVEL)/Makefile.common

Propchange: klee/trunk/runtime/klee-libc/Makefile

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/runtime/klee-libc/__cxa_atexit.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/__cxa_atexit.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/__cxa_atexit.c (added)
+++ klee/trunk/runtime/klee-libc/__cxa_atexit.c Wed May 20 23:36:41 2009
@@ -0,0 +1,49 @@
+//===-- __cxa_atexit.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/klee.h"
+
+#define MAX_ATEXIT 128
+
+static struct {
+  void (*fn)(void*);
+  void *arg;
+  void *dso_handle;
+} AtExit[MAX_ATEXIT];
+static unsigned NumAtExit = 0;
+
+static void RunAtExit(void) __attribute__((destructor));
+static void RunAtExit(void) {
+  unsigned i;
+
+  for (i=0; i<NumAtExit; ++i)
+    AtExit[i].fn(AtExit[i].arg);
+}
+
+int __cxa_atexit(void (*fn)(void*),
+                 void *arg,
+                 void *dso_handle) {
+  klee_warning_once("FIXME: __cxa_atexit being ignored");
+  
+  /* Better to just report an error here than return 1 (the defined
+   * semantics).
+   */
+  if (NumAtExit == MAX_ATEXIT)
+    klee_report_error(__FILE__,
+                      __LINE__,
+                      "__cxa_atexit: no room in array!",
+                      "exec");
+  
+  AtExit[NumAtExit].fn = fn;
+  AtExit[NumAtExit].arg = arg;
+  ++NumAtExit;
+  
+  return 0;
+}
+

Added: klee/trunk/runtime/klee-libc/abort.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/abort.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/abort.c (added)
+++ klee/trunk/runtime/klee-libc/abort.c Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+//===-- abort.c -----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+#include "klee/klee.h"
+
+void abort(void) {
+  klee_abort();
+}

Added: klee/trunk/runtime/klee-libc/atexit.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/atexit.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/atexit.c (added)
+++ klee/trunk/runtime/klee-libc/atexit.c Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+//===-- atexit.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int __cxa_atexit(void (*fn)(void*),
+                 void *arg,
+                 void *dso_handle);
+
+int atexit(void (*fn)(void)) {
+  return __cxa_atexit((void(*)(void*)) fn, 0, 0);
+}

Added: klee/trunk/runtime/klee-libc/atoi.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/atoi.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/atoi.c (added)
+++ klee/trunk/runtime/klee-libc/atoi.c Wed May 20 23:36:41 2009
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <stdlib.h>
+
+int atoi(const char *str) {
+  return (int)strtol(str, (char **)NULL, 10);
+}

Added: klee/trunk/runtime/klee-libc/calloc.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/calloc.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/calloc.c (added)
+++ klee/trunk/runtime/klee-libc/calloc.c Wed May 20 23:36:41 2009
@@ -0,0 +1,46 @@
+//===-- calloc.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+#include <string.h>
+
+// DWD - I prefer to be internal
+#if 0
+void *calloc(size_t nmemb, size_t size) {
+	unsigned nbytes = nmemb * size;
+	void *addr = malloc(nbytes);
+	if(addr)
+		memset(addr, 0, nbytes);
+	return addr;
+}
+// Always reallocate.
+void *realloc(void *ptr, size_t nbytes) {
+	if(!ptr)
+		return malloc(nbytes);
+
+	if(!nbytes) {
+		free(ptr);
+		return 0;
+	}
+
+        unsigned copy_nbytes = klee_get_obj_size(ptr);
+	//printf("REALLOC: current object = %d bytes!\n", copy_nbytes);
+
+	void *addr = malloc(nbytes);
+	if(addr) {
+		// shrinking
+		if(copy_nbytes > nbytes)
+			copy_nbytes = nbytes;
+		//printf("REALLOC: copying = %d bytes!\n", copy_nbytes);
+		memcpy(addr, ptr, copy_nbytes);
+		free(ptr);
+	} 
+	return addr;
+}
+#endif

Added: klee/trunk/runtime/klee-libc/htonl.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/htonl.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/htonl.c (added)
+++ klee/trunk/runtime/klee-libc/htonl.c Wed May 20 23:36:41 2009
@@ -0,0 +1,49 @@
+//===-- htonl.c -----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdint.h>
+
+#undef htons
+#undef htonl
+#undef ntohs
+#undef ntohl
+
+// Make sure we can recognize the endianness.
+#if (!defined(BYTE_ORDER) || !defined(BIG_ENDIAN) || !defined(LITTLE_ENDIAN))
+#error "Unknown platform endianness!"
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+uint16_t htons(uint16_t v) {
+  return (v >> 8) | (v << 8);
+}
+uint32_t htonl(uint32_t v) {
+  return htons(v >> 16) | (htons((uint16_t) v) << 16);
+}
+
+#else
+
+uint16_t htons(uint16_t v) {
+  return v;
+}
+uint32_t htonl(uint32_t v) {
+  return v;
+}
+
+#endif
+
+uint16_t ntohs(uint32_t v) {
+  return htons(v);
+}
+uint32_t ntohl(uint32_t v) {
+  return htonl(v);
+}

Added: klee/trunk/runtime/klee-libc/klee-choose.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/klee-choose.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/klee-choose.c (added)
+++ klee/trunk/runtime/klee-libc/klee-choose.c Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+//===-- klee-choose.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/klee.h"
+
+unsigned klee_choose(unsigned n) {
+  unsigned x;
+  klee_make_symbolic(&x, sizeof x);
+
+  // NB: this will *not* work if they don't compare to n values.
+  if(x >= n)
+    klee_silent_exit(0);
+  return x;
+}

Added: klee/trunk/runtime/klee-libc/memchr.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/memchr.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/memchr.c (added)
+++ klee/trunk/runtime/klee-libc/memchr.c Wed May 20 23:36:41 2009
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+void *
+memchr(s, c, n)
+	const void *s;
+	int c;
+	size_t n;
+{
+	if (n != 0) {
+		const unsigned char *p = s;
+
+		do {
+			if (*p++ == c)
+				return ((void *)(p - 1));
+		} while (--n != 0);
+	}
+	return (NULL);
+}

Added: klee/trunk/runtime/klee-libc/memcmp.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/memcmp.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/memcmp.c (added)
+++ klee/trunk/runtime/klee-libc/memcmp.c Wed May 20 23:36:41 2009
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+/*
+ * Compare memory regions.
+ */
+int memcmp(const void *s1, const void *s2, size_t n) {
+  if (n != 0) {
+    const unsigned char *p1 = s1, *p2 = s2;
+    
+    do {
+      if (*p1++ != *p2++) {
+        return (*--p1 - *--p2);
+      }
+    } while (--n != 0);
+  }
+  return (0);
+}

Added: klee/trunk/runtime/klee-libc/memcpy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/memcpy.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/memcpy.c (added)
+++ klee/trunk/runtime/klee-libc/memcpy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+//===-- memcpy.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *memcpy(void *destaddr, void const *srcaddr, unsigned int len) {
+  char *dest = destaddr;
+  char const *src = srcaddr;
+
+  while (len-- > 0)
+    *dest++ = *src++;
+  return destaddr;
+}

Added: klee/trunk/runtime/klee-libc/memmove.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/memmove.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/memmove.c (added)
+++ klee/trunk/runtime/klee-libc/memmove.c Wed May 20 23:36:41 2009
@@ -0,0 +1,28 @@
+//===-- memmove.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *memmove(void *dst, const void *src, size_t count) {
+  char *a = dst;
+  const char *b = src;
+
+  if (src == dst)
+    return dst;
+
+  if (src>dst) {
+    while (count--) *a++ = *b++;
+  } else {
+    a+=count-1;
+    b+=count-1;
+    while (count--) *a-- = *b--;
+  }
+
+  return dst;
+}

Added: klee/trunk/runtime/klee-libc/mempcpy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/mempcpy.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/mempcpy.c (added)
+++ klee/trunk/runtime/klee-libc/mempcpy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+//===-- mempcpy.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *mempcpy(void *destaddr, void const *srcaddr, unsigned int len) {
+  char *dest = destaddr;
+  char const *src = srcaddr;
+
+  while (len-- > 0)
+    *dest++ = *src++;
+  return dest;
+}

Added: klee/trunk/runtime/klee-libc/memset.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/memset.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/memset.c (added)
+++ klee/trunk/runtime/klee-libc/memset.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+//===-- memset.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+void *memset(void * dst, int s, size_t count) {
+    char * a = dst;
+    while (count-- > 0)
+      *a++ = s;
+    return dst;
+}

Added: klee/trunk/runtime/klee-libc/putchar.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/putchar.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/putchar.c (added)
+++ klee/trunk/runtime/klee-libc/putchar.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+//===-- putchar.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#include <unistd.h>
+
+int putchar(int c) {
+  char x = c;
+  write(1, &x, 1);
+  return 1;
+}

Added: klee/trunk/runtime/klee-libc/stpcpy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/stpcpy.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/stpcpy.c (added)
+++ klee/trunk/runtime/klee-libc/stpcpy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1999
+ *	David E. O'Brien
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+/* Defeat object checking stuff. */
+#undef stpcpy
+
+char *
+stpcpy(char * to, const char * from)
+{
+
+	for (; (*to = *from); ++from, ++to);
+	return(to);
+}

Added: klee/trunk/runtime/klee-libc/strcat.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strcat.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strcat.c (added)
+++ klee/trunk/runtime/klee-libc/strcat.c Wed May 20 23:36:41 2009
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+/* Defeat object checking stuff. */
+#undef strcat
+
+char * strcat(char * s, const char * append) {
+	char *save = s;
+
+	for (; *s; ++s)
+		;
+	while ((*s++ = *append++))
+		;
+	return(save);
+}

Added: klee/trunk/runtime/klee-libc/strchr.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strchr.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strchr.c (added)
+++ klee/trunk/runtime/klee-libc/strchr.c Wed May 20 23:36:41 2009
@@ -0,0 +1,23 @@
+//===-- strchr.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+char *strchr(const char *p, int ch) {
+  char c;
+
+  c = ch;
+  for (;; ++p) {
+    if (*p == c) {
+      return ((char *)p);
+    } else if (*p == '\0') {
+      return 0;
+    }
+  }
+  /* NOTREACHED */  
+  return 0;
+}

Added: klee/trunk/runtime/klee-libc/strcmp.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strcmp.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strcmp.c (added)
+++ klee/trunk/runtime/klee-libc/strcmp.c Wed May 20 23:36:41 2009
@@ -0,0 +1,14 @@
+//===-- strcmp.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int strcmp(const char *a, const char *b) {
+  while (*a && *a == *b)
+    ++a, ++b;
+  return *a - *b;
+}

Added: klee/trunk/runtime/klee-libc/strcoll.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strcoll.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strcoll.c (added)
+++ klee/trunk/runtime/klee-libc/strcoll.c Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+//===-- strcoll.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+// according to the manpage, this is equiv in the POSIX/C locale.
+int strcoll(const char *s1, const char *s2) {
+  return strcmp(s1,s2);
+}

Added: klee/trunk/runtime/klee-libc/strcpy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strcpy.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strcpy.c (added)
+++ klee/trunk/runtime/klee-libc/strcpy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+//===-- strcpy.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+char *strcpy(char *to, const char *from) {
+  char *start = to;
+
+  while ((*to = *from))
+    ++to, ++from;
+
+  return start;
+}

Added: klee/trunk/runtime/klee-libc/strlen.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strlen.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strlen.c (added)
+++ klee/trunk/runtime/klee-libc/strlen.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+//===-- strlen.c ----------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+size_t strlen(const char *str) {
+  const char *s = str;
+  while (*s)
+    ++s;
+  return s - str;
+}

Added: klee/trunk/runtime/klee-libc/strncmp.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strncmp.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strncmp.c (added)
+++ klee/trunk/runtime/klee-libc/strncmp.c Wed May 20 23:36:41 2009
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+
+	if (n == 0)
+		return (0);
+	do {
+		if (*s1 != *s2++)
+			return (*(unsigned char *)s1 -
+				*(unsigned char *)(s2 - 1));
+		if (*s1++ == 0)
+			break;
+	} while (--n != 0);
+	return (0);
+}

Added: klee/trunk/runtime/klee-libc/strncpy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strncpy.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strncpy.c (added)
+++ klee/trunk/runtime/klee-libc/strncpy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+/*
+ * Copy src to dst, truncating or null-padding to always copy n bytes.
+ * Return dst.
+ */
+char * strncpy(char * dst, const char * src, size_t n)
+{
+	if (n != 0) {
+		char *d = dst;
+		const char *s = src;
+
+		do {
+			if ((*d++ = *s++) == 0) {
+				/* NUL pad the remaining n-1 bytes */
+				while (--n != 0)
+					*d++ = 0;
+				break;
+			}
+		} while (--n != 0);
+	}
+	return (dst);
+}

Added: klee/trunk/runtime/klee-libc/strrchr.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strrchr.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strrchr.c (added)
+++ klee/trunk/runtime/klee-libc/strrchr.c Wed May 20 23:36:41 2009
@@ -0,0 +1,21 @@
+//===-- strrchr.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+char *strrchr(const char *t, int c) {
+  char ch;
+  const char *l=0;
+
+  ch = c;
+  for (;;) {
+    if (*t == ch) l=t; if (!*t) return (char*)l; ++t;
+  }
+  return (char*)l;
+}

Added: klee/trunk/runtime/klee-libc/strtol.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strtol.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strtol.c (added)
+++ klee/trunk/runtime/klee-libc/strtol.c Wed May 20 23:36:41 2009
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long
+strtol(const char * nptr, char ** endptr, int base)
+{
+	const char *s;
+	unsigned long acc;
+	char c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for longs is
+	 * [-2147483648..2147483647] and the input base is 10,
+	 * cutoff will be set to 214748364 and cutlim to either
+	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
+	 * the number is too big, and we will return a range error.
+	 *
+	 * Set 'any' if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
+	    : LONG_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LONG_MIN : LONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}

Added: klee/trunk/runtime/klee-libc/strtoul.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/strtoul.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/strtoul.c (added)
+++ klee/trunk/runtime/klee-libc/strtoul.c Wed May 20 23:36:41 2009
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+strtoul(const char * nptr, char ** endptr, int base)
+{
+	const char *s;
+	unsigned long acc;
+	char c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = ULONG_MAX / base;
+	cutlim = ULONG_MAX % base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULONG_MAX;
+		errno = ERANGE;
+	} else if (!any) {
+noconv:
+		errno = EINVAL;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}

Added: klee/trunk/runtime/klee-libc/tolower.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/tolower.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/tolower.c (added)
+++ klee/trunk/runtime/klee-libc/tolower.c Wed May 20 23:36:41 2009
@@ -0,0 +1,14 @@
+//===-- tolower.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int tolower(int ch) {
+  if ( (unsigned int)(ch - 'A') < 26u )
+    ch -= 'A' - 'a';
+  return ch;
+}

Added: klee/trunk/runtime/klee-libc/toupper.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/runtime/klee-libc/toupper.c?rev=72205&view=auto

==============================================================================
--- klee/trunk/runtime/klee-libc/toupper.c (added)
+++ klee/trunk/runtime/klee-libc/toupper.c Wed May 20 23:36:41 2009
@@ -0,0 +1,14 @@
+//===-- toupper.c ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int toupper(int ch) {
+  if ( (unsigned int)(ch - 'a') < 26u )
+    ch += 'A' - 'a';
+  return ch;
+}

Added: klee/trunk/scripts/IStatsMerge.py
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/scripts/IStatsMerge.py?rev=72205&view=auto

==============================================================================
--- klee/trunk/scripts/IStatsMerge.py (added)
+++ klee/trunk/scripts/IStatsMerge.py Wed May 20 23:36:41 2009
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+
+from __future__ import division
+
+import sys, os
+
+class MergeError(Exception):
+    pass
+
+def checkAssemblies(directories):
+    def read(d):
+        try:
+            return open(os.path.join(d,'assembly.ll')).read()
+        except:
+            raise MergeError("unable to open assembly for: %s"%(`d`,))
+    
+    reference = read(directories[0])
+    for d in directories[1:]:
+        if reference != read(d):
+            return False
+    return True
+
+def allEqual(l):
+    return not [i for i in l if i!=l[0]]
+
+def merge(inputs, output, outputDir):
+    inputs = [[None,iter(i)] for i in inputs]
+
+    def getLine(elt):
+        la,i = elt
+        if la is None:
+            try:
+                ln = i.next()
+            except StopIteration:
+                ln = None
+            except:
+                raise MergeError("unexpected IO error")
+            return ln
+        else:
+            elt[0] = None
+            return la
+    def getLines():
+        return map(getLine,inputs)
+    def putback(ln,elt):
+        assert elt[0] is None
+        elt[0] = ln
+        
+    events = None
+    
+    # read header (up to ob=)
+    while 1:
+        lns = getLines()
+        ln = lns[0]
+        if ln.startswith('ob='):
+            if [l for l in lns if not l.startswith('ob=')]:
+                raise MergeError("headers differ")
+            output.write('ob=%s\n'%(os.path.join(outputDir,'assembly.ll'),))
+            break
+        else:
+            if ln.startswith('positions:'):
+                if ln!='positions: instr line\n':
+                    raise MergeError("unexpected 'positions' directive")
+            elif ln.startswith('events:'):
+                events = ln[len('events: '):].strip().split(' ')
+            if not allEqual(lns):
+                raise MergeError("headers differ")
+            output.write(ln)
+
+    if events is None:
+        raise MergeError('missing events directive')
+    boolTypes = set(['Icov','Iuncov'])
+    numEvents = len(events)
+    eventTypes = [e in boolTypes for e in events]
+
+    def mergeStats(datas):
+        if not allEqual([d[:2] for d in datas]):
+            raise MergeError("instruction or line specifications differ")
+        elif [d for d in datas if len(d)!=numEvents+2]:
+            raise MergeError("statistics differ in event counts")
+        
+        result = [datas[0][0],datas[0][1]]
+        for i,ev in enumerate(events):
+            s = sum([d[i+2] for d in datas])
+            if ev=='Icov':
+                result.append(max([d[i+2] for d in datas])) # true iff any are non-zero
+            elif ev=='Iuncov':
+                result.append(min([d[i+2] for d in datas])) # true iff any are non-zero
+            else:
+                result.append(s)
+        return result
+
+    def readCalls():
+        results = {}
+        for elt in inputs:
+            while 1:
+                ln = getLine(elt)
+                if ln is not None and (ln.startswith('cfl=') or ln.startswith('cfn=')):
+                    if ln.startswith('cfl='):
+                        cfl = ln
+                        cfn = getLine(elt)
+                        if not cfn.startswith('cfn='):
+                            raise MergeError("unexpected cfl directive without function")
+                    else:
+                        cfl = None
+                        cfn = ln
+                    target = getLine(elt)
+                    if not target.startswith('calls='):
+                        raise MergeError("unexpected cfn directive with calls")
+                    stat = map(int,getLine(elt).strip().split(' '))
+                    key = target
+                    existing = results.get(target)
+                    if existing is None:
+                        results[key] = [cfl,cfn,target,stat]
+                    else:
+                        if existing[0]!=cfl or existing[1]!=cfn:
+                            raise MergeError("multiple call descriptions for a single target")
+                        existing[3] = mergeStats([existing[3],stat])
+                else:
+                    putback(ln, elt)
+                    break
+        return results
+    
+    # read statistics
+    while 1:
+        lns = getLines()
+        ln = lns[0]
+        if ln is None:
+            if not allEqual(lns):
+                raise MergeError("unexpected end of input")
+            break
+        elif ln.startswith('fn') or ln.startswith('fl'):
+            if not allEqual(lns):
+                raise MergeError("files differ")
+            output.write(ln)
+        else:
+            # an actual statistic
+            data = [map(int,ln.strip().split(' ')) for ln in lns]
+            print >>output,' '.join(map(str,mergeStats(data)))
+
+            # read any associated calls
+            for cfl,cfn,calls,stat in readCalls().values():
+                if cfl is not None:
+                    output.write(cfl)
+                output.write(cfn)
+                output.write(calls)
+                print >>output,' '.join(map(str,stat))
+            
+def main(args):
+    from optparse import OptionParser
+    op = OptionParser("usage: %prog [options] directories+ output")
+    opts,args = op.parse_args()
+
+    output = args.pop()
+    directories = args
+
+    if len(directories)<=1:
+        op.error("incorrect number of arguments")
+
+    print 'Merging:',', '.join(directories)
+    print 'Into:',output
+
+    if not checkAssemblies(directories):
+        raise MergeError("executables differ")
+
+    if not os.path.exists(output):
+        os.mkdir(output)
+        
+    assembly = open(os.path.join(directories[0],'assembly.ll')).read()
+    open(os.path.join(output,'assembly.ll'),'w').write(assembly)
+
+    inputs = [open(os.path.join(d,'run.istats')) for d in directories]
+    merge(inputs, open(os.path.join(output,'run.istats'),'w'), output)
+
+if __name__=='__main__':
+    main(sys.argv)

Propchange: klee/trunk/scripts/IStatsMerge.py

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/scripts/IStatsSum.py
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/scripts/IStatsSum.py?rev=72205&view=auto

==============================================================================
--- klee/trunk/scripts/IStatsSum.py (added)
+++ klee/trunk/scripts/IStatsSum.py Wed May 20 23:36:41 2009
@@ -0,0 +1,129 @@
+#!/usr/bin/python
+
+from __future__ import division
+
+import sys, os
+
+def getSummary(input):
+    inputs = [[None,iter(open(input))]]
+    def getLine(elt):
+        la,i = elt
+        if la is None:
+            try:
+                ln = i.next()
+            except StopIteration:
+                ln = None
+            except:
+                raise ValueError("unexpected IO error")
+            return ln
+        else:
+            elt[0] = None
+            return la
+    def getLines():
+        return map(getLine,inputs)
+    def putback(ln,elt):
+        assert elt[0] is None
+        elt[0] = ln
+        
+    events = None
+    
+    # read header (up to ob=)
+    while 1:
+        lns = getLines()
+        ln = lns[0]
+        if ln.startswith('ob='):
+            break
+        else:
+            if ln.startswith('positions:'):
+                if ln!='positions: instr line\n':
+                    raise ValueError("unexpected 'positions' directive")
+            elif ln.startswith('events:'):
+                events = ln[len('events: '):].strip().split(' ')
+
+    if events is None:
+        raise ValueError('missing events directive')
+    boolTypes = set(['Icov','Iuncov'])
+    numEvents = len(events)
+    eventTypes = [e in boolTypes for e in events]
+
+    def readCalls():
+        results = {}
+        for elt in inputs:
+            while 1:
+                ln = getLine(elt)
+                if ln is not None and (ln.startswith('cfl=') or ln.startswith('cfn=')):
+                    if ln.startswith('cfl='):
+                        cfl = ln
+                        cfn = getLine(elt)
+                        if not cfn.startswith('cfn='):
+                            raise ValueError("unexpected cfl directive without function")
+                    else:
+                        cfl = None
+                        cfn = ln
+                    target = getLine(elt)
+                    if not target.startswith('calls='):
+                        raise ValueError("unexpected cfn directive with calls")
+                    stat = map(int,getLine(elt).strip().split(' '))
+                    key = target
+                    existing = results.get(target)
+                    if existing is None:
+                        results[key] = [cfl,cfn,target,stat]
+                    else:
+                        if existing[0]!=cfl or existing[1]!=cfn:
+                            raise ValueError("multiple call descriptions for a single target")
+                        existing[3] = mergeStats([existing[3],stat])
+                else:
+                    putback(ln, elt)
+                    break
+        return results
+
+    summed = [0]*len(events)
+    
+    # read statistics
+    while 1:
+        lns = getLines()
+        ln = lns[0]
+        if ln is None:
+            break
+        elif ln.startswith('fn') or ln.startswith('fl'):
+            pass
+        elif ln.strip():
+            # an actual statistic
+            data = [map(int,ln.strip().split(' ')) for ln in lns][0]
+            summed = map(lambda a,b: a+b, data[2:], summed)
+
+            # read any associated calls
+            for cfl,cfn,calls,stat in readCalls().values():
+                pass
+
+    return events,summed
+    
+def main(args):
+    from optparse import OptionParser
+    op = OptionParser("usage: %prog [options] file")
+    opts,args = op.parse_args()
+
+    total = {}
+    for i in args:
+        events,summed = getSummary(i)
+        for e,s in zip(events,summed):
+            total[e] = total.get(e,[0,0])
+            total[e][0] += s
+            total[e][1] += 1
+        print '-- %s --'%(i,)
+        items = zip(events,summed)
+        items.sort()
+        for e,s in items:
+            print '%s: %s'%(e,s)
+
+    print '-- totals --'
+    items = total.items()
+    table = []    
+    for e,(s,N) in items:
+        table.append((str(e),str(s),str(N),str(s//N)))
+    w = map(lambda l: max(map(len,l)), zip(*table))
+    for (a,b,c,d) in table:
+        print '%-*s: %*s (in %*s files, avg: %*s)'%(w[0],a,w[1],b,w[2],c,w[3],d)
+
+if __name__=='__main__':
+    main(sys.argv)

Propchange: klee/trunk/scripts/IStatsSum.py

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/scripts/PrintStats.py
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/scripts/PrintStats.py?rev=72205&view=auto

==============================================================================
--- klee/trunk/scripts/PrintStats.py (added)
+++ klee/trunk/scripts/PrintStats.py Wed May 20 23:36:41 2009
@@ -0,0 +1,231 @@
+#!/usr/bin/python
+
+from __future__ import division
+
+import sys
+import os
+    
+def getFile(dir):
+    return os.path.join(dir,'run.stats')
+
+def getLastRecord(dir):
+    f = open(getFile(dir))
+    try:
+        f.seek(-1024, 2)
+    except IOError:
+        pass # at beginning?
+    for ln in f.read(1024).split('\n')[::-1]:
+        ln = ln.strip()
+        if ln.startswith('(') and ln.endswith(')'):
+            if '(' in ln[1:]:
+                print >>sys.stderr, 'WARNING: corrupted line in file, out of disk space?'
+                ln = ln[ln.index('(',1):]
+            return eval(ln)
+    raise IOError
+
+
+class LazyEvalList:
+    def __init__(self, lines):
+        self.lines = lines
+
+    def __getitem__(self, index):
+        item = self.lines[index]
+        if isinstance(item,str):
+            item = self.lines[index] = eval(item)
+        return item
+
+    def __len__(self):
+        return len(self.lines)
+
+
+def getMatchedRecord(data,reference,key):
+    refKey = key(reference)
+    lo = 1 # header
+    hi = len(data)-1
+    while lo<hi:
+        mid = (lo+hi)//2
+        if key(data[mid])<=refKey:
+            lo = mid + 1
+        else:
+            hi = mid
+    return data[lo]
+
+
+def stripCommonPathPrefix(table, col):
+    paths = map(os.path.normpath, [row[col] for row in table])
+    pathElts = [p.split('/') for p in paths]
+    zipped = zip(*pathElts)
+    idx = 0
+    for idx,elts in enumerate(zipped):
+        if len(set(elts))>1:
+            break
+    paths = ['/'.join(elts[idx:]) for elts in pathElts]
+    for i,row in enumerate(table):
+        table[i] = row[:col] + (paths[i],) + row[col+1:]
+
+
+def getKeyIndex(keyName,labels):
+    def normalizedKey(key):
+        if key.endswith("(#)") or key.endswith("(%)") or key.endswith("(s)"):
+            key = key[:-3]
+        return key.lower()
+
+    keyIndex = None
+    for i,title in enumerate(labels):
+        if normalizedKey(title)==normalizedKey(keyName):
+            keyIndex = i
+            break
+    else:
+        raise ValueError,'invalid keyName to sort by: %s'%`keyName`
+    return keyIndex
+
+
+def sortTable(table, labels, keyName, ascending=False):   
+    indices = range(len(table))
+    keyIndex = getKeyIndex(keyName,labels)
+    indices.sort(key = lambda n: table[n][keyIndex])
+    if not ascending:
+        indices.reverse()
+    table[:] = [table[n] for n in indices]
+
+
+def printTable(table):
+    def strOrNone(ob):
+        if ob is None:
+            return ''
+        elif isinstance(ob,float):
+            return '%.2f'%ob
+        else:
+            return str(ob)
+    def printRow(row):
+        if row is None:
+            print header
+        else:
+            out.write('|')
+            for j,elt in enumerate(row):
+                if j:
+                    out.write(' %*s |'%(widths[j],elt))
+                else:
+                    out.write(' %-*s |'%(widths[j],elt))
+            out.write('\n')
+    maxLen = max([len(r) for r in table if r])
+    for i,row in enumerate(table):
+        if row:
+            table[i] = row + (None,)*(maxLen-len(row))
+    table = [row and map(strOrNone,row) or None for row in table]
+    tableLens = [map(len,row) for row in table if row]
+    from pprint import pprint
+    widths = map(max, zip(*tableLens))
+    out = sys.stdout
+    header = '-'*(sum(widths) + maxLen*3 + 1)
+    map(printRow, table)
+        
+
+def main(args):
+    from optparse import OptionParser
+    op = OptionParser(usage="usage: %prog [options] directories*",
+                      epilog=
+                      "LEGEND                                                                          " 
+                      "------                                                                          " 
+                      "Instrs:  Number of executed instructions                                        "
+                      "Time:    Total wall time (s)                                                    "
+                      "ICov:    Instruction coverage in the LLVM bitcode (%)                           "
+                      "BCov:    Branch coverage in the LLVM bitcode (%)                                "
+                      "ICount:  Total static instructions in the LLVM bitcode                          "
+                      "Solver:  Time spent in the constraint solver (%)                                "
+                      "States:  Number of currently active states                                      "
+                      "Mem:     Megabytes of memory currently used                                     "
+                      "Queries: Number of queries issued to STP                                        "
+                      "AvgQC:   Average number of query constructs per query                           "
+                      "Tcex:    Time spent in the counterexample caching code (%)                                        "
+                      "Tfork:   Time spent forking (%)                                                 ")
+
+    op.add_option('', '--print-more', dest='printMore',
+                  action='store_true', default=False,
+                  help='Print extra information (needed when monitoring an ongoing run).')
+    op.add_option('', '--print-all', dest='printAll',
+                  action='store_true', default=False,
+                  help='Print all available information.')
+    op.add_option('','--sort-by', dest='sortBy',
+                  help='key value to sort by, e.g. --sort-by=Instrs')
+    op.add_option('','--ascending', dest='ascending',
+                  action='store_true', default=False,
+                  help='sort in ascending order (default is descending)')
+    op.add_option('','--compare-by', dest='compBy',
+                  help="key value on which to compare runs to the reference one (which is the first one).  E.g., --compare-by=Instrs shows how each run compares to the reference run after executing the same number of instructions as the reference run.  If a run hasn't executed as many instructions as the reference one, we simply print the statistics at the end of that run.")
+    opts,dirs = op.parse_args()
+
+    actualDirs = []
+    for dir in dirs:
+        if os.path.exists(os.path.join(dir,'info')):
+            actualDirs.append(dir)
+        else:
+            for root,dirs,_ in os.walk(dir):
+                for d in dirs:
+                    p = os.path.join(root,d)
+                    if os.path.exists(os.path.join(p,'info')):
+                        actualDirs.append(p)
+    dirs = actualDirs
+    
+    summary = []
+    
+    if (opts.printAll):
+        labels = ('Path','Instrs','Time(s)','ICov(%)','BCov(%)','ICount','Solver(%)', 'States', 'Mem(MB)', 'Queries', 'AvgQC', 'Tcex(%)', 'Tfork(%)')
+    elif (opts.printMore):
+        labels = ('Path','Instrs','Time(s)','ICov(%)','BCov(%)','ICount','Solver(%)', 'States', 'Mem(MB)')
+    else:
+        labels = ('Path','Instrs','Time(s)','ICov(%)','BCov(%)','ICount','Solver(%)')
+
+
+    def addRecord(Path,rec):
+        (I,BFull,BPart,BTot,T,St,Mem,QTot,QCon,NObjs,Treal,SCov,SUnc,QT,Ts,Tcex,Tf) = rec
+        Mem=Mem/1024./1024.
+        AvgQC = int(QCon/max(1,QTot))
+        if (opts.printAll):
+            table.append((Path, I, Treal, 100.*SCov/(SCov+SUnc), 100.*(2*BFull+BPart)/(2.*BTot),
+                          SCov+SUnc, 100.*Ts/Treal, St, Mem, QTot, AvgQC, 100.*Tcex/Treal, 100.*Tf/Treal))
+        elif (opts.printMore):
+            table.append((Path, I, Treal, 100.*SCov/(SCov+SUnc), 100.*(2*BFull+BPart)/(2.*BTot),
+                          SCov+SUnc, 100.*Ts/Treal, St, Mem))
+        else:
+            table.append((Path, I, Treal, 100.*SCov/(SCov+SUnc), 100.*(2*BFull+BPart)/(2.*BTot),
+                          SCov+SUnc, 100.*Ts/Treal))
+        
+    def addRow(Path,data):
+        data = tuple(data[:17]) + (None,)*(17-len(data))
+        addRecord(Path,data)
+        if not summary:
+            summary[:] = list(data)
+        else:
+            summary[:] = [(a+b) for a,b in zip(summary,data)]
+
+    datas = [(dir,LazyEvalList(list(open(getFile(dir))))) for dir in dirs]
+    reference = datas[0][1][-1]
+
+    table = []    
+
+    for dir,data in datas:
+        try:
+            if opts.compBy:
+                addRow(dir,getMatchedRecord(data,reference,lambda f: f[getKeyIndex(opts.compBy,labels)-1]))
+            else: 
+                addRow(dir, data[len(data)-1])  #getLastRecord(dir))
+        except IOError:
+            print 'Unable to open: ',dir
+            continue
+
+    stripCommonPathPrefix(table, 0)
+    if opts.sortBy:
+        sortTable(table, labels, opts.sortBy, opts.ascending)
+    if not table:
+        sys.exit(1)
+    elif len(table)>1:
+        table.append(None)
+        addRecord('Total (%d)'%(len(table)-1,),summary)
+    table[0:0] = [None,labels,None]
+    table.append(None)
+    printTable(table)
+        
+        
+if __name__=='__main__':
+    main(sys.argv)

Propchange: klee/trunk/scripts/PrintStats.py

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/scripts/klee-control
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/scripts/klee-control?rev=72205&view=auto

==============================================================================
--- klee/trunk/scripts/klee-control (added)
+++ klee/trunk/scripts/klee-control Wed May 20 23:36:41 2009
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+
+import os, signal, popen2
+
+def getPID(dir):
+    f = open(os.path.join(dir,'info'))
+    for ln in f.readlines():
+        if ln.startswith('PID: '):
+            return int(ln[5:])
+    return None
+
+def execCmd(pid, gdbCmd, opts):
+    cmd = ("gdb " +
+           "--batch " +
+           "--pid=%d " +
+           "--eval-command=\"%s\" " +
+           "--eval-command=detach")%(pid,gdbCmd)
+    cout,cin = popen2.popen2(cmd)
+    cin.close()
+    return cout.read()
+    
+def main():
+    from optparse import OptionParser
+    op = OptionParser("usage: %prog <PID | test directory>")
+    op.add_option('','--backtrace', dest='backtrace',
+                  action='store_true', default=False)
+    op.add_option('-s','--stop-forking', dest='stopForking',
+                  action='store_true', default=False)
+    op.add_option('-H','--halt-execution', dest='haltExecution',
+                  action='store_true', default=False)
+    op.add_option('-d','--dump-states', dest='dumpStates',
+                  action='store_true', default=False)
+    op.add_option('-t','--dump-tree', dest='dumpTree',
+                  action='store_true', default=False)
+    op.add_option('-i','--int', dest='int',
+                  action='store_true', default=False)
+    op.add_option('-k','--kill', dest='kill',
+                  action='store_true', default=False)
+    op.add_option('','--print-pid', dest='printPid',
+                  action='store_true', default=False)
+    op.add_option('','--print-ticks', dest='printTicks',
+                  action='store_true', default=False)
+    opts,args = op.parse_args()
+
+    if len(args) != 1:
+        op.error("invalid arguments")
+
+    try:
+        pid = int(args[0])
+    except:
+        pid = None
+
+    if pid is None:
+        try:
+            pid = getPID(args[0])
+        except:
+            pid = None
+            
+    if pid is None:
+        op.error("unable to determine PID (bad pid or test directory)")
+
+    if opts.printPid:
+        print pid
+        return
+    print 'pid: %d'%pid    
+    if opts.backtrace:
+        execCmd(pid, 'bt', opts)
+    if opts.dumpStates:
+        execCmd(pid, "p dumpStates = 1", opts)        
+    if opts.dumpTree:
+        execCmd(pid, "p dumpPTree = 1", opts)        
+    if opts.stopForking:
+        execCmd(pid, 'p stop_forking()', opts)    
+    if opts.haltExecution:
+        execCmd(pid, 'p halt_execution()', opts)
+    if opts.printTicks:
+        res = execCmd(pid, 'p timerTicks', opts)
+        lns = res.split('\n')
+        for ln in lns:
+            if ln.startswith('$1') and '=' in ln:
+                print ln.split('=',1)[1].strip()
+    if opts.int:    
+        os.kill(pid, signal.SIGINT)
+    if opts.kill:    
+        os.kill(pid, signal.SIGKILL)
+
+if __name__=='__main__':
+    main()
+

Propchange: klee/trunk/scripts/klee-control

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/scripts/objdump
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/scripts/objdump?rev=72205&view=auto

==============================================================================
--- klee/trunk/scripts/objdump (added)
+++ klee/trunk/scripts/objdump Wed May 20 23:36:41 2009
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+"""
+An objdump wrapper for use with klee & kcachegrind.
+
+This allows klee to output instruction level statistic information which
+kcachegrind can then display by intercepting kcachegrind's calls to objdump
+and returning the LLVM instructions in a format that it can parse.
+"""
+
+import os, sys
+
+kActualObjdump = os.path.join(os.path.dirname(__file__),'objdump.actual')
+if not os.path.exists(kActualObjdump):
+    for path in ['/usr/bin','/usr/local/bin']:
+        p = os.path.join(path,'objdump')
+        if os.path.exists(p):
+            kActualObjdump = p
+
+def fakeObjdumpOutput(file, start, end):
+    print 'Using fake objdump output:\n\n'
+    
+    lines = open(file).readlines()
+    for i in range(max(0,start-1),min(end-1,len(lines))):
+        print '%x: _ %s'%(i+1,lines[i])
+        
+def main(args):
+    # exact pattern match kcachegrind's calling sequence
+    if   (len(args)>=6 and
+          args[1]=='-C' and
+          args[2]=='-d' and
+          args[3].startswith('--start-address=') and
+          args[4].startswith('--stop-address=') and
+          args[5].endswith('.ll')):
+        fakeObjdumpOutput(args[5], eval(args[3].split('=',1)[1]), eval(args[4].split('=',1)[1]))
+    else:
+        os.execv(kActualObjdump, args)
+        raise RuntimeError
+    
+if __name__=='__main__':
+    main(sys.argv)

Propchange: klee/trunk/scripts/objdump

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/stp/AST/AST.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/AST.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/AST.cpp (added)
+++ klee/trunk/stp/AST/AST.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,1587 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "AST.h"
+namespace BEEV {
+  //some global variables that are set through commandline options. it
+  //is best that these variables remain global. Default values set
+  //here
+  //
+  //collect statistics on certain functions
+  bool stats = false;
+  //print DAG nodes
+  bool print_nodes = false;
+  //tentative global var to allow for variable activity optimization
+  //in the SAT solver. deprecated.
+  bool variable_activity_optimize = false;
+  //run STP in optimized mode
+  bool optimize = true;
+  //do sat refinement, i.e. underconstraint the problem, and feed to
+  //SAT. if this works, great. else, add a set of suitable constraints
+  //to re-constraint the problem correctly, and call SAT again, until
+  //all constraints have been added.
+  bool arrayread_refinement = true;
+  //flag to control write refinement
+  bool arraywrite_refinement = true;
+  //check the counterexample against the original input to STP
+  bool check_counterexample = false;
+  //construct the counterexample in terms of original variable based
+  //on the counterexample returned by SAT solver
+  bool construct_counterexample = true;
+  bool print_counterexample = false;
+  //if this option is true then print the way dawson wants using a
+  //different printer. do not use this printer.
+  bool print_arrayval_declaredorder = false;
+  //flag to decide whether to print "valid/invalid" or not
+  bool print_output = false;
+  //do linear search in the array values of an input array. experimental
+  bool linear_search = false;
+  //print the variable order chosen by the sat solver while it is
+  //solving.
+  bool print_sat_varorder = false; 
+  //turn on word level bitvector solver
+  bool wordlevel_solve = true;
+  //turn off XOR flattening
+  bool xor_flatten = false;
+
+  //the smtlib parser has been turned on
+  bool smtlib_parser_enable = false;
+  //print the input back
+  bool print_STPinput_back = false;
+  
+  //global BEEVMGR for the parser
+  BeevMgr * globalBeevMgr_for_parser;
+
+  void (*vc_error_hdlr)(const char* err_msg) = NULL;
+  /** This is reusable empty vector, for representing empty children arrays */
+  ASTVec _empty_ASTVec;  
+  ////////////////////////////////////////////////////////////////
+  //  ASTInternal members
+  ////////////////////////////////////////////////////////////////  
+  /** Trivial but virtual destructor */
+  ASTInternal::~ASTInternal() { }
+
+  ////////////////////////////////////////////////////////////////
+  //  ASTInterior members
+  ////////////////////////////////////////////////////////////////
+  /** Copy constructor */
+  // ASTInterior::ASTInterior(const ASTInterior &int_node)
+  // {
+  //   _kind = int_node._kind;
+  //   _children = int_node._children;
+  // }
+  
+  /** Trivial but virtual destructor */
+  ASTInterior::~ASTInterior() { }
+  
+  // FIXME: Darn it! I think this ends up copying the children twice!
+  /** Either return an old node or create it if it doesn't exist. 
+      Note that nodes are physically allocated in the hash table. */
+  
+  // There is  an inelegance here that  I don't know how  to solve.  I'd
+  // like to heap allocate and do some other initialization on keys only
+  // if  they aren't  in  the hash  table.   It would  be  great if  the
+  // "insert"  method took a  "creator" class  so that  I could  do that
+  // between  when it  notices that  the key  is not  there and  when it
+  // inserts it.  Alternatively, it would be great if I could insert the
+  // temporary key and replace it  if it actually got inserted.  But STL
+  // hash_set  doesn't have  the creator  feature  and paternalistically
+  // declares that keys are immutable, even though (it seems to me) that
+  // they  could be  mutated if  the hash  value and  eq values  did not
+  // change.
+  
+  ASTInterior *BeevMgr::LookupOrCreateInterior(ASTInterior *n_ptr) {
+    ASTInteriorSet::iterator it;
+    
+    if ((it = _interior_unique_table.find(n_ptr)) == _interior_unique_table.end()) {
+      // Make a new ASTInterior node
+      // We want (NOT alpha) always to have alpha.nodenum + 1.
+      if (n_ptr->GetKind() == NOT) {
+	n_ptr->SetNodeNum(n_ptr->GetChildren()[0].GetNodeNum()+1);
+      }
+      else {
+	n_ptr->SetNodeNum(NewNodeNum());
+      }
+      pair<ASTInteriorSet::const_iterator, bool> p = _interior_unique_table.insert(n_ptr);
+      return *(p.first);
+    }
+    else
+      // Delete the temporary node, and return the found node.
+      delete n_ptr;
+      return *it;
+  }
+  
+  size_t ASTInterior::ASTInteriorHasher::operator() (const ASTInterior *int_node_ptr) const {
+    //size_t hashval = 0;
+    size_t hashval = ((size_t) int_node_ptr->GetKind());
+    const ASTVec &ch = int_node_ptr->GetChildren();
+    ASTVec::const_iterator iend = ch.end();
+    for (ASTVec::const_iterator i = ch.begin(); i != iend; i++) {
+      //Using "One at a time hash" by Bob Jenkins
+      hashval += i->Hash();
+      hashval += (hashval << 10);
+      hashval ^= (hashval >> 6);
+    }
+
+    hashval += (hashval << 3);
+    hashval ^= (hashval >> 11);
+    hashval += (hashval << 15);
+    return hashval;
+    //return hashval += ((size_t) int_node_ptr->GetKind());
+  }
+  
+
+  void ASTInterior::CleanUp() {
+    // cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._interior_unique_table.erase(this);
+    delete this;
+  }
+
+  ////////////////////////////////////////////////////////////////
+  //  ASTNode members
+  ////////////////////////////////////////////////////////////////
+  //ASTNode constructors are inlined in AST.h
+  bool ASTNode::IsAlreadyPrinted() const {
+    BeevMgr &bm = GetBeevMgr();
+    return (bm.AlreadyPrintedSet.find(*this) != bm.AlreadyPrintedSet.end());
+  }
+
+  void ASTNode::MarkAlreadyPrinted() const {
+    // FIXME: Fetching BeevMgr is annoying.  Can we put this in lispprinter class?
+    BeevMgr &bm = GetBeevMgr();
+    bm.AlreadyPrintedSet.insert(*this);
+  }
+
+  // Get the name from a symbol (char *).  It's an error if kind != SYMBOL
+  const char * const ASTNode::GetName() const {
+    if (GetKind() != SYMBOL)
+      FatalError("GetName: Called GetName on a non-symbol: ", *this);
+    return ((ASTSymbol *) _int_node_ptr)->GetName();    
+  }
+  
+  // Print in lisp format
+  ostream &ASTNode::LispPrint(ostream &os, int indentation) const {
+    // Clear the PrintMap
+    BeevMgr& bm = GetBeevMgr(); 
+    bm.AlreadyPrintedSet.clear();
+    return LispPrint_indent(os, indentation);
+  }
+
+  // Print newline and indentation, then print the thing.
+  ostream &ASTNode::LispPrint_indent(ostream &os,
+				     int indentation) const
+  {
+    os << endl << spaces(indentation);
+    LispPrint1(os, indentation);
+    return os;
+  }
+  
+  /** Internal function to print in lisp format.  Assume newline
+      and indentation printed already before first line.  Recursive
+      calls will have newline & indent, though */
+  ostream &ASTNode::LispPrint1(ostream &os, int indentation) const {
+    if (!IsDefined()) {
+      os << "<undefined>";
+      return os;
+    }
+    Kind kind = GetKind();
+    // FIXME: figure out how to avoid symbols with same names as kinds.
+//    if (kind == READ) {
+//      const ASTVec &children = GetChildren();
+//      children[0].LispPrint1(os, indentation);
+//	os << "[" << children[1] << "]";
+//    } else 
+    if(kind == BVGETBIT) {
+      const ASTVec &children = GetChildren();
+      // child 0 is a symbol.  Print without the NodeNum.
+      os << GetNodeNum() << ":";
+
+
+
+      children[0]._int_node_ptr->nodeprint(os);
+      //os << "{" << children[1].GetBVConst() << "}";
+      os << "{";
+      children[1]._int_node_ptr->nodeprint(os);
+      os << "}";
+    } else if (kind == NOT) {
+      const ASTVec &children = GetChildren();
+      os << GetNodeNum() << ":";	
+      os << "(NOT ";
+      children[0].LispPrint1(os, indentation);
+      os << ")";
+    }
+    else if (Degree() == 0) {
+      // Symbol or a kind with no children print as index:NAME if shared,
+      // even if they have been printed before.	
+      os << GetNodeNum() << ":";
+      _int_node_ptr->nodeprint(os); 
+      // os << "(" << _int_node_ptr->_ref_count << ")";
+      // os << "{" << GetValueWidth() << "}";
+    }
+    else if (IsAlreadyPrinted()) {
+      // print non-symbols as "[index]" if seen before.
+      os << "[" << GetNodeNum() << "]";
+      //	   << "(" << _int_node_ptr->_ref_count << ")";
+    }
+    else {
+      MarkAlreadyPrinted();
+      const ASTVec &children = GetChildren();
+      os << GetNodeNum() << ":"
+	//<< "(" << _int_node_ptr->_ref_count << ")" 
+	 << "(" << kind << " ";
+      // os << "{" << GetValueWidth() << "}";
+      ASTVec::const_iterator iend = children.end();
+      for (ASTVec::const_iterator i = children.begin(); i != iend; i++) {
+	i->LispPrint_indent(os, indentation+2);
+	}
+      os << ")";	
+    }
+    return os;
+  }
+
+  //print in PRESENTATION LANGUAGE
+  //
+  //two pass algorithm: 
+  //
+  //1. In the first pass, letize this Node, N: i.e. if a node
+  //1. appears more than once in N, then record this fact.
+  //
+  //2. In the second pass print a "global let" and then print N
+  //2. as follows: Every occurence of a node occuring more than
+  //2. once is replaced with the corresponding let variable.
+  ostream& ASTNode::PL_Print(ostream &os,
+			     int indentation) const {
+    // Clear the PrintMap
+    BeevMgr& bm = GetBeevMgr(); 
+    bm.PLPrintNodeSet.clear();
+    bm.NodeLetVarMap.clear();
+    bm.NodeLetVarVec.clear();
+    bm.NodeLetVarMap1.clear();
+
+    //pass 1: letize the node
+    LetizeNode();
+
+    //pass 2: 
+    //
+    //2. print all the let variables and their counterpart expressions
+    //2. as follows (LET var1 = expr1, var2 = expr2, ...
+    //
+    //3. Then print the Node itself, replacing every occurence of
+    //3. expr1 with var1, expr2 with var2, ...
+    //os << "(";
+    if(0 < bm.NodeLetVarMap.size()) {
+      //ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
+      //ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
+      std::vector<pair<ASTNode,ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
+      std::vector<pair<ASTNode,ASTNode> >::iterator itend = bm.NodeLetVarVec.end();
+
+      os << "(LET ";      
+      //print the let var first
+      it->first.PL_Print1(os,indentation,false);
+      os << " = ";
+      //print the expr
+      it->second.PL_Print1(os,indentation,false);
+
+      //update the second map for proper printing of LET
+      bm.NodeLetVarMap1[it->second] = it->first;
+
+      for(it++;it!=itend;it++) {
+        os << "," << endl;
+	//print the let var first
+	it->first.PL_Print1(os,indentation,false);
+	os << " = ";
+	//print the expr
+	it->second.PL_Print1(os,indentation,false);
+
+        //update the second map for proper printing of LET
+        bm.NodeLetVarMap1[it->second] = it->first;
+      }
+    
+      os << " IN " << endl;      
+      PL_Print1(os,indentation, true);
+      os << ") ";
+    }
+    else
+      PL_Print1(os,indentation, false);
+    //os << " )";
+    os << " ";
+    return os;
+  } //end of PL_Print()
+
+  //traverse "*this", and construct "let variables" for terms that
+  //occur more than once in "*this".
+  void ASTNode::LetizeNode(void) const {
+    Kind kind = this->GetKind();
+
+    if(kind == SYMBOL  || 
+       kind == BVCONST ||
+       kind == FALSE   ||
+       kind == TRUE)
+      return;
+
+    //FIXME: this is ugly.
+    BeevMgr& bm = GetBeevMgr();     
+    const ASTVec &c = this->GetChildren();
+    for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
+      ASTNode ccc = *it;
+      if(bm.PLPrintNodeSet.find(ccc) == bm.PLPrintNodeSet.end()){
+	//If branch: if *it is not in NodeSet then,
+	//
+	//1. add it to NodeSet
+	//
+	//2. Letize its childNodes
+
+	//FIXME: Fetching BeevMgr is annoying.  Can we put this in
+	//some kind of a printer class
+	bm.PLPrintNodeSet.insert(ccc);
+	//debugging
+	//cerr << ccc;
+	ccc.LetizeNode();
+      } 
+      else{
+	Kind k = ccc.GetKind();
+	if(k == SYMBOL  || 
+	   k == BVCONST ||
+	   k == FALSE   ||
+	   k == TRUE)
+	  continue;
+	
+	//0. Else branch: Node has been seen before
+	//
+	//1. Check if the node has a corresponding letvar in the
+	//1. NodeLetVarMap.
+	//
+	//2. if no, then create a new var and add it to the
+	//2. NodeLetVarMap
+	if(bm.NodeLetVarMap.find(ccc) == bm.NodeLetVarMap.end()) {
+	  //Create a new symbol. Get some name. if it conflicts with a
+	  //declared name, too bad. 
+	  int sz = bm.NodeLetVarMap.size();
+	  ostringstream oss;
+	  oss << "let_k_" << sz;
+
+	  ASTNode CurrentSymbol = bm.CreateSymbol(oss.str().c_str());
+	  CurrentSymbol.SetValueWidth(this->GetValueWidth());
+	  CurrentSymbol.SetIndexWidth(this->GetIndexWidth());	  
+	  /* If for some reason the variable being created here is
+	   * already declared by the user then the printed output will
+	   * not be a legal input to the system. too bad. I refuse to
+	   * check for this.  [Vijay is the author of this comment.]
+	   */
+	  
+	  bm.NodeLetVarMap[ccc] = CurrentSymbol;
+	  std::pair<ASTNode,ASTNode> node_letvar_pair(CurrentSymbol,ccc);
+	  bm.NodeLetVarVec.push_back(node_letvar_pair);
+	}
+      }    
+    }
+  } //end of LetizeNode()
+
+  void ASTNode::PL_Print1(ostream& os,
+			  int indentation, 
+			  bool letize) const {
+    //os << spaces(indentation);
+    //os << endl << spaces(indentation);
+    if (!IsDefined()) {
+      os << "<undefined>";
+      return;
+    }
+    
+    //if this node is present in the letvar Map, then print the letvar
+    BeevMgr &bm = GetBeevMgr();
+
+    //this is to print letvars for shared subterms inside the printing
+    //of "(LET v0 = term1, v1=term1 at term2,...
+    if((bm.NodeLetVarMap1.find(*this) != bm.NodeLetVarMap1.end()) && !letize) {
+      (bm.NodeLetVarMap1[*this]).PL_Print1(os,indentation,letize);
+      return;
+    }
+
+    //this is to print letvars for shared subterms inside the actual
+    //term to be printed
+    if((bm.NodeLetVarMap.find(*this) != bm.NodeLetVarMap.end()) && letize) {
+      (bm.NodeLetVarMap[*this]).PL_Print1(os,indentation,letize);
+      return;
+    }
+    
+    //otherwise print it normally
+    Kind kind = GetKind();
+    const ASTVec &c = GetChildren();     
+    switch(kind) {
+    case BVGETBIT:
+      c[0].PL_Print1(os,indentation,letize);
+      os << "{";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "}";
+      break;
+    case BITVECTOR:
+      os << "BITVECTOR(";
+      unsigned char * str;
+      str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
+      os << str << ")";
+      CONSTANTBV::BitVector_Dispose(str);
+      break;
+    case BOOLEAN:
+      os << "BOOLEAN";
+      break;
+    case FALSE:
+    case TRUE:
+      os << kind;
+      break;
+    case BVCONST:
+    case SYMBOL:
+      _int_node_ptr->nodeprint(os); 
+      break;
+    case READ:
+      c[0].PL_Print1(os, indentation,letize);
+      os << "[";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "]";
+      break;
+    case WRITE:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " WITH [";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "] := ";
+      c[2].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << endl;
+      break;
+    case BVUMINUS:
+      os << kind << "( ";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case NOT:
+      os << "NOT(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ") " << endl;
+      break;
+    case BVNEG:
+      os << " ~(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVCONCAT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " @ ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVOR:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " | ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVAND:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " & ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVEXTRACT:
+      c[0].PL_Print1(os,indentation,letize);
+      os << "[";
+      os << GetUnsignedConst(c[1]);
+      os << ":";
+      os << GetUnsignedConst(c[2]);
+      os << "]";
+      break;
+    case BVLEFTSHIFT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " << ";
+      os << GetUnsignedConst(c[1]);
+      os << ")";
+      break;
+    case BVRIGHTSHIFT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " >> ";
+      os << GetUnsignedConst(c[1]);
+      os << ")";
+      break;
+    case BVMULT:
+    case BVSUB:
+    case BVPLUS:
+    case SBVDIV:      
+    case SBVMOD:
+    case BVDIV:      
+    case BVMOD:
+      os << kind << "(";
+      os << this->GetValueWidth();
+      for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	os << ", " << endl;
+	it->PL_Print1(os,indentation,letize);	
+      }
+      os << ")" << endl;
+      break;    
+    case ITE:
+      os << "IF(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      os << "THEN ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << endl << "ELSE ";
+      c[2].PL_Print1(os,indentation,letize);
+      os << endl << "ENDIF";
+      break;
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVXOR:
+    case BVNAND:
+    case BVNOR:
+    case BVXNOR:
+      os << kind << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSLT:
+      os << "SBVLT" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSLE:
+      os << "SBVLE" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSGT:
+      os << "SBVGT" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSGE:
+      os << "SBVGE" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case EQ:
+      c[0].PL_Print1(os,indentation,letize);
+      os << " = ";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << endl;
+      break;
+    case NEQ:
+      c[0].PL_Print1(os,indentation,letize);
+      os << " /= ";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << endl;
+      break;
+    case AND:
+    case OR:
+    case NAND:
+    case NOR:
+    case XOR: {
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      ASTVec::const_iterator it=c.begin();
+      ASTVec::const_iterator itend=c.end();
+
+      it++;
+      for(;it!=itend;it++) {
+	os << " " << kind << " ";
+	it->PL_Print1(os,indentation,letize);
+	os << endl;
+      }
+      os << ")";
+      break;
+    }
+    case IFF:
+      os << "(";
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << " <=> ";
+      os << "(";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << ")";
+      os << ")";
+      os << endl;
+      break;
+    case IMPLIES:
+      os << "(";
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << " => ";
+      os << "(";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << ")";
+      os << endl;
+      break;
+    case BVSX:
+      os << kind << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      os << this->GetValueWidth();
+      os << ")" << endl;
+      break;
+    default:
+      //remember to use LispPrinter here. Otherwise this function will
+      //go into an infinite loop. Recall that "<<" is overloaded to
+      //the lisp printer. FatalError uses lispprinter
+      FatalError("PL_Print1: printing not implemented for this kind: ",*this);
+      break;
+    }
+  } //end of PL_Print1()
+
+  ////////////////////////////////////////////////////////////////
+  //  BeevMgr members
+  ////////////////////////////////////////////////////////////////
+  ASTNode BeevMgr::CreateNode(Kind kind, const ASTVec & back_children) {
+    // create a new node.  Children will be modified.
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+
+    // insert all of children at end of new_children.
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTVec & back_children) {
+
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    ASTNode n(CreateInteriorNode(kind, n_ptr,  back_children));
+    return n;
+  }
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTNode& child1,
+			      const ASTVec & back_children) {
+
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    front_children.push_back(child1);
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTNode& child1,
+			      const ASTNode& child2,
+			      const ASTVec & back_children) {
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    front_children.push_back(child1);
+    front_children.push_back(child2);
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  
+  ASTInterior *BeevMgr::CreateInteriorNode(Kind kind,
+					   // children array of this node will be modified.
+					   ASTInterior *n_ptr,
+					   const ASTVec & back_children) {
+
+    // insert back_children at end of front_children
+    ASTVec &front_children = n_ptr->_children;
+
+    front_children.insert(front_children.end(), back_children.begin(), back_children.end());
+
+    // check for undefined nodes.
+    ASTVec::const_iterator it_end = front_children.end();
+    for (ASTVec::const_iterator it = front_children.begin(); it != it_end; it++) {
+      if (it->IsNull())
+	FatalError("CreateInteriorNode: Undefined childnode in CreateInteriorNode: ", ASTUndefined);      
+    }
+
+    return LookupOrCreateInterior(n_ptr);
+  }
+    
+  /** Trivial but virtual destructor */
+  ASTSymbol::~ASTSymbol() {}
+  
+  ostream &operator<<(ostream &os, const ASTNodeMap &nmap)
+  {
+    ASTNodeMap::const_iterator iend = nmap.end();
+    for (ASTNodeMap::const_iterator i = nmap.begin(); i!=iend; i++) {
+      os << "Key: " << i->first << endl;
+      os << "Value: " << i->second << endl;
+    }
+    return os;
+  }
+  
+  ////////////////////////////////////////////////////////////////
+  // BeevMgr member functions to create ASTSymbol and ASTBVConst
+  ////////////////////////////////////////////////////////////////
+  ASTNode BeevMgr::CreateSymbol(const char * const name) 
+  { 
+    ASTSymbol temp_sym(name, *this);
+    ASTNode n(LookupOrCreateSymbol(temp_sym));
+    return n;
+  }
+
+#ifndef NATIVE_C_ARITH
+  //Create a ASTBVConst node
+  ASTNode BeevMgr::CreateBVConst(unsigned int width, 
+				 unsigned long long int bvconst){ 
+    if(width > (sizeof(unsigned long long int)<<3) || width <= 0)
+      FatalError("CreateBVConst: trying to create a bvconst of width: ", ASTUndefined, width);
+    
+
+    CBV bv = CONSTANTBV::BitVector_Create(width, true);
+    unsigned long c_val = (0x00000000ffffffffLL) & bvconst;
+    unsigned int copied = 0;
+
+    // sizeof(unsigned long) returns the number of bytes in unsigned
+    // long. In order to convert it to bits, we need to shift left by
+    // 3. Hence, sizeof(unsigned long) << 3
+
+    //The algo below works as follows: It starts by copying the
+    //lower-order bits of the input "bvconst" in chunks of size =
+    //number of bits in unsigned long. The variable "copied" keeps
+    //track of the number of chunks copied so far
+
+    while(copied + (sizeof(unsigned long)<<3) < width){
+      CONSTANTBV::BitVector_Chunk_Store(bv, sizeof(unsigned long)<<3,copied,c_val);
+      bvconst = bvconst >> (sizeof(unsigned long) << 3);
+      c_val = (0x00000000ffffffffLL) & bvconst;
+      copied += sizeof(unsigned long) << 3;
+    }
+    CONSTANTBV::BitVector_Chunk_Store(bv,width - copied,copied,c_val);
+    return CreateBVConst(bv,width);
+  }
+
+  //Create a ASTBVConst node from std::string
+  ASTNode BeevMgr::CreateBVConst(const char* const strval, int base) {
+    size_t width = strlen((const char *)strval);    
+    if(!(2 == base || 10 == base || 16 == base)){
+      FatalError("CreateBVConst: unsupported base: ",ASTUndefined,base);
+    }
+    //FIXME Tim: Earlier versions of the code assume that the length of
+    //binary strings is 32 bits.
+    if(10 == base) width = 32;
+    if(16 == base) width = width * 4;
+
+    //checking if the input is in the correct format
+    CBV bv = CONSTANTBV::BitVector_Create(width,true);
+    CONSTANTBV::ErrCode e;
+    if(2 == base){
+      e = CONSTANTBV::BitVector_from_Bin(bv, (unsigned char*)strval);
+    }else if(10 == base){
+      e = CONSTANTBV::BitVector_from_Dec(bv, (unsigned char*)strval);
+    }else if(16 == base){
+      e = CONSTANTBV::BitVector_from_Hex(bv, (unsigned char*)strval);
+    }else{
+      e = CONSTANTBV::ErrCode_Pars;
+    }
+
+    if(0 != e) {
+      cerr << "CreateBVConst: " << BitVector_Error(e);
+      FatalError("",ASTUndefined);
+    }
+
+    //FIXME 
+    return CreateBVConst(bv, width);
+  }
+  
+
+  //FIXME Code currently assumes that it will destroy the bitvector passed to it
+  ASTNode BeevMgr::CreateBVConst(CBV bv, unsigned width){
+     ASTBVConst temp_bvconst(bv, width, *this);
+     ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+     
+     CONSTANTBV::BitVector_Destroy(bv);
+     
+     return n;
+  }
+
+  ASTNode BeevMgr::CreateZeroConst(unsigned width) {
+    CBV z = CONSTANTBV::BitVector_Create(width, true);
+    return CreateBVConst(z, width);
+  }
+  
+  ASTNode BeevMgr::CreateOneConst(unsigned width) {
+    CBV o = CONSTANTBV::BitVector_Create(width, true);
+    CONSTANTBV::BitVector_increment(o);
+    
+    return CreateBVConst(o,width);
+  }
+
+  ASTNode BeevMgr::CreateTwoConst(unsigned width) {
+    CBV two = CONSTANTBV::BitVector_Create(width, true);
+    CONSTANTBV::BitVector_increment(two);
+    CONSTANTBV::BitVector_increment(two);
+
+    return CreateBVConst(two,width);
+  }
+
+  ASTNode BeevMgr::CreateMaxConst(unsigned width) {
+    CBV max = CONSTANTBV::BitVector_Create(width, false);
+    CONSTANTBV::BitVector_Fill(max);
+
+    return CreateBVConst(max,width);
+  }
+
+  //To ensure unique BVConst nodes, lookup the node in unique-table
+  //before creating a new one.
+  ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
+    ASTBVConst *s_ptr = &s;  // it's a temporary key.
+    
+    // Do an explicit lookup to see if we need to create a copy of the string.    
+    ASTBVConstSet::const_iterator it;
+    if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
+      // Make a new ASTBVConst with duplicated string (can't assign
+      // _name because it's const).  Can cast the iterator to
+      // non-const -- carefully.
+
+      ASTBVConst * s_copy = new ASTBVConst(s);      
+      s_copy->SetNodeNum(NewNodeNum());
+      
+      pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_copy);
+      return *p.first;
+    }
+    else{
+      // return symbol found in table.
+      return *it;
+    }
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTBVConst::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._bvconst_unique_table.erase(this);
+    delete this;
+  }
+
+  // Get the value of bvconst from a bvconst.  It's an error if kind != BVCONST
+  CBV const ASTNode::GetBVConst() const {
+    if(GetKind() != BVCONST)
+      FatalError("GetBVConst: non bitvector-constant: ",*this);
+    return ((ASTBVConst *) _int_node_ptr)->GetBVConst();      
+  }
+#else
+  //Create a ASTBVConst node
+  ASTNode BeevMgr::CreateBVConst(const unsigned int width, 
+				 const unsigned long long int bvconst) { 
+    if(width > 64 || width <= 0)
+      FatalError("Fatal Error: CreateBVConst: trying to create a bvconst of width:", ASTUndefined, width);
+    
+    //64 bit mask
+    unsigned long long int mask = 0xffffffffffffffffLL;
+    mask = mask >> (64 - width);
+
+    unsigned long long int bv = bvconst;
+    bv = bv & mask;
+
+    ASTBVConst temp_bvconst(bv, *this);
+    temp_bvconst._value_width = width;    
+    ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+    n.SetValueWidth(width);
+    n.SetIndexWidth(0);
+    return n;
+  }
+  //Create a ASTBVConst node from std::string
+  ASTNode BeevMgr::CreateBVConst(const char* strval, int base) {    
+    if(!(base == 2 || base == 16 || base == 10))
+      FatalError("CreateBVConst: This base is not supported: ", ASTUndefined, base);
+
+    if(10 != base) {
+      unsigned int width = (base == 2) ? strlen(strval) : strlen(strval)*4;
+      unsigned long long int val =  strtoull(strval, NULL, base);
+      ASTNode bvcon = CreateBVConst(width, val);
+      return bvcon;
+    }
+    else {
+      //this is an ugly hack to accomodate SMTLIB format
+      //restrictions. SMTLIB format represents bitvector constants in
+      //base 10 (what a terrible idea, but i have no choice but to
+      //support it), and make an implicit assumption that the length
+      //is 32 (another terrible idea).
+      unsigned width = 32;
+      unsigned long long int val = strtoull(strval, NULL, base);
+      ASTNode bvcon = CreateBVConst(width, val);
+      return bvcon;
+    }
+  }
+  
+  //To ensure unique BVConst nodes, lookup the node in unique-table
+  //before creating a new one.
+  ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
+    ASTBVConst *s_ptr = &s;	// it's a temporary key.
+
+    // Do an explicit lookup to see if we need to create a copy of the
+    // string.
+    ASTBVConstSet::const_iterator it;
+    if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
+      // Make a new ASTBVConst. Can cast the iterator to non-const --
+      // carefully.
+      unsigned int width = s_ptr->_value_width;
+      ASTBVConst * s_ptr1 = new ASTBVConst(s_ptr->GetBVConst(), *this);
+      s_ptr1->SetNodeNum(NewNodeNum());
+      s_ptr1->_value_width = width;
+      pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_ptr1);
+      return *p.first;
+    }
+    else
+      // return BVConst found in table.
+      return *it;
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTBVConst::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._bvconst_unique_table.erase(this);
+    delete this;
+  }
+
+  // Get the value of bvconst from a bvconst.  It's an error if kind
+  // != BVCONST
+  unsigned long long int ASTNode::GetBVConst() const {
+    if(GetKind() != BVCONST)
+      FatalError("GetBVConst: non bitvector-constant: ", *this);
+    return ((ASTBVConstTmp *) _int_node_ptr)->GetBVConst();
+  }
+
+  ASTNode BeevMgr::CreateZeroConst(unsigned width) {
+    return CreateBVConst(width,0);
+  }
+  
+  ASTNode BeevMgr::CreateOneConst(unsigned width) {
+    return CreateBVConst(width,1);
+  }
+
+  ASTNode BeevMgr::CreateTwoConst(unsigned width) {
+    return CreateBVConst(width,2);
+  }
+
+  ASTNode BeevMgr::CreateMaxConst(unsigned width) {
+    std::string s;
+    s.insert(s.end(),width,'1');
+    return CreateBVConst(s.c_str(),2);
+  }
+
+#endif  
+
+  // FIXME: _name is now a constant field, and this assigns to it
+  // because it tries not to copy the string unless it needs to.  How
+  // do I avoid copying children in ASTInterior?  Perhaps I don't!
+  
+  // Note: There seems to be a limitation of hash_set, in that insert
+  // returns a const iterator to the value.  That prevents us from
+  // modifying the name (in a hash-preserving way) after the symbol is
+  // inserted.  FIXME: Is there a way to do this with insert?  Need a
+  // function to make a new object in the middle of insert.  Read STL
+  // documentation.
+  
+  ASTSymbol *BeevMgr::LookupOrCreateSymbol(ASTSymbol& s) {
+    ASTSymbol *s_ptr = &s;  // it's a temporary key.
+    
+    // Do an explicit lookup to see if we need to create a copy of the string.    
+    ASTSymbolSet::const_iterator it;
+    if ((it = _symbol_unique_table.find(s_ptr)) == _symbol_unique_table.end()) {
+      // Make a new ASTSymbol with duplicated string (can't assign
+      // _name because it's const).  Can cast the iterator to
+      // non-const -- carefully.
+      //std::string strname(s_ptr->GetName());
+      ASTSymbol * s_ptr1 = new ASTSymbol(strdup(s_ptr->GetName()), *this);
+      s_ptr1->SetNodeNum(NewNodeNum());
+      s_ptr1->_value_width = s_ptr->_value_width;
+      pair<ASTSymbolSet::const_iterator, bool> p = _symbol_unique_table.insert(s_ptr1);
+      return *p.first;
+    }
+    else
+      // return symbol found in table.
+      return *it;    
+  }
+
+  bool BeevMgr::LookupSymbol(ASTSymbol& s) {
+    ASTSymbol* s_ptr = &s;  // it's a temporary key.
+
+    if(_symbol_unique_table.find(s_ptr) == _symbol_unique_table.end()) 
+      return false;
+    else
+      return true;
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTSymbol::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._symbol_unique_table.erase(this);
+    //FIXME This is a HUGE free to invoke.
+    //TEST IT!
+    free((char*) this->_name);
+    delete this;
+  }
+  
+  ////////////////////////////////////////////////////////////////
+  //
+  //  IO manipulators for Lisp format printing of AST.
+  //
+  ////////////////////////////////////////////////////////////////
+  
+  // FIXME: Additional controls
+  //   * Print node numbers  (addresses/nums)
+  //   * Printlength limit
+  //   * Printdepth limit
+  
+  /** Print a vector of ASTNodes in lisp format */
+  ostream &LispPrintVec(ostream &os, const ASTVec &v, int indentation)
+  {
+    // Print the children
+    ASTVec::const_iterator iend = v.end();
+    for (ASTVec::const_iterator i = v.begin(); i != iend; i++) {
+      i->LispPrint_indent(os, indentation);
+    }
+    return os;
+  }
+
+  // FIXME: Made non-ref in the hope that it would work better.
+  void lp(ASTNode node)
+  {
+    cout << lisp(node) << endl;
+  }
+
+  void lpvec(const ASTVec &vec)
+  {
+    vec[0].GetBeevMgr().AlreadyPrintedSet.clear();
+    LispPrintVec(cout, vec, 0);
+    cout << endl;
+  }
+
+  // Copy constructor.  Maintain _ref_count
+  ASTNode::ASTNode(const ASTNode &n) : _int_node_ptr(n._int_node_ptr) {
+#ifndef SMTLIB    
+    if (n._int_node_ptr) {
+      n._int_node_ptr->IncRef();
+    }
+#endif
+  }
+  
+
+  /* FUNCTION: Typechecker for terms and formulas
+   * 
+   * TypeChecker: Assumes that the immediate Children of the input
+   * ASTNode have been typechecked. This function is suitable in
+   * scenarios like where you are building the ASTNode Tree, and you
+   * typecheck as you go along. It is not suitable as a general
+   * typechecker      
+   */
+  void BeevMgr::BVTypeCheck(const ASTNode& n) {
+    Kind k = n.GetKind();
+    //The children of bitvector terms are in turn bitvectors.
+    ASTVec v = n.GetChildren();
+    if(is_Term_kind(k)) {
+      switch(k) {
+      case BVCONST:
+	if(BITVECTOR_TYPE != n.GetType())
+	  FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",n);
+	break;
+      case SYMBOL:
+	return;
+      case ITE:     
+	if(BOOLEAN_TYPE != n[0].GetType() && 
+	   BITVECTOR_TYPE != n[1].GetType() &&
+	   BITVECTOR_TYPE != n[2].GetType())
+	  FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",n);
+	if(n[1].GetValueWidth() != n[2].GetValueWidth())
+	  FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n",n);
+	if(n[1].GetIndexWidth() != n[2].GetIndexWidth())
+	  FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n",n);
+	break;
+      case READ:
+	if(n[0].GetIndexWidth() != n[1].GetValueWidth()) {
+	  cerr << "Length of indexwidth of array: " << n[0] << " is : " << n[0].GetIndexWidth() << endl;
+	  cerr << "Length of the actual index is: " << n[1] << " is : " << n[1].GetValueWidth() << endl;
+	  FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n",n);
+	}
+	break;      
+      case WRITE:
+	if(n[0].GetIndexWidth() != n[1].GetValueWidth())
+	  FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n",n);
+	if(n[0].GetValueWidth() != n[2].GetValueWidth())
+	  FatalError("BVTypeCheck: valuewidth of array != length of actual value in the term t = \n",n);
+	break;      
+      case BVOR:
+      case BVAND:
+      case BVXOR:
+      case BVNOR:
+      case BVNAND:
+      case BVXNOR: 
+      case BVPLUS: 
+      case BVMULT:
+      case BVDIV:
+      case BVMOD:
+      case BVSUB: {
+	if(!(v.size() >= 2))
+	  FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have atleast two arguments\n",n);
+	unsigned int width = n.GetValueWidth();
+	for(ASTVec::iterator it=v.begin(),itend=v.end();it!=itend;it++){
+	  if(width != it->GetValueWidth()) {
+	    cerr << "BVTypeCheck:Operands of bitwise-Booleans and BV arith operators must be of equal length\n";
+	    cerr << n << endl;
+	    cerr << "width of term:" << width << endl;
+	    cerr << "width of offending operand:" << it->GetValueWidth() << endl;
+	    FatalError("BVTypeCheck:Offending operand:\n",*it);
+	  }
+	  if(BITVECTOR_TYPE != it->GetType())
+	    FatalError("BVTypeCheck: ChildNodes of bitvector-terms must be bitvectors\n",n);
+	}
+	break;
+      }
+      case BVSX:
+	//in BVSX(n[0],len), the length of the BVSX term must be
+	//greater than the length of n[0]
+	if(n[0].GetValueWidth() >= n.GetValueWidth()) {
+	  FatalError("BVTypeCheck: BVSX(t,bvsx_len) : length of 't' must be <= bvsx_len\n",n);
+	} 
+	break;
+      default:
+	for(ASTVec::iterator it=v.begin(),itend=v.end();it!=itend;it++)
+	  if(BITVECTOR_TYPE != it->GetType()) {
+	    cerr << "The type is: " << it->GetType() << endl;
+	    FatalError("BVTypeCheck:ChildNodes of bitvector-terms must be bitvectors\n",n);
+	  }
+	break;
+      }
+      
+      switch(k) {
+      case BVCONCAT:
+	if(n.Degree() != 2)
+	  FatalError("BVTypeCheck: should have exactly 2 args\n",n);
+	if(n.GetValueWidth() != n[0].GetValueWidth() + n[1].GetValueWidth())
+	  FatalError("BVTypeCheck:BVCONCAT: lengths do not add up\n",n);	
+	break;
+      case BVUMINUS:
+      case BVNEG:
+	if(n.Degree() != 1)
+	  FatalError("BVTypeCheck: should have exactly 1 args\n",n);
+	break;
+      case BVEXTRACT:
+	if(n.Degree() != 3)
+	  FatalError("BVTypeCheck: should have exactly 3 args\n",n);
+	if(!(BVCONST == n[1].GetKind() && BVCONST == n[2].GetKind()))
+	  FatalError("BVTypeCheck: indices should be BVCONST\n",n);
+	if(n.GetValueWidth() != GetUnsignedConst(n[1])- GetUnsignedConst(n[2])+1)
+	  FatalError("BVTypeCheck: length mismatch\n",n);
+	break;
+      case BVLEFTSHIFT:
+      case BVRIGHTSHIFT:
+	if(n.Degree() != 2)
+	  FatalError("BVTypeCheck: should have exactly 2 args\n",n);
+	break;
+	//case BVVARSHIFT:
+	//case BVSRSHIFT:
+	break;
+      default:
+	break;
+      }
+    }
+    else {
+      if(!(is_Form_kind(k) && BOOLEAN_TYPE == n.GetType()))
+	FatalError("BVTypeCheck: not a formula:",n);
+      switch(k){
+      case TRUE:
+      case FALSE:
+      case SYMBOL:
+	return;
+      case EQ:
+      case NEQ:	 
+	if(!(n[0].GetValueWidth() == n[1].GetValueWidth() &&
+	     n[0].GetIndexWidth() == n[1].GetIndexWidth())) {
+	  cerr << "valuewidth of lhs of EQ: " << n[0].GetValueWidth() << endl;
+	  cerr << "valuewidth of rhs of EQ: " << n[1].GetValueWidth() << endl;
+	  cerr << "indexwidth of lhs of EQ: " << n[0].GetIndexWidth() << endl;
+	  cerr << "indexwidth of rhs of EQ: " << n[1].GetIndexWidth() << endl;
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	}
+	break;
+      case BVLT:
+      case BVLE:
+      case BVGT:
+      case BVGE:
+      case BVSLT:
+      case BVSLE:
+      case BVSGT:
+      case BVSGE:	
+	if(BITVECTOR_TYPE != n[0].GetType() && BITVECTOR_TYPE != n[1].GetType())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be bitvectors",n);
+	if(n[0].GetValueWidth() != n[1].GetValueWidth())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	if(n[0].GetIndexWidth() != n[1].GetIndexWidth())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	break;
+      case NOT:
+	if(1 != n.Degree())
+	  FatalError("BVTypeCheck: NOT formula can have exactly one childNode",n);
+	break;
+      case AND:
+      case OR:
+      case XOR:
+      case NAND:
+      case NOR:
+	if(2 > n.Degree())
+	  FatalError("BVTypeCheck: AND/OR/XOR/NAND/NOR: must have atleast 2 ChildNodes",n);
+	break;
+      case IFF:
+      case IMPLIES:	
+	if(2 != n.Degree())
+	  FatalError("BVTypeCheck:IFF/IMPLIES must have exactly 2 ChildNodes",n);
+	break;
+      case ITE:
+	if(3 != n.Degree())
+	  FatalError("BVTypeCheck:ITE must have exactly 3 ChildNodes",n);		
+	break;
+      default:
+	FatalError("BVTypeCheck: Unrecognized kind: ",ASTUndefined);
+	break;
+      }
+    }
+  } //End of TypeCheck function
+
+  //add an assertion to the current logical context
+  void BeevMgr::AddAssert(const ASTNode& assert) {
+    if(!(is_Form_kind(assert.GetKind()) && BOOLEAN_TYPE == assert.GetType())) {
+      FatalError("AddAssert:Trying to assert a non-formula:",assert);
+    }
+      
+    ASTVec * v;
+    //if the stack of ASTVec is not empty, then take the top ASTVec
+    //and add the input assert to it
+    if(!_asserts.empty()) {
+      v = _asserts.back();
+      //v->push_back(TransformFormula(assert));
+      v->push_back(assert);
+    }
+    else {
+      //else create a logical context, and add it to the top of the
+      //stack
+      v = new ASTVec();
+      //v->push_back(TransformFormula(assert));
+      v->push_back(assert);
+      _asserts.push_back(v);	
+    }
+  }
+  
+  void BeevMgr::Push(void) {
+    ASTVec * v;
+    v = new ASTVec();
+    _asserts.push_back(v);
+  }
+  
+  void BeevMgr::Pop(void) {
+    if(!_asserts.empty()) {
+       ASTVec * c = _asserts.back();
+             //by calling the clear function we ensure that the ref count is
+             //decremented for the ASTNodes stored in c
+             c->clear();
+             delete c;
+      _asserts.pop_back();
+    }
+  }
+
+  void BeevMgr::AddQuery(const ASTNode& q) {
+    //_current_query = TransformFormula(q);
+    //cerr << "\nThe current query is: " << q << endl;
+    _current_query = q;
+  }
+    
+  const ASTNode BeevMgr::PopQuery() {
+    ASTNode q = _current_query;
+    _current_query = ASTTrue;
+    return q;
+  }
+   
+  const ASTNode BeevMgr::GetQuery() {
+    return _current_query;
+  }
+  
+  const ASTVec BeevMgr::GetAsserts(void) {
+    vector<ASTVec *>::iterator it = _asserts.begin();
+    vector<ASTVec *>::iterator itend = _asserts.end();
+    
+    ASTVec v;
+    for(;it!=itend;it++) {
+      if(!(*it)->empty())
+	  v.insert(v.end(),(*it)->begin(),(*it)->end());
+    }
+    return v;
+  }
+
+  //Create a new variable of ValueWidth 'n'
+  ASTNode BeevMgr::NewArrayVar(unsigned int index, unsigned int value) {
+    std:: string c("v");
+    char d[32];
+    sprintf(d,"%d",_symbol_count++);
+    std::string ccc(d);
+    c += "_writearray_" + ccc;
+    
+    ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+    CurrentSymbol.SetValueWidth(value);
+    CurrentSymbol.SetIndexWidth(index);
+    return CurrentSymbol;
+  } //end of NewArrayVar()
+
+
+  //Create a new variable of ValueWidth 'n'
+  ASTNode BeevMgr::NewVar(unsigned int value) {
+    std:: string c("v");
+    char d[32];
+    sprintf(d,"%d",_symbol_count++);
+    std::string ccc(d);
+    c += "_new_stp_var_" + ccc;
+    
+    ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+    CurrentSymbol.SetValueWidth(value);
+    CurrentSymbol.SetIndexWidth(0);
+    _introduced_symbols.insert(CurrentSymbol);
+    return CurrentSymbol;
+  } //end of NewVar()
+
+  //prints statistics for the ASTNode
+  void BeevMgr::ASTNodeStats(const char * c, const ASTNode& a){
+    if(!stats)
+      return;
+
+    StatInfoSet.clear();
+    //print node size:
+    cout << endl << "Printing: " << c;
+    if(print_nodes) {
+      //a.PL_Print(cout,0);
+      //cout << endl;
+      cout << a << endl;
+    }
+    cout << "Node size is: ";
+    cout << NodeSize(a) << endl << endl;    
+  }
+
+  unsigned int BeevMgr::NodeSize(const ASTNode& a, bool clearStatInfo) {    
+    if(clearStatInfo)
+      StatInfoSet.clear();
+
+    ASTNodeSet::iterator it;
+    if((it = StatInfoSet.find(a)) != StatInfoSet.end())
+      //has already been counted
+      return 0;
+
+    //record that you have seen this node already
+    StatInfoSet.insert(a);
+    
+    //leaf node has a size of 1
+    if(a.Degree() == 0)
+      return 1;
+
+    unsigned newn = 1;
+    ASTVec c = a.GetChildren();
+    for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
+      newn += NodeSize(*it);
+    return newn;
+  }
+
+  void BeevMgr::ClearAllTables(void) {
+    //clear all tables before calling toplevelsat
+    _ASTNode_to_SATVar.clear();
+    _SATVar_to_AST.clear();
+
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
+	  itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
+      delete it->second;
+    }
+    _ASTNode_to_Bitvector.clear();
+    
+    /* OLD Destructor
+     * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+
+    /*What should I do here? For ASTNodes?
+     * for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+    BBTermMemo.clear();
+    BBFormMemo.clear();
+    NodeLetVarMap.clear();
+    NodeLetVarMap1.clear();
+    PLPrintNodeSet.clear();
+    AlreadyPrintedSet.clear();
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    SolverMap.clear();
+    AlwaysTrueFormMap.clear();
+    _arrayread_ite.clear();
+    _arrayread_symbol.clear();
+    _introduced_symbols.clear();
+    TransformMap.clear();
+    _letid_expr_map.clear();
+    CounterExampleMap.clear();
+    ComputeFormulaMap.clear();
+    StatInfoSet.clear();
+
+    // for(std::vector<ASTVec *>::iterator it=_asserts.begin(),
+    // 	  itend=_asserts.end();it!=itend;it++) {
+    //       (*it)->clear();
+    //     }
+    _asserts.clear();
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), 
+	  iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      iset->second.clear();
+    }
+
+    _arrayname_readindices.clear();
+    _interior_unique_table.clear();
+    _symbol_unique_table.clear();
+    _bvconst_unique_table.clear();
+  }
+
+  void BeevMgr::ClearAllCaches(void) {
+    //clear all tables before calling toplevelsat
+    _ASTNode_to_SATVar.clear();
+    _SATVar_to_AST.clear();
+
+
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
+	  itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
+      delete it->second;
+    }
+    _ASTNode_to_Bitvector.clear();
+    
+    /*OLD destructor
+     * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+
+    /*What should I do here?
+     *for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+    BBTermMemo.clear();
+    BBFormMemo.clear();
+    NodeLetVarMap.clear();
+    NodeLetVarMap1.clear();
+    PLPrintNodeSet.clear();
+    AlreadyPrintedSet.clear();
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    SolverMap.clear();
+    AlwaysTrueFormMap.clear();
+    _arrayread_ite.clear();
+    _arrayread_symbol.clear();
+    _introduced_symbols.clear();
+    TransformMap.clear();
+    _letid_expr_map.clear();
+    CounterExampleMap.clear();
+    ComputeFormulaMap.clear();
+    StatInfoSet.clear();
+
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), 
+	  iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      iset->second.clear();
+    }
+
+    _arrayname_readindices.clear();
+    //_interior_unique_table.clear();
+    //_symbol_unique_table.clear();
+    //_bvconst_unique_table.clear();
+  }
+
+  void BeevMgr::CopySolverMap_To_CounterExample(void) {
+    if(!SolverMap.empty()) {
+      CounterExampleMap.insert(SolverMap.begin(),SolverMap.end());
+    }
+  }
+
+  void FatalError(const char * str, const ASTNode& a, int w) {
+    if(a.GetKind() != UNDEFINED) {
+      cerr << "Fatal Error: " << str << endl << a << endl;
+      cerr << w << endl;
+    }
+    else {
+      cerr << "Fatal Error: " << str << endl;
+      cerr << w << endl;
+    }
+    if (vc_error_hdlr)
+      vc_error_hdlr(str);
+    exit(-1);
+    //assert(0);
+  }
+
+  void FatalError(const char * str) {
+    cerr << "Fatal Error: " << str << endl;
+    if (vc_error_hdlr)
+      vc_error_hdlr(str);
+    exit(-1);
+    //assert(0);
+  }
+
+  //Variable Order Printer: A global function which converts a MINISAT
+  //var into a ASTNODE var. It then prints this var along with
+  //variable order dcisions taken by MINISAT.
+  void Convert_MINISATVar_To_ASTNode_Print(int minisat_var, 
+  					   int decision_level, int polarity) {
+    BEEV::ASTNode vv = globalBeevMgr_for_parser->_SATVar_to_AST[minisat_var];
+    cout << spaces(decision_level);
+    if(polarity) {
+      cout << "!";
+    }
+    vv.PL_Print(cout,0);
+    cout << endl;
+  }
+
+  void SortByExprNum(ASTVec& v) {
+    sort(v.begin(), v.end(), exprless);
+  }
+
+  bool isAtomic(Kind kind) {
+    if(TRUE == kind ||
+       FALSE == kind ||
+       EQ == kind ||
+       NEQ == kind ||
+       BVLT == kind ||
+       BVLE == kind ||
+       BVGT == kind ||
+       BVGE == kind ||
+       BVSLT == kind ||
+       BVSLE == kind ||
+       BVSGT == kind ||
+       BVSGE == kind ||
+       SYMBOL == kind ||
+       BVGETBIT == kind)
+      return true;
+    return false;
+  }
+
+  BeevMgr::~BeevMgr() {
+    ClearAllTables();
+  }
+}; // end namespace
+

Added: klee/trunk/stp/AST/AST.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/AST.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/AST.h (added)
+++ klee/trunk/stp/AST/AST.h Wed May 20 23:36:41 2009
@@ -0,0 +1,1805 @@
+// -*- c++ -*-
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+
+#ifndef AST_H
+#define AST_H
+#include <vector>
+#ifdef EXT_HASH_MAP
+#include <ext/hash_set>
+#include <ext/hash_map>
+#else
+#include <hash_set>
+#include <hash_map>
+#endif
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <map>
+#include <set>
+#include "ASTUtil.h"
+#include "ASTKind.h"
+#include "../sat/Solver.h"
+#include "../sat/SolverTypes.h"
+#include <cstdlib>
+#ifndef NATIVE_C_ARITH
+#include "../constantbv/constantbv.h"
+#endif
+/*****************************************************************************
+ * LIST OF CLASSES DECLARED IN THIS FILE:
+ *
+ * class BeevMgr;  
+ * class ASTNode; 
+ * class ASTInternal;  
+ * class ASTInterior;  
+ * class ASTSymbol;
+ * class ASTBVConst;
+ *****************************************************************************/
+namespace BEEV {
+  using namespace std; 
+  using namespace MINISAT;
+#ifdef EXT_HASH_MAP
+  using namespace __gnu_cxx;
+#endif
+
+  //return types for the GetType() function in ASTNode class
+  enum types {
+    BOOLEAN_TYPE = 0,
+    BITVECTOR_TYPE,
+    ARRAY_TYPE,
+    UNKNOWN_TYPE
+  };
+  
+  class BeevMgr;  
+  class ASTNode; 
+  class ASTInternal;  
+  class ASTInterior;  
+  class ASTSymbol;
+  class ASTBVConst;
+  class BVSolver;
+
+  //Vector of ASTNodes, used for child nodes among other things.  
+  typedef vector<ASTNode> ASTVec;
+  extern ASTVec _empty_ASTVec;
+  extern BeevMgr * globalBeevMgr_for_parser;
+
+  typedef unsigned int * CBV;
+
+  /***************************************************************************/
+  /*  Class ASTNode: Smart pointer to actual ASTNode internal datastructure. */
+  /***************************************************************************/
+  class ASTNode {
+    friend class BeevMgr;
+    friend class vector<ASTNode>;
+    //Print the arguments in lisp format.
+    friend ostream &LispPrintVec(ostream &os, 
+				 const ASTVec &v, int indentation = 0); 
+
+  private:
+    // FIXME: make this into a reference?
+    ASTInternal * _int_node_ptr;	// The real data.
+
+    // Usual constructor.  
+    ASTNode(ASTInternal *in);
+
+    //Check if it points to a null node
+    bool IsNull () const { return _int_node_ptr == NULL; }
+
+    //Equal iff ASTIntNode pointers are the same.
+    friend bool operator==(const ASTNode node1, const ASTNode node2){
+      return ((size_t) node1._int_node_ptr) == ((size_t) node2._int_node_ptr);
+    }
+    
+    /* FIXME:  Nondeterministic code *** */
+    /** questionable pointer comparison function */
+    friend bool operator<(const ASTNode node1, const ASTNode node2){
+      return ((size_t) node1._int_node_ptr) < ((size_t) node2._int_node_ptr);
+    }
+
+  public:
+    // This is for sorting by expression number (used in Boolean
+    //optimization)
+    friend bool exprless(const ASTNode n1, const ASTNode n2) {
+      Kind k1 = n1.GetKind();
+      Kind k2 = n2.GetKind();
+      
+      if(BVCONST == k1 && BVCONST != k2){
+	return true;
+      }
+      if(BVCONST != k1 && BVCONST == k2){
+	return false;
+      }
+      
+      if(SYMBOL == k1 && SYMBOL != k2) {
+      	return true;
+      }
+      
+      if(SYMBOL != k1 && SYMBOL == k2) {
+      	return false;
+      }
+
+      return (n1.GetNodeNum() < n2.GetNodeNum());
+    }//end of exprless 
+    
+    // Internal lisp-form printer that does not clear _node_print_table
+    ostream &LispPrint1(ostream &os, int indentation) const;
+
+    ostream &LispPrint_indent(ostream &os, int indentation) const;
+
+    // For lisp DAG printing.  Has it been printed already, so we can
+    // just print the node number?
+    bool IsAlreadyPrinted() const;
+    void MarkAlreadyPrinted() const;
+
+  public:
+    // Default constructor.  This gets used when declaring an ASTVec
+    // of a given size, in the hash table, etc.  For faster
+    // refcounting, create a symbol node for NULL.  Give it a big
+    // initial refcount.  Never free it.  also check, for ref-count
+    // overflow?
+    ASTNode() : _int_node_ptr(NULL) { };
+
+    // Copy constructor
+    ASTNode(const ASTNode &n);
+
+    // Destructor
+    ~ASTNode();
+
+    // Assignment (for ref counting)
+    ASTNode& operator=(const ASTNode& n);
+
+    BeevMgr &GetBeevMgr() const;
+
+    // Access node number
+    int GetNodeNum() const;
+
+    // Access kind.  Inlined later because of declaration ordering problems.
+    Kind GetKind() const;
+
+    // access Children
+    const ASTVec &GetChildren() const;
+    
+    // Return the number of child nodes
+    size_t Degree() const{ 
+      return GetChildren().size(); 
+    };    
+
+    // Get indexth childNode.
+    const ASTNode operator[](size_t index) const { 
+      return GetChildren()[index]; 
+    };    
+
+    // Get begin() iterator for child nodes
+    ASTVec::const_iterator begin() const{ 
+      return GetChildren().begin(); 
+    };  
+
+    // Get end() iterator for child nodes
+    ASTVec::const_iterator end() const{ 
+      return GetChildren().end(); 
+    };
+
+    //Get back() element for child nodes
+    const ASTNode back() const{
+      return GetChildren().back();
+    };  
+
+    // Get the name from a symbol (char *).  It's an error if kind != SYMBOL
+    const char * const GetName() const;
+
+    //Get the BVCONST value
+#ifndef NATIVE_C_ARITH
+    const CBV GetBVConst() const;
+#else
+    unsigned long long int GetBVConst() const;
+#endif
+
+    /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
+     *
+     *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
+     *
+     *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+     *
+     *both indexwidth and valuewidth should never be less than 0
+     */
+    unsigned int GetIndexWidth () const;
+
+    // FIXME: This function is dangerous.  Try to eliminate it's use.
+    void SetIndexWidth (unsigned int iw) const;
+
+    unsigned int GetValueWidth () const;
+
+    // FIXME: This function is dangerous.  Try to eliminate it's use.
+    void SetValueWidth (unsigned int vw) const;
+
+    //return the type of the ASTNode
+    //0 iff BOOLEAN
+    //1 iff BITVECTOR
+    //2 iff ARRAY
+
+    /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
+     *
+     *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
+     *
+     *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+     *
+     *both indexwidth and valuewidth should never be less than 0
+     */    
+    types GetType(void) const;
+
+    // Hash is pointer value of _int_node_ptr.
+    const size_t Hash() const{ 
+      return (size_t) _int_node_ptr; 
+      //return GetNodeNum(); 
+    }
+
+    // lisp-form printer 
+    ostream& LispPrint(ostream &os, int indentation = 0) const;
+
+    //Presentation Language Printer
+    ostream& PL_Print(ostream &os, int indentation = 0) const;
+
+    void PL_Print1(ostream &os, int indentation = 0, bool b = false) const;
+
+    //Construct let variables for shared subterms
+    void LetizeNode(void) const;
+
+    // Attempt to define something that will work in the gdb
+    friend void lp(ASTNode &node);
+    friend void lpvec(const ASTVec &vec);
+
+    friend ostream &operator<<(ostream &os, const ASTNode &node) { 
+      node.LispPrint(os, 0); 
+      return os; 
+    };
+    
+    // Check whether the ASTNode points to anything.  Undefined nodes
+    // are created by the default constructor.  In binding table (for
+    // lambda args, etc.), undefined nodes are used to represent
+    // deleted entries.
+    bool IsDefined() const { return _int_node_ptr != NULL; }        
+
+    /* Hasher class for STL hash_maps and hash_sets that use ASTNodes
+     * as keys.  Needs to be public so people can define hash tables
+     * (and use ASTNodeMap class)*/
+    class ASTNodeHasher {
+    public:
+      size_t operator() (const ASTNode& n) const{ 
+	return (size_t) n._int_node_ptr; 
+	//return (size_t)n.GetNodeNum();
+      };
+    }; //End of ASTNodeHasher
+  
+    /* Equality for ASTNode hash_set and hash_map. Returns true iff
+     * internal pointers are the same.  Needs to be public so people
+     * can define hash tables (and use ASTNodeSet class)*/
+    class ASTNodeEqual {
+    public:
+      bool operator()(const ASTNode& n1, const ASTNode& n2) const{ 
+	return (n1._int_node_ptr == n2._int_node_ptr); 
+      }
+    }; //End of ASTNodeEqual
+  }; //End of Class ASTNode
+
+  void FatalError(const char * str, const ASTNode& a, int w = 0);
+  void FatalError(const char * str);
+  void SortByExprNum(ASTVec& c);
+  bool exprless(const ASTNode n1, const ASTNode n2);
+  bool isAtomic(Kind k);
+
+  /***************************************************************************/
+  /*  Class ASTInternal:Abstract base class for internal node representation.*/
+  /*                    Requires Kind and ChildNodes so same traversal works */
+  /*                    on all nodes.                                        */
+  /***************************************************************************/
+  class ASTInternal {
+
+    friend class ASTNode;
+
+  protected:    
+
+    // reference count.
+    int _ref_count;
+
+    // Kind.  It's a type tag and the operator.
+    Kind _kind;  
+
+    // The vector of children (*** should this be in ASTInterior? ***)
+    ASTVec _children;
+
+    // Manager object.  Having this backpointer means it's easy to
+    // find the manager when we need it.
+    BeevMgr &_bm;
+
+    //Nodenum is a unique positive integer for the node.  The nodenum
+    //of a node should always be greater than its descendents (which
+    //is easily achieved by incrementing the number each time a new
+    //node is created).
+    int _node_num;
+
+    // Length of bitvector type for array index.  The term is an
+    // array iff this is positive.  Otherwise, the term is a bitvector
+    // or a bit.
+    unsigned int _index_width;
+
+    // Length of bitvector type for scalar value or array element.
+    // If this is one, the term represents a single bit (same as a bitvector
+    // of length 1).  It must be 1 or greater.
+    unsigned int _value_width;
+
+    // Increment refcount.
+#ifndef SMTLIB
+    void IncRef() { ++_ref_count; }
+#else
+    void IncRef() { }
+#endif
+
+    // DecRef is a potentially expensive, because it has to delete 
+    // the node from the unique table, in addition to freeing it.
+    // FIXME:  Consider putting in a backpointer (iterator) to the hash
+    // table entry so it can be deleted without looking it up again.
+    void DecRef();
+
+    virtual const Kind GetKind() const { return _kind; }
+
+    virtual ASTVec const &GetChildren() const { return _children; }
+
+    int GetNodeNum() const { return _node_num; }
+
+    void SetNodeNum(int nn) { _node_num = nn; };
+
+    // Constructor (bm only)
+    ASTInternal(BeevMgr &bm, int nodenum = 0) :
+      _ref_count(0),
+      _kind(UNDEFINED),
+      _bm(bm),
+      _node_num(nodenum),
+      _index_width(0),
+      _value_width(0) { }
+
+    // Constructor (kind only, empty children, int nodenum) 
+    ASTInternal(Kind kind, BeevMgr &bm, int nodenum = 0) : 
+      _ref_count(0),
+      _kind(kind),
+      _bm(bm),
+      _node_num(nodenum),
+      _index_width(0),
+      _value_width(0) { } 
+
+    // Constructor (kind and children).  This copies the contents of
+    // the child nodes.
+    // FIXME: is there a way to avoid repeating these?
+    ASTInternal(Kind kind, const ASTVec &children, BeevMgr &bm, int nodenum = 0) : 
+      _ref_count(0),
+      _kind(kind),
+      _children(children),
+      _bm(bm),
+      _node_num(nodenum),
+      _index_width(0),
+      _value_width(0) { } 
+
+    // Copy constructor.  This copies the contents of the child nodes
+    // array, along with everything else.  Assigning the smart pointer,
+    // ASTNode, does NOT invoke this; This should only be used for 
+    // temporary hash keys before uniquefication.
+    // FIXME:  I don't think children need to be copied.
+    ASTInternal(const ASTInternal &int_node, int nodenum = 0) :
+      _ref_count(0),
+      _kind(int_node._kind),
+      _children(int_node._children),
+      _bm(int_node._bm),
+      _node_num(int_node._node_num), 
+      _index_width(int_node._index_width),
+      _value_width(int_node._value_width) { } 
+
+    // Copying assign operator.  Also copies contents of children.
+    ASTInternal& operator=(const ASTInternal &int_node);
+
+    // Cleanup function for removing from hash table
+    virtual void CleanUp() = 0;
+
+    // Destructor (does nothing, but is declared virtual here.
+    virtual ~ASTInternal();
+
+    // Abstract virtual print function for internal node.
+    virtual void nodeprint(ostream& os) { os << "*"; };
+  }; //End of Class ASTInternal
+
+  // FIXME: Should children be only in interior node type?
+  /***************************************************************************
+    Class ASTInterior: Internal representation of an interior
+       ASTNode.  Generally, these nodes should have at least one
+      child
+  ***************************************************************************/
+  class ASTInterior : public ASTInternal {    
+
+    friend class BeevMgr;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;   
+
+  private:
+
+    // Hasher for ASTInterior pointer nodes
+    class ASTInteriorHasher {
+    public:
+      size_t operator()(const ASTInterior *int_node_ptr) const;
+    };
+
+    // Equality for ASTInterior nodes
+    class ASTInteriorEqual {
+    public:
+      bool operator()(const ASTInterior *int_node_ptr1, 
+		      const ASTInterior *int_node_ptr2) const{
+	return (*int_node_ptr1 == *int_node_ptr2);
+      }
+    };
+
+    // Used in Equality class for hash tables
+    friend bool operator==(const ASTInterior &int_node1, 
+			   const ASTInterior &int_node2){
+      return (int_node1._kind == int_node2._kind) && 
+	(int_node1._children == int_node2._children);
+    }
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    // Returns kinds.  "lispprinter" handles printing of parenthesis
+    // and childnodes.
+    virtual void nodeprint(ostream& os) {
+      os << _kind_names[_kind];
+    }
+    public:
+
+    // FIXME: This should not be public, but has to be because the
+    // ASTInterior hash table insists on it.  I can't seem to make the
+    // private destructor visible to hash_set.  It does not even work
+    // to put "friend class hash_set<ASTInterior, ...>" in here.
+
+    // Basic constructors
+    ASTInterior(Kind kind,  BeevMgr &bm) :
+      ASTInternal(kind, bm) {  }    
+
+    ASTInterior(Kind kind, ASTVec &children, BeevMgr &bm) :
+      ASTInternal(kind, children, bm) {  }    
+
+    //Copy constructor.  This copies the contents of the child nodes
+    //array, along with everything else. Assigning the smart pointer,
+    //ASTNode, does NOT invoke this.
+    ASTInterior(const ASTInterior &int_node) : ASTInternal(int_node) { }
+
+    // Destructor (does nothing, but is declared virtual here.
+    virtual ~ASTInterior();
+
+  }; //End of ASTNodeInterior
+
+
+  /***************************************************************************/
+  /*  Class ASTSymbol:  Class to represent internals of Symbol node.         */
+  /***************************************************************************/
+  class ASTSymbol : public ASTInternal{
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+
+  private:
+    // The name of the symbol
+    const char * const _name;
+    
+    class ASTSymbolHasher{
+    public:
+      size_t operator() (const ASTSymbol *sym_ptr) const{ 
+	hash<char*> h; 
+	return h(sym_ptr->_name); 
+      };
+    };
+
+    // Equality for ASTInternal nodes
+    class ASTSymbolEqual{
+    public:
+      bool operator()(const ASTSymbol *sym_ptr1, const ASTSymbol *sym_ptr2) const{ 
+	return (*sym_ptr1 == *sym_ptr2); 
+      }
+    };
+
+    friend bool operator==(const ASTSymbol &sym1, const ASTSymbol &sym2){
+      return (strcmp(sym1._name, sym2._name) == 0);
+    }
+
+    const char * const GetName() const{return _name;}  
+
+    // Print function for symbol -- return name */
+    virtual void nodeprint(ostream& os) { os << _name;}
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    public:
+
+    // Default constructor
+    ASTSymbol(BeevMgr &bm) : ASTInternal(bm), _name(NULL) { }
+
+    // Constructor.  This does NOT copy its argument.
+    ASTSymbol(const char * const name, BeevMgr &bm) : ASTInternal(SYMBOL, bm), 
+						      _name(name) { }
+    
+    // Destructor (does nothing, but is declared virtual here.
+    virtual ~ASTSymbol();
+    
+    // Copy constructor
+    // FIXME: seems to be calling default constructor for astinternal
+    ASTSymbol(const ASTSymbol &sym) :
+      ASTInternal(sym._kind, sym._children, sym._bm), 
+      _name(sym._name) { } 
+  }; //End of ASTSymbol
+  
+
+  /***************************************************************************/
+  /*  Class ASTBVConst:  Class to represent internals of a bitvectorconst    */
+  /***************************************************************************/
+
+#ifndef NATIVE_C_ARITH
+
+  class ASTBVConst : public ASTInternal {
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+    
+  private:
+    //This is the private copy of a bvconst currently
+    //This should not be changed at any point
+    CBV _bvconst;
+
+    class ASTBVConstHasher{
+    public:
+      size_t operator() (const ASTBVConst * bvc) const {
+        return CONSTANTBV::BitVector_Hash(bvc->_bvconst);
+      };
+    };
+
+    class ASTBVConstEqual{
+    public:
+      bool operator()(const ASTBVConst * bvc1, const ASTBVConst  * bvc2) const { 
+        if( bvc1->_value_width != bvc2->_value_width){
+	  return false;
+	}  
+	return (0==CONSTANTBV::BitVector_Compare(bvc1->_bvconst,bvc2->_bvconst));
+      }
+    };
+    
+    //FIXME Keep an eye on this function
+    ASTBVConst(CBV bv, unsigned int width, BeevMgr &bm) :
+      ASTInternal(BVCONST, bm)
+    {
+      _bvconst = CONSTANTBV::BitVector_Clone(bv);
+      _value_width = width;
+    }
+
+    friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2){
+      if(bvc1._value_width != bvc2._value_width)
+        return false;
+      return (0==CONSTANTBV::BitVector_Compare(bvc1._bvconst,bvc2._bvconst));
+    }
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    // Print function for bvconst -- return _bvconst value in bin format
+    virtual void nodeprint(ostream& os) {
+      unsigned char *res;
+      const char *prefix;
+
+      if (_value_width%4 == 0) {
+        res = CONSTANTBV::BitVector_to_Hex(_bvconst);
+        prefix = "0hex";
+      } else {      
+        res = CONSTANTBV::BitVector_to_Bin(_bvconst);
+        prefix = "0bin";
+      }
+      if (NULL == res) {
+        os << "nodeprint: BVCONST : could not convert to string" << _bvconst;
+        FatalError("");
+      }
+      os << prefix << res;
+      CONSTANTBV::BitVector_Dispose(res);
+    }
+
+    // Copy constructor.     
+    ASTBVConst(const ASTBVConst &sym) : 
+      ASTInternal(sym._kind, sym._children, sym._bm)
+    {
+      _bvconst = CONSTANTBV::BitVector_Clone(sym._bvconst);
+      _value_width = sym._value_width;
+    }
+    
+  public:
+    virtual ~ASTBVConst(){
+       CONSTANTBV::BitVector_Destroy(_bvconst);
+    }
+
+    CBV GetBVConst() const {return _bvconst;}
+  }; //End of ASTBVConst
+
+  //FIXME This function is DEPRICATED
+  //Do not use in the future
+  inline unsigned int GetUnsignedConst(const ASTNode n) {
+    if(32 < n.GetValueWidth())
+      FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");
+        
+    return (unsigned int) *((unsigned int *)n.GetBVConst());
+  }
+#else
+  class ASTBVConst : public ASTInternal {
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+
+  private:
+    // the bitvector contents. bitvector contents will be in two
+    // modes. one mode where all bitvectors are NATIVE and in this
+    // mode we use native unsigned long long int to represent the
+    // 32/64 bitvectors. The other for arbitrary length bitvector
+    // operations.
+    const unsigned long long int _bvconst;
+
+    class ASTBVConstHasher{
+    public:
+      size_t operator() (const ASTBVConst * bvc) const{ 
+	//Thomas Wang's 64 bit Mix Function
+	unsigned long long int key(bvc->_bvconst);
+	key += ~(key << 32);
+	key ^= (key  >> 22);
+	key += ~(key << 13);
+	key ^= (key  >> 8);
+	key += (key  << 3);
+	key ^= (key  >> 15);
+	key += ~(key << 27);
+	key ^= (key  >> 31);
+	
+	size_t return_key = key;
+	return return_key;
+      };
+    };
+
+    class ASTBVConstEqual{
+    public:
+      bool operator()(const ASTBVConst * bvc1, const ASTBVConst  * bvc2) const { 
+	return ((bvc1->_bvconst == bvc2->_bvconst) 
+		&& (bvc1->_value_width == bvc2->_value_width));
+      }
+    };
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+  public:
+    // Default constructor
+    ASTBVConst(const unsigned long long int bv, BeevMgr &bm) : 
+      ASTInternal(BVCONST, bm), _bvconst(bv) { 
+    }
+
+    // Copy constructor. FIXME: figure out how this is supposed to
+    // work.
+    ASTBVConst(const ASTBVConst &sym) : 
+      ASTInternal(sym._kind, sym._children, sym._bm), 
+      _bvconst(sym._bvconst) { 
+      _value_width = sym._value_width;
+    } 
+
+    // Destructor (does nothing, but is declared virtual here)
+    virtual ~ASTBVConst() { } 
+    
+    friend bool operator==(const ASTBVConst &sym1, const ASTBVConst &sym2){
+      return ((sym1._bvconst == sym2._bvconst) && 
+	      (sym1._value_width == sym2._value_width));
+    }
+
+    // Print function for bvconst -- return _bvconst value in binary format
+    virtual void nodeprint(ostream& os) {
+      string s = "0bin";
+      unsigned long long int bitmask = 0x8000000000000000LL;
+      bitmask = bitmask >> (64-_value_width);
+
+      for (; bitmask > 0; bitmask >>= 1)
+	s += (_bvconst & bitmask) ? '1' : '0';	
+      os << s;
+    }
+    
+    unsigned long long int GetBVConst() const  {return _bvconst;}
+  }; //End of ASTBVConst
+
+  //return value of bvconst
+  inline unsigned int GetUnsignedConst(const ASTNode n) {
+    if(32 < n.GetValueWidth())
+      FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");    
+    return (unsigned int)n.GetBVConst();
+  }
+#endif
+/*
+#else
+  // the bitvector contents. bitvector contents will be in two
+  // modes. one mode where all bitvectors are NATIVE and in this mode
+  // we use native unsigned long long int to represent the 32/64
+  // bitvectors. The other for arbitrary length bitvector operations.
+
+  //BVCONST defined for arbitrary length bitvectors
+  class ASTBVConst : public ASTInternal{
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+
+  private:
+    const char * const _bvconst;
+
+    class ASTBVConstHasher{
+    public:
+      size_t operator() (const ASTBVConst * bvc) const{ 
+	hash<char*> h;	
+	return h(bvc->_bvconst);
+      };
+    };
+
+    class ASTBVConstEqual{
+    public:
+      bool operator()(const ASTBVConst * bvc1, const ASTBVConst  * bvc2) const { 
+	if(bvc1->_value_width != bvc2->_value_width)
+	  return false;
+	return (0 == strncmp(bvc1->_bvconst,bvc2->_bvconst,bvc1->_value_width));
+      }
+    };
+    
+    ASTBVConst(const char * bv, BeevMgr &bm) : 
+      ASTInternal(BVCONST, bm), _bvconst(bv) { 
+      //_value_width = strlen(bv);
+    }
+
+    friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2){
+      if(bvc1._value_width != bvc2._value_width)
+	return false;
+      return (0 == strncmp(bvc1._bvconst,bvc2._bvconst,bvc1._value_width));
+    }
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    // Print function for bvconst -- return _bvconst value in binary format
+    virtual void nodeprint(ostream& os) {
+      if(_value_width%4 == 0) {
+	unsigned int *  iii = CONSTANTBV::BitVector_Create(_value_width,true);
+	CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,(unsigned char*)_bvconst);
+	//error printing
+	if(0 != e) {
+	  os << "nodeprint: BVCONST : wrong hex value: " << BitVector_Error(e);
+	  FatalError("");
+	}
+	unsigned char * ccc = CONSTANTBV::BitVector_to_Hex(iii);
+	os << "0hex" << ccc;
+	CONSTANTBV::BitVector_Destroy(iii);
+      }
+      else {
+	std::string s(_bvconst,_value_width);
+	s = "0bin" + s;
+	os << s;
+      }
+    }
+
+    // Copy constructor.     
+    ASTBVConst(const ASTBVConst &sym) : ASTInternal(sym._kind, sym._children, sym._bm),_bvconst(sym._bvconst) { 
+      //checking if the input is in the correct format
+      for(unsigned int jj=0;jj<sym._value_width;jj++)
+	if(!(sym._bvconst[jj] == '0' || sym._bvconst[jj] == '1')) {
+	  cerr << "Fatal Error: wrong input to ASTBVConst copy constructor:" << sym._bvconst << endl;
+	  FatalError("");
+	}
+      _value_width = sym._value_width;
+    } 
+  public:
+    // Destructor (does nothing, but is declared virtual here)
+    virtual ~ASTBVConst(){}
+
+    const char * const GetBVConst() const {return _bvconst;}
+  }; //End of ASTBVConst
+
+  unsigned int * ConvertToCONSTANTBV(const char * s);
+
+  //return value of bvconst
+  inline unsigned int GetUnsignedConst(const ASTNode n) {
+    if(32 < n.GetValueWidth())
+      FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");    
+    std::string s(n.GetBVConst(), n.GetValueWidth());
+      unsigned int output = strtoul(s.c_str(),NULL,2);
+      return output;
+  } //end of ASTBVConst class
+#endif
+*/
+  /***************************************************************************
+   * Typedef ASTNodeMap:  This is a hash table from ASTNodes to ASTNodes.
+   * It is very convenient for attributes that are not speed-critical
+   **************************************************************************/
+  // These are generally useful for storing ASTNodes or attributes thereof
+  // Hash table from ASTNodes to ASTNodes
+  typedef hash_map<ASTNode, ASTNode, 
+		   ASTNode::ASTNodeHasher, 
+		   ASTNode::ASTNodeEqual> ASTNodeMap;
+
+  // Function to dump contents of ASTNodeMap
+  ostream &operator<<(ostream &os, const ASTNodeMap &nmap);
+  
+  /***************************************************************************
+   Typedef ASTNodeSet:  This is a hash set of ASTNodes.  Very useful
+   for representing things like "visited nodes"
+  ***************************************************************************/
+  typedef hash_set<ASTNode, 
+		   ASTNode::ASTNodeHasher, 
+		   ASTNode::ASTNodeEqual> ASTNodeSet;
+
+  typedef hash_multiset<ASTNode, 
+			ASTNode::ASTNodeHasher, 
+			ASTNode::ASTNodeEqual> ASTNodeMultiSet;
+
+  //external parser table for declared symbols.
+  //FIXME: move to a more appropriate place
+  extern ASTNodeSet _parser_symbol_table;
+  
+  /***************************************************************************
+    Class LispPrinter:  iomanipulator for printing ASTNode or ASTVec       
+  ***************************************************************************/
+  class LispPrinter {
+
+  public:
+    ASTNode _node;
+
+    // number of spaces to print before first real character of
+    // object.
+    int _indentation;  
+
+    // FIXME: pass ASTNode by reference
+    // Constructor to build the LispPrinter object
+    LispPrinter(ASTNode node, int indentation): _node(node), _indentation(indentation) { }    
+
+    friend ostream &operator<<(ostream &os, const LispPrinter &lp){ 
+      return lp._node.LispPrint(os, lp._indentation); 
+    };
+
+  }; //End of ListPrinter
+  
+  //This is the IO manipulator.  It builds an object of class
+  //"LispPrinter" that has a special overloaded "<<" operator.
+  inline LispPrinter lisp(const ASTNode &node, int indentation = 0){
+    LispPrinter lp(node, indentation);
+    return lp;
+  }
+  
+  /***************************************************************************/
+  /*  Class LispVecPrinter:iomanipulator for printing vector of ASTNodes     */
+  /***************************************************************************/
+  class LispVecPrinter {
+
+  public:
+    const ASTVec * _vec;
+    // number of spaces to print before first real
+    // character of object.    
+    int _indentation;
+    
+    // Constructor to build the LispPrinter object
+    LispVecPrinter(const ASTVec &vec, int indentation){
+      _vec = &vec; _indentation = indentation; 
+    }
+    
+    friend ostream &operator<<(ostream &os, const LispVecPrinter &lvp){
+    LispPrintVec(os, *lvp._vec, lvp._indentation);
+    return os;
+    };
+  }; //End of Class ListVecPrinter
+
+  //iomanipulator. builds an object of class "LisPrinter" that has a
+  //special overloaded "<<" operator.
+  inline LispVecPrinter lisp(const ASTVec &vec, int indentation = 0){
+    LispVecPrinter lvp(vec, indentation);
+    return lvp;
+  }
+
+
+  /*****************************************************************
+   * INLINE METHODS from various classed, declared here because of
+   * dependencies on classes that are declared later.
+   *****************************************************************/
+  // ASTNode accessor function.
+  inline Kind ASTNode::GetKind() const { 
+    //cout << "GetKind: " << _int_node_ptr; 
+    return _int_node_ptr->GetKind(); 
+  }
+
+  // FIXME: should be const ASTVec const?  
+  // Declared here because of same ordering problem as  GetKind.
+  inline const ASTVec &ASTNode::GetChildren() const { 
+    return _int_node_ptr->GetChildren(); 
+  }
+
+  // Access node number
+  inline int ASTNode::GetNodeNum() const { 
+    return _int_node_ptr->_node_num; 
+  }
+
+  inline unsigned int ASTNode::GetIndexWidth () const { 
+    return _int_node_ptr->_index_width; 
+  }
+  
+  inline void ASTNode::SetIndexWidth (unsigned int iw) const { 
+    _int_node_ptr->_index_width = iw;
+  }
+  
+  inline unsigned int ASTNode::GetValueWidth () const { 
+    return _int_node_ptr->_value_width; 
+  }
+  
+  inline void ASTNode::SetValueWidth (unsigned int vw) const {
+    _int_node_ptr->_value_width = vw; 
+  }
+
+  //return the type of the ASTNode: 0 iff BOOLEAN; 1 iff BITVECTOR; 2
+  //iff ARRAY; 3 iff UNKNOWN;
+  inline types ASTNode::GetType() const {
+    if((GetIndexWidth() == 0) && (GetValueWidth() == 0)) //BOOLEAN
+      return BOOLEAN_TYPE;
+    if((GetIndexWidth() == 0) && (GetValueWidth() > 0))  //BITVECTOR
+      return BITVECTOR_TYPE;
+    if((GetIndexWidth() > 0) && (GetValueWidth() > 0)) //ARRAY
+      return ARRAY_TYPE;
+    return UNKNOWN_TYPE; 
+  }
+
+  // Constructor; creates a new pointer, increments refcount of
+  // pointed-to object.
+#ifndef SMTLIB
+  inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in) { 
+    if (in) in->IncRef(); 
+  }
+#else
+  inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in) { };
+#endif
+
+  // Assignment.  Increment refcount of new value, decrement refcount
+  // of old value and destroy if this was the last pointer.  FIXME:
+  // accelerate this by creating an intnode with a ref counter instead
+  // of pointing to NULL.  Need a special check in CleanUp to make
+  // sure the null node never gets freed.
+
+#ifndef SMTLIB
+  inline ASTNode& ASTNode::operator=(const ASTNode& n) {
+    if (n._int_node_ptr) {
+      n._int_node_ptr->IncRef();
+    }
+    if (_int_node_ptr) {
+      _int_node_ptr->DecRef();
+    }
+    _int_node_ptr = n._int_node_ptr;
+    return *this;
+  }
+#else
+  inline ASTNode& ASTNode::operator=(const ASTNode& n) {
+    _int_node_ptr = n._int_node_ptr;
+    return *this;
+  }
+#endif
+
+#ifndef SMTLIB
+  inline void ASTInternal::DecRef()
+  {
+    if (--_ref_count == 0) {
+      // Delete node from unique table and kill it.
+      CleanUp();
+    }
+  }
+
+  // Destructor
+  inline ASTNode::~ASTNode()
+  {
+    if (_int_node_ptr) {
+      _int_node_ptr->DecRef();
+    }
+  };
+#else
+  // No refcounting
+  inline void ASTInternal::DecRef()
+  {
+  }
+
+  // Destructor
+  inline ASTNode::~ASTNode()
+  {
+  };
+#endif
+
+  inline BeevMgr& ASTNode::GetBeevMgr() const { return _int_node_ptr->_bm; }
+
+  /***************************************************************************
+   * Class BeevMgr.  This holds all "global" variables for the system, such as
+   * unique tables for the various kinds of nodes.
+   ***************************************************************************/
+  class BeevMgr {
+    friend class ASTNode;	// ASTNode modifies AlreadyPrintedSet
+				// in BeevMgr
+    friend class ASTInterior;
+    friend class ASTBVConst;
+    friend class ASTSymbol;
+
+    // FIXME: The values appear to be the same regardless of the value of SMTLIB
+    // initial hash table sizes, to save time on resizing.
+#ifdef SMTLIB
+    static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
+    static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
+
+    static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
+    static const int INITIAL_SOLVER_MAP_SIZE = 100;
+    static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
+    static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
+#else
+    // these are the STL defaults
+    static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
+    static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
+
+    static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
+    static const int INITIAL_SOLVER_MAP_SIZE = 100;
+    static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
+    static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
+#endif
+
+  private:
+    // Typedef for unique Interior node table. 
+    typedef hash_set<ASTInterior *, 
+		     ASTInterior::ASTInteriorHasher, 
+		     ASTInterior::ASTInteriorEqual> ASTInteriorSet;
+
+    // Typedef for unique Symbol node (leaf) table.
+    typedef hash_set<ASTSymbol *, 
+		     ASTSymbol::ASTSymbolHasher, 
+		     ASTSymbol::ASTSymbolEqual> ASTSymbolSet;
+
+    // Unique tables to share nodes whenever possible.
+    ASTInteriorSet _interior_unique_table;
+    //The _symbol_unique_table is also the symbol table to be used
+    //during parsing/semantic analysis
+    ASTSymbolSet _symbol_unique_table;
+    
+    //Typedef for unique BVConst node (leaf) table.
+    typedef hash_set<ASTBVConst *, 
+		     ASTBVConst::ASTBVConstHasher,
+		     ASTBVConst::ASTBVConstEqual> ASTBVConstSet;
+
+    //table to uniquefy bvconst
+    ASTBVConstSet _bvconst_unique_table;
+
+    // type of memo table.
+    typedef hash_map<ASTNode, ASTVec,
+		     ASTNode::ASTNodeHasher, 
+		     ASTNode::ASTNodeEqual> ASTNodeToVecMap;
+
+    typedef hash_map<ASTNode,ASTNodeSet,
+		     ASTNode::ASTNodeHasher,
+		     ASTNode::ASTNodeEqual> ASTNodeToSetMap;
+    
+    // Memo table for bit blasted terms.  If a node has already been
+    // bitblasted, it is mapped to a vector of Boolean formulas for
+    // the bits.
+    
+    //OLD: ASTNodeToVecMap BBTermMemo;
+    ASTNodeMap BBTermMemo;
+    
+    // Memo table for bit blasted formulas.  If a node has already
+    // been bitblasted, it is mapped to a node representing the
+    // bitblasted equivalent
+    ASTNodeMap BBFormMemo;
+    
+    //public:
+    // Get vector of Boolean formulas for sum of two
+    // vectors of Boolean formulas
+    void BBPlus2(ASTVec& sum, const ASTVec& y, ASTNode cin);
+    // Increment
+    ASTVec BBInc(ASTVec& x);
+    // Add one bit to a vector of bits.
+    ASTVec BBAddOneBit(ASTVec& x, ASTNode cin);
+    // Bitwise complement
+    ASTVec BBNeg(const ASTVec& x);
+    // Unary minus
+    ASTVec BBUminus(const ASTVec& x);
+    // Multiply.
+    ASTVec BBMult(const ASTVec& x, const ASTVec& y);
+    // AND each bit of vector y with single bit b and return the result.
+    // (used in BBMult)
+    ASTVec BBAndBit(const ASTVec& y, ASTNode b);
+    // Returns ASTVec for result - y.  This destroys "result".
+    void BBSub(ASTVec& result, const ASTVec& y);
+    // build ITE's (ITE cond then[i] else[i]) for each i.
+    ASTVec BBITE(const ASTNode& cond, 
+		 const ASTVec& thn, const ASTVec& els);
+    // Build a vector of zeros.
+    ASTVec BBfill(unsigned int width, ASTNode fillval);
+    // build an EQ formula
+    ASTNode BBEQ(const ASTVec& left, const ASTVec& right);
+
+    // This implements a variant of binary long division.
+    // q and r are "out" parameters.  rwidth puts a bound on the
+    // recursion depth.   Unsigned only, for now.
+    void BBDivMod(const ASTVec &y,
+		  const ASTVec &x,
+		  ASTVec &q,
+		  ASTVec &r,
+		  unsigned int rwidth);
+    
+    // Return formula for majority function of three formulas.
+    ASTNode Majority(const ASTNode& a, const ASTNode& b, const ASTNode& c);
+
+    // Internal bit blasting routines.
+    ASTNode BBBVLE(const ASTVec& x, const ASTVec& y, bool is_signed);
+
+    // Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc. 
+    ASTNode BBcompare(const ASTNode& form);
+
+    // Left and right shift one.  Writes into x.
+    void BBLShift(ASTVec& x);
+    void BBRShift(ASTVec& x);
+
+  public:
+    // Simplifying create functions
+    ASTNode CreateSimpForm(Kind kind, ASTVec &children);
+    ASTNode CreateSimpForm(Kind kind, const ASTNode& child0);
+    ASTNode CreateSimpForm(Kind kind,
+				    const ASTNode& child0,
+				    const ASTNode& child1);
+    ASTNode CreateSimpForm(Kind kind,
+				    const ASTNode& child0,
+				    const ASTNode& child1,
+				    const ASTNode& child2);
+
+    ASTNode CreateSimpNot(const ASTNode& form);
+
+    // These are for internal use only.
+    // FIXME: Find a way to make this local to SimpBool, so they're
+    // not in AST.h
+    ASTNode CreateSimpXor(const ASTNode& form1,
+			  const ASTNode& form2);
+    ASTNode CreateSimpXor(ASTVec &children);
+    ASTNode CreateSimpAndOr(bool isAnd,
+				     const ASTNode& form1,
+				     const ASTNode& form2);
+    ASTNode CreateSimpAndOr(bool IsAnd, ASTVec &children);
+    ASTNode CreateSimpFormITE(const ASTNode& child0,
+				       const ASTNode& child1,
+				       const ASTNode& child2);
+    
+
+    // Declarations of BitBlaster functions (BitBlast.cpp)
+  public:
+    // Adds or removes a NOT as necessary to negate a literal.
+    ASTNode Negate(const ASTNode& form);
+
+    // Bit blast a bitvector term.  The term must have a kind for a
+    // bitvector term.  Result is a ref to a vector of formula nodes
+    // representing the boolean formula.
+    const ASTNode BBTerm(const ASTNode& term);
+
+    const ASTNode BBForm(const ASTNode& formula);
+
+    // Declarations of CNF conversion (ToCNF.cpp)
+  public:
+    // ToCNF converts a bit-blasted Boolean formula to Conjunctive
+    // 	Normal Form, suitable for many SAT solvers.  Our CNF representation
+    // 	is an STL vector of STL vectors, for independence from any particular
+    // 	SAT solver's representation.  There needs to be a separate driver to
+    // 	convert our clauselist to the representation used by the SAT solver.    
+    // 	Currently, there is only one such solver and its driver is "ToSAT"
+    
+    // Datatype for clauses
+    typedef ASTVec * ClausePtr;
+    
+    // Datatype for Clauselists
+    typedef vector<ClausePtr> ClauseList;
+
+    // Convert a Boolean formula to an equisatisfiable CNF formula.
+    ClauseList *ToCNF(const ASTNode& form);
+
+    // Print function for debugging
+    void PrintClauseList(ostream& os, ClauseList& cll); 
+
+    // Free the clause list and all its clauses.
+    void DeleteClauseList(BeevMgr::ClauseList *cllp);
+
+    // Map from formulas to representative literals, for debugging.
+    ASTNodeMap RepLitMap;
+
+  private:
+    // Global for assigning new node numbers.
+    int _max_node_num;
+    
+    const ASTNode ASTFalse, ASTTrue, ASTUndefined;
+    
+    // I just did this so I could put it in as a fake return value in
+    // methods that return a ASTNode &, to make -Wall shut up.
+    ASTNode dummy_node;
+
+    //BeevMgr Constructor, Destructor and other misc. functions
+  public:
+
+    int NewNodeNum() { _max_node_num += 2; return _max_node_num; } 
+    
+    // Table for DAG printing.
+    ASTNodeSet AlreadyPrintedSet;
+
+    //Tables for Presentation language printing
+
+    //Nodes seen so far
+    ASTNodeSet PLPrintNodeSet;
+
+    //Map from ASTNodes to LetVars
+    ASTNodeMap NodeLetVarMap;
+    
+    //This is a vector which stores the Node to LetVars pairs. It
+    //allows for sorted printing, as opposed to NodeLetVarMap
+    std::vector<pair<ASTNode,ASTNode> > NodeLetVarVec;
+
+    //a partial Map from ASTNodes to LetVars. Needed in order to
+    //correctly print shared subterms inside the LET itself
+    ASTNodeMap NodeLetVarMap1;
+
+    //functions to lookup nodes from the memo tables. these should be
+    //private.
+  private:
+    //Destructively appends back_child nodes to front_child nodes.
+    //If back_child nodes is NULL, no appending is done.  back_child
+    //nodes are not modified.  Then it returns the hashed copy of the
+    //node, which is created if necessary.
+    ASTInterior *CreateInteriorNode(Kind kind,
+				    ASTInterior *new_node,
+				    // this is destructively modified.
+				    const ASTVec & back_children = _empty_ASTVec);
+
+    // Create unique ASTInterior node.
+    ASTInterior *LookupOrCreateInterior(ASTInterior *n);
+
+    // Create unique ASTSymbol node. 
+    ASTSymbol *LookupOrCreateSymbol(ASTSymbol& s);
+    
+    // Called whenever we want to make sure that the Symbol is
+    // declared during semantic analysis
+    bool LookupSymbol(ASTSymbol& s);
+      
+    // Called by ASTNode constructors to uniqueify ASTBVConst
+    ASTBVConst *LookupOrCreateBVConst(ASTBVConst& s);
+
+    //Public functions for CreateNodes and Createterms
+  public:
+    // Create and return an ASTNode for a symbol
+    ASTNode CreateSymbol(const char * const name);
+
+    // Create and return an ASTNode for a symbol
+    // Width is number of bits.
+    ASTNode CreateBVConst(unsigned int width, unsigned long long int bvconst);
+    ASTNode CreateZeroConst(unsigned int width);
+    ASTNode CreateOneConst(unsigned int width);
+    ASTNode CreateTwoConst(unsigned int width);
+    ASTNode CreateMaxConst(unsigned int width);
+
+    // Create and return an ASTNode for a symbol
+    // Optional base was a problem because 0 could be an int or char *,
+    // so CreateBVConst was ambiguous.
+    ASTNode CreateBVConst(const char *strval, int base);
+
+    //FIXME This is a dangerous function 
+    ASTNode CreateBVConst(CBV bv, unsigned width);
+
+    // Create and return an interior ASTNode
+    ASTNode CreateNode(Kind kind, const ASTVec &children = _empty_ASTVec);
+
+    ASTNode CreateNode(Kind kind,
+		       const ASTNode& child0,
+		       const ASTVec &children = _empty_ASTVec);
+
+    ASTNode CreateNode(Kind kind,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTVec &children = _empty_ASTVec);    
+
+    ASTNode CreateNode(Kind kind,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTNode& child2,
+		       const ASTVec &children = _empty_ASTVec);
+
+    // Create and return an ASTNode for a term
+    inline ASTNode CreateTerm(Kind kind, 
+		       unsigned int width, 
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, children);
+      n.SetValueWidth(width);
+
+      //by default we assume that the term is a Bitvector. If
+      //necessary the indexwidth can be changed later
+      n.SetIndexWidth(0);
+      return n;
+    }
+
+    inline ASTNode CreateTerm(Kind kind,
+		       unsigned int width,
+		       const ASTNode& child0,
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, child0, children);
+      n.SetValueWidth(width);
+      return n;
+    }
+     
+    inline ASTNode CreateTerm(Kind kind,
+		       unsigned int width,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, child0, child1, children);
+      n.SetValueWidth(width);
+      return n;
+    }
+
+    inline ASTNode CreateTerm(Kind kind,
+		       unsigned int width,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTNode& child2,
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, child0, child1, child2, children);
+      n.SetValueWidth(width);
+      return n;
+    }
+
+    ASTNode SimplifyFormula_NoRemoveWrites(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyFormula_TopLevel(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyTerm_TopLevel(const ASTNode& b);
+    ASTNode SimplifyTerm(const ASTNode& a);
+    void CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output);    
+  private:
+    //memo table for simplifcation
+    ASTNodeMap SimplifyMap;
+    ASTNodeMap SimplifyNegMap;
+    ASTNodeMap SolverMap;
+    ASTNodeSet AlwaysTrueFormMap;
+    ASTNodeMap MultInverseMap;
+
+  public:
+    ASTNode SimplifyAtomicFormula(const ASTNode& a, bool pushNeg);
+    ASTNode CreateSimplifiedEQ(const ASTNode& t1, const ASTNode& t2);
+    ASTNode ITEOpt_InEqs(const ASTNode& in1);
+    ASTNode CreateSimplifiedTermITE(const ASTNode& t1, const ASTNode& t2, const ASTNode& t3);
+    ASTNode CreateSimplifiedINEQ(Kind k, const ASTNode& a0, const ASTNode& a1, bool pushNeg);
+    ASTNode SimplifyNotFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyAndOrFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyXorFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyNandFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyNorFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyImpliesFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyIffFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyIteFormula(const ASTNode& a, bool pushNeg);
+    ASTNode FlattenOneLevel(const ASTNode& a);
+    ASTNode FlattenAndOr(const ASTNode& a);
+    ASTNode CombineLikeTerms(const ASTNode& a);
+    ASTNode LhsMinusRhs(const ASTNode& eq);
+    ASTNode DistributeMultOverPlus(const ASTNode& a, 
+				   bool startdistribution=false);
+    ASTNode ConvertBVSXToITE(const ASTNode& a);
+    //checks if the input constant is odd or not
+    bool BVConstIsOdd(const ASTNode& c);
+    //computes the multiplicatve inverse of the input
+    ASTNode MultiplicativeInverse(const ASTNode& c);
+ 
+    void ClearAllTables(void);
+    void ClearAllCaches(void);
+    int  BeforeSAT_ResultCheck(const ASTNode& q);
+    int  CallSAT_ResultCheck(MINISAT::Solver& newS, 
+			     const ASTNode& q, const ASTNode& orig_input);   
+    int  SATBased_ArrayReadRefinement(MINISAT::Solver& newS, 
+				      const ASTNode& q, const ASTNode& orig_input);
+    int SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input);
+    //creates array write axiom only for the input term or formula, if
+    //necessary. If there are no axioms to produce then it simply
+    //generates TRUE
+    ASTNode Create_ArrayWriteAxioms(const ASTNode& array_readoverwrite_term, const ASTNode& array_newname);
+    ASTVec ArrayWrite_RemainingAxioms;
+    //variable indicates that counterexample will now be checked by
+    //the counterexample checker, and hence simplifyterm must switch
+    //off certain optimizations. In particular, array write
+    //optimizations
+    bool start_abstracting;
+    bool Begin_RemoveWrites;
+    bool SimplifyWrites_InPlace_Flag;
+
+    void CopySolverMap_To_CounterExample(void);
+    //int LinearSearch(const ASTNode& orig_input);    
+    //Datastructures and functions needed for counterexample
+    //generation, and interface with MINISAT
+  private:
+    /* MAP: This is a map from ASTNodes to MINISAT::Vars. 
+     *
+     * The map is populated while ASTclauses are read from the AST
+     * ClauseList returned by CNF converter. For every new boolean
+     * variable in ASTClause a new MINISAT::Var is created (these vars
+     * typedefs for ints)
+     */
+    typedef hash_map<ASTNode, MINISAT::Var, 
+		     ASTNode::ASTNodeHasher, 
+		     ASTNode::ASTNodeEqual> ASTtoSATMap;        
+    ASTtoSATMap _ASTNode_to_SATVar;
+
+  public:  
+    //converts the clause to SAT and calls SAT solver
+    bool toSATandSolve(MINISAT::Solver& S, ClauseList& cll);
+
+    ///print SAT solver statistics
+    void PrintStats(MINISAT::SolverStats& stats);
+
+    //accepts query and returns the answer. if query is valid, return
+    //true, else return false. Automatically constructs counterexample
+    //for invalid queries, and prints them upon request.
+    int TopLevelSAT(const ASTNode& query, const ASTNode& asserts);
+
+    // Debugging function to find problems in BitBlast and ToCNF.
+    // See body in ToSAT.cpp for more explanation.
+    ASTNode CheckBBandCNF(MINISAT::Solver& newS, ASTNode form);
+
+    // Internal recursive body of above.
+    ASTNode CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form);
+
+    // Helper function for CheckBBandCNF
+    ASTNode SymbolTruthValue(MINISAT::Solver &newS, ASTNode form); 
+
+    //looksup a MINISAT var from the minisat-var memo-table. if none
+    //exists, then creates one.
+    const MINISAT::Var LookupOrCreateSATVar(MINISAT::Solver& S, const ASTNode& n);
+
+    // Memo table for CheckBBandCNF debugging function
+    ASTNodeMap CheckBBandCNFMemo;
+
+
+    //Data structures for Array Read Transformations
+  private:
+    /* MAP: This is a map from Array Names to list of array-read
+     * indices in the input. This map is used by the TransformArray()
+     * function
+     *
+     * This map is useful in converting array reads into nested ITE
+     * constructs. Suppose there are two array reads in the input
+     * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
+     * symbolic constant, say v1, and Read(A,j) is replaced with the
+     * following ITE:
+     *
+     * ITE(i=j,v1,v2)
+     */
+    //CAUTION: I tried using a set instead of vector for
+    //readindicies. for some odd reason the performance went down
+    //considerably. this is totally inexplicable.
+    ASTNodeToVecMap _arrayname_readindices;
+        
+    /* MAP: This is a map from Array Names to nested ITE constructs,
+     * which are built as described below. This map is used by the
+     * TransformArray() function
+     *
+     * This map is useful in converting array reads into nested ITE
+     * constructs. Suppose there are two array reads in the input
+     * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
+     * symbolic constant, say v1, and Read(A,j) is replaced with the
+     * following ITE:
+     *
+     * ITE(i=j,v1,v2)
+     */
+    ASTNodeMap _arrayread_ite;
+
+    /*MAP: This is a map from array-reads to symbolic constants. This
+     *map is used by the TransformArray()
+     */
+    ASTNodeMap _arrayread_symbol;
+
+    ASTNodeSet _introduced_symbols;
+
+    /*Memoization map for TransformFormula/TransformTerm/TransformArray function
+     */
+    ASTNodeMap TransformMap;
+    
+    //count to keep track of new symbolic constants introduced
+    //corresponding to Array Reads
+    unsigned int _symbol_count;
+
+    //Formula/Term Transformers. Let Expr Manager, Type Checker
+  public:
+    //Functions that Transform ASTNodes
+    ASTNode TransformFormula(const ASTNode& query);
+    ASTNode TransformTerm(const ASTNode& term);
+    ASTNode TransformArray(const ASTNode& term);
+    ASTNode TranslateSignedDivMod(const ASTNode& term);
+
+    //LET Management
+  private:
+    // MAP: This map is from bound IDs that occur in LETs to
+    // expression. The map is useful in checking replacing the IDs
+    // with the corresponding expressions.
+    ASTNodeMap _letid_expr_map;
+  public:
+
+    ASTNode ResolveID(const ASTNode& var);
+
+    //Functions that are used to manage LET expressions
+    void LetExprMgr(const ASTNode& var, const ASTNode& letExpr);
+
+    //Delete Letid Map
+    void CleanupLetIDMap(void);
+
+    //Allocate LetID map
+    void InitializeLetIDMap(void);
+
+    //Substitute Let-vars with LetExprs
+    ASTNode SubstituteLetExpr(ASTNode inExpr);
+
+    /* MAP: This is a map from MINISAT::Vars to ASTNodes
+     *
+     * This is a reverse map, useful in constructing
+     * counterexamples. MINISAT returns a model in terms of MINISAT
+     * Vars, and this map helps us convert it to a model over ASTNode
+     * variables.
+     */    
+    vector<ASTNode> _SATVar_to_AST;
+
+  private:        
+    /* MAP: This is a map from ASTNodes to vectors of bits
+     *
+     * This map is used in constructing and printing
+     * counterexamples. MINISAT returns values for each bit (a
+     * BVGETBIT Node), and this maps allows us to assemble the bits
+     * into bitvectors.
+     */    
+    typedef hash_map<ASTNode, hash_map<unsigned int, bool> *, 
+		     ASTNode::ASTNodeHasher, 
+		     ASTNode::ASTNodeEqual> ASTtoBitvectorMap;        
+    ASTtoBitvectorMap _ASTNode_to_Bitvector;
+
+    //Data structure that holds the counter-model
+    ASTNodeMap CounterExampleMap;
+
+    //Checks if the counter_example is ok. In order for the
+    //counter_example to be ok, Every assert must evaluate to true 
+    //w.r.t couner_example and the query must evaluate to
+    //false. Otherwise the counter_example is bogus.
+    void CheckCounterExample(bool t);    
+
+    //Converts a vector of bools to a BVConst
+    ASTNode BoolVectoBVConst(hash_map<unsigned,bool> * w, unsigned int l);
+
+    //accepts a term and turns it into a constant-term w.r.t counter_example 
+    ASTNode TermToConstTermUsingModel(const ASTNode& term, bool ArrayReadFlag = true);
+    ASTNode Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool ArrayReadFlag = true);
+    //Computes the truth value of a formula w.r.t counter_example
+    ASTNode ComputeFormulaUsingModel(const ASTNode& form);
+
+    //Replaces WRITE(Arr,i,val) with ITE(j=i, val, READ(Arr,j))
+    ASTNode RemoveWrites_TopLevel(const ASTNode& term);
+    ASTNode RemoveWrites(const ASTNode& term);
+    ASTNode SimplifyWrites_InPlace(const ASTNode& term);
+    ASTNode ReadOverWrite_To_ITE(const ASTNode& term);
+
+    ASTNode NewArrayVar(unsigned int index, unsigned int value);
+    ASTNode NewVar(unsigned int valuewidth);
+    //For ArrayWrite Abstraction: map from read-over-write term to
+    //newname.
+    ASTNodeMap ReadOverWrite_NewName_Map;
+    //For ArrayWrite Refinement: Map new arraynames to Read-Over-Write
+    //terms
+    ASTNodeMap NewName_ReadOverWrite_Map;
+    
+  public:
+    //print the STP solver output
+    void PrintOutput(bool true_iff_valid);
+
+    //Converts MINISAT counterexample into an AST memotable (i.e. the
+    //function populates the datastructure CounterExampleMap)
+    void ConstructCounterExample(MINISAT::Solver& S);
+
+    //Prints the counterexample to stdout
+    void PrintCounterExample(bool t,std::ostream& os=cout);
+
+    //Prints the counterexample to stdout
+    void PrintCounterExample_InOrder(bool t);
+
+    //queries the counterexample, and returns the value corresponding
+    //to e
+    ASTNode GetCounterExample(bool t, const ASTNode& e);
+
+    int CounterExampleSize(void) const {return CounterExampleMap.size();}
+
+    //FIXME: This is bloody dangerous function. Hack attack to take
+    //care of requests from users who want to store complete
+    //counter-examples in their own data structures.
+    ASTNodeMap GetCompleteCounterExample() {return CounterExampleMap;}
+
+    // prints MINISAT assigment one bit at a time, for debugging.
+    void PrintSATModel(MINISAT::Solver& S);
+
+    //accepts constant input and normalizes it. 
+    ASTNode BVConstEvaluator(const ASTNode& t);
+
+    //FUNCTION TypeChecker: Assumes that the immediate Children of the
+    //input ASTNode have been typechecked. This function is suitable
+    //in scenarios like where you are building the ASTNode Tree, and
+    //you typecheck as you go along. It is not suitable as a general
+    //typechecker
+    void BVTypeCheck(const ASTNode& n);
+    
+  private:
+    //stack of Logical Context. each entry in the stack is a logical
+    //context. A logical context is a vector of assertions. The
+    //logical context is represented by a ptr to a vector of
+    //assertions in that logical context. Logical contexts are created
+    //by PUSH/POP
+    std::vector<ASTVec *>  _asserts;
+    //The query for the current logical context.
+    ASTNode _current_query;
+
+    //this flag, when true, indicates that counterexample is being
+    //checked by the counterexample checker
+    bool counterexample_checking_during_refinement;
+
+    //this flag indicates as to whether the input has been determined to
+    //be valid or not by this tool
+    bool ValidFlag;
+
+    //this flag, when true, indicates that a BVDIV divide by zero
+    //exception occured. However, the program must not exit with a
+    //fatalerror. Instead, it should evaluate the whole formula (which
+    //contains the BVDIV term) to be FALSE.
+    bool bvdiv_exception_occured;
+
+  public:
+    //set of functions that manipulate Logical Contexts.
+    //
+    //add an assertion to the current logical context
+    void AddAssert(const ASTNode& assert);
+    void Push(void);
+    void Pop(void);
+    void AddQuery(const ASTNode& q);    
+    const ASTNode PopQuery();
+    const ASTNode GetQuery();
+    const ASTVec GetAsserts(void);
+
+    //reports node size.  Second arg is "clearstatinfo", whatever that is.
+    unsigned int NodeSize(const ASTNode& a, bool t = false);
+
+  private:
+    //This memo map is used by the ComputeFormulaUsingModel()
+    ASTNodeMap ComputeFormulaMap;
+    //Map for statiscal purposes
+    ASTNodeSet StatInfoSet;
+
+
+    ASTNodeMap TermsAlreadySeenMap;
+    ASTNode CreateSubstitutionMap(const ASTNode& a);
+  public:
+    //prints statistics for the ASTNode. can add a prefix string c
+    void ASTNodeStats(const char * c, const ASTNode& a);
+
+    //substitution
+    bool CheckSubstitutionMap(const ASTNode& a, ASTNode& output);  
+    bool CheckSubstitutionMap(const ASTNode& a);
+    bool UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1);
+    //if (a > b) in the termorder, then return 1
+    //elseif (a < b) in the termorder, then return -1
+    //else return 0
+    int TermOrder(const ASTNode& a, const ASTNode& b);
+    //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
+    //and index is a BVCONST
+    void FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1);
+    bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
+
+    //functions for checking and updating simplifcation map
+    bool CheckSimplifyMap(const ASTNode& key, ASTNode& output, bool pushNeg);
+    void UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg);
+    bool CheckAlwaysTrueFormMap(const ASTNode& key);
+    void UpdateAlwaysTrueFormMap(const ASTNode& val);
+    bool CheckMultInverseMap(const ASTNode& key, ASTNode& output);
+    void UpdateMultInverseMap(const ASTNode& key, const ASTNode& value);
+
+    //Map for solved variables
+    bool CheckSolverMap(const ASTNode& a, ASTNode& output);
+    bool CheckSolverMap(const ASTNode& a);
+    bool UpdateSolverMap(const ASTNode& e0, const ASTNode& e1);
+  public:
+    //FIXME: HACK_ATTACK. this vector was hacked into the code to
+    //support a special request by Dawson' group. They want the
+    //counterexample to be printed in the order of variables declared.
+    //TO BE COMMENTED LATER (say by 1st week of march,2006)
+    ASTVec _special_print_set;
+
+    //prints the initial activity levels of variables
+    void PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS);
+
+    //this function biases the activity levels of MINISAT variables.
+    void ChangeActivityLevels_Of_SATVars(MINISAT::Solver& n);
+
+    // Constructor
+    BeevMgr() : _interior_unique_table(INITIAL_INTERIOR_UNIQUE_TABLE_SIZE),
+		_symbol_unique_table(INITIAL_SYMBOL_UNIQUE_TABLE_SIZE),
+		_bvconst_unique_table(INITIAL_BVCONST_UNIQUE_TABLE_SIZE),
+		BBTermMemo(INITIAL_BBTERM_MEMO_TABLE_SIZE),
+		BBFormMemo(INITIAL_BBFORM_MEMO_TABLE_SIZE),
+		_max_node_num(0),
+		ASTFalse(CreateNode(FALSE)),
+		ASTTrue(CreateNode(TRUE)),
+		ASTUndefined(CreateNode(UNDEFINED)),
+		SimplifyMap(INITIAL_SIMPLIFY_MAP_SIZE),
+		SimplifyNegMap(INITIAL_SIMPLIFY_MAP_SIZE),
+		SolverMap(INITIAL_SOLVER_MAP_SIZE),
+		_arrayread_symbol(INITIAL_ARRAYREAD_SYMBOL_SIZE),
+		_introduced_symbols(INITIAL_INTRODUCED_SYMBOLS_SIZE),
+		_symbol_count(0) { 
+      _current_query = ASTUndefined;
+      ValidFlag = false;
+      bvdiv_exception_occured = false;
+      counterexample_checking_during_refinement = false;
+      start_abstracting = false;
+      Begin_RemoveWrites = false;
+      SimplifyWrites_InPlace_Flag = false;
+    };
+    
+    //destructor
+    ~BeevMgr();
+  }; //End of Class BeevMgr
+
+
+  class CompleteCounterExample {
+    ASTNodeMap counterexample;
+    BeevMgr * bv;
+  public:
+    CompleteCounterExample(ASTNodeMap a, BeevMgr* beev) : counterexample(a), bv(beev){} 
+    ASTNode GetCounterExample(ASTNode e) {
+      if(BOOLEAN_TYPE == e.GetType() && SYMBOL != e.GetKind()) {
+	FatalError("You must input a term or propositional variables\n",e);
+      }
+      if(counterexample.find(e) != counterexample.end()) {
+	return counterexample[e];
+      }
+      else {
+	if(SYMBOL == e.GetKind() && BOOLEAN_TYPE == e.GetType()) {
+	  return bv->CreateNode(BEEV::FALSE);
+	}
+
+	if(SYMBOL == e.GetKind()) {
+	  ASTNode z = bv->CreateZeroConst(e.GetValueWidth());
+	  return z;
+	}
+
+	return e;	  
+      }
+    }
+  };
+
+}; // end namespace BEEV
+#endif

Added: klee/trunk/stp/AST/ASTKind.kinds
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/ASTKind.kinds?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/ASTKind.kinds (added)
+++ klee/trunk/stp/AST/ASTKind.kinds Wed May 20 23:36:41 2009
@@ -0,0 +1,71 @@
+#Please refer LICENSE FILE in the home directory for licensing information
+# name minkids maxkids cat1 cat2 ...
+Categories:	Term	Form
+
+# Leaf nodes.
+UNDEFINED	0	0
+SYMBOL		0	0	Term	Form 
+
+# These always produce terms
+BVCONST		0	0	Term
+BVNEG		1	1	Term
+BVCONCAT	2	-	Term
+BVOR		1	-	Term
+BVAND		1	-	Term
+BVXOR		1	-	Term
+BVNAND		1	-	Term
+BVNOR		1	-	Term
+BVXNOR		1	-	Term
+BVEXTRACT	3	3	Term
+BVLEFTSHIFT	3	3	Term
+BVRIGHTSHIFT	3	3	Term
+BVSRSHIFT	3	3	Term
+BVVARSHIFT	3	3	Term
+BVPLUS		1	-	Term
+BVSUB		2	2	Term
+BVUMINUS	1	1	Term
+BVMULTINVERSE	1	1	Term
+BVMULT		1	-	Term
+BVDIV		2	2	Term
+BVMOD		2	2	Term
+SBVDIV		2	2	Term
+SBVMOD		2	2	Term
+BVSX		1	1	Term
+BOOLVEC         0       -       Term
+
+# Formula OR term, depending on context
+ITE		3	3	Term	Form
+
+# These produce formulas.
+BVGETBIT	2	2	Form
+BVLT		2	2	Form
+BVLE		2	2	Form
+BVGT		2	2	Form
+BVGE		2	2	Form
+BVSLT		2	2	Form
+BVSLE		2	2	Form
+BVSGT		2	2	Form
+BVSGE		2	2	Form
+EQ		2	2	Form
+NEQ		2	2	Form
+FALSE		0	0	Form
+TRUE		0	0	Form
+NOT		1	1	Form
+AND		1	-	Form
+OR		1	-	Form
+NAND		1	-	Form
+NOR		1	-	Form
+XOR		1	-	Form
+IFF		1	-	Form
+IMPLIES		2	2	Form
+
+# array operations
+READ		2	2	Term
+WRITE		3	3	Term
+
+#Types: These kinds are used only in the API. Once processed inside
+#the API, they are never used again in the system 
+ARRAY           0       0
+BITVECTOR       0       0
+BOOLEAN         0       0
+

Added: klee/trunk/stp/AST/ASTUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/ASTUtil.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/ASTUtil.cpp (added)
+++ klee/trunk/stp/AST/ASTUtil.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,45 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "ASTUtil.h"
+#include <ostream>
+
+namespace BEEV {
+  ostream &operator<<(ostream &os, const Spacer &sp) {
+    // Instead of wrapping lines with hundreds of spaces, prints
+    // a "+" at the beginning of the line for each wrap-around.
+    // so lines print like: +14+		(XOR ...
+    int blanks = sp._spaces % 60;
+    int wraps = sp._spaces / 60;
+    if (wraps > 0) {
+      os << "+" << wraps;
+    }
+    for (int i = 0; i < blanks; i++)
+      os << " ";  
+    return os;
+  }
+   
+  //this function accepts the name of a function (as a char *), and
+  //records some stats about it. if the input is "print_func_stats",
+  //the function will then print the stats that it has collected.
+  void CountersAndStats(const char * functionname) {
+    if(!stats)
+      return;
+    static function_counters s;
+    
+    if(!strcmp(functionname,"print_func_stats")) {
+      cout << endl;
+      for(hash_map<const char*,int,hash<const char*>,eqstr>::iterator it=s.begin(),itend=s.end();
+	  it!=itend;it++)
+	cout << "Number of times the function: " << it->first << ": is called: " << it->second << endl;
+      return;
+    }
+    s[functionname] += 1;
+  }
+};// end of namespace

Added: klee/trunk/stp/AST/ASTUtil.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/ASTUtil.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/ASTUtil.h (added)
+++ klee/trunk/stp/AST/ASTUtil.h Wed May 20 23:36:41 2009
@@ -0,0 +1,107 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#ifndef ASTUTIL_H
+#define ASTUTIL_H
+
+#include <cstring>
+#include <iostream>
+#include <vector>
+#ifdef EXT_HASH_MAP
+#include <ext/hash_set>
+#include <ext/hash_map>
+#else
+#include <hash_set>
+#include <hash_map>
+#endif
+
+using namespace std; 
+namespace BEEV {
+#ifdef EXT_HASH_MAP
+  using namespace __gnu_cxx;
+#endif
+  //some global variables that are set through commandline options. it
+  //is best that these variables remain global. Default values set
+  //here
+  //
+  //collect statistics on certain functions
+  extern bool stats;
+  //print DAG nodes
+  extern bool print_nodes;
+  //tentative global var to allow for variable activity optimization
+  //in the SAT solver. deprecated.
+  extern bool variable_activity_optimize;
+  //run STP in optimized mode
+  extern bool optimize;
+  //do sat refinement, i.e. underconstraint the problem, and feed to
+  //SAT. if this works, great. else, add a set of suitable constraints
+  //to re-constraint the problem correctly, and call SAT again, until
+  //all constraints have been added.
+  extern bool arrayread_refinement;
+  //switch to control write refinements
+  extern bool arraywrite_refinement;
+  //check the counterexample against the original input to STP
+  extern bool check_counterexample;
+  //construct the counterexample in terms of original variable based
+  //on the counterexample returned by SAT solver
+  extern bool construct_counterexample;
+  extern bool print_counterexample;
+  //if this option is true then print the way dawson wants using a
+  //different printer. do not use this printer.
+  extern bool print_arrayval_declaredorder;
+  //flag to decide whether to print "valid/invalid" or not
+  extern bool print_output;
+  //do linear search in the array values of an input array. experimental
+  extern bool linear_search;
+  //print the variable order chosen by the sat solver while it is
+  //solving.
+  extern bool print_sat_varorder; 
+  //turn on word level bitvector solver
+  extern bool wordlevel_solve;
+  //XOR flattening optimizations.
+  extern bool xor_flatten;
+  //this flag indicates that the BVSolver() succeeded
+  extern bool toplevel_solved;
+  //the smtlib parser has been turned on
+  extern bool smtlib_parser_enable;
+  //print the input back
+  extern bool print_STPinput_back;
+
+  extern void (*vc_error_hdlr)(const char* err_msg);
+  /*Spacer class is basically just an int, but the new class allows
+    overloading of << with a special definition that prints the int as
+    that many spaces. */
+  class Spacer {
+  public:
+    int _spaces;
+    Spacer(int spaces) { _spaces = spaces; }
+    friend ostream& operator<<(ostream& os, const Spacer &ind);
+  };
+
+  inline Spacer spaces(int width) {
+    Spacer sp(width);
+    return sp;
+  }
+
+  struct eqstr {
+    bool operator()(const char* s1, const char* s2) const {
+      return strcmp(s1, s2) == 0;
+    }
+  };
+  
+  typedef hash_map<const char*,int, 
+		   hash<const char *>,eqstr> function_counters;
+  void CountersAndStats(const char * functionname);
+
+  //global function which accepts an integer and looks up the
+  //corresponding ASTNode and prints a char* of that ASTNode
+  void Convert_MINISATVar_To_ASTNode_Print(int minisat_var, 
+					   int decision, int polarity=0);
+}; // end namespace.
+#endif

Added: klee/trunk/stp/AST/BitBlast.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/BitBlast.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/BitBlast.cpp (added)
+++ klee/trunk/stp/AST/BitBlast.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,812 @@
+/********************************************************************
+ * AUTHORS: David L. Dill, Vijay Ganesh
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+// BitBlast -- convert bitvector terms and formulas to boolean
+// formulas.  A term is something that can represent a multi-bit
+// bitvector, such as BVPLUS or BVXOR (or a BV variable or constant).
+// A formula (form) represents a boolean value, such as EQ or BVLE.
+// Bit blasting a term representing an n-bit bitvector with BBTerm
+// yields a vector of n boolean formulas (returning ASTVec).
+// Bit blasting a formula returns a single boolean formula (type ASTNode).
+
+// A bitblasted term is a vector of ASTNodes for formulas.
+// The 0th element of the vector corresponds to bit 0 -- the low-order bit.
+
+#include "AST.h"
+namespace BEEV {
+  //  extern void lpvec(ASTVec &vec);
+
+// FIXME: Assert no zero-length bit vectors!!!
+// FIXME: Need top-level functions that create and destroy the memo tables.
+// FIXME:  Check resource limits and generate an exception when exceeded.
+// FIXME:  THis does a lot of unnecessary copying of vectors.
+//    Had to be careful not to modify memoized vectors!
+// FIXME:  Might be some redundant variables.
+
+// accepts a term, and returns a vector of bitblasted bits(ASTVec)
+
+ASTNode ASTJunk;
+const ASTNode BeevMgr::BBTerm(const ASTNode& term) {
+  //CHANGED TermMemo is now an ASTNodeMap. Based on BBFormMemo
+  ASTNodeMap::iterator it = BBTermMemo.find(term);
+  if (it != BBTermMemo.end()) {
+    // already there.  Just return it.
+    return it->second;
+  }
+
+//  ASTNode& result = ASTJunk;
+  ASTNode result;
+
+  Kind k = term.GetKind();
+  if (!is_Term_kind(k))
+    FatalError("BBTerm: Illegal kind to BBTerm",term);
+
+  ASTVec::const_iterator kids_end = term.end(); 
+  unsigned int num_bits = term.GetValueWidth();
+  switch (k) {
+  case BVNEG: {
+    // bitwise complement
+    // bitblast the child.
+    //FIXME Uses a tempory const ASTNode
+    const ASTNode& bbkids = BBTerm(term[0]);
+    result = CreateNode(BOOLVEC, BBNeg(bbkids.GetChildren()));
+    break;
+  }
+  case BVSRSHIFT:
+  case BVVARSHIFT: 
+    FatalError("BBTerm: These kinds have not been implemented in the BitBlaster: ", term);
+    break;
+  case ITE: {
+    // Term version of ITE.
+
+    // Blast the args
+    // FIXME Uses temporary const ASTNodes and an ASTVec&
+    const ASTNode& cond = BBForm(term[0]);
+    const ASTNode& thn = BBTerm(term[1]);
+    const ASTNode& els = BBTerm(term[2]);
+    result = 
+       CreateNode(BOOLVEC, BBITE(cond, thn.GetChildren(), els.GetChildren()));
+    break;
+  }
+  case BVSX: {
+    // Replicate high-order bit as many times as necessary.
+    // Arg 0 is expression to be sign extended.
+    const ASTNode& arg = term[0];
+    unsigned long result_width = term.GetValueWidth();
+    unsigned long arg_width = arg.GetValueWidth();
+    //FIXME Uses a temporary const ASTNode reference
+    const ASTNode& bbarg = BBTerm(arg);
+
+    if (result_width == arg_width) {
+      //nothing to sign extend
+      break;
+    }
+    else {
+      //we need to sign extend
+      const ASTNode& msbX = bbarg.back();
+      //const ASTNode& msb1 = msbX;
+      
+      ASTVec ccc = msbX.GetChildren();
+      const ASTNode& msb = CreateSimpForm(msbX.GetKind(),ccc);
+
+     //  Old version
+     //  ASTNode msb = bbarg.back();
+     //  const ASTNode msb1 = msb;
+      
+     //  ASTVec ccc = msb.GetChildren();
+     //  msb = CreateSimpForm(msb.GetKind(),ccc);
+
+      // DD 1/14/07 Simplify silently drops all but first two args of XOR.
+      // I expanded XOR to N args with flattening optimization.
+      // This bug took 2 days to track down!
+
+      // msb = SimplifyFormula(msb,false);
+
+      // cout << "!!!!!!!!!!!!!!!!" << endl
+      // << "Simplify msb:" << msb2 << endl
+      // << "Simplify result:" << msb << endl;
+
+      //FIXME Dynamically allocate the result vector?
+      //Is this doing multiple copies?
+      //ASTVec& tmp_res = *(new ASTVec(result_width));
+      ASTVec tmp_res(result_width);
+
+      //FIXME Should these be gotten from result?
+      ASTVec::const_iterator bb_it = bbarg.begin();
+      ASTVec::iterator res_it = tmp_res.begin();
+      ASTVec::iterator res_ext = res_it+arg_width; // first bit of extended part
+      ASTVec::iterator res_end = tmp_res.end();
+      // copy LSBs directly from bbvec
+      for( ; res_it < res_ext; (res_it++, bb_it++)) {
+	*res_it = *bb_it;
+      }
+      // repeat MSB to fill up rest of result.
+      for( ; res_it < res_end; (res_it++, bb_it++)) {
+	*res_it = msb;
+      }
+      
+       //Temporary debugging code
+       //    cout << "Sign extending:" << endl 
+       //	        << "  Vec ";
+       //    lpvec( bbarg.GetChildren() );
+       //    cout << "  Extended to ";
+       //    lp(result);
+       //    cout << endl;
+      
+      result = CreateNode(BOOLVEC, tmp_res);
+
+      break;
+    }
+  }
+  case BVEXTRACT: {
+    // bitblast the child, then extract the relevant bits.
+    // Note: This could be optimized by not bitblasting the bits
+    // that aren't fetched.  But that would be tricky, especially
+    // with memo-ization.
+
+    //FIXME Using const ASTNode w/out reference
+    const ASTNode& bbkids = BBTerm(term[0]); 
+    unsigned int high = GetUnsignedConst(term[1]);
+    unsigned int low = GetUnsignedConst(term[2]);
+
+    ASTVec::const_iterator bbkfit = bbkids.begin();
+    // I should have used pointers to ASTVec, to avoid this crock
+    
+    //FIXME Creates a new local ASTVec and does the CreateNode from that
+    result = CreateNode(BOOLVEC, ASTVec(bbkfit+low, bbkfit+high+1));
+    break;
+  }
+  case BVCONCAT: {
+    //FIXME Using temporary const ASTNodes 
+    const ASTNode& vec1 = BBTerm(term[0]);
+    const ASTNode& vec2 = BBTerm(term[1]);
+
+    //FIXME This has to be an unnessecary copy and a memory leak
+    //Leaking ASTVec tmp_res = *(new ASTVec(vec2.GetChildren()));
+    ASTVec tmp_res(vec2.GetChildren());
+    tmp_res.insert(tmp_res.end(), vec1.begin(), vec1.end());
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }
+  case BVPLUS: {
+    // ASSERT: at least one child.
+    // ASSERT: all children and result are the same size.
+    // Previous phase must make sure this is true.
+    // Add children pairwise and accumulate in BBsum
+
+    // FIXME: Unnecessary array copies.
+    ASTVec::const_iterator it = term.begin();
+    ASTVec tmp_res = BBTerm(*it).GetChildren();
+    for (++it; it < kids_end; it++) {
+      const ASTVec& tmp = BBTerm(*it).GetChildren();
+      BBPlus2(tmp_res, tmp, ASTFalse);
+    }
+
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }
+  case BVUMINUS: {
+    //FIXME Using const ASTNode reference
+    const ASTNode& bbkid = BBTerm(term[0]);
+    result = CreateNode(BOOLVEC, BBUminus(bbkid.GetChildren()));
+    break;
+  }
+  case BVSUB: {
+    // complement of subtrahend
+    // copy, since BBSub writes into it.
+    
+    //FIXME: Unnecessary array copies?
+    ASTVec tmp_res = BBTerm(term[0]).GetChildren(); 
+
+    const ASTVec& bbkid1 = BBTerm(term[1]).GetChildren();
+    BBSub(tmp_res, bbkid1);
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }
+  case BVMULT: {
+    // ASSERT 2 arguments, same length, result is same length.
+
+    const ASTNode& t0 = term[0];
+    const ASTNode& t1 = term[1];
+
+    const ASTNode& mpcd1 = BBTerm(t0);
+    const ASTNode& mpcd2 = BBTerm(t1);
+    //Reverese the order of the nodes w/out the need for temporaries
+    //This is needed because t0 an t1 must be const
+    if ((BVCONST != t0.GetKind()) && (BVCONST == t1.GetKind())) {
+      result = CreateNode(BOOLVEC, 
+        BBMult(mpcd2.GetChildren(), mpcd1.GetChildren()) );
+    }else{
+      result = CreateNode(BOOLVEC, 
+        BBMult(mpcd1.GetChildren(), mpcd2.GetChildren()) );
+    }
+    break;
+  }
+  case BVDIV:
+  case BVMOD: {
+    const ASTNode& dvdd = BBTerm(term[0]);
+    const ASTNode& dvsr = BBTerm(term[1]);
+    unsigned int width = dvdd.Degree();
+    ASTVec q(width); 
+    ASTVec r(width); 
+    BBDivMod(dvdd.GetChildren(),  dvsr.GetChildren(), q, r, width);
+    if (k == BVDIV)
+      result = CreateNode(BOOLVEC, q);    
+    else
+      result = CreateNode(BOOLVEC, r);
+    break;
+  }
+  //  n-ary bitwise operators.
+  case BVXOR:
+  case BVXNOR:
+  case BVAND:
+  case BVOR:
+  case BVNOR:
+  case BVNAND: {
+    // Add children pairwise and accumulate in BBsum
+    ASTVec::const_iterator it = term.begin();
+    Kind bk = UNDEFINED;  // Kind of individual bit op.
+    switch (k) {
+    case BVXOR: bk = XOR;  break;
+    case BVXNOR: bk = IFF; break;
+    case BVAND: bk = AND; break;
+    case BVOR: bk = OR; break;
+    case BVNOR: bk = NOR; break;
+    case BVNAND: bk = NAND; break;
+    default:
+      FatalError("BBTerm: Illegal kind to BBTerm",term);
+      break;
+    }
+
+    // Sum is destructively modified in the loop, so make a copy of value
+    // returned by BBTerm.
+    ASTNode temp = BBTerm(*it);
+    ASTVec sum(temp.GetChildren());	// First operand.
+
+    // Iterate over remaining bitvector term operands
+    for (++it; it < kids_end; it++) {
+      //FIXME FIXME FIXME: Why does using a temp. var change the behavior?
+      temp = BBTerm(*it);
+      const ASTVec& y = temp.GetChildren();
+      
+      // Iterate over bits
+      // FIXME: Why is this not using an iterator???
+      int n = y.size();
+      for (int i = 0; i < n; i++) {
+	sum[i] = CreateSimpForm(bk, sum[i], y[i]);
+      }
+    }
+    result = CreateNode(BOOLVEC, sum);
+    break;
+  }
+  case SYMBOL: {
+    // ASSERT: IndexWidth = 0?  Semantic analysis should check.
+    //Leaking ASTVec& bbvec = *(new ASTVec);
+    
+    //FIXME Why is isn't this ASTVEC bbvec(num_bits) ?
+    ASTVec bbvec;
+    for (unsigned int i = 0; i < num_bits; i++) {
+      ASTNode bit_node =
+	CreateNode(BVGETBIT, term, CreateBVConst(32,i));
+      bbvec.push_back(bit_node); 
+    }
+    result = CreateNode(BOOLVEC, bbvec);
+    break;
+  }
+  case BVCONST: {
+    ASTVec tmp_res(num_bits);
+#ifndef NATIVE_C_ARITH
+    CBV bv = term.GetBVConst();
+    for(unsigned int i = 0; i < num_bits; i++){
+      tmp_res[i] = CONSTANTBV::BitVector_bit_test(bv,i) ? ASTTrue : ASTFalse; 
+    }  
+#else
+    const unsigned long long int c = term.GetBVConst();
+    unsigned long long int bitmask = 0x00000000000000001LL;
+    for (unsigned int i = 0; i < num_bits; i++, bitmask <<= 1)
+      tmp_res[i] = ((c & (bitmask)) ? ASTTrue : ASTFalse);    
+#endif
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }		  
+  case BOOLVEC: {
+    cerr << "Hit a boolvec! what to do?" << endl;
+    break;
+  }
+  default:
+    FatalError("BBTerm: Illegal kind to BBTerm",term);
+  }
+
+  //if(result == ASTJunk)
+  //  cout<<"result does not change"<<endl;
+  // cout << "================" << endl << "BBTerm:" << term << endl;
+  // cout << "----------------" << endl << "BBTerm result:";
+  // lpvec(result);
+  // cout << endl;
+
+  return (BBTermMemo[term] = result);
+
+}
+
+// bit blast a formula (boolean term).  Result is one bit wide,
+// so it returns a single ASTNode.
+// FIXME:  Add IsNegated flag.
+const ASTNode BeevMgr::BBForm(const ASTNode& form)
+{
+
+  ASTNodeMap::iterator it = BBFormMemo.find(form);
+  if (it != BBFormMemo.end()) {
+    // already there.  Just return it.
+    return it->second;
+  }
+
+  ASTNode result = ASTUndefined;
+
+  Kind k = form.GetKind();
+  if (!is_Form_kind(k)) {
+    FatalError("BBForm: Illegal kind: ",form);
+  }
+
+  //  Not returning until end, and memoizing everything, makes it easier
+  // to trace coherently.
+    
+  // Various special cases
+  switch (k) {
+  case TRUE:
+  case FALSE: {
+    result = form;
+    break;
+  }
+
+  case SYMBOL:
+    if (form.GetType() != BOOLEAN_TYPE) {
+      FatalError("BBForm: Symbol represents more than one bit", form);
+    }
+
+    result = form;
+    break;
+
+  case BVGETBIT: {
+    // exactly two children
+    const ASTNode bbchild = BBTerm(form[0]);
+    unsigned int index =  GetUnsignedConst(form[1]);
+    result = bbchild[index];
+    break;
+  }
+
+  case NOT:
+    result = CreateSimpNot(BBForm(form[0]));
+    break;  
+
+  case ITE:
+    // FIXME: SHould this be CreateSimpITE?
+    result = CreateNode(ITE, BBForm(form[0]), BBForm(form[1]), BBForm(form[2]));
+    break;
+
+  case AND: 
+  case OR: 
+  case NAND: 
+  case NOR: 
+  case IFF: 
+  case XOR:
+  case IMPLIES: {
+    ASTVec bbkids;		// bit-blasted children (formulas)
+
+    // FIXME: Put in fast exits for AND/OR/NAND/NOR/IMPLIES
+    ASTVec::const_iterator kids_end = form.end(); 
+    for (ASTVec::const_iterator it = form.begin(); it != kids_end; it++) {
+      bbkids.push_back(BBForm(*it));
+    }
+    result = CreateSimpForm(k, bbkids);
+    break;
+  }
+
+  case NEQ: {
+    ASTNode bbkid = BBForm(CreateNode(EQ, form.GetChildren()));
+    result = CreateSimpNot(bbkid);
+    break;
+  }
+
+  case EQ: {
+    // Common code for binary operations
+    // FIXME:  This ought to be in a semantic analysis phase.
+    const ASTNode left = BBTerm(form[0]);
+    const ASTNode right = BBTerm(form[1]);
+    if (left.Degree() != right.Degree()) {
+      cerr << "BBForm: Size mismatch" << endl << form[0] << endl << form[1] << endl;
+      FatalError("",ASTUndefined);
+    }
+    result = BBEQ(left.GetChildren(), right.GetChildren());
+    break;
+  }
+
+  case BVLE: 
+  case BVGE: 
+  case BVGT: 
+  case BVLT: 
+  case BVSLE:
+  case BVSGE:
+  case BVSGT:
+  case BVSLT: {
+    result = BBcompare(form);
+    break;
+  }
+  default:
+    FatalError("BBForm: Illegal kind: ", form);
+    break;
+  }
+
+  // cout << "================" << endl
+  // << "BBForm: " << form << endl
+  // << "----------------" << endl
+  // << "BBForm Result: " << result << endl;
+
+  return (BBFormMemo[form] = result);
+}
+  
+// Bit blast a sum of two equal length BVs.
+// Update sum vector destructively with new sum.
+void BeevMgr::BBPlus2(ASTVec& sum, const ASTVec& y, ASTNode cin)
+{
+//   cout << "Bitblasting plus.  Operand 1: " << endl;
+//   lpvec(sum);
+//   cout << endl << " operand 2: " << endl;
+//   lpvec(y);
+//   cout << endl << "carry: " << endl << cin << endl;
+
+
+  int n = sum.size();
+  // ASSERT: y.size() == x.size()
+  // FIXME: Don't bother computing i+1 carry, which is discarded.
+  for (int i = 0; i < n; i++) {
+    ASTNode nextcin = Majority(sum[i], y[i], cin); 
+    sum[i] = CreateSimpForm(XOR, CreateSimpForm(XOR, sum[i], y[i]), cin);
+    cin = nextcin;
+  }
+
+//   cout << "----------------" << endl << "Result: " << endl;
+//   lpvec(sum);
+//   cout << endl;
+
+}
+
+// Stores result - x in result, destructively
+void BeevMgr::BBSub(ASTVec& result, const ASTVec& y)
+{
+  ASTVec compsubtrahend  = BBNeg(y);
+  BBPlus2(result, compsubtrahend, ASTTrue);
+}
+
+// Add one bit
+ASTVec BeevMgr::BBAddOneBit(ASTVec& x, ASTNode cin)
+{
+  ASTVec result = ASTVec(0);
+  ASTVec::const_iterator itend = x.end();
+  for (ASTVec::const_iterator it = x.begin(); it < itend; it++) {
+    ASTNode nextcin = CreateSimpForm(AND, *it, cin); 
+    result.push_back(CreateSimpForm(XOR, *it, cin));
+    cin = nextcin;
+  }
+  // FIXME: unnecessary array copy on return?
+  return result;
+}
+
+// Increment bit-blasted vector and return result.
+ASTVec BeevMgr::BBInc(ASTVec& x)
+{
+  return BBAddOneBit(x, ASTTrue);
+}
+
+// Return formula for majority function of three bits.
+// Pass arguments by reference to reduce refcounting.
+ASTNode BeevMgr::Majority(const ASTNode& a, const ASTNode& b,const ASTNode& c)
+{
+  // Checking explicitly for constant a, b and c could
+  // be more efficient, because they are repeated in the logic.
+  if (ASTTrue == a) {
+    return CreateSimpForm(OR, b, c);
+  }
+  else if (ASTFalse == a) {
+    return CreateSimpForm(AND, b, c);
+  }
+  else if (ASTTrue == b) {
+    return CreateSimpForm(OR, a, c);
+  }
+  else if (ASTFalse == b) {
+    return CreateSimpForm(AND, a, c);
+  }
+  else if (ASTTrue == c) {
+    return CreateSimpForm(OR, a, b);
+  }
+  else if (ASTFalse == c) {
+    return CreateSimpForm(AND, a, b);
+  }
+  // there are lots more simplifications, but I'm not sure they're
+  // worth doing explicitly (e.g., a = b, a = ~b, etc.) 
+  else {
+    return
+      CreateSimpForm(OR,
+		     CreateSimpForm(AND, a, b),
+		     CreateSimpForm(AND, b, c),
+		     CreateSimpForm(AND, a, c));
+  }
+}
+
+
+// Bitwise complement
+ASTVec BeevMgr::BBNeg(const ASTVec& x)
+{
+  ASTVec result = ASTVec(0);		// FIXME: faster to preallocate n entries?
+  // Negate each bit.
+  ASTVec::const_iterator xend = x.end();
+  for (ASTVec::const_iterator it = x.begin(); it < xend; it++) {
+    result.push_back(CreateSimpNot(*it));
+  }
+  // FIXME: unecessary array copy when it returns?
+  return result;
+}
+
+// Compute unary minus
+ASTVec BeevMgr::BBUminus(const ASTVec& x)
+{
+  ASTVec xneg = BBNeg(x);
+  return BBInc(xneg);
+}
+
+// Multiply two bitblasted numbers
+ASTVec BeevMgr::BBMult(const ASTVec& x, const ASTVec& y)
+{
+  ASTVec ycopy(y);
+  ASTVec::const_iterator xend = x.end();
+  ASTVec::const_iterator xit = x.begin();
+  // start prod with first partial product.
+  // FIXME: This is unnecessary. Clean it up.
+  ASTVec prod = ASTVec(BBAndBit(y, *xit));
+  // start loop at next bit.
+  for(xit++; xit < xend; xit++) {
+    // shift first
+    BBLShift(ycopy);
+
+    if (ASTFalse == *xit) {
+      // If this bit is zero, the partial product will
+      // be zero.  No reason to add that in.
+      continue;
+    }
+
+    ASTVec pprod = BBAndBit(ycopy, *xit);
+    // accumulate in the product.
+    BBPlus2(prod, pprod, ASTFalse);
+  }
+  return prod;
+}
+
+// This implements a variant of binary long division.
+// q and r are "out" parameters.  rwidth puts a bound on the
+// recursion depth.
+void BeevMgr::BBDivMod(const ASTVec &y, const ASTVec &x, ASTVec &q, ASTVec &r, unsigned int rwidth)
+{
+  unsigned int width = y.size();
+  if (rwidth == 0) {
+    // When we have shifted the entire width, y is guaranteed to be 0.
+    q = BBfill(width, ASTFalse);
+    r = BBfill(width, ASTFalse);
+  }
+  else {
+    ASTVec q1, r1;
+    ASTVec yrshift1(y);
+    BBRShift(yrshift1);
+
+    // recursively divide y/2 by x.
+    BBDivMod(yrshift1, x, q1, r1, rwidth-1);
+
+    ASTVec q1lshift1(q1);
+    BBLShift(q1lshift1);
+
+    ASTVec r1lshift1(r1);
+    BBLShift(r1lshift1);
+    
+    ASTVec r1lshift1plusyodd = BBAddOneBit(r1lshift1, y[0]);
+    ASTVec rminusx(r1lshift1plusyodd);
+    BBSub(rminusx, x);
+
+    // Adjusted q, r values when when r is too large.
+    ASTNode rtoolarge = BBBVLE(x, r1lshift1plusyodd, false);
+    ASTVec ygtrxqval = BBITE(rtoolarge, BBInc(q1lshift1), q1lshift1);
+    ASTVec ygtrxrval = BBITE(rtoolarge, rminusx, r1lshift1plusyodd);
+
+    // q & r values when y >= x
+    ASTNode yeqx = BBEQ(y, x);
+    // *** Problem: the bbfill for qval is wrong.  Should be 1, not -1.
+    ASTVec one = BBfill(width, ASTFalse);
+    one[0] = ASTTrue;
+    ASTVec notylessxqval = BBITE(yeqx, one, ygtrxqval);
+    ASTVec notylessxrval = BBITE(yeqx, BBfill(width, ASTFalse), ygtrxrval);
+    // y < x <=> not x >= y.
+    ASTNode ylessx = CreateSimpNot(BBBVLE(x, y, false));
+    // final values of q and r
+    q = BBITE(ylessx, BBfill(width, ASTFalse), notylessxqval);
+    r = BBITE(ylessx, y, notylessxrval);
+  }
+}
+
+// build ITE's (ITE cond then[i] else[i]) for each i.
+ASTVec BeevMgr::BBITE(const ASTNode& cond, const ASTVec& thn, const ASTVec& els)
+{
+  // Fast exits.
+  if (ASTTrue == cond) {
+    return thn;
+  }
+  else if (ASTFalse == cond) {
+    return els;
+  }
+
+  ASTVec result(0);
+  ASTVec::const_iterator th_it_end = thn.end();
+  ASTVec::const_iterator el_it = els.begin();
+  for (ASTVec::const_iterator th_it = thn.begin(); th_it < th_it_end; th_it++, el_it++) {
+    result.push_back(CreateSimpForm(ITE, cond, *th_it, *el_it));
+  }
+  return result;
+}
+// AND each bit of vector y with single bit b and return the result.
+ASTVec BeevMgr::BBAndBit(const ASTVec& y, ASTNode b)
+{
+  ASTVec result(0); 
+
+  if (ASTTrue == b) {
+    return y;
+  }
+  // FIXME: put in fast exits when b is constant 0. 
+
+  ASTVec::const_iterator yend = y.end();
+  for(ASTVec::const_iterator yit = y.begin(); yit < yend; yit++) {
+    result.push_back(CreateSimpForm(AND, *yit, b));
+  }
+  return result;
+}
+
+
+// Workhorse for comparison routines.  This does a signed BVLE if is_signed
+// is true, else it's unsigned.  All other comparison operators can be reduced
+// to this by swapping args or complementing the result bit.
+// FIXME:  If this were done MSB first, it would enable a fast exit sometimes
+// when the MSB is constant, deciding the result without looking at the rest
+// of the bits.
+ASTNode BeevMgr::BBBVLE(const ASTVec& left, const ASTVec& right, bool is_signed)
+{
+  // "thisbit" represents BVLE of the suffixes of the BVs
+  // from that position .  if R < L, return TRUE, else if L < R
+  // return FALSE, else return BVLE of lower-order bits.  MSB is
+  // treated separately, because signed comparison is done by
+  // complementing the MSB of each BV, then doing an unsigned
+  // comparison.
+  ASTVec::const_iterator lit = left.begin();
+  ASTVec::const_iterator litend = left.end();
+  ASTVec::const_iterator rit = right.begin();
+  ASTNode prevbit = ASTTrue;
+  for ( ; lit  < litend-1; lit++, rit++) {
+    ASTNode neglit = CreateSimpNot(*lit);
+    ASTNode thisbit =
+      CreateSimpForm(OR,
+		 CreateSimpForm(AND,neglit,*rit), // TRUE if l < r
+		 CreateSimpForm(AND,
+			    CreateSimpForm(OR, neglit, *rit), // false if not equal
+			    prevbit)); // else prevbit
+    prevbit = thisbit;
+  }
+
+  // Handle MSB -- negate MSBs if signed comparison
+  // FIXME: make into refs after it's debugged.
+  ASTNode lmsb = *lit;
+  ASTNode rmsb = *rit;
+  if (is_signed) {
+    lmsb = CreateSimpNot(*lit);
+    rmsb = CreateSimpNot(*rit);
+  }
+
+  ASTNode neglmsb = CreateSimpNot(lmsb);
+  ASTNode msb =
+    CreateSimpForm(OR,
+	       CreateSimpForm(AND,neglmsb, rmsb), // TRUE if l < r
+	       CreateSimpForm(AND,
+			  CreateSimpForm(OR, neglmsb, rmsb), // false if not equal
+			  prevbit)); // else prevbit
+  return msb;
+}
+
+// Left shift by 1 within fixed field inserting zeros at LSB.
+// Writes result into first argument.
+// Fixme: generalize to n bits
+void BeevMgr::BBLShift(ASTVec& x)
+{
+  // left shift x (destructively) within width.
+  // loop backwards so that copy to self works correctly. (DON'T use STL insert!)
+  ASTVec::iterator xbeg = x.begin();
+  for(ASTVec::iterator xit = x.end()-1; xit > xbeg; xit--) {
+    *xit = *(xit-1);
+  }
+  *xbeg = ASTFalse;		// new LSB is zero.
+  // cout << "Shifted result" << endl;
+  // lpvec(x);
+}
+
+// Right shift by 1 within fixed field, inserting new zeros at MSB.
+// Writes result into first argument.
+// Fixme: generalize to n bits.
+void BeevMgr::BBRShift(ASTVec& x)
+{
+  ASTVec::iterator xend = x.end() - 1;
+  ASTVec::iterator xit = x.begin();
+  for( ; xit < xend; xit++) {
+    *xit = *(xit+1);
+  }
+  *xit = ASTFalse;		// new MSB is zero.
+}
+
+
+// Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc. 
+ASTNode BeevMgr::BBcompare(const ASTNode& form) {
+  const ASTNode lnode = BBTerm(form[0]);
+  const ASTNode rnode = BBTerm(form[1]);
+  const ASTVec& left = lnode.GetChildren();
+  const ASTVec& right = rnode.GetChildren();
+
+  //const ASTVec& left = BBTerm(form[0]).GetChildren();
+  //const ASTVec& right = BBTerm(form[1]).GetChildren();
+
+  Kind k = form.GetKind();
+  switch(k) {
+  case BVLE: { return BBBVLE(left, right, false); break; }
+  case BVGE: { return BBBVLE(right, left, false); break; }
+  case BVGT: { return CreateSimpNot(BBBVLE(left, right, false)); break; }
+  case BVLT: { return CreateSimpNot(BBBVLE(right, left, false)); break; }
+  case BVSLE: { return BBBVLE(left, right, true); break; }
+  case BVSGE: { return BBBVLE(right, left, true); break; }
+  case BVSGT: { return CreateSimpNot(BBBVLE(left, right, true)); break; }
+  case BVSLT: { return CreateSimpNot(BBBVLE(right, left, true)); break; }
+  default:
+    cerr << "BBCompare: Illegal kind" << form << endl;    
+    FatalError("",ASTUndefined);
+  }
+  return ASTUndefined;
+}
+
+
+// return a vector with n copies of fillval
+ASTVec BeevMgr::BBfill(unsigned int width, ASTNode fillval)
+{
+  ASTVec zvec(width, fillval);
+  return zvec;
+}
+
+ASTNode BeevMgr::BBEQ(const ASTVec& left, const ASTVec& right)
+{
+  ASTVec andvec;
+  ASTVec::const_iterator lit = left.begin();
+  ASTVec::const_iterator litend = left.end();
+  ASTVec::const_iterator rit = right.begin();
+  
+  if(left.size() > 1) {
+    for(; lit != litend; lit++, rit++) {
+      ASTNode biteq = CreateSimpForm(IFF, *lit, *rit);
+      // fast path exit
+      if (biteq == ASTFalse) {
+	return ASTFalse;
+      }
+      else {
+	andvec.push_back(biteq);
+      }
+    }
+    ASTNode n = CreateSimpForm(AND, andvec);  
+    return n;
+  }
+  else
+    return CreateSimpForm(IFF,*lit,*rit);
+}
+} // BEEV namespace

Added: klee/trunk/stp/AST/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/Makefile (added)
+++ klee/trunk/stp/AST/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,54 @@
+include ../Makefile.common
+
+SRCS = AST.cpp ASTKind.cpp  ASTUtil.cpp BitBlast.cpp SimpBool.cpp  ToCNF.cpp ToSAT.cpp Transform.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+#Make the ast library for use by other modules
+libast.a:	$(OBJS)
+	-rm -rf $@
+	$(AR) rc libast.a $(OBJS)
+	$(RANLIB) libast.a
+
+ASTKind.o: ASTKind.h ASTKind.cpp
+	$(CXX) $(CXXFLAGS)   -c -o ASTKind.o ASTKind.cpp
+
+# ASTKind.h and ASTKind.cpp are automatically generated
+ASTKind.h ASTKind.cpp:	ASTKind.kinds genkinds.pl
+	./genkinds.pl
+
+# cnftest:	cnftest.o ToCNF.o AST.o ASTUtil.o ASTKind.o BitBlast.o AST.h
+#	$(CC) $(LDFLAGS) ToCNF.o BitBlast.o ASTKind.o  ASTUtil.o AST.o  cnftest.o  -o cnftest 
+
+# bbtest: $(OBJS)
+#	$(CC) $(LDFLAGS) BitBlast.o ASTKind.o  ASTUtil.o AST.o  bbtest.o -o bbtest 
+
+# asttest: $(OBJS)
+#	$(CC) $(LDFLAGS) ASTKind.o  ASTUtil.o AST.o asttest.o  -lstdc++ -o asttest
+
+clean:
+	rm -rf *.o *~ bbtest asttest cnftest *.a  ASTKind.h ASTKind.cpp .#*
+
+depend:
+	makedepend -Y -- $(CFLAGS) -- $(SRCS)
+# DO NOT DELETE
+
+AST.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+AST.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+AST.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ASTUtil.o: ASTUtil.h
+BitBlast.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+BitBlast.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+BitBlast.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+SimpBool.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+SimpBool.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+SimpBool.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ToCNF.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+ToCNF.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+ToCNF.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ToSAT.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+ToSAT.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+ToSAT.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ToSAT.o: ../simplifier/bvsolver.h ../AST/AST.h
+Transform.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+Transform.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+Transform.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h

Added: klee/trunk/stp/AST/STLport_config.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/STLport_config.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/STLport_config.h (added)
+++ klee/trunk/stp/AST/STLport_config.h Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+// STLport debug checking, if we use STLport threads flag is to get
+// rid of link errors, since iostreams compiles with threads.  alloc
+// and uninitialized are extra checks Later on, if used with Purify or
+// Valgrind, may want to set flags to prevent reporting of false
+// leaks.  For some reason, _STLP_THREADS works on the command line
+// but not here (?)
+#define _STLP_THREADS
+#define _STLP_DEBUG 1
+#define _STLP_DEBUG_LEVEL _STLP_STANDARD_DBG_LEVEL 
+#define _STLP_DEBUG_ALLOC 1
+#define _STLP_DEBUG_UNINITIALIZED 1

Added: klee/trunk/stp/AST/SimpBool.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/SimpBool.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/SimpBool.cpp (added)
+++ klee/trunk/stp/AST/SimpBool.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,408 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: April, 2006
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+
+// -*- c++ -*-
+
+// Simplifying create methods for Boolean operations.
+// These are only very simple local simplifications.
+
+// This is somewhat redundant with Vijay's simplifier code.  They
+// need to be merged.
+// FIXME: control with optimize flag.
+
+static bool _trace_simpbool = 0;
+static bool _disable_simpbool = 0;
+
+#include "AST.h"
+
+// SMTLIB experimental hack.  Try allocating a single stack here for
+// children to reduce growing of vectors.
+//BEEV::ASTVec child_stack;
+
+namespace BEEV {
+
+  ASTNode BeevMgr::CreateSimpForm(Kind kind, ASTVec &children = _empty_ASTVec) {
+    if (_disable_simpbool) {
+      return CreateNode(kind, children);
+    }
+    else {
+      switch (kind) {
+      case NOT: return CreateSimpNot(children[0]); break; 
+      case AND: return CreateSimpAndOr(1, children); break; 
+      case OR: return CreateSimpAndOr(0, children); break;
+      case NAND: return CreateSimpNot(CreateSimpAndOr(1, children)); break;
+      case NOR: return CreateSimpNot(CreateSimpAndOr(0, children)); break;
+      case IFF: {
+	// Not sure children can ever be empty, but what the heck.
+	//	if (children.size() == 0) {
+	//	  return ASTTrue;
+	//	}
+	// Convert IFF to XOR ASAP.  IFF is not associative, so this makes
+	// flattening much easier.
+	children[0] = CreateSimpNot(children[0]);
+	return CreateSimpXor(children); break;
+      }
+      case XOR: 
+	return CreateSimpXor(children); break;
+	// FIXME: Earlier, check that this only has two arguments
+      case IMPLIES: return CreateSimpAndOr(0, CreateSimpNot(children[0]), children[1]); break;
+      case ITE: return CreateSimpFormITE(children[0], children[1], children[2]);
+      default: return CreateNode(kind, children);
+      }
+    }
+  }
+
+  // specialized versions
+  
+  ASTNode BeevMgr::CreateSimpForm(Kind kind,
+				  const ASTNode& child0) {
+    ASTVec children;
+    //child_stack.clear();	// could just reset top pointer.
+    children.push_back(child0);
+    //child_stack.push_back(child0);
+    return CreateSimpForm(kind, children);
+    //return CreateSimpForm(kind, child_stack);
+  }
+  
+  ASTNode BeevMgr::CreateSimpForm(Kind kind,
+				  const ASTNode& child0,
+				  const ASTNode& child1) {
+    ASTVec children;
+    //child_stack.clear();	// could just reset top pointer.
+    children.push_back(child0);
+    //child_stack.push_back(child0);
+    children.push_back(child1);
+    //child_stack.push_back(child1);
+    return CreateSimpForm(kind, children);
+    //return CreateSimpForm(kind, child_stack);
+  }
+  
+  
+  ASTNode BeevMgr::CreateSimpForm(Kind kind,
+				  const ASTNode& child0,
+				  const ASTNode& child1,
+				  const ASTNode& child2) {
+    ASTVec children;
+    //child_stack.clear();	// could just reset top pointer.
+    children.push_back(child0);
+    //child_stack.push_back(child0);
+    children.push_back(child1);
+    //child_stack.push_back(child1);
+    children.push_back(child2);
+    //child_stack.push_back(child2);
+    return CreateSimpForm(kind, children);
+    //return CreateSimpForm(kind, child_stack);
+  }
+    
+  ASTNode BeevMgr::CreateSimpNot(const ASTNode& form) {
+    Kind k = form.GetKind();
+    switch (k) {
+    case FALSE: { return ASTTrue; }
+    case TRUE: { return ASTFalse; }
+    case NOT: { return form[0]; } // NOT NOT cancellation
+    case XOR: {
+      // Push negation down in this case.
+      // FIXME: Separate pre-pass to push negation down?
+      // CreateSimp should be local, and this isn't.  
+      // It isn't memoized.  Arg.
+      ASTVec children = form.GetChildren();
+      children[0] = CreateSimpNot(children[0]);
+      return CreateSimpXor(children);
+    }
+    default: { return CreateNode(NOT, form); }
+    }
+  }
+
+  // I don't think this is even called, since it called
+  // CreateSimpAndOr instead of CreateSimpXor until 1/9/07 with no
+  // ill effects.  Calls seem to go to the version that takes a vector
+  // of children.
+  ASTNode BeevMgr::CreateSimpXor(const ASTNode& form1, const ASTNode& form2) {
+    ASTVec children;
+    children.push_back(form1);
+    children.push_back(form2);
+    return CreateSimpXor(children);
+  }
+
+
+  ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, const ASTNode& form1, const ASTNode& form2) {
+    ASTVec children;
+    children.push_back(form1);
+    children.push_back(form2);
+    return CreateSimpAndOr(IsAnd, children);
+  }
+
+  ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, ASTVec &children) {
+
+    if (_trace_simpbool) {
+      cout << "========" << endl << "CreateSimpAndOr " << (IsAnd ? "AND " : "OR ") ;
+      lpvec(children);
+      cout << endl;
+    }
+
+    ASTVec new_children;
+
+    // sort so that identical nodes occur in sequential runs, followed by
+    // their negations.
+
+    SortByExprNum(children);
+    
+    ASTNode annihilator = (IsAnd ? ASTFalse : ASTTrue);
+    ASTNode identity = (IsAnd ? ASTTrue : ASTFalse);
+
+    ASTNode retval;
+
+    ASTVec::const_iterator it_end = children.end();
+    ASTVec::const_iterator next_it;
+    for(ASTVec::const_iterator it = children.begin(); it != it_end; it = next_it) {
+      next_it = it + 1;
+      bool nextexists = (next_it < it_end);
+
+      if (*it == annihilator) {
+	retval = annihilator;
+	if (_trace_simpbool) {
+	  cout << "returns " << retval << endl;
+	}
+	return retval;
+      }
+      else if (*it == identity) {
+	// just drop it
+      }
+      else if (nextexists && (*next_it == *it)) {
+	// drop it
+	//	cout << "Dropping [" << it->GetNodeNum() << "]" << endl;
+      }
+      else if (nextexists && (next_it->GetKind() == NOT) && ((*next_it)[0] == *it)) {
+	// form and negation -- return FALSE for AND, TRUE for OR.
+	retval = annihilator;
+	// cout << "X and/or NOT X" << endl; 
+	if (_trace_simpbool) {
+	  cout << "returns " << retval << endl;
+	}
+	return retval;
+      }
+      else {
+	// add to children
+	new_children.push_back(*it);
+      }
+    }
+
+    // If we get here, we saw no annihilators, and children should
+    // be only the non-True nodes.
+    if (new_children.size() < 2) {
+      if (0 == new_children.size()) {
+	retval = identity;
+      }
+      else {
+	// there is just one child
+	retval = new_children[0];
+      }
+    }
+    else {
+      // 2 or more children.  Create a new node.
+      retval = CreateNode(IsAnd ? AND : OR, new_children);
+    }
+    if (_trace_simpbool) {
+      cout << "returns " << retval << endl;
+    }
+    return retval;
+  }
+
+
+  // Constant children are accumulated in "accumconst".  
+  ASTNode BeevMgr::CreateSimpXor(ASTVec &children) {
+
+    if (_trace_simpbool) {
+      cout << "========" << endl
+	   << "CreateSimpXor ";
+      lpvec(children);
+      cout << endl;
+    }
+
+    // Change this not to init to children if flattening code is present.
+    // ASTVec flat_children = children;		// empty vector
+
+    ASTVec flat_children;		// empty vector
+
+    ASTVec::const_iterator it_end = children.end();
+
+    if (xor_flatten) {
+
+      bool fflag = 0;		// ***Temp debugging
+      
+      // Experimental flattening code.
+      
+      for(ASTVec::iterator it = children.begin(); it != it_end; it++) {
+	Kind ck = it->GetKind();
+	const ASTVec &gchildren = it->GetChildren();
+	if (XOR == ck) {
+	  fflag = 1;
+	  // append grandchildren to children
+	  flat_children.insert(flat_children.end(), gchildren.begin(), gchildren.end());
+	}
+	else {
+	  flat_children.push_back(*it);
+	}
+      }
+      
+      if (_trace_simpbool && fflag) {
+	cout << "========" << endl;
+	cout << "Flattening: " << endl;
+	lpvec(children);
+	
+	cout << "--------" << endl;
+	cout << "Flattening result: " << endl;
+	lpvec(flat_children);
+      }
+    }
+    else {
+      flat_children = children;
+    }
+      
+
+    // sort so that identical nodes occur in sequential runs, followed by
+    // their negations.
+    SortByExprNum(flat_children);
+
+    ASTNode retval;
+
+    // This is the C Boolean value of all constant args seen.  It is initially
+    // 0.  TRUE children cause it to change value.
+    bool accumconst = 0;
+
+    ASTVec new_children;
+
+    it_end = flat_children.end();
+    ASTVec::iterator next_it;
+    for(ASTVec::iterator it = flat_children.begin(); it != it_end; it++) {
+      next_it = it + 1;
+      bool nextexists = (next_it < it_end);
+
+      if (ASTTrue == *it) {
+	accumconst = !accumconst;
+      }
+      else if (ASTFalse == *it) {
+	// Ignore it
+      }
+      else if (nextexists && (*next_it == *it)) {
+	// x XOR x = FALSE.  Skip current, write "false" into next_it
+	// so that it gets tossed, too.
+	*next_it = ASTFalse;
+      }
+      else if (nextexists && (next_it->GetKind() == NOT) && ((*next_it)[0] == *it)) {
+	// x XOR NOT x = TRUE.  Skip current, write "true" into next_it
+	// so that it gets tossed, too.
+	*next_it = ASTTrue;
+      }
+      else if (NOT == it->GetKind()) {
+	// If child is (NOT alpha), we can flip accumconst and use alpha.
+	// This is ok because (NOT alpha) == TRUE XOR alpha
+	accumconst = !accumconst;
+	// CreateSimpNot just takes child of not.
+	new_children.push_back(CreateSimpNot(*it));
+      }
+      else {
+	new_children.push_back(*it);
+      }
+    }
+
+    // Children should be non-constant.
+    if (new_children.size() < 2) {
+      if (0 == new_children.size()) {
+	// XOR(TRUE, FALSE) -- accumconst will be 1.
+	if (accumconst) {
+	  retval = ASTTrue;
+	}
+	else {
+	  retval = ASTFalse;
+	}
+      }
+      else {
+	// there is just one child
+	// XOR(x, TRUE) -- accumconst will be 1.
+	if (accumconst) {
+	  retval =  CreateSimpNot(new_children[0]);
+	}
+	else {
+	  retval = new_children[0];
+	}
+      }
+    }
+    else {
+      // negate first child if accumconst == 1
+      if (accumconst) {
+	new_children[0] = CreateSimpNot(new_children[0]);
+      }
+      retval = CreateNode(XOR, new_children);
+    }
+
+    if (_trace_simpbool) {    
+      cout << "returns " << retval << endl;
+    }
+    return retval;
+  }
+
+  // FIXME:  How do I know whether ITE is a formula or not?
+  ASTNode BeevMgr::CreateSimpFormITE(const ASTNode& child0,
+				     const ASTNode& child1,
+				     const ASTNode& child2) {
+
+    ASTNode retval;
+    
+    if (_trace_simpbool) {
+      cout << "========" << endl << "CreateSimpFormITE "
+	   << child0 
+	   << child1 
+	   << child2 << endl;
+    }
+
+    if (ASTTrue == child0) {
+      retval = child1;
+    }
+    else if (ASTFalse == child0) {
+      retval = child2;
+    }
+    else if (child1 == child2) {
+      retval = child1;
+    }    
+    // ITE(x, TRUE, y ) == x OR y
+    else if (ASTTrue == child1) {
+      retval = CreateSimpAndOr(0, child0, child2);
+    }
+    // ITE(x, FALSE, y ) == (!x AND y)
+    else if (ASTFalse == child1) {
+      retval = CreateSimpAndOr(1, CreateSimpNot(child0), child2); 
+    }
+    // ITE(x, y, TRUE ) == (!x OR y)
+    else if (ASTTrue == child2) {
+      retval = CreateSimpAndOr(0, CreateSimpNot(child0), child1); 
+    }
+    // ITE(x, y, FALSE ) == (x AND y)
+    else if (ASTFalse == child2) {
+      retval = CreateSimpAndOr(1, child0, child1); 
+    }
+    // ITE (x, !y, y) == x XOR y
+//     else if (NOT == child1.GetKind() && (child1[0] == child2)) {
+//       retval = CreateSimpXor(child0, child2);
+//     }
+//     // ITE (x, y, !y) == x IFF y.  I think other cases are covered
+//     // by XOR/IFF optimizations
+//     else if (NOT == child2.GetKind() && (child2[0] == child1)) {
+//       retval = CreateSimpXor(CreateSimpNot(child0), child2);
+//     }
+    else {
+      retval = CreateNode(ITE, child0, child1, child2);
+    }
+
+    if (_trace_simpbool) {
+      cout << "returns " << retval << endl;
+    }
+
+    return retval;
+  }
+} // BEEV namespace

Added: klee/trunk/stp/AST/ToCNF.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/ToCNF.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/ToCNF.cpp (added)
+++ klee/trunk/stp/AST/ToCNF.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,506 @@
+/********************************************************************
+ * AUTHORS: David L. Dill, Vijay Ganesh 
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+// THEORY: This code translates an arbitrary Boolean DAG, generated by
+// the BitBlast.cpp, to an equi-satisfiable CNF formula.  There are
+// four kinds of variables in the CNF formula: (1) propositional
+// variables from the original formula; (2) BVGETBIT formulas from the
+// original formula (a precondition is that the BVGETBIT can only be
+// applied to bitvector-valued variables, array reads, or
+// uninterpreted functions); (3) TRUE; or (4) representative variables
+// (see below).  Each literal in the CNF formula is one of these or
+// its negation.  
+
+// It is convenient (though not perfectly efficient) to be able to add
+// TRUE and FALSE constants to clauses, which is not allowed in CNF.
+// So, there is a "dummy variable" representing TRUE, which is used in
+// its place (so FALSE is represented by the negation of the dummy
+// var).  The CNF formula has a unit clause containing this dummy
+// variable, so that any satisfying assignment must make the dummy var
+// TRUE.
+
+// Every sub-formula of the input formula has a "representative
+// literal."  A truth assignment satisfies the CNF formula iff the
+// restriction of that assignment to the original variables satisfies
+// the original formula, AND the rep lits have the same truth values
+// as the subformulas they represent in the original formula.  In the
+// trivial cases, the representative literal is the input variable, or
+// dummy true var, or its negation.  Representative literals may be
+// negated variables -- essentially, only AND formulas are translated,
+// and everything else is handled by rewriting or negating formulas.
+// The representative for (NOT alpha) is the negation of the
+// representative for alpha.
+
+// The translation is performed by ToCNF_int, which traverses the original
+// formula.  ToCNF adds clauses that constrain the representative variables
+// to be equal to the truth values of the formulas they represent.
+// ToCNF always returns a literal whose value must be equivalent to the formula
+// it translated.  In trivial cases, this literal is a literal from the original
+// formula, or the dummy true/false literals.  If the formula is of the form
+// (not alpha), ToCNF_int negates the literal representing alpha (which may
+// itself be a negative literal) and returns it.  Otherwise, ToCNF_int assigns
+// a new rep var, adds the clauses, and returns the new var.  ToCNF_int is
+// memoized so that it doesn't assign more than one variable to a subformula,
+// and to prevent exponential numbers of redundant visits to shared subformulas.
+
+// In reality, only AND/OR/NOT formulas are translated directly.  Everything
+// else (XOR, IFF, IMPLIES) is rewritten on-the-fly into these forms.  I
+// could have done that in bit-blasting, but I thought that, in the future,
+// we might be able to translate these operations differently in different
+// contexts to optimize the CNF formula.
+
+// FIXME: Inspection of the clauses is kind of horrifying.  In
+// addition to true/false, there are duplicate literals and duplicate
+// clauses all over the place.
+#include "AST.h"
+static bool CNF_trace = false;
+namespace BEEV {
+/**  Statistics class.  Total number of variables is best tracked in
+     ToSAT.  Number of clauses is just cll.size() */
+
+class CNFstats {
+public:
+  int _num_new_rep_vars;
+  int _num_clauses;
+  
+  // constructor
+  CNFstats() : _num_new_rep_vars(0), _num_clauses(0) {}
+
+  void printStats() {
+    if(stats) {
+      cout << "ToCNF statistics:" << endl;
+      cout << "Number of new representative variables: "
+	   << _num_new_rep_vars << endl;
+      cout << "Number of new clauses: "
+	   << _num_clauses << endl;
+    }
+  }
+
+};
+
+
+/** This class contains private data and function members for the
+    CNF conversion */
+class CNFMgr {
+
+  friend class BeevMgr;
+
+public:    
+
+  // Needed in the body of BeevMgr::ToCNF.  It's not visible outside
+  // this file, though.
+  ASTNode dummy_true_var;
+
+  // CNF Pre-pass
+  ASTNodeMap ToCNFPrePassMemo;
+
+  // CNF Memo Table.
+  ASTNodeMap CNFMemo;
+
+
+private:
+
+  // Pointer back to BeevMgr with the node tables, etc.
+  BeevMgr *bm;
+  
+  // For ToCNF conversion.  This holds a dummy variable representing
+  // "True".  It is added as a unit clause, so that it will be assigned
+  // to true and propagated immediately by any CNF solver.
+
+  ASTNode dummy_false_var;	// not of dummy_true_var
+
+  CNFstats stats;
+
+  // constructor
+  CNFMgr(BeevMgr *bmgr)
+  {
+    bm = bmgr;
+
+    // Dummy variable so TRUE can be a literal.
+    dummy_true_var = bm->CreateSymbol("*TrueDummy*");
+    dummy_false_var = bm->CreateSimpNot(dummy_true_var);
+  }
+  
+  // Returns true iff result has been memoized.
+  // if it returns true, result is returned in by-ref parameter "result"
+  // Consider just putitng this in-line.
+  bool CNFIsMemoized(ASTNode &form, ASTNode &result)
+  {
+    ASTNodeMap::iterator it = CNFMemo.find(form);
+    if (it != CNFMemo.end()) {
+      result = it->second;  //already there. Just return it.
+      return true;
+    }
+    else {
+      return false;
+    }
+  }
+
+
+  // Convert a big XOR to a bunch of AND/ORs.  Assumes subformulas have
+  // already been converted.
+  ASTNode convertXORs(ASTVec children)
+  {
+    ASTNode accum = children[0];
+    ASTVec::iterator itend = children.end();
+    for (ASTVec::iterator it = children.begin()+1; it < itend; it++) {
+      // a XOR b -> (a | b) & (!a | !b)
+
+      // For each XOR node with k children, creates approximately
+      // 5*(k-1) nodes. AND + 2 OR + 2 NOT.
+
+      ASTNode or1 = bm->CreateNode(OR, accum, *it);
+      ASTNode or2 = bm->CreateNode(OR, bm->CreateSimpNot(accum), bm->CreateSimpNot(*it));
+      accum = bm->CreateNode(AND, or1, or2);
+      
+    }
+    
+    return accum;
+  }
+
+
+  // Do preliminary transformations on bitblasted formula to make 
+  // CNF conversion easier.
+  // Converts XORs to AND/OR form.
+  ASTNode ToCNFPrePass(const ASTNode &form)
+  {
+
+    // Check memo table
+    ASTNodeMap::iterator mem_it = ToCNFPrePassMemo.find(form);
+    if (mem_it != ToCNFPrePassMemo.end()) {
+      return mem_it->second;
+    }
+    
+    ASTNode result;
+
+    ASTVec new_children;
+    ASTVec::const_iterator endit = form.end();
+    for (ASTVec::const_iterator it = form.begin(); it != endit; it++) {
+      ASTNode ch = ToCNFPrePass(*it);
+      new_children.push_back(ch);
+    }
+
+    Kind k = form.GetKind();
+
+    switch (k) {
+    case FALSE: 
+    case TRUE:
+    case SYMBOL: 
+    case BVGETBIT: {
+      result = form;
+      break;
+    }
+    case XOR: {
+      // convertXORs can only be called once per XOR node.
+      result = convertXORs(new_children);
+
+      // cout << "convertXORs num args: "  << new_children.size() << endl;
+      // temporary node for node count.
+      // ASTNode tmp = bm->CreateNode(XOR, new_children );
+      // cout << "convertXORs size of [" << form.GetNodeNum() << "] " << bm->NodeSize(form, true) << endl;
+      // cout << "convertXORs before size: " << bm->NodeSize(tmp, true) << endl;
+      // cout << "convertXORs after size: " << bm->NodeSize(result, true) << endl;
+      break;
+    }
+    default: {
+      // Be cautious about using CreateSimpForm -- It makes big xors!
+      result = bm->CreateNode(k, new_children);
+    }
+    }
+
+//     cout << "================" << endl
+// 	 << "ToCNFPrePass:" << form << endl
+// 	 << "----------------" << endl
+// 	 << "ToCNFPrePass Result:" << result << endl;
+    
+    return (ToCNFPrePassMemo[form] = result);
+    
+  }
+
+  // Memoize and return formula value
+  ASTNode CNFMemoize(ASTNode& form, ASTNode result)
+  {
+    CNFMemo[form] = result;
+    return result;    
+  }
+
+ 
+  // Create a representative variable for an original formula.
+  // The convention is that the variable will have the same truth
+  // value as the expression numbered "num."  
+  ASTNode RepLit(const char *name, int exprnum)
+  {
+    // FIXME: can this be done more efficiently with string type?
+    ostringstream oss;
+    oss << name << "{" << exprnum << "}";
+    ASTNode t = bm->CreateSymbol(oss.str().c_str());
+
+    // Track how many we're generating.
+    stats._num_new_rep_vars++;
+    
+    //ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+    t.SetIndexWidth(0);
+    t.SetValueWidth(0);
+    return t;
+  }
+
+  // Handle the cases where it's necessary to do n children.
+  // This code translates ANDs, and converts NAND, NOR, OR by negating
+  // the inputs or outputs of the AND.
+  ASTNode ToCNF_AndLike(Kind k, BeevMgr::ClauseList& cll, ASTNode form)
+  {  
+    // Build vectors of positive and negative rep lits for children
+    ASTVec kidlits(0);
+    ASTVec negkidlits(0);
+    ASTVec::const_iterator kids_end = form.end();
+    for (ASTVec::const_iterator it = form.begin(); it != kids_end; it++) {
+      ASTNode kidreplit = ToCNF_int(cll, *it);
+      kidlits.push_back(kidreplit);
+      negkidlits.push_back(bm->CreateSimpNot(kidreplit));
+    }
+    
+    ASTNode replit;
+    // translate the AND, negating inputs as appropriate.
+    if (k == OR || k == NOR) {
+      replit = ToCNF_AND(cll, form.GetNodeNum(), negkidlits, kidlits);
+    }
+    else {
+      replit = ToCNF_AND(cll, form.GetNodeNum(), kidlits, negkidlits);
+    }
+    
+    // Reduce NAND/OR to AND by negating result.
+    if (k == NAND || k == OR) {
+      return CNFMemoize(form, bm->CreateSimpNot(replit));
+    }
+    else {
+      return CNFMemoize(form, replit);
+    }
+  }
+
+  ASTNode ToCNF_AND(BeevMgr::ClauseList& cll, int nodenum, ASTVec& kidlits, ASTVec& negkidlits)
+  {
+    // Translate an AND, given rep lits for children
+    // Build clauses for (replit <-> a AND b AND c)
+
+    ASTNode replit = RepLit("cnf", nodenum);
+    ASTNode notreplit = bm->CreateSimpNot(replit);
+
+    if (CNF_trace) {
+      cout << "Translating AND" << endl << "-----------------------" << endl
+	   << "Rep lit =" <<  replit << endl
+	   << "-----------------------";
+    }
+
+    // (a AND b AND c -> replit) ==   (~a OR ~b OR ~c OR replit)
+    BeevMgr::ClausePtr clp = new ASTVec(negkidlits);
+    clp->push_back(replit);
+
+    if (CNF_trace) {
+      LispPrintVec(cout, *clp, 0);
+      cout << endl << "-----------------------" << endl;
+    }
+
+    cll.push_back(clp);
+
+    // (replit -> (a AND b AND c)) == 
+    //     (~replit OR a) AND (~replit OR b) AND (~replit OR c)
+    ASTVec::const_iterator kidlits_end = kidlits.end();
+    for (ASTVec::iterator it = kidlits.begin(); it != kidlits_end; it++) {
+      clp = new ASTVec();
+      clp->push_back(notreplit);
+      clp->push_back(*it);
+
+      if (CNF_trace) {
+	LispPrintVec(cout, *clp, 0);
+	cout << endl << "-----------------------" << endl;
+      }
+
+      cll.push_back(clp);
+    }
+
+    return replit;
+  }
+
+public:
+   
+  /** Builds clauses globally and returns a literal.
+      The literal can be a leaf from the expression, or a rep var
+      made up to represent the subexpression. */
+  ASTNode ToCNF_int(BeevMgr::BeevMgr::ClauseList& cll, ASTNode form) {
+    // FIXME: assert indexwidth= 0, valuewidth = 1
+
+    // FIXME:  rewriting is top-down, which is not efficient.
+    // It rewrites the top node of the tree, then does the children.
+    // Either rewrite in a separate pass, or translate children
+    // before rewriting somehow (might require handling rep lits
+    // as though they were real lits, which is probably ok).
+    
+    // Return memoized value if seen before.
+    ASTNode result;
+    Kind k = form.GetKind();
+
+    if (CNFIsMemoized(form, result)) {
+      return result;
+    }
+
+    switch (k) {
+      // handle the trivial cases here.  If none apply, call the
+      // heavy-duty function.  If a constant or literal, just return
+      // without creating a clause.
+    case FALSE: {
+      result = dummy_false_var;
+      break;
+    }
+    case TRUE: {
+      result =  dummy_true_var;
+      break;
+    }
+    case SYMBOL: 
+    case BVGETBIT: {
+      result = form;
+      break;
+    }
+      
+    case NOT: {
+	ASTNode replit = ToCNF_int(cll, form[0]);
+	result = bm->CreateSimpNot(replit);
+      break;
+    }
+      
+      // For these, I can't think of anything better than expanding into ANDs/ORs
+    case ITE: {
+      // (ite a b c) == (~a OR b) AND (a OR c)
+      ASTNode l = bm->CreateNode(OR, bm->CreateSimpNot(form[0]), form[1]);
+      ASTNode r = bm->CreateNode(OR, form[0], form[2]);
+      ASTNode andor = bm->CreateNode(AND, l, r);
+      if (CNF_trace) {
+	cout << "Rewriting " << form << endl
+	     << "to" << andor << endl
+	     << "-------------------" << endl;
+      }
+      result = ToCNF_int(cll, andor);
+      break;
+    }
+    case IMPLIES: {
+      // Just rewrite into (~a OR b)
+      ASTNode l = bm->CreateSimpNot(form[0]);
+      ASTNode andor = bm->CreateNode(OR, l, form[1]);
+      if (CNF_trace) {
+	cout << "Rewriting " << form << endl
+	     << "to" << andor << endl
+	     << "-------------------" << endl;
+      }
+      result = ToCNF_int(cll, andor);
+      break;
+    }
+    case XOR: {
+      FatalError("ToCNF_int: XORs should have been converted to AND/OR by this point.");
+      break;
+    }
+
+    case IFF: {
+      FatalError("BitBlaster failed to eliminate all IFFs.");
+      break;
+    }
+    
+    case AND:
+    case OR:
+    case NOR:
+    case NAND: {
+      result = ToCNF_AndLike(k, cll, form);
+      break;
+    }
+    default:
+      cerr << "ToCNF: can't handle this kind: " << k << endl;
+      FatalError("");
+    }
+
+    if (CNF_trace) {
+      cout << "ToCNF_int: Literal " << result << " represents formula " <<
+	form << endl << "---------------" << endl;
+    }
+
+    return CNFMemoize(form, result);
+  } //end of ToCNF_int()
+
+
+}; // end of CNFMgr class
+
+  // These are the bodies of functions in the BeevMgr that are part of
+  // the public interface.
+
+  // Debug printing function.
+  void BeevMgr::PrintClauseList(ostream& os, BeevMgr::ClauseList& cll)
+  {
+    int num_clauses = cll.size();
+    os << "Clauses: " << endl << "=========================================" << endl;
+    for(int i=0; i < num_clauses; i++) {
+      os << "Clause " << i << endl
+	 << "-------------------------------------------" << endl;
+      LispPrintVec(os, *cll[i], 0);
+      os << endl
+	 << "-------------------------------------------" << endl;
+    }
+  }
+
+  void BeevMgr::DeleteClauseList(BeevMgr::ClauseList *cllp)
+  {
+    BeevMgr::ClauseList::const_iterator iend = cllp->end();
+    for (BeevMgr::ClauseList::const_iterator i = cllp->begin(); i < iend; i++) {
+      delete *i;
+    }
+    delete cllp;
+  }
+
+  // Top level conversion function
+  BeevMgr::ClauseList *BeevMgr::ToCNF(const ASTNode& form) 
+  {
+
+    // FIXME: This is leaked as well.
+    CNFMgr *cm = new CNFMgr(this);
+   
+    // Prepass
+    ASTNode form1 = cm->ToCNFPrePass(form);
+
+    // cout << "Number of nodes after ToCNFPrePass" << NodeSize(form1, true) << endl;
+
+    // cout << "ToCNF: After ToCNFPrePass" << form1 << endl;
+
+    // FIXME: Assert CNFMemo is empty.
+
+    // The clause list we will be building up.
+    // FIXME: This is never freed.
+    ClauseList *cllp = new ClauseList();
+
+    BeevMgr::ClausePtr dummy_true_unit_clause = new ASTVec();
+    dummy_true_unit_clause->push_back(cm->dummy_true_var);
+    cllp->push_back(dummy_true_unit_clause);
+
+    // This is where the translation happens.
+    ASTNode toplit = cm->ToCNF_int(*cllp, form1);
+
+    // Add the top literal as a unit clause, since it must
+    // be true when original formula is satsfied.
+    BeevMgr::ClausePtr clp = new ASTVec(0);
+    clp->push_back(toplit);
+    cllp->push_back(clp);
+
+    cm->stats._num_clauses = cllp->size();
+    cm->stats.printStats();
+
+    RepLitMap = cm->CNFMemo;	// Save memo table for debugging (DD 1/13/07).
+
+    cm->CNFMemo.clear();   // Important to do this so nodes get freed.
+
+    delete cm;
+
+    return cllp;
+  }
+
+} // end namespace

Added: klee/trunk/stp/AST/ToSAT.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/ToSAT.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/ToSAT.cpp (added)
+++ klee/trunk/stp/AST/ToSAT.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,1385 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+#include "AST.h"
+#include "ASTUtil.h"
+#include "../simplifier/bvsolver.h"
+#include <math.h>
+
+
+namespace BEEV {
+  /* FUNCTION: lookup or create a new MINISAT literal
+   * lookup or create new MINISAT Vars from the global MAP
+   * _ASTNode_to_SATVar.
+   */
+  const MINISAT::Var BeevMgr::LookupOrCreateSATVar(MINISAT::Solver& newS, const ASTNode& n) {  
+    ASTtoSATMap::iterator it;  
+    MINISAT::Var v;
+    
+    //look for the symbol in the global map from ASTNodes to ints. if
+    //not found, create a S.newVar(), else use the existing one.
+    if((it = _ASTNode_to_SATVar.find(n)) == _ASTNode_to_SATVar.end()) {
+      v = newS.newVar();
+      _ASTNode_to_SATVar[n] = v;	
+      
+      //ASSUMPTION: I am assuming that the newS.newVar() call increments v
+      //by 1 each time it is called, and the initial value of a
+      //MINISAT::Var is 0.
+      _SATVar_to_AST.push_back(n);
+    }
+    else
+      v = it->second;
+    return v;
+  }
+  
+  /* FUNCTION: convert ASTClauses to MINISAT clauses and solve.
+   * Accepts ASTClauses and converts them to MINISAT clauses. Then adds
+   * the newly minted MINISAT clauses to the local SAT instance, and
+   * calls solve(). If solve returns unsat, then stop and return
+   * unsat. else continue.
+   */  
+  // FIXME: Still need to deal with TRUE/FALSE in clauses!
+ bool BeevMgr::toSATandSolve(MINISAT::Solver& newS, BeevMgr::ClauseList& cll)
+ {
+    CountersAndStats("SAT Solver");
+
+    //iterate through the list (conjunction) of ASTclauses cll
+    BeevMgr::ClauseList::const_iterator i = cll.begin(), iend = cll.end();
+    
+    if(i == iend)
+      FatalError("toSATandSolve: Nothing to Solve",ASTUndefined);
+    
+    //turnOffSubsumption
+    newS.turnOffSubsumption();
+
+    // (*i) is an ASTVec-ptr which denotes an ASTclause
+    for(; i!=iend; i++) {    
+      //Clause for the SATSolver
+      MINISAT::vec<MINISAT::Lit> satSolverClause;
+      
+      //now iterate through the internals of the ASTclause itself
+      ASTVec::const_iterator j = (*i)->begin(), jend = (*i)->end();
+      //j is a disjunct in the ASTclause (*i)
+      for(;j!=jend;j++) {
+
+	bool negate = (NOT == j->GetKind()) ? true : false;		
+	ASTNode n = negate ? (*j)[0] : *j;
+	
+	//Lookup or create the MINISAT::Var corresponding to the Booelan
+	//ASTNode Variable, and push into sat Solver clause
+	MINISAT::Var v = LookupOrCreateSATVar(newS,n);
+	MINISAT::Lit l(v, negate);
+	satSolverClause.push(l);
+      }
+      newS.addClause(satSolverClause);
+      // clause printing.
+      // (printClause<MINISAT::vec<MINISAT::Lit> >)(satSolverClause);
+      // cout << " 0 ";
+      // cout << endl;
+      
+      if(newS.okay()) {
+	continue;
+      }
+      else {
+	PrintStats(newS.stats);
+	return false;
+      }
+      
+      if(!newS.simplifyDB(false)) {
+      	PrintStats(newS.stats);
+      	return false;
+      }
+    }
+
+    // if input is UNSAT return false, else return true    
+    if(!newS.simplifyDB(false)) {
+      PrintStats(newS.stats);
+      return false;
+    }
+    
+    //PrintActivityLevels_Of_SATVars("Before SAT:",newS);
+    //ChangeActivityLevels_Of_SATVars(newS);
+    //PrintActivityLevels_Of_SATVars("Before SAT and after initial bias:",newS); 
+    newS.solve();
+    //PrintActivityLevels_Of_SATVars("After SAT",newS);
+
+    PrintStats(newS.stats);
+    if (newS.okay())
+      return true;
+    else
+      return false;
+  }
+
+  // GLOBAL FUNCTION: Prints statistics from the MINISAT Solver   
+  void BeevMgr::PrintStats(MINISAT::SolverStats& s) {
+    if(!stats)
+      return;
+    double  cpu_time = MINISAT::cpuTime();
+    MINISAT::int64   mem_used = MINISAT::memUsed();
+    reportf("restarts              : %"I64_fmt"\n", s.starts);
+    reportf("conflicts             : %-12"I64_fmt"   (%.0f /sec)\n", s.conflicts   , s.conflicts   /cpu_time);
+    reportf("decisions             : %-12"I64_fmt"   (%.0f /sec)\n", s.decisions   , s.decisions   /cpu_time);
+    reportf("propagations          : %-12"I64_fmt"   (%.0f /sec)\n", s.propagations, s.propagations/cpu_time);
+    reportf("conflict literals     : %-12"I64_fmt"   (%4.2f %% deleted)\n", 
+	    s.tot_literals, 
+	    (s.max_literals - s.tot_literals)*100 / (double)s.max_literals);
+    if (mem_used != 0) reportf("Memory used           : %.2f MB\n", mem_used / 1048576.0);
+    reportf("CPU time              : %g s\n", cpu_time);
+  }
+  
+  // Prints Satisfying assignment directly, for debugging.
+  void BeevMgr::PrintSATModel(MINISAT::Solver& newS) {
+    if(!newS.okay())
+      FatalError("PrintSATModel: NO COUNTEREXAMPLE TO PRINT",ASTUndefined);
+    // FIXME: Don't put tests like this in the print functions.  The print functions
+    // should print unconditionally.  Put a conditional around the call if you don't 
+    // want them to print
+    if(!(stats && print_nodes))
+      return;
+
+    int num_vars = newS.nVars();
+    cout << "Satisfying assignment: " << endl;
+    for (int i = 0; i < num_vars; i++) {
+      if (newS.model[i] == MINISAT::l_True) {
+	ASTNode s = _SATVar_to_AST[i];
+	cout << s << endl;
+      }
+      else if (newS.model[i] == MINISAT::l_False) {
+	ASTNode s = _SATVar_to_AST[i];
+	cout << CreateNode(NOT, s) << endl;
+      }
+    }
+  }
+
+
+  // Looks up truth value of ASTNode SYMBOL in MINISAT satisfying assignment.
+  // Returns ASTTrue if true, ASTFalse if false or undefined.
+  ASTNode BeevMgr::SymbolTruthValue(MINISAT::Solver &newS, ASTNode form) 
+  {
+    MINISAT::Var satvar = _ASTNode_to_SATVar[form];
+    if (newS.model[satvar] == MINISAT::l_True) {
+      return ASTTrue;
+    }
+    else if (newS.model[satvar] == MINISAT::l_False){
+      // False
+      return ASTFalse;
+    }
+    else {
+      return (rand() > 4096) ? ASTTrue : ASTFalse; 
+    }
+  }
+
+
+  // This function is for debugging problems with BitBlast and especially
+  // ToCNF. It evaluates the bit-blasted formula in the satisfying
+  // assignment.  While doing that, it checks that every subformula has
+  // the same truth value as its representative literal, if it has one.
+  // If this condition is violated, it halts immediately (on the leftmost
+  // lowest term).
+  // Use CreateSimpForm to evaluate, even though it's expensive, so that
+  // we can use the partial truth assignment.
+  ASTNode BeevMgr::CheckBBandCNF(MINISAT::Solver& newS, ASTNode form)
+  {
+    // Clear memo table (in case newS has changed).
+    CheckBBandCNFMemo.clear();
+    // Call recursive version that does the work.
+    return CheckBBandCNF_int(newS, form);
+  }
+
+  // Recursive body CheckBBandCNF
+  // FIXME:  Modify this to just check if result is true, and print mismatch 
+  // if not.   Might have a trace flag for the other stuff.
+  ASTNode BeevMgr::CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form)
+  {
+
+    //    cout << "++++++++++++++++" << endl << "CheckBBandCNF_int form = " <<
+    //      form << endl;
+  
+    ASTNodeMap::iterator memoit = CheckBBandCNFMemo.find(form);
+    if (memoit != CheckBBandCNFMemo.end()) {
+      // found it.  Return memoized value.
+      return memoit->second;
+    }
+
+    ASTNode result;		// return value, to memoize.
+
+    Kind k = form.GetKind();
+    switch (k) {
+    case TRUE:
+    case FALSE: {
+      return form;
+      break;
+    }
+    case SYMBOL: 
+    case BVGETBIT:  {
+      // Look up the truth value
+      // ASTNode -> Sat -> Truthvalue -> ASTTrue or ASTFalse;
+      // FIXME: Could make up a fresh var in undefined case.
+
+      result = SymbolTruthValue(newS, form);
+
+      cout << "================" << endl << "Checking BB formula:" << form << endl;
+      cout << "----------------" << endl << "Result:" << result << endl;
+
+      break;
+    }
+    default: {
+      // Evaluate the children recursively.
+      ASTVec eval_children;
+      ASTVec ch = form.GetChildren();
+      ASTVec::iterator itend = ch.end();
+      for(ASTVec::iterator it = ch.begin(); it < itend; it++) {
+	eval_children.push_back(CheckBBandCNF_int(newS, *it));
+      }
+      result = CreateSimpForm(k, eval_children);
+
+      cout << "================" << endl << "Checking BB formula:" << form << endl;
+      cout << "----------------" << endl << "Result:" << result << endl;
+
+      ASTNode replit_eval;
+      // Compare with replit, if there is one.
+      ASTNodeMap::iterator replit_it = RepLitMap.find(form);
+      if (replit_it != RepLitMap.end()) {
+	ASTNode replit = RepLitMap[form];
+	// Replit is symbol or not symbol.
+	if (SYMBOL == replit.GetKind()) {
+	  replit_eval = SymbolTruthValue(newS, replit);
+	}
+	else {
+	  // It's (NOT sym).  Get value of sym and complement.
+	  replit_eval = CreateSimpNot(SymbolTruthValue(newS, replit[0]));
+	}
+
+	cout << "----------------" << endl << "Rep lit: " << replit << endl;
+	cout << "----------------" << endl << "Rep lit value: " << replit_eval << endl;
+
+	if (result != replit_eval) {
+	  // Hit the panic button.
+	  FatalError("Truth value of BitBlasted formula disagrees with representative literal in CNF.");
+	}
+      }
+      else {
+	cout << "----------------" << endl << "No rep lit" << endl;
+      }
+
+    }
+    }
+
+    return (CheckBBandCNFMemo[form] = result);
+  }
+
+  /*FUNCTION: constructs counterexample from MINISAT counterexample
+   * step1 : iterate through MINISAT counterexample and assemble the
+   * bits for each AST term. Store it in a map from ASTNode to vector
+   * of bools (bits).
+   *
+   * step2: Iterate over the map from ASTNodes->Vector-of-Bools and
+   * populate the CounterExampleMap data structure (ASTNode -> BVConst)
+   */
+  void BeevMgr::ConstructCounterExample(MINISAT::Solver& newS) {
+    //iterate over MINISAT counterexample and construct a map from AST
+    //terms to vector of bools. We need this iteration step because
+    //MINISAT might return the various bits of a term out of
+    //order. Therfore, we need to collect all the bits and assemble
+    //them properly
+    
+    if(!newS.okay())
+      return;
+    if(!construct_counterexample)
+      return;    
+
+    CopySolverMap_To_CounterExample();
+    for (int i = 0; i < newS.nVars(); i++) {
+      //Make sure that the MINISAT::Var is defined
+      if (newS.model[i] != MINISAT::l_Undef) {
+	
+	//mapping from MINISAT::Vars to ASTNodes. We do not need to
+	//print MINISAT vars or CNF vars.
+	ASTNode s = _SATVar_to_AST[i];
+	
+	//assemble the counterexample here
+	if(s.GetKind() == BVGETBIT && s[0].GetKind() == SYMBOL) {
+	  ASTNode symbol = s[0];
+	  unsigned int symbolWidth = symbol.GetValueWidth();
+	  
+	  //'v' is the map from bit-index to bit-value
+	  hash_map<unsigned,bool> * v;	
+	  if(_ASTNode_to_Bitvector.find(symbol) == _ASTNode_to_Bitvector.end())
+	    _ASTNode_to_Bitvector[symbol] = new hash_map<unsigned,bool>(symbolWidth);	
+	  
+	  //v holds the map from bit-index to bit-value
+	  v = _ASTNode_to_Bitvector[symbol];
+	  
+	  //kk is the index of BVGETBIT
+	  unsigned int kk = GetUnsignedConst(s[1]); 	
+	  
+	  //Collect the bits of 'symbol' and store in v. Store in reverse order.
+	  if(newS.model[i]==MINISAT::l_True)
+	    (*v)[(symbolWidth-1) - kk] = true;
+	  else
+	    (*v)[(symbolWidth-1) - kk] = false;
+	}
+	else {	 
+	  if(s.GetKind() == SYMBOL && s.GetType() == BOOLEAN_TYPE) {
+	    const char * zz = s.GetName();
+	    //if the variables are not cnf variables then add them to the counterexample
+	    if(0 != strncmp("cnf",zz,3) && 0 != strcmp("*TrueDummy*",zz)) {
+	      if(newS.model[i]==MINISAT::l_True)
+		CounterExampleMap[s] = ASTTrue;
+	      else
+		CounterExampleMap[s] = ASTFalse;	    
+	    }
+	  }
+	}
+      }
+    }
+
+    //iterate over the ASTNode_to_Bitvector data-struct and construct
+    //the the aggregate value of the bitvector, and populate the
+    //CounterExampleMap datastructure
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),itend=_ASTNode_to_Bitvector.end();
+	it!=itend;it++) {
+      ASTNode var = it->first;      
+      //debugging
+      //cerr << var;
+      if(SYMBOL != var.GetKind())
+	FatalError("ConstructCounterExample: error while constructing counterexample: not a variable: ",var);
+
+      //construct the bitvector value
+      hash_map<unsigned,bool> * w = it->second;
+      ASTNode value = BoolVectoBVConst(w, var.GetValueWidth());      
+      //debugging
+      //cerr << value;
+
+      //populate the counterexample datastructure. add only scalars
+      //variables which were declared in the input and newly
+      //introduced variables for array reads
+      CounterExampleMap[var] = value;
+    }
+    
+    //In this loop, we compute the value of each array read, the
+    //corresponding ITE against the counterexample generated above.
+    for(ASTNodeMap::iterator it=_arrayread_ite.begin(),itend=_arrayread_ite.end();
+	it!=itend;it++){
+      //the array read
+      ASTNode arrayread = it->first;
+      ASTNode value_ite = _arrayread_ite[arrayread];
+      
+      //convert it to a constant array-read and store it in the
+      //counter-example. First convert the index into a constant. then
+      //construct the appropriate array-read and store it in the
+      //counterexample
+      ASTNode arrayread_index = TermToConstTermUsingModel(arrayread[1]);
+      ASTNode key = CreateTerm(READ,arrayread.GetValueWidth(),arrayread[0],arrayread_index);
+
+      //Get the ITE corresponding to the array-read and convert it
+      //to a constant against the model
+      ASTNode value = TermToConstTermUsingModel(value_ite);
+      //save the result in the counter_example
+      if(!CheckSubstitutionMap(key))
+	CounterExampleMap[key] = value;      
+    }
+  } //End of ConstructCounterExample
+
+  // FUNCTION: accepts a non-constant term, and returns the
+  // corresponding constant term with respect to a model. 
+  //
+  // term READ(A,i) is treated as follows:
+  //
+  //1. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
+  //1. has value in counterexample), then return the value of the
+  //1. arrayread.
+  //
+  //2. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
+  //2. doesn't have value in counterexample), then return the
+  //2. arrayread itself (normalized such that arrayread has a constant
+  //2. index)
+  //
+  //3. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
+  //3. has a value in the counterexample then return the value of the
+  //3. arrayread.
+  //
+  //4. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
+  //4. doesn't have a value in the counterexample then return 0 as the
+  //4. value of the arrayread.
+  ASTNode BeevMgr::TermToConstTermUsingModel(const ASTNode& t, bool ArrayReadFlag) {
+    Begin_RemoveWrites = false;
+    SimplifyWrites_InPlace_Flag = false;
+    //ASTNode term = SimplifyTerm(t);
+    ASTNode term = t;
+    Kind k = term.GetKind();
+    
+
+    //cerr << "Input to TermToConstTermUsingModel: " << term << endl;
+    if(!is_Term_kind(k)) {
+      FatalError("TermToConstTermUsingModel: The input is not a term: ",term);
+    }
+    if(k == WRITE) {
+      FatalError("TermToConstTermUsingModel: The input has wrong kind: WRITE : ",term);
+    }
+    if(k == SYMBOL && BOOLEAN_TYPE == term.GetType()) {
+      FatalError("TermToConstTermUsingModel: The input has wrong kind: Propositional variable : ",term);
+    }
+
+    ASTNodeMap::iterator it1;
+    if((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end()) {
+      ASTNode val = it1->second;
+      if(BVCONST != val.GetKind()) {
+	//CounterExampleMap has two maps rolled into
+	//one. SubstitutionMap and SolverMap.
+	//
+	//recursion is fine here. There are two maps that are checked
+	//here. One is the substitutionmap. We garuntee that the value
+	//of a key in the substitutionmap is always a constant.
+	//
+	//in the SolverMap we garuntee that "term" does not occur in
+	//the value part of the map
+	if(term == val) {
+	  FatalError("TermToConstTermUsingModel: The input term is stored as-is "
+		     "in the CounterExample: Not ok: ",term);    
+	}
+	return TermToConstTermUsingModel(val,ArrayReadFlag);
+      }
+      else {
+	return val;
+      }
+    }
+
+    ASTNode output;
+    switch(k) {
+    case BVCONST:
+      output = term;
+      break;
+    case SYMBOL: {
+      if(term.GetType() == ARRAY_TYPE) {
+	return term;
+      }
+
+      //when all else fails set symbol values to some constant by
+      //default. if the variable is queried the second time then add 1
+      //to and return the new value.
+      ASTNode zero = CreateZeroConst(term.GetValueWidth());
+      output = zero;
+      break;    
+    }
+    case READ: {      
+      ASTNode arrName = term[0];
+      ASTNode index = term[1];
+      if(0 == arrName.GetIndexWidth()) {
+	FatalError("TermToConstTermUsingModel: array has 0 index width: ",arrName);
+      }
+      
+      //READ over a WRITE
+      if(WRITE == arrName.GetKind()) {
+	ASTNode wrtterm = Expand_ReadOverWrite_UsingModel(term, ArrayReadFlag);
+	if(wrtterm == term) {
+	  FatalError("TermToConstTermUsingModel: Read_Over_Write term must be expanded into an ITE", term);
+	}
+	ASTNode rtterm = TermToConstTermUsingModel(wrtterm,ArrayReadFlag);	
+	return rtterm;
+      } 
+      //READ over an ITE
+      if(ITE == arrName.GetKind()) {
+	arrName = TermToConstTermUsingModel(arrName,ArrayReadFlag);
+      }
+
+      ASTNode modelentry;
+      if(CounterExampleMap.find(index) != CounterExampleMap.end()) {	
+	//index has a const value in the CounterExampleMap
+	ASTNode indexVal = CounterExampleMap[index];
+	modelentry = CreateTerm(READ, arrName.GetValueWidth(), arrName, indexVal);
+      }
+      else { 
+	//index does not have a const value in the CounterExampleMap. compute it.
+	ASTNode indexconstval = TermToConstTermUsingModel(index,ArrayReadFlag);
+	//update model with value of the index
+	//CounterExampleMap[index] = indexconstval;
+	modelentry = CreateTerm(READ,arrName.GetValueWidth(), arrName,indexconstval);	
+      }
+      //modelentry is now an arrayread over a constant index
+      BVTypeCheck(modelentry);
+      
+      //if a value exists in the CounterExampleMap then return it
+      if(CounterExampleMap.find(modelentry) != CounterExampleMap.end()) {
+	output = TermToConstTermUsingModel(CounterExampleMap[modelentry],ArrayReadFlag);
+      }
+      else if(ArrayReadFlag) {
+	//return the array read over a constantindex
+	output = modelentry;
+      }
+      else {
+	//when all else fails set symbol values to some constant by
+	//default. if the variable is queried the second time then add 1
+	//to and return the new value.
+	ASTNode zero = CreateZeroConst(modelentry.GetValueWidth());
+	output = zero;
+      }
+      break;
+    }
+    case ITE: {
+      ASTNode condcompute = ComputeFormulaUsingModel(term[0]);
+      if(ASTTrue == condcompute) {
+	output = TermToConstTermUsingModel(term[1],ArrayReadFlag);
+      }
+      else if(ASTFalse == condcompute) {
+	output = TermToConstTermUsingModel(term[2],ArrayReadFlag);
+      } 
+      else {
+	cerr << "TermToConstTermUsingModel: termITE: value of conditional is wrong: " << condcompute << endl; 
+	FatalError(" TermToConstTermUsingModel: termITE: cannot compute ITE conditional against model: ",term);
+      }
+      break;
+    }
+    default: {
+      ASTVec c = term.GetChildren();
+      ASTVec o;
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	ASTNode ff = TermToConstTermUsingModel(*it,ArrayReadFlag);
+	o.push_back(ff);
+      }
+      output = CreateTerm(k,term.GetValueWidth(),o);
+      //output is a CONST expression. compute its value and store it
+      //in the CounterExampleMap
+      ASTNode oo = BVConstEvaluator(output);
+      //the return value
+      output = oo;
+      break;
+    }
+    }
+
+    //when this flag is false, we should compute the arrayread to a
+    //constant. this constant is stored in the counter_example
+    //datastructure
+    if(!ArrayReadFlag) {
+      CounterExampleMap[term] = output;
+    }
+    
+    //cerr << "Output to TermToConstTermUsingModel: " << output << endl;
+    return output;
+  } //End of TermToConstTermUsingModel
+
+  //Expands read-over-write by evaluating (readIndex=writeIndex) for
+  //every writeindex until, either it evaluates to TRUE or all
+  //(readIndex=writeIndex) evaluate to FALSE
+  ASTNode BeevMgr::Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool arrayread_flag) {
+    if(READ != term.GetKind() && 
+       WRITE != term[0].GetKind()) {
+      FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+    }
+
+    ASTNode output;
+    ASTNodeMap::iterator it1;    
+    if((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end()) {
+      ASTNode val = it1->second;
+      if(BVCONST != val.GetKind()) {
+	//recursion is fine here. There are two maps that are checked
+	//here. One is the substitutionmap. We garuntee that the value
+	//of a key in the substitutionmap is always a constant.
+	if(term == val) {
+	  FatalError("TermToConstTermUsingModel: The input term is stored as-is "
+		     "in the CounterExample: Not ok: ",term);    
+	}
+	return TermToConstTermUsingModel(val,arrayread_flag);
+      }
+      else {
+	return val;
+      }
+    }
+
+    unsigned int width = term.GetValueWidth();
+    ASTNode writeA = ASTTrue; 
+    ASTNode newRead = term;
+    ASTNode readIndex = TermToConstTermUsingModel(newRead[1],false);
+    //iteratively expand read-over-write, and evaluate against the
+    //model at every iteration
+    do {
+      ASTNode write = newRead[0];
+      writeA = write[0];
+      ASTNode writeIndex = TermToConstTermUsingModel(write[1],false);
+      ASTNode writeVal = TermToConstTermUsingModel(write[2],false);
+      
+      ASTNode cond = ComputeFormulaUsingModel(CreateSimplifiedEQ(writeIndex,readIndex));
+      if(ASTTrue == cond) {
+	//found the write-value. return it
+	output = writeVal;
+	CounterExampleMap[term] = output;
+	return output;
+      }
+
+      newRead = CreateTerm(READ,width,writeA,readIndex);
+    } while(READ == newRead.GetKind() && WRITE == newRead[0].GetKind());
+    
+    output = TermToConstTermUsingModel(newRead,arrayread_flag);
+        
+    //memoize
+    CounterExampleMap[term] = output;
+    return output;  
+  } //Exand_ReadOverWrite_To_ITE_UsingModel()
+
+  /* FUNCTION: accepts a non-constant formula, and checks if the
+   * formula is ASTTrue or ASTFalse w.r.t to a model
+   */
+  ASTNode BeevMgr::ComputeFormulaUsingModel(const ASTNode& form) {
+    ASTNode in = form;
+    Kind k = form.GetKind();
+    if(!(is_Form_kind(k) && BOOLEAN_TYPE == form.GetType())) {
+      FatalError(" ComputeConstFormUsingModel: The input is a non-formula: ", form);
+    }
+
+    //cerr << "Input to ComputeFormulaUsingModel:" << form << endl;
+    ASTNodeMap::iterator it1;
+    if((it1 = ComputeFormulaMap.find(form)) != ComputeFormulaMap.end()) {
+      ASTNode res = it1->second;
+      if(ASTTrue == res || ASTFalse == res) {
+	return res;
+      }
+      else {
+	FatalError("ComputeFormulaUsingModel: The value of a formula must be TRUE or FALSE:", form);
+      }
+    }
+    
+    ASTNode t0,t1;
+    ASTNode output = ASTFalse;
+    switch(k) {
+    case TRUE:
+    case FALSE:
+      output = form;      
+      break;
+    case SYMBOL:
+      if(BOOLEAN_TYPE != form.GetType())
+	FatalError(" ComputeFormulaUsingModel: Non-Boolean variables are not formulas",form);
+      if(CounterExampleMap.find(form) != CounterExampleMap.end()) {
+	ASTNode counterexample_val = CounterExampleMap[form];
+	if(!VarSeenInTerm(form,counterexample_val)) {
+	  output = ComputeFormulaUsingModel(counterexample_val);
+	}
+	else {
+	  output = counterexample_val;
+	}
+      }
+      else
+	output = ASTFalse;
+      break;  
+    case EQ:
+    case NEQ:
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVSLT:
+    case BVSLE:
+    case BVSGT:
+    case BVSGE:
+      //convert form[0] into a constant term
+      t0 = TermToConstTermUsingModel(form[0],false);
+      //convert form[0] into a constant term
+      t1 = TermToConstTermUsingModel(form[1],false);
+      output = BVConstEvaluator(CreateNode(k,t0,t1));
+      
+      //evaluate formula to false if bvdiv execption occurs while
+      //counterexample is being checked during refinement.
+      if(bvdiv_exception_occured && 
+	 counterexample_checking_during_refinement) {
+	output = ASTFalse;
+      }
+      break;   
+    case NAND: {
+      ASTNode o = ASTTrue;
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++)
+	if(ASTFalse == ComputeFormulaUsingModel(*it)) {
+	  o = ASTFalse;
+	  break;
+	}      
+      if(o == ASTTrue) 
+	output = ASTFalse;
+      else 
+	output = ASTTrue;
+      break;
+    }
+    case NOR: {
+      ASTNode o = ASTFalse;
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++)
+	if(ASTTrue == ComputeFormulaUsingModel(*it)) {
+	  o = ASTTrue;
+	  break;
+	}
+      if(o == ASTTrue) 
+	output = ASTFalse;
+      else 
+	output = ASTTrue;
+      break;
+    }
+    case NOT:
+      if(ASTTrue == ComputeFormulaUsingModel(form[0]))
+	output = ASTFalse;
+      else
+	output = ASTTrue;
+      break;
+    case OR:
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++) 
+	if(ASTTrue == ComputeFormulaUsingModel(*it))
+	  output = ASTTrue;
+      break;
+    case AND:
+      output = ASTTrue;
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++) {
+	if(ASTFalse == ComputeFormulaUsingModel(*it)) {	    
+	  output = ASTFalse;
+	  break;	  
+	}
+      }
+      break;
+    case XOR:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      t1 = ComputeFormulaUsingModel(form[1]);
+      if((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
+	output = ASTFalse;
+      else
+	output = ASTTrue;
+      break;
+    case IFF:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      t1 = ComputeFormulaUsingModel(form[1]);
+      if((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
+	output = ASTTrue;
+      else
+	output = ASTFalse;
+      break;
+    case IMPLIES:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      t1 = ComputeFormulaUsingModel(form[1]);
+      if((ASTFalse == t0) || (ASTTrue == t0 && ASTTrue == t1))
+	output = ASTTrue;
+      else
+	output = ASTFalse;
+      break;    
+    case ITE:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      if(ASTTrue == t0)
+	output = ComputeFormulaUsingModel(form[1]);
+      else if(ASTFalse == t0)
+	output = ComputeFormulaUsingModel(form[2]);
+      else 
+	FatalError("ComputeFormulaUsingModel: ITE: something is wrong with the formula: ",form);
+      break;
+    default:
+      FatalError(" ComputeFormulaUsingModel: the kind has not been implemented", ASTUndefined);
+      break;
+    }
+
+    //cout << "ComputeFormulaUsingModel output is:" << output << endl;
+    ComputeFormulaMap[form] = output;
+    return output;
+  }
+
+  void BeevMgr::CheckCounterExample(bool t) {
+    // FIXME:  Code is more useful if enable flags are check OUTSIDE the method.
+    // If I want to check a counterexample somewhere, I don't want to have to set
+    // the flag in order to make it actualy happen!
+
+    if(!check_counterexample) {
+      return;
+    }
+
+    //input is valid, no counterexample to check
+    if(ValidFlag)
+      return;
+
+    //t is true if SAT solver generated a counterexample, else it is false
+    if(!t)
+      FatalError("CheckCounterExample: No CounterExample to check", ASTUndefined);
+    const ASTVec c = GetAsserts();    
+    for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++)
+      if(ASTFalse == ComputeFormulaUsingModel(*it))
+	FatalError("CheckCounterExample:counterexample bogus:"\
+		   "assert evaluates to FALSE under counterexample: NOT OK",*it);
+        
+    if(ASTTrue == ComputeFormulaUsingModel(_current_query))
+      FatalError("CheckCounterExample:counterexample bogus:"\
+		 "query evaluates to TRUE under counterexample: NOT OK",_current_query);
+  }
+
+  /* FUNCTION: prints a counterexample for INVALID inputs.  iterate
+   * through the CounterExampleMap data structure and print it to
+   * stdout
+   */
+  void BeevMgr::PrintCounterExample(bool t, std::ostream& os) {
+    //global command-line option
+    // FIXME: This should always print the counterexample.  If you want
+    // to turn it off, check the switch at the point of call.
+    if(!print_counterexample)
+      return;
+
+    //input is valid, no counterexample to print
+    if(ValidFlag)
+      return;
+
+    //if this option is true then print the way dawson wants using a
+    //different printer. do not use this printer.
+    if(print_arrayval_declaredorder)
+      return;
+
+    //t is true if SAT solver generated a counterexample, else it is
+    //false
+    if(!t) {
+      cerr << "PrintCounterExample: No CounterExample to print: " << endl;
+      return;
+    }
+
+    //os << "\nCOUNTEREXAMPLE: \n" << endl;
+    ASTNodeMap::iterator it  = CounterExampleMap.begin();
+    ASTNodeMap::iterator itend = CounterExampleMap.end();
+    for(;it!=itend;it++) {
+      ASTNode f = it->first;
+      ASTNode se = it->second;
+      
+      if(ARRAY_TYPE == se.GetType()) {
+	FatalError("TermToConstTermUsingModel: entry in counterexample is an arraytype. bogus:",se);
+      }
+
+      //skip over introduced variables
+      if(f.GetKind() == SYMBOL && (_introduced_symbols.find(f) != _introduced_symbols.end())) 
+	continue;
+      if(f.GetKind() == SYMBOL || 
+	 (f.GetKind() == READ && f[0].GetKind() == SYMBOL && f[1].GetKind() == BVCONST)) {
+	os << "ASSERT( ";
+	f.PL_Print(os,0);
+	os << " = ";	
+	if(BITVECTOR_TYPE == se.GetType()) {
+	  TermToConstTermUsingModel(se,false).PL_Print(os,0);
+	}
+	else {
+	  se.PL_Print(os,0);
+	}
+	os << " );" << endl;
+      }
+    }	      
+    //os << "\nEND OF COUNTEREXAMPLE" << endl;
+  } //End of PrintCounterExample
+
+  /* iterate through the CounterExampleMap data structure and print it
+   * to stdout. this function prints only the declared array variables
+   * IN the ORDER in which they were declared. It also assumes that
+   * the variables are of the form 'varname_number'. otherwise it will
+   * not print anything. This function was specifically written for
+   * Dawson Engler's group (bug finding research group at Stanford)
+   */
+  void BeevMgr::PrintCounterExample_InOrder(bool t) {
+    //global command-line option to print counterexample. we do not
+    //want both counterexample printers to print at the sametime.
+    // FIXME: This should always print the counterexample.  If you want
+    // to turn it off, check the switch at the point of call.
+    if(print_counterexample)
+      return;
+
+    //input is valid, no counterexample to print
+    if(ValidFlag)
+      return;
+    
+    //print if the commandline option is '-q'. allows printing the
+    //counterexample in order.
+    if(!print_arrayval_declaredorder)
+      return;
+
+    //t is true if SAT solver generated a counterexample, else it is
+    //false
+    if(!t) {
+      cerr << "PrintCounterExample: No CounterExample to print: " << endl;
+      return;
+    }
+    
+    //vector to store the integer values
+    std::vector<int> out_int;	
+    cout << "% ";
+    for(ASTVec::iterator it=_special_print_set.begin(),itend=_special_print_set.end();
+	it!=itend;it++) {
+      if(ARRAY_TYPE == it->GetType()) {
+	//get the name of the variable
+	const char * c = it->GetName();
+	std::string ss(c);
+	if(!(0 == strncmp(ss.c_str(),"ini_",4)))
+	  continue;
+	reverse(ss.begin(),ss.end());
+
+	//cout << "debugging: " << ss;
+	size_t pos = ss.find('_',0);
+	if(!(0 < pos && pos < ss.size()))
+	  continue;
+
+	//get the associated length
+	std::string sss = ss.substr(0,pos);
+	reverse(sss.begin(),sss.end());
+	int n = atoi(sss.c_str());
+
+	it->PL_Print(cout,2);
+	for(int j=0;j < n; j++) {
+	  ASTNode index = CreateBVConst(it->GetIndexWidth(),j);
+	  ASTNode readexpr = CreateTerm(READ,it->GetValueWidth(),*it,index);
+	  ASTNode val = GetCounterExample(t, readexpr);
+	  //cout << "ASSERT( ";
+	  //cout << " = ";	  
+	  out_int.push_back(GetUnsignedConst(val));
+	  //cout << "\n";
+	}
+      }
+    }
+    cout << endl;
+    for(unsigned int jj=0; jj < out_int.size();jj++)
+      cout << out_int[jj] << endl;
+    cout << endl;
+  } //End of PrintCounterExample_InOrder
+
+  /* FUNCTION: queries the CounterExampleMap object with 'expr' and
+   * returns the corresponding counterexample value.
+   */
+  ASTNode BeevMgr::GetCounterExample(bool t, const ASTNode& expr) {    
+    //input is valid, no counterexample to get
+    if(ValidFlag)
+      return ASTUndefined;
+    
+    if(BOOLEAN_TYPE == expr.GetType()) {
+      return ComputeFormulaUsingModel(expr);
+    }
+
+    if(BVCONST == expr.GetKind()) {
+      return expr;
+    }
+
+    ASTNodeMap::iterator it;
+    ASTNode output;
+    if((it = CounterExampleMap.find(expr)) != CounterExampleMap.end())
+      output =  TermToConstTermUsingModel(CounterExampleMap[expr],false);
+    else
+      output = CreateZeroConst(expr.GetValueWidth());
+    return output;
+  } //End of GetCounterExample
+
+  // FIXME:  Don't use numeric codes.  Use an enum type!
+  //Acceps a query, calls the SAT solver and generates Valid/InValid.
+  //if returned 0 then input is INVALID
+  //if returned 1 then input is VALID
+  //if returned 2 then ERROR
+  int BeevMgr::TopLevelSAT( const ASTNode& inputasserts, const ASTNode& query) {  
+    /******start solving**********/
+    ASTNode q = CreateNode(AND, inputasserts, CreateNode(NOT,query));
+    ASTNode orig_input = q;
+    ASTNodeStats("input asserts and query: ", q);
+ 
+    ASTNode newq = q;
+    //round of substitution, solving, and simplification. ensures that
+    //DAG is minimized as much as possibly, and ideally should
+    //garuntee that all liketerms in BVPLUSes have been combined.
+    BVSolver bvsolver(this);
+    SimplifyWrites_InPlace_Flag = false;
+    Begin_RemoveWrites = false;
+    start_abstracting = false;    
+    TermsAlreadySeenMap.clear();
+    do {
+      q = newq;
+      newq = CreateSubstitutionMap(newq);
+      //ASTNodeStats("after pure substitution: ", newq);
+      newq = SimplifyFormula_TopLevel(newq,false);
+      //ASTNodeStats("after simplification: ", newq);
+      //newq = bvsolver.TopLevelBVSolve(newq);
+      //ASTNodeStats("after solving: ", newq);      
+    }while(q!=newq);
+
+    ASTNodeStats("Before SimplifyWrites_Inplace begins: ", newq);
+    SimplifyWrites_InPlace_Flag = true;
+    Begin_RemoveWrites = false;
+    start_abstracting = false;
+    TermsAlreadySeenMap.clear();
+    do {
+      q = newq;
+      //newq = CreateSubstitutionMap(newq);
+      //ASTNodeStats("after pure substitution: ", newq);
+      newq = SimplifyFormula_TopLevel(newq,false);
+      //ASTNodeStats("after simplification: ", newq);
+      newq = bvsolver.TopLevelBVSolve(newq);
+      //ASTNodeStats("after solving: ", newq);      
+    }while(q!=newq);
+    ASTNodeStats("After SimplifyWrites_Inplace: ", newq);        
+
+    start_abstracting = (arraywrite_refinement) ? true : false;
+    SimplifyWrites_InPlace_Flag = false;
+    Begin_RemoveWrites = (start_abstracting) ? false : true;    
+    if(start_abstracting) {
+      ASTNodeStats("before abstraction round begins: ", newq);
+    }
+
+    TermsAlreadySeenMap.clear();
+    do {
+      q = newq;
+      //newq = CreateSubstitutionMap(newq);
+      //Begin_RemoveWrites = true;
+      //ASTNodeStats("after pure substitution: ", newq);
+      newq = SimplifyFormula_TopLevel(newq,false);
+      //ASTNodeStats("after simplification: ", newq);
+      //newq = bvsolver.TopLevelBVSolve(newq);
+      //ASTNodeStats("after solving: ", newq);
+    }while(q!=newq);
+
+    if(start_abstracting) {
+      ASTNodeStats("After abstraction: ", newq);
+    }
+    start_abstracting = false;
+    SimplifyWrites_InPlace_Flag = false;
+    Begin_RemoveWrites = false;    
+    
+    newq = TransformFormula(newq);
+    ASTNodeStats("after transformation: ", newq);
+    TermsAlreadySeenMap.clear();
+
+    int res;    
+    //solver instantiated here
+    MINISAT::Solver newS;
+    if(arrayread_refinement) {
+      counterexample_checking_during_refinement = true;
+    }
+    
+    //call SAT and check the result
+    res = CallSAT_ResultCheck(newS,newq,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }
+
+    res = SATBased_ArrayReadRefinement(newS,newq,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }
+ 
+    res = SATBased_ArrayWriteRefinement(newS,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }          
+
+    res = SATBased_ArrayReadRefinement(newS,newq,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }
+
+    FatalError("TopLevelSAT: reached the end without proper conclusion:" 
+	       "either a divide by zero in the input or a bug in STP");
+    //bogus return to make the compiler shut up
+    return 2;
+  } //End of TopLevelSAT
+
+  //go over the list of indices for each array, and generate Leibnitz
+  //axioms. Then assert these axioms into the SAT solver. Check if the
+  //addition of the new constraints has made the bogus counterexample
+  //go away. if yes, return the correct answer. if no, continue adding
+  //Leibnitz axioms systematically.
+  // FIXME:  What it really does is, for each array, loop over each index i.
+  // inside that loop, it finds all the true and false axioms with i as first
+  // index.  When it's got them all, it adds the false axioms to the formula
+  // and re-solves, and returns if the result is correct.  Otherwise, it
+  // goes on to the next index.
+  // If it gets through all the indices without a correct result (which I think
+  // is impossible, but this is pretty confusing), it then solves with all
+  // the true axioms, too.
+  // This is not the most obvious way to do it, and I don't know how it 
+  // compares with other approaches (e.g., one false axiom at a time or
+  // all the false axioms each time).
+  int BeevMgr::SATBased_ArrayReadRefinement(MINISAT::Solver& newS, 
+					    const ASTNode& q, const ASTNode& orig_input) {
+    if(!arrayread_refinement)
+      FatalError("SATBased_ArrayReadRefinement: Control should not reach here");
+
+    ASTVec FalseAxiomsVec, RemainingAxiomsVec;
+    RemainingAxiomsVec.push_back(ASTTrue);   
+    FalseAxiomsVec.push_back(ASTTrue);
+
+    //in these loops we try to construct Leibnitz axioms and add it to
+    //the solve(). We add only those axioms that are false in the
+    //current counterexample. we keep adding the axioms until there
+    //are no more axioms to add
+    //
+    //for each array, fetch its list of indices seen so far
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      ASTVec listOfIndices = iset->second;
+      //loop over the list of indices for the array and create LA, and add to q
+      for(ASTVec::iterator it=listOfIndices.begin(),itend=listOfIndices.end();it!=itend;it++) {
+	if(BVCONST == it->GetKind()) {
+	  continue;
+	}	
+
+	ASTNode the_index = *it;
+	//get the arrayname
+	ASTNode ArrName = iset->first;
+	// if(SYMBOL != ArrName.GetKind())
+	// 	  FatalError("SATBased_ArrayReadRefinement: arrname is not a SYMBOL",ArrName);
+	ASTNode arr_read1 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, the_index);
+	//get the variable corresponding to the array_read1
+	ASTNode arrsym1 = _arrayread_symbol[arr_read1];
+	if(!(SYMBOL == arrsym1.GetKind() || BVCONST == arrsym1.GetKind()))
+	  FatalError("TopLevelSAT: refinementloop:term arrsym1 corresponding to READ must be a var", arrsym1);
+
+	//we have nonconst index here. create Leibnitz axiom for it
+	//w.r.t every index in listOfIndices
+	for(ASTVec::iterator it1=listOfIndices.begin(),itend1=listOfIndices.end();
+	    it1!=itend1;it1++) {
+	  ASTNode compare_index = *it1;
+	  //do not compare with yourself
+	  if(the_index == compare_index)
+	    continue;
+	  
+	  //prepare for SAT LOOP 
+	  //first construct the antecedent for the LA axiom
+	  ASTNode eqOfIndices = 
+	    (exprless(the_index,compare_index)) ? 
+	    CreateSimplifiedEQ(the_index,compare_index) : CreateSimplifiedEQ(compare_index,the_index);
+	  	  
+	  ASTNode arr_read2 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, compare_index);
+	  //get the variable corresponding to the array_read2
+	  ASTNode arrsym2 = _arrayread_symbol[arr_read2];
+	  if(!(SYMBOL == arrsym2.GetKind() || BVCONST == arrsym2.GetKind()))
+	    FatalError("TopLevelSAT: refinement loop:"
+		       "term arrsym2 corresponding to READ must be a var", arrsym2);
+	  
+	  ASTNode eqOfReads = CreateSimplifiedEQ(arrsym1,arrsym2);
+	  //construct appropriate Leibnitz axiom
+	  ASTNode LeibnitzAxiom = CreateNode(IMPLIES, eqOfIndices, eqOfReads);
+	  if(ASTFalse == ComputeFormulaUsingModel(LeibnitzAxiom))
+	    //FalseAxioms = CreateNode(AND,FalseAxioms,LeibnitzAxiom);
+	    FalseAxiomsVec.push_back(LeibnitzAxiom);
+	  else
+	    //RemainingAxioms = CreateNode(AND,RemainingAxioms,LeibnitzAxiom);
+	    RemainingAxiomsVec.push_back(LeibnitzAxiom);
+	}
+	ASTNode FalseAxioms = (FalseAxiomsVec.size()>1) ? CreateNode(AND,FalseAxiomsVec) : FalseAxiomsVec[0];
+	ASTNodeStats("adding false readaxioms to SAT: ", FalseAxioms);  
+	int res2 = CallSAT_ResultCheck(newS,FalseAxioms,orig_input);
+	if(2!=res2) {
+	  return res2;
+	}	
+      }
+    }
+    ASTNode RemainingAxioms = (RemainingAxiomsVec.size()>1) ? CreateNode(AND,RemainingAxiomsVec):RemainingAxiomsVec[0];
+    ASTNodeStats("adding remaining readaxioms to SAT: ", RemainingAxioms);  
+    return CallSAT_ResultCheck(newS,RemainingAxioms,orig_input);
+  } //end of SATBased_ArrayReadRefinement
+
+  ASTNode BeevMgr::Create_ArrayWriteAxioms(const ASTNode& term, const ASTNode& newvar) {
+    if(READ != term.GetKind() && WRITE != term[0].GetKind()) {
+      FatalError("Create_ArrayWriteAxioms: Input must be a READ over a WRITE",term);
+    }
+    
+    ASTNode lhs = newvar;
+    ASTNode rhs = term;
+    ASTNode arraywrite_axiom = CreateSimplifiedEQ(lhs,rhs);
+    return arraywrite_axiom;
+  }//end of Create_ArrayWriteAxioms()
+
+  int BeevMgr::SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input) {
+    ASTNode writeAxiom;
+    ASTNodeMap::iterator it = ReadOverWrite_NewName_Map.begin();
+    ASTNodeMap::iterator itend = ReadOverWrite_NewName_Map.end();
+    //int count = 0;
+    //int num_write_axioms = ReadOverWrite_NewName_Map.size();
+
+    ASTVec FalseAxioms, RemainingAxioms;
+    FalseAxioms.push_back(ASTTrue);
+    RemainingAxioms.push_back(ASTTrue);
+    for(;it!=itend;it++) {
+      //Guided refinement starts here
+      ComputeFormulaMap.clear();      
+      writeAxiom = Create_ArrayWriteAxioms(it->first,it->second);
+      if(ASTFalse == ComputeFormulaUsingModel(writeAxiom)) {
+	writeAxiom = TransformFormula(writeAxiom);
+	FalseAxioms.push_back(writeAxiom);
+      }
+      else {
+	writeAxiom = TransformFormula(writeAxiom);
+	RemainingAxioms.push_back(writeAxiom);
+      }
+    }
+      
+    writeAxiom = (FalseAxioms.size() != 1) ? CreateNode(AND,FalseAxioms) : FalseAxioms[0];
+    ASTNodeStats("adding false writeaxiom to SAT: ", writeAxiom);
+    int res2 = CallSAT_ResultCheck(newS,writeAxiom,orig_input);
+    if(2!=res2) {
+      return res2;
+    }
+    
+    writeAxiom = (RemainingAxioms.size() != 1) ? CreateNode(AND,RemainingAxioms) : RemainingAxioms[0];
+    ASTNodeStats("adding remaining writeaxiom to SAT: ", writeAxiom);
+    res2 = CallSAT_ResultCheck(newS,writeAxiom,orig_input);
+    if(2!=res2) {
+	return res2;
+    }
+    
+    return 2;
+  } //end of SATBased_ArrayWriteRefinement
+
+  //Check result after calling SAT FIXME: Document arguments in
+  //comments, and give them meaningful names.  How is anyone supposed
+  //to know what "q" is?
+  int BeevMgr::CallSAT_ResultCheck(MINISAT::Solver& newS, 
+				   const ASTNode& q, const ASTNode& orig_input) {
+    //Bitblast, CNF, call SAT now
+    ASTNode BBFormula = BBForm(q);
+    //ASTNodeStats("after bitblasting", BBFormula);    
+    ClauseList *cllp = ToCNF(BBFormula);
+    // if(stats && print_nodes) {
+    //       cout << "\nClause list" << endl;
+    //       PrintClauseList(cout, *cllp);
+    //       cerr << "\n finished printing clauselist\n";
+    //     }
+
+    bool sat = toSATandSolve(newS,*cllp);    
+    // Temporary debugging call.
+    // CheckBBandCNF(newS, BBFormula);
+
+    DeleteClauseList(cllp);
+    if(!sat) {
+      PrintOutput(true);
+      return 1;
+    }
+    else if(newS.okay()) {
+      CounterExampleMap.clear();
+      ConstructCounterExample(newS);
+      if (stats && print_nodes) {
+	PrintSATModel(newS);
+      }
+      //check if the counterexample is good or not
+      ComputeFormulaMap.clear();
+      if(counterexample_checking_during_refinement)
+	bvdiv_exception_occured = false;
+      ASTNode orig_result = ComputeFormulaUsingModel(orig_input);
+      if(!(ASTTrue == orig_result || ASTFalse == orig_result))
+      	FatalError("TopLevelSat: Original input must compute to true or false against model");
+      
+//       if(!arrayread_refinement && !(ASTTrue == orig_result)) {
+// 	print_counterexample = true;
+// 	PrintCounterExample(true);
+//       	FatalError("counterexample bogus : arrayread_refinement is switched off: " 
+//       		   "EITHER all LA axioms have not been added OR bitblaster() or ToCNF()"
+// 		   "or satsolver() or counterexamplechecker() have a bug");
+//       }
+
+      // if the counterexample is indeed a good one, then return
+      // invalid
+      if(ASTTrue == orig_result) {
+	CheckCounterExample(newS.okay());
+	PrintOutput(false);
+	PrintCounterExample(newS.okay());
+	PrintCounterExample_InOrder(newS.okay());
+	return 0;	
+      }
+      // counterexample is bogus: flag it
+      else {
+	if(stats && print_nodes) {
+	  cout << "Supposedly bogus one: \n";
+	  bool tmp = print_counterexample;
+	  print_counterexample = true;
+	  PrintCounterExample(true);
+	  print_counterexample = tmp;
+	}
+
+	return 2;
+      }
+    }
+    else {
+      PrintOutput(true);
+      return -100;
+    }
+  } //end of CALLSAT_ResultCheck
+
+
+  //FUNCTION: this function accepts a boolvector and returns a BVConst   
+  ASTNode BeevMgr::BoolVectoBVConst(hash_map<unsigned,bool> * w, unsigned int l) {    
+    unsigned len = w->size();
+    if(l < len)
+      FatalError("BoolVectorBVConst : length of bitvector does not match hash_map size:",ASTUndefined,l);
+    std::string cc;
+    for(unsigned int jj = 0; jj < l; jj++) {
+      if((*w)[jj] == true)
+	cc += '1';
+      else if((*w)[jj] == false)
+	cc += '0';
+      else 
+	cc += '0';
+    }
+    return CreateBVConst(cc.c_str(),2);
+  }
+
+  void BeevMgr::PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS) {
+    if(!print_sat_varorder)
+      return;
+
+    ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();   
+    ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
+   
+    cout << init_msg;
+    cout << ": Printing activity levels of variables\n";
+    for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
+      cout << (it->second) << "  :  ";
+      (it->first).PL_Print(cout,0);
+      cout << "   :   ";
+      cout << newS.returnActivity(it->second) << endl;
+    }
+  }
+
+  //this function biases the activity levels of MINISAT variables.
+  void BeevMgr::ChangeActivityLevels_Of_SATVars(MINISAT::Solver& newS) {
+    if(!variable_activity_optimize)
+      return;
+
+    ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();   
+    ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
+   
+    unsigned int index=1;
+    double base = 2;
+    for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
+      ASTNode n = it->first;
+
+      if(BVGETBIT == n.GetKind() || NOT == n.GetKind()) {
+      	if(BVGETBIT == n.GetKind())
+      	  index = GetUnsignedConst(n[1]);
+      	else if (NOT == n.GetKind() && BVGETBIT == n[0].GetKind())
+      	  index = GetUnsignedConst(n[0][1]);
+      	else 
+      	  index = 0;
+	double initial_activity = pow(base,(double)index);
+	newS.updateInitialActivity(it->second,initial_activity);
+      } 
+      else {
+	double initial_activity = pow(base,pow(base,(double)index));
+	newS.updateInitialActivity(it->second,initial_activity);	
+      }    
+    }
+  }
+
+  //This function prints the output of the STP solver
+  void BeevMgr::PrintOutput(bool true_iff_valid) {
+    //self-explanatory
+    if(true_iff_valid) {
+      ValidFlag = true;
+      if(print_output) {
+	if(smtlib_parser_enable)
+	  cout << "unsat\n";
+	else
+	  cout << "Valid.\n";
+      }
+    }
+    else {
+      ValidFlag = false;
+      if(print_output) {
+	if(smtlib_parser_enable)
+	  cout << "sat\n";
+	else
+	  cout << "Invalid.\n";
+      }
+    }
+  }
+}; //end of namespace BEEV

Added: klee/trunk/stp/AST/Transform.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/Transform.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/Transform.cpp (added)
+++ klee/trunk/stp/AST/Transform.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,492 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "AST.h"
+#include <stdlib.h>
+#include <stdio.h>
+namespace BEEV {  
+  
+  //Translates signed BVDIV/BVMOD into unsigned variety
+  ASTNode BeevMgr::TranslateSignedDivMod(const ASTNode& in) {
+    if(!(SBVMOD == in.GetKind() || SBVDIV == in.GetKind())) {
+      FatalError("TranslateSignedDivMod: input must be signed DIV/MOD\n",in);
+    }
+
+    ASTNode dividend = in[0];
+    ASTNode divisor  = in[1];      
+    unsigned len = in.GetValueWidth();
+    if(SBVMOD == in.GetKind()) {
+      //if(TopBit(dividend)==1) 
+      //
+      //then -BVMOD(-dividend,abs(divisor)) 
+      //
+      //else BVMOD(dividend,abs(divisor))
+
+      //create the condition for the dividend
+      ASTNode hi1  = CreateBVConst(32,len-1);
+      ASTNode one  = CreateOneConst(1);
+      ASTNode cond = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1));
+
+      //create the condition and conditional for the divisor
+      ASTNode cond_divisor = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1));
+      ASTNode pos_divisor  = CreateTerm(ITE,len,cond_divisor,CreateTerm(BVUMINUS,len,divisor),divisor);
+
+      //create the modulus term for each case
+      ASTNode modnode = CreateTerm(BVMOD,len,dividend,pos_divisor);
+      ASTNode minus_modnode = CreateTerm(BVMOD,len,CreateTerm(BVUMINUS,len,dividend),pos_divisor);
+      minus_modnode = CreateTerm(BVUMINUS,len,minus_modnode);
+
+      //put everything together, simplify, and return
+      ASTNode n = CreateTerm(ITE,len,cond,minus_modnode,modnode);
+      return SimplifyTerm_TopLevel(n);
+    }
+    
+    //now handle the BVDIV case
+    //if topBit(dividend) is 1 and topBit(divisor) is 0
+    //
+    //then output is -BVDIV(-dividend,divisor)
+    //
+    //elseif topBit(dividend) is 0 and topBit(divisor) is 1
+    //
+    //then output is -BVDIV(dividend,-divisor)
+    //
+    //elseif topBit(dividend) is 1 and topBit(divisor) is 1
+    //
+    // then output is BVDIV(-dividend,-divisor)
+    //
+    //else simply output BVDIV(dividend,divisor)
+    ASTNode hi1 = CreateBVConst(32,len-1);
+    ASTNode zero = CreateZeroConst(1);
+    ASTNode one = CreateOneConst(1);
+    ASTNode divnode = CreateTerm(BVDIV, len, dividend, divisor);
+
+    ASTNode cond1 = CreateNode(AND,
+			       CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+			       CreateNode(EQ,one, CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+    ASTNode minus_divnode1 = CreateTerm(BVDIV,len,
+					dividend,
+					CreateTerm(BVUMINUS,len,divisor));
+    minus_divnode1 = CreateTerm(BVUMINUS,len,minus_divnode1);
+
+    ASTNode cond2 = CreateNode(AND,
+			       CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+			       CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+    ASTNode minus_divnode2 = CreateTerm(BVDIV,len,
+					CreateTerm(BVUMINUS,len,dividend),
+					divisor);
+    minus_divnode2 = CreateTerm(BVUMINUS,len,minus_divnode2);
+
+    ASTNode cond3 = CreateNode(AND,
+			       CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+			       CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+    ASTNode minus_divnode3 = CreateTerm(BVDIV,len,
+					CreateTerm(BVUMINUS,len,dividend),
+					CreateTerm(BVUMINUS,len,divisor));
+    ASTNode n = CreateTerm(ITE,len,
+			   cond1,
+			   minus_divnode1,
+			   CreateTerm(ITE,len,
+				      cond2,
+				      minus_divnode2,
+				      CreateTerm(ITE,len,
+						 cond3,
+						 minus_divnode3,
+						 divnode)));
+  return SimplifyTerm_TopLevel(n);
+  }//end of TranslateSignedDivMod()
+
+  ASTNode BeevMgr::TransformFormula(const ASTNode& form) {
+    ASTNode result;
+
+    ASTNode simpleForm = form;
+    Kind k = simpleForm.GetKind();
+    if(!(is_Form_kind(k) && BOOLEAN_TYPE == simpleForm.GetType())) {
+      //FIXME: "You have inputted a NON-formula"?
+      FatalError("TransformFormula: You have input a NON-formula",simpleForm);
+    }
+
+    ASTNodeMap::iterator iter;
+    if((iter = TransformMap.find(simpleForm)) != TransformMap.end())
+      return iter->second;
+
+    switch(k) {
+    case TRUE:
+    case FALSE: {
+      result = simpleForm;
+      break;
+    }
+    case NOT: {
+      ASTVec c;
+      c.push_back(TransformFormula(simpleForm[0]));
+      result = CreateNode(NOT,c);      
+      break;
+    }
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVSLT:
+    case BVSLE:
+    case BVSGT:
+    case BVSGE:      
+    case NEQ: {
+      ASTVec c;
+      c.push_back(TransformTerm(simpleForm[0]));      
+      c.push_back(TransformTerm(simpleForm[1]));
+      result = CreateNode(k,c);
+      break;
+    }
+    case EQ: {
+      ASTNode term1 = TransformTerm(simpleForm[0]);      
+      ASTNode term2 = TransformTerm(simpleForm[1]);
+      result = CreateSimplifiedEQ(term1,term2);     
+      break;
+    }
+    case AND:
+    case OR: 
+    case NAND:
+    case NOR:
+    case IFF:
+    case XOR:
+    case ITE:
+    case IMPLIES: {
+      ASTVec vec;
+      ASTNode o;
+      for (ASTVec::const_iterator it = simpleForm.begin(),itend=simpleForm.end(); it != itend; it++){
+	o = TransformFormula(*it);	
+	vec.push_back(o);
+      }
+
+      result = CreateNode(k, vec);
+      break;
+    }
+    default:
+      if(k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType())
+	result = simpleForm;      
+      else {
+	cerr << "The input is: " << simpleForm << endl;
+	cerr << "The valuewidth of input is : " << simpleForm.GetValueWidth() << endl;
+	FatalError("TransformFormula: Illegal kind: ",ASTUndefined, k);
+      }
+      break;    
+    } 
+    //BVTypeCheck(result);
+    TransformMap[simpleForm] = result;
+    return result;
+  } //End of TransformFormula
+
+  ASTNode BeevMgr::TransformTerm(const ASTNode& inputterm) {
+    ASTNode result;
+    ASTNode term = inputterm;
+
+    Kind k = term.GetKind();
+    if(!is_Term_kind(k))
+      FatalError("TransformTerm: Illegal kind: You have input a nonterm:", inputterm, k);
+    ASTNodeMap::iterator iter;
+    if((iter = TransformMap.find(term)) != TransformMap.end())
+      return iter->second;
+    switch(k) {
+    case SYMBOL: {
+      // ASTNodeMap::iterator itsym;
+//       if((itsym = CounterExampleMap.find(term)) != CounterExampleMap.end())	
+//       	result = itsym->second;
+//       else
+	result = term;
+      break;
+    }
+    case BVCONST:
+      result = term;
+      break;
+    case WRITE:
+      FatalError("TransformTerm: this kind is not supported",term);
+      break;
+    case READ:
+      result = TransformArray(term);
+      break;
+    case ITE: {
+      ASTNode cond = term[0];
+      ASTNode thn  = term[1];
+      ASTNode els  = term[2];
+      cond = TransformFormula(cond);
+      thn = TransformTerm(thn);
+      els = TransformTerm(els);
+      //result = CreateTerm(ITE,term.GetValueWidth(),cond,thn,els);
+      result = CreateSimplifiedTermITE(cond,thn,els);
+      result.SetIndexWidth(term.GetIndexWidth());
+      break;
+    }
+    default: {
+      ASTVec c = term.GetChildren();
+      ASTVec::iterator it = c.begin();
+      ASTVec::iterator itend = c.end();
+      unsigned width = term.GetValueWidth();
+      unsigned indexwidth = term.GetIndexWidth();
+      ASTVec o;
+      for(;it!=itend;it++) {
+	o.push_back(TransformTerm(*it));
+      }
+
+      result = CreateTerm(k,width,o);
+      result.SetIndexWidth(indexwidth);
+
+      if(SBVDIV == result.GetKind() || SBVMOD == result.GetKind()) {
+	result = TranslateSignedDivMod(result);
+      }
+      break;
+    }
+    }
+
+    TransformMap[term] = result;
+    if(term.GetValueWidth() != result.GetValueWidth())
+      FatalError("TransformTerm: result and input terms are of different length", result);
+    if(term.GetIndexWidth() != result.GetIndexWidth()) {
+      cerr << "TransformTerm: input term is : " << term << endl;
+      FatalError("TransformTerm: result and input terms have different index length", result);
+    }
+    return result;
+  } //End of TransformTerm
+
+  /* This function transforms Array Reads, Read over Writes, Read over
+   * ITEs into flattened form.
+   *
+   * Transform1: Suppose there are two array reads in the input
+   * Read(A,i) and Read(A,j) over the same array. Then Read(A,i) is
+   * replaced with a symbolic constant, say v1, and Read(A,j) is
+   * replaced with the following ITE:
+   *
+   * ITE(i=j,v1,v2)
+   *
+   * Transform2:
+   * 
+   * Transform3:
+   */
+  ASTNode BeevMgr::TransformArray(const ASTNode& term) {
+    ASTNode result = term;
+
+    unsigned int width = term.GetValueWidth();
+    Kind k = term.GetKind();
+    if (!is_Term_kind(k))
+      FatalError("TransformArray: Illegal kind: You have input a nonterm:", ASTUndefined, k);
+    ASTNodeMap::iterator iter;
+    if((iter = TransformMap.find(term)) != TransformMap.end())
+      return iter->second;
+
+    switch(k) {
+      //'term' is of the form READ(arrName, readIndex) 
+    case READ: {
+      ASTNode arrName = term[0];
+      switch (arrName.GetKind()) {
+      case SYMBOL: {
+	/* input is of the form: READ(A, readIndex)
+	 * 
+	 * output is of the from: A1, if this is the first READ over A
+         *                           
+	 *                        ITE(previous_readIndex=readIndex,A1,A2)
+	 *                        
+         *                        .....
+	 */
+
+	//  Recursively transform read index, which may also contain reads.
+	ASTNode readIndex = TransformTerm(term[1]);	
+	ASTNode processedTerm = CreateTerm(READ,width,arrName,readIndex);
+	
+	//check if the 'processedTerm' has a corresponding ITE construct
+	//already. if so, return it. else continue processing.
+	ASTNodeMap::iterator it;
+	if((it = _arrayread_ite.find(processedTerm)) != _arrayread_ite.end()) {
+	  result = it->second;	
+	  break;
+	}
+	//Constructing Symbolic variable corresponding to 'processedTerm'
+	ASTNode CurrentSymbol;
+	ASTNodeMap::iterator it1;
+	// First, check if read index is constant and it has a constant value in the substitution map.
+	if(CheckSubstitutionMap(processedTerm,CurrentSymbol)) {
+	  _arrayread_symbol[processedTerm] = CurrentSymbol;
+	}
+	// Check if it already has an abstract variable.
+	else if((it1 = _arrayread_symbol.find(processedTerm)) != _arrayread_symbol.end()) {
+	  CurrentSymbol = it1->second;
+	}
+	else {
+	  // Make up a new abstract variable.
+	  // FIXME: Make this into a method (there already may BE a method) and
+	  // get rid of the fixed-length buffer!
+	  //build symbolic name corresponding to array read. The symbolic
+	  //name has 2 components: stringname, and a count
+	  const char * b = arrName.GetName();
+	  std::string c(b);
+	  char d[32];
+	  sprintf(d,"%d",_symbol_count++);
+	  std::string ccc(d);
+	  c += "array_" + ccc;
+	  
+	  CurrentSymbol = CreateSymbol(c.c_str());
+	  CurrentSymbol.SetValueWidth(processedTerm.GetValueWidth());
+	  CurrentSymbol.SetIndexWidth(processedTerm.GetIndexWidth());
+	  _arrayread_symbol[processedTerm] = CurrentSymbol;	  
+	}
+	
+	//list of array-read indices corresponding to arrName, seen while
+	//traversing the AST tree. we need this list to construct the ITEs
+	// Dill: we hope to make this irrelevant.  Harmless for now.
+	ASTVec readIndices = _arrayname_readindices[arrName];
+	
+	//construct the ITE structure for this array-read
+	ASTNode ite = CurrentSymbol;
+	_introduced_symbols.insert(CurrentSymbol);
+	BVTypeCheck(ite);
+	
+	if(arrayread_refinement) {
+	  // ite is really a variable here; it is an ite in the
+	  // else-branch
+	  result = ite;
+	}
+	else {
+	  // Full Seshia transform if we're not doing read refinement.
+	  //do not loop if the current readIndex is a BVCONST
+	  // if(BVCONST == term[1].GetKind() && !SeenNonConstReadIndex && optimize) {
+	  // 	    result = ite; 
+	  // 	  }
+	  // 	  else {	  
+	    //else part: SET the SeenNonConstReadIndex var, and do the hard work
+	    //SeenNonConstReadIndex = true;
+	    ASTVec::reverse_iterator it2=readIndices.rbegin();
+	    ASTVec::reverse_iterator it2end=readIndices.rend();
+	    for(;it2!=it2end;it2++) {
+	      ASTNode cond = CreateSimplifiedEQ(readIndex,*it2);
+	      if(ASTFalse == cond)
+		continue;
+	      
+	      ASTNode arrRead = CreateTerm(READ,width,arrName,*it2);
+	      //Good idea to TypeCheck internally constructed nodes
+	      BVTypeCheck(arrRead);
+	      
+	      ASTNode arrayreadSymbol = _arrayread_symbol[arrRead];
+	      if(arrayreadSymbol.IsNull())
+		FatalError("TransformArray:symbolic variable for processedTerm, p," 
+			   "does not exist:p = ",arrRead);
+	      ite = CreateSimplifiedTermITE(cond,arrayreadSymbol,ite);
+	    }
+	    result = ite;
+	    //}
+	}
+	
+	_arrayname_readindices[arrName].push_back(readIndex);	
+	//save the ite corresponding to 'processedTerm'
+	_arrayread_ite[processedTerm] = result;
+	break;
+      } //end of READ over a SYMBOL
+      case WRITE:{	
+	/* The input to this case is: READ((WRITE A i val) j)
+	 *
+	 * The output of this case is: ITE( (= i j) val (READ A i))
+	 */
+	
+	/* 1. arrName or term[0] is infact a WRITE(A,i,val) expression
+	 *
+	 * 2. term[1] is the read-index j
+	 *
+	 * 3. arrName[0] is the new arrName i.e. A. A can be either a
+              SYMBOL or a nested WRITE. no other possibility
+	 *
+	 * 4. arrName[1] is the WRITE index i.e. i
+	 *
+	 * 5. arrName[2] is the WRITE value i.e. val (val can inturn
+	 *    be an array read)
+	 */
+	ASTNode readIndex = TransformTerm(term[1]);
+	ASTNode writeIndex = TransformTerm(arrName[1]);
+	ASTNode writeVal = TransformTerm(arrName[2]);
+	
+	if(!(SYMBOL == arrName[0].GetKind() || 
+	     WRITE == arrName[0].GetKind())) 
+	  FatalError("TransformArray: An array write is being attempted on a non-array:",term);
+	if(ARRAY_TYPE != arrName[0].GetType())
+	  FatalError("TransformArray: An array write is being attempted on a non-array:",term);
+	
+	ASTNode cond = CreateSimplifiedEQ(writeIndex,readIndex);
+	//TypeCheck internally created node
+	BVTypeCheck(cond);
+	ASTNode readTerm = CreateTerm(READ,width,arrName[0],readIndex);
+	//TypeCheck internally created node
+	BVTypeCheck(readTerm);
+	ASTNode readPushedIn = TransformArray(readTerm);
+	//TypeCheck internally created node
+	BVTypeCheck(readPushedIn);
+	//result = CreateTerm(ITE, arrName[0].GetValueWidth(),cond,writeVal,readPushedIn);
+	result = CreateSimplifiedTermITE(cond,writeVal,readPushedIn);
+
+	//Good idea to typecheck terms created inside the system
+	BVTypeCheck(result);
+	break;
+      } //end of READ over a WRITE
+      case ITE: {
+	/* READ((ITE cond thn els) j) 
+	 *
+	 * is transformed into
+	 *
+	 * (ITE cond (READ thn j) (READ els j))
+	 */
+	
+	//(ITE cond thn els)
+	ASTNode term0 = term[0];
+	//READINDEX j
+	ASTNode j = TransformTerm(term[1]);
+	
+	ASTNode cond = term0[0];
+	//first array 
+	ASTNode t01  = term0[1];
+	//second array
+	ASTNode t02  = term0[2];
+	
+	cond = TransformFormula(cond);
+	ASTNode thn = TransformTerm(t01);
+	ASTNode els = TransformTerm(t02);
+	
+	if(!(t01.GetValueWidth() == t02.GetValueWidth() &&
+	     t01.GetValueWidth() == thn.GetValueWidth() &&
+	     t01.GetValueWidth() == els.GetValueWidth()))
+	  FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n",term);
+
+	if(!(t01.GetIndexWidth() == t02.GetIndexWidth() &&
+	     t01.GetIndexWidth() == thn.GetIndexWidth() &&
+	     t01.GetIndexWidth() == els.GetIndexWidth()))
+	  FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n",term);
+
+	//(READ thn j)
+	ASTNode thnRead = CreateTerm(READ,width,thn,j);
+	BVTypeCheck(thnRead);
+	thnRead = TransformArray(thnRead);
+	
+	//(READ els j)
+	ASTNode elsRead = CreateTerm(READ,width,els,j);
+	BVTypeCheck(elsRead);
+	elsRead = TransformArray(elsRead);
+	
+	//(ITE cond (READ thn j) (READ els j))
+	result = CreateSimplifiedTermITE(cond,thnRead,elsRead);
+	BVTypeCheck(result);
+      break;
+      }
+      default:
+	FatalError("TransformArray: The READ is NOT over SYMBOL/WRITE/ITE",term);
+	break;
+      } 
+      break;
+    } //end of READ switch
+    default:
+      FatalError("TransformArray: input term is of wrong kind: ",ASTUndefined);
+      break;
+    }
+    
+    TransformMap[term] = result;
+    return result;
+  } //end of TransformArray()  
+} //end of namespace BEEV

Added: klee/trunk/stp/AST/asttest.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/asttest.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/asttest.cpp (added)
+++ klee/trunk/stp/AST/asttest.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,29 @@
+#include "AST.h"
+
+using namespace BEEV;
+
+int main()
+{
+
+  BeevMgr * bm = new BeevMgr();
+  ASTNode s1 = bm->CreateSymbol("foo");
+  s1 = bm->CreateSymbol("foo1");
+  s1 = bm->CreateSymbol("foo2");
+  ASTNode s2 = bm->CreateSymbol("bar");
+  cout << "s1" <<  s1 << endl;
+  cout << "s2" <<  s2 << endl;
+
+  ASTNode b1 = bm->CreateBVConst(5,12);
+  ASTNode b2 = bm->CreateBVConst(6,36);
+  cout << "b1: " <<  b1 << endl;
+  cout << "b2: " <<  b2 << endl;
+
+  ASTNode a1 = bm->CreateNode(EQ, s1, s2);
+  ASTNode a2 = bm->CreateNode(AND, s1, s2);
+  a1 = bm->CreateNode(OR, s1, s2);
+  ASTNode a3 = bm->CreateNode(IMPLIES, a1, a2);
+  ASTNode a4 = bm->CreateNode(IMPLIES, s1, a2);
+  cout << "a3" <<  a3 << endl;
+  cout << "a4" <<  a4 << endl;
+  return 0;
+}

Added: klee/trunk/stp/AST/bbtest.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/bbtest.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/bbtest.cpp (added)
+++ klee/trunk/stp/AST/bbtest.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,96 @@
+#include "AST.h"
+
+using namespace BEEV;
+
+int main()
+{
+  const int size = 32;
+
+  BeevMgr *bm = new BeevMgr();
+  ASTNode s1 = bm->CreateSymbol("x");
+  s1.SetValueWidth(size);
+  cout << "s1" <<  s1 << endl;
+  ASTNode s2 = bm->CreateSymbol("y");
+  s2.SetValueWidth(size);
+  cout << "s2" <<  s2 << endl;
+  ASTNode s3 = bm->CreateSymbol("z");
+  s3.SetValueWidth(size);
+  cout << "s3" <<  s3 << endl;
+
+  ASTNode c1 = bm->CreateBVConst(size,0);
+  cout << "c1" <<  c1 << endl;
+  ASTVec bbc1 = bm->BBTerm(c1);
+  cout << "bitblasted c1 " << endl;
+  LispPrintVec(cout, bbc1, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode c2 = bm->CreateBVConst(size,1);
+  c2.SetValueWidth(size);
+  cout << "c2" <<  c2 << endl;
+  ASTVec bbc2 = bm->BBTerm(c2);
+  cout << "bitblasted c2 " << endl;
+  LispPrintVec(cout, bbc2, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode c3 = bm->CreateBVConst(size, 0xFFFFFFFF);
+  c3.SetValueWidth(size);
+  cout << "c3" <<  c3 << endl;
+  ASTVec bbc3 = bm->BBTerm(c3);
+  cout << "bitblasted c3 " << endl;
+  LispPrintVec(cout, bbc3, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode c4 = bm->CreateBVConst(size, 0xAAAAAAAA);
+  c4.SetValueWidth(size);
+  cout << "c4" <<  c4 << endl;
+  ASTVec bbc4 = bm->BBTerm(c4);
+  cout << "bitblasted c4 " << endl;
+  LispPrintVec(cout, bbc4, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+//   ASTNode b1 = bm->CreateBVConst(12);
+//   ASTNode b2 = bm->CreateBVConst(36);
+//   cout << "b1: " <<  b1 << endl;
+//   cout << "b2: " <<  b2 << endl;
+
+  ASTNode a1 = bm->CreateNode(BVPLUS, s1, s2);
+  a1.SetValueWidth(size);
+
+  ASTVec& bba1 = bm->BBTerm(a1);
+  cout << "bitblasted a1 " << endl;
+  LispPrintVec(cout, bba1, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode a2 = bm->CreateNode(BVPLUS, s1, s2, s3);
+  a1.SetValueWidth(2);
+
+  ASTVec& bba2 = bm->BBTerm(a2);
+  cout << "bitblasted a2 " << endl;
+  LispPrintVec(cout, bba2, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode a3 = bm->CreateNode(BVXOR, s1, s2);
+  a3.SetValueWidth(2);
+
+  ASTVec& bba3 = bm->BBTerm(a3);
+  cout << "bitblasted a3 " << endl;
+  LispPrintVec(cout, bba3, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode a4 = bm->CreateNode(EQ, s1, s2);
+  ASTNode bba4 = bm->BBForm(a4);
+  cout << "bitblasted a4 " << endl << bba4 << endl;
+
+  ASTNode a5 = bm->CreateNode(BVLE, s1, s2);
+  ASTNode bba5 = bm->BBForm(a5);
+  cout << "bitblasted a5 " << endl << bba5 << endl;
+
+  return 0;
+}

Added: klee/trunk/stp/AST/cnftest.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/cnftest.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/cnftest.cpp (added)
+++ klee/trunk/stp/AST/cnftest.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,47 @@
+// -*- c++ -*-
+
+// Test program for CNF conversion.
+
+#include "AST.h"
+
+using namespace BEEV;
+
+int main()
+{
+  const int size = 1;
+  
+  BeevMgr *bm = new BeevMgr();
+  ASTNode s1 = bm->CreateSymbol("x");
+  s1.SetValueWidth(size);
+  
+  cout << "s1" <<  s1 << endl;
+  ASTNode s2 = bm->CreateSymbol("y");
+  s2.SetValueWidth(size);
+
+  cout << "s2" <<  s2 << endl;
+  ASTNode s3 = bm->CreateSymbol("z");
+  s3.SetValueWidth(size);
+  
+  cout << "s3" <<  s3 << endl;
+
+  ASTNode bbs1 = bm->BBForm(s1);
+  cout << "bitblasted s1" << endl << bbs1 << endl;
+  bm->PrintClauseList(cout, bm->ToCNF(bbs1));
+
+  ASTNode a2 = bm->CreateNode(AND, s1, s2);
+  ASTNode bba2 = bm->BBForm(a2);
+  cout << "bitblasted a2" << endl << bba2 << endl;
+  bm->PrintClauseList(cout, bm->ToCNF(bba2));
+
+  ASTNode a3 = bm->CreateNode(OR, s1, s2);
+  ASTNode bba3 = bm->BBForm(a3);
+  cout << "bitblasted a3" << endl << bba3 << endl;
+  bm->PrintClauseList(cout, bm->ToCNF(bba3));
+
+  ASTNode a4 = bm->CreateNode(EQ, s1, s2);
+  ASTNode bba4 = bm->BBForm(a4);
+  cout << "bitblasted a4 " << endl << bba4 << endl;
+
+  bm->PrintClauseList(cout, bm->ToCNF(bba4));
+
+}

Added: klee/trunk/stp/AST/genkinds.pl
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/AST/genkinds.pl?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/AST/genkinds.pl (added)
+++ klee/trunk/stp/AST/genkinds.pl Wed May 20 23:36:41 2009
@@ -0,0 +1,123 @@
+#!/usr/bin/perl -w
+
+#AUTHORS: Vijay Ganesh, David L. Dill BEGIN DATE: November, 2005
+#LICENSE: Please view LICENSE file in the home dir of this Program
+#given a file containing kind names, one per line produces .h and .cpp
+#files for the kinds.
+
+#globals
+ at kindnames = ();
+$minkids = 0;
+$maxkids = 0;
+ at cat_bits = ();
+ at category_names = ();
+%cat_index = ();
+
+$now = localtime time;
+
+sub read_kind_defs {
+    open(KFILE, "< ASTKind.kinds") || die "Cannot open .kinds file: $!\n";
+    @kindlines = <KFILE>;
+    close(KFILE)
+}
+
+# create lists of things indexed by kinds.
+sub split_fields {
+    my $kind_cat_bits;
+    # matches anything with three whitespace-delimited alphanumeric fields,
+    # followed by rest of line.  Automatically ignores lines beginning with '#' and blank lines.
+    for (@kindlines) {
+	if (/Categories:\s+(.*)/) {
+	    @category_names = split(/\s+/, $1);
+	    $i = 0;
+	    for (@category_names) {
+		$cat_index{$_} = $i++;
+		# print "cat_index{$_} = $i\n";
+	    }
+	}
+	elsif (/^(\w+)\s+(\w+)\s+(\w+|-)\s+(.*)/) {
+	    push(@kindnames, $1);
+	    push(@minkids, $2);
+	    push(@maxkids, $3);
+	    @kind_cats = split(/\s+/, $4);
+	    # build a bit vector of categories.
+	    $kind_cat_bits = 0;
+	    for (@kind_cats) {
+		$kind_cat_bits |= (1 << int($cat_index{$_}));
+	    }
+	    push(@cat_bits, $kind_cat_bits); 
+	}
+    }
+}
+
+sub gen_h_file {
+    open(HFILE, "> ASTKind.h") || die "Cannot open .h file: $!\n";
+
+    print HFILE 
+	"// -*- c++ -*-\n",
+	"#ifndef TESTKINDS_H\n",
+	"#define TESTKINDS_H\n",
+	"// Generated automatically by genkinds.pl from ASTKind.kinds $now.\n",
+	"// Do not edit\n",
+	"namespace BEEV {\n  typedef enum {\n";
+
+    for (@kindnames) {
+	print HFILE "    $_,\n";
+    }
+
+    print HFILE 
+	"} Kind;\n\n",
+	"extern unsigned char _kind_categories[];\n\n";
+
+    # For category named "cat", generate functions "bool is_cat_kind(k);"
+
+
+    for (@category_names) {
+	my $catname = $_;
+	my $kind_cat_bit = (1 << int($cat_index{$catname}));
+	print HFILE "inline bool is_", $catname, "_kind(Kind k) { return (_kind_categories[k] & $kind_cat_bit); }\n\n"
+    }
+
+    print HFILE
+	"extern const char *_kind_names[];\n\n",
+	"/** Prints symbolic name of kind */\n",
+	"inline ostream& operator<<(ostream &os, const Kind &kind) { os << _kind_names[kind]; return os; }\n",
+	"\n\n",
+	"};  // end namespace\n",
+	"\n\n#endif\n";
+
+    close(HFILE);
+}
+
+# generate the .cpp file
+
+sub gen_cpp_file {
+    open(CPPFILE, "> ASTKind.cpp") || die "Cannot open .h file: $!\n";
+
+    print CPPFILE
+	"// Generated automatically by genkinds.h from ASTKind.kinds $now.\n",
+	"// Do not edit\n",
+	"namespace BEEV {\n",
+	"const char * _kind_names[] =  {\n";
+    for (@kindnames) {
+	print CPPFILE "   \"$_\",\n";
+    }
+    print CPPFILE "};\n\n";
+
+    # category bits
+    print CPPFILE
+	"unsigned char _kind_categories[] = {\n";
+    for (@cat_bits) {
+	print CPPFILE "   $_,\n";
+    }
+    print CPPFILE 
+	"};\n",
+	"\n};  // end namespace\n";
+
+    close(CPPFILE);
+}
+
+&read_kind_defs;
+&split_fields;
+&gen_h_file;
+&gen_cpp_file;

Propchange: klee/trunk/stp/AST/genkinds.pl

------------------------------------------------------------------------------
    svn:executable = *

Added: klee/trunk/stp/INSTALL
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/INSTALL?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/INSTALL (added)
+++ klee/trunk/stp/INSTALL Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+1. To install STP perform the following steps on your Unix/GNU-Linux/MacOS X commandline:
+
+./configure --with-prefix=$HOME (or another installation directory)
+make clean
+make
+make install
+
+2. To test the system after installation:
+
+make regressall
\ No newline at end of file

Added: klee/trunk/stp/LICENSE
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/LICENSE?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/LICENSE (added)
+++ klee/trunk/stp/LICENSE Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+/*****************************************************************************/
+/*  AUTHORS:    Vijay Ganesh, David L. Dill             DATE: Nov 2005       */
+/*****************************************************************************/
+/* Copyright (C) 2005 by the Board of Trustees of Leland Stanford            */
+/* Junior University.                                                        */
+/*                                                                           */
+/* License to use, copy, modify, sell and/or distribute this software        */
+/* and its documentation for any purpose is hereby granted without           */
+/* royalty, subject to the terms and conditions defined in the \ref          */
+/* LICENSE file provided with this distribution.  In particular:             */
+/*                                                                           */
+/* - The above copyright notice and this permission notice must appear       */
+/* in all copies of the software and related documentation.                  */
+/*                                                                           */
+/* - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,               */
+/* EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.                           */
+/*****************************************************************************/

Added: klee/trunk/stp/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/Makefile (added)
+++ klee/trunk/stp/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,64 @@
+ # STP (Simple Theorem Prover) top level makefile
+ #
+ # To make in debug mode, type 'make "CLFAGS=-ggdb"
+ # To make in optimized mode, type 'make "CFLAGS=-O2" 
+
+include Makefile.common
+
+BINARIES=bin/stp
+LIBS=AST/libast.a sat/libsatsolver.a simplifier/libsimplifier.a bitvec/libconsteval.a constantbv/libconstantbv.a c_interface/libcinterface.a
+DIRS=AST sat simplifier bitvec c_interface constantbv parser
+
+# NB: the TAGS target is a hack to get around this recursive make nonsense
+# we want all the source and header files generated before we make tags
+.PHONY: all
+all: lib/libstp.a bin/stp include/stp/c_interface.h
+
+AST/libast.a:
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+sat/libsatsolver.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+simplifier/libsimplifier.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+bitvec/libconsteval.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+constantbv/libconstantbv.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+c_interface/libcinterface.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+parser/parser: $(LIBS)
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+
+lib/libstp.a: parser/parser $(LIBS)
+	@mkdir -p lib
+	rm -f $@
+	@for dir in $(DIRS); do \
+		$(AR) rc $@ $$dir/*.o; \
+	done
+	$(RANLIB) $@
+
+bin/stp: parser/parser $(LIBS)
+	@mkdir -p bin
+	@cp parser/parser $@
+
+include/stp/c_interface.h: $(LIBS)
+	@mkdir -p include/stp
+	@cp c_interface/c_interface.h $@
+
+.PHONY: clean
+clean:
+	rm -rf *~
+	rm -rf *.a
+	rm -rf lib/*.a
+	rm -rf bin/*~
+	rm -rf bin/stp
+	rm -rf *.log
+	rm -f TAGS
+	$(MAKE) clean -C AST
+	$(MAKE) clean -C sat
+	$(MAKE) clean -C simplifier
+	$(MAKE) clean -C bitvec
+	$(MAKE) clean -C parser
+	$(MAKE) clean -C c_interface
+	$(MAKE) clean -C constantbv
+

Added: klee/trunk/stp/Makefile.common.in
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/Makefile.common.in?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/Makefile.common.in (added)
+++ klee/trunk/stp/Makefile.common.in Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+# -*- Makefile -*-
+
+CFLAGS := @CFLAGS@
+CXXFLAGS := @CXXFLAGS@ -O2
+LDFLAGS := @LDFLAGS@ -lstdc++
+
+# use the darmin test as a proxy for detecting Mac OS X
+ifneq ($(shell uname -s), Darwin)
+  CFLAGS += -static
+endif
+
+CXXFLAGS += -Wall -DEXT_HASH_MAP
+
+LEX := flex
+YACC := bison -d -y --debug -v
+RANLIB := ranlib

Added: klee/trunk/stp/README
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/README?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/README (added)
+++ klee/trunk/stp/README Wed May 20 23:36:41 2009
@@ -0,0 +1,26 @@
+/********************************************************************
+ * PROGRAM NAME: STP (Simple Theorem Prover)	
+ *		
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *	
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+
+Install
+-------
+See INSTALL file in the home dir of this program
+
+Authors
+-------
+Vijay Ganesh, Stanford University, Stanford, CA, USA
+David L. Dill, Stanford University, Stanford, CA, USA
+Tim King, Stanford University, Stanford, CA, USA
+
+Makefiles and configuration scripts
+------------------------------------
+Cristian Cadar, Stanford University, Stanford, CA, USA
+Paul Twohey, Stanford University, Stanford, CA, USA
+Sergey Berezin, ATG Synopsys, Mountain View, CA, USA
+Clark Barrett, New York University, New York, NY, USA

Added: klee/trunk/stp/bitvec/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/bitvec/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/bitvec/Makefile (added)
+++ klee/trunk/stp/bitvec/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,11 @@
+include ../Makefile.common
+
+SRCS = consteval.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libconsteval.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:	
+	rm -rf *.o *~ *.a .#*

Added: klee/trunk/stp/bitvec/consteval.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/bitvec/consteval.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/bitvec/consteval.cpp (added)
+++ klee/trunk/stp/bitvec/consteval.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,1044 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+namespace BEEV {
+
+  //error printing
+  static void BVConstEvaluatorError(CONSTANTBV::ErrCode e, const ASTNode& t){
+    std::string ss("BVConstEvaluator:");
+    ss += (const char*)BitVector_Error(e);	
+    FatalError(ss.c_str(), t);
+  }
+
+#ifndef NATIVE_C_ARITH
+  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
+    ASTNode OutputNode;
+    Kind k = t.GetKind();
+
+    if(CheckSolverMap(t,OutputNode))
+      return OutputNode;
+    OutputNode = t;
+
+    unsigned int inputwidth = t.GetValueWidth();
+    unsigned int outputwidth = inputwidth;
+    CBV output = NULL;
+
+    CBV tmp0 = NULL;
+    CBV tmp1 = NULL;
+
+    //saving some typing. BVPLUS does not use these variables. if the
+    //input BVPLUS has two nodes, then we want to avoid setting these
+    //variables.
+    if(1 == t.Degree() ){
+      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+    }else if(2 == t.Degree() && k != BVPLUS ) {
+      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+      tmp1 = BVConstEvaluator(t[1]).GetBVConst();
+    }
+
+    switch(k) {
+    case UNDEFINED:
+    case READ:
+    case WRITE:
+    case SYMBOL:
+      FatalError("BVConstEvaluator: term is not a constant-term",t);
+      break;
+    case BVCONST:
+      //FIXME Handle this special case better
+      OutputNode = t;
+      break;
+    case BVNEG:{
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_Complement(output,tmp0);
+      OutputNode = CreateBVConst(output,outputwidth);
+      break;
+    }
+    case BVSX: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      //unsigned * out0 = BVConstEvaluator(t[0]).GetBVConst();
+      unsigned t0_width = t[0].GetValueWidth();
+      if(inputwidth == t0_width) {
+        CONSTANTBV::BitVector_Copy(output, tmp0);
+        OutputNode = CreateBVConst(output, outputwidth);    
+      }
+      else {
+        bool topbit_sign = (CONSTANTBV::BitVector_Sign(tmp0) < 0 );
+
+        if(topbit_sign){
+          CONSTANTBV::BitVector_Fill(output);
+        }
+        CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, t0_width);
+        OutputNode = CreateBVConst(output, outputwidth);    
+      }
+      break;
+    }
+    case BVAND: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_Intersection(output,tmp0,tmp1);
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    case BVOR: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_Union(output,tmp0,tmp1);
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    case BVXOR: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_ExclusiveOr(output,tmp0,tmp1);
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    case BVSUB: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      bool carry = false;
+      CONSTANTBV::BitVector_sub(output,tmp0,tmp1,&carry);
+      OutputNode = CreateBVConst(output, outputwidth);    
+      break;
+    }
+    case BVUMINUS: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::BitVector_Negate(output, tmp0);
+      OutputNode = CreateBVConst(output, outputwidth);    
+      break;
+    }
+    case BVEXTRACT: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+      unsigned int len = hi-low+1;
+
+      CONSTANTBV::BitVector_Destroy(output);
+      output = CONSTANTBV::BitVector_Create(len, false);
+      CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, low, len);
+      outputwidth = len;
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    //FIXME Only 2 inputs?
+    case BVCONCAT: {
+       output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      unsigned t0_width = t[0].GetValueWidth();
+      unsigned t1_width = t[1].GetValueWidth();
+      CONSTANTBV::BitVector_Destroy(output);
+      
+      output = CONSTANTBV::BitVector_Concat(tmp0, tmp1);
+      outputwidth = t0_width + t1_width;
+      OutputNode = CreateBVConst(output, outputwidth);
+      
+      break;
+    }
+    case BVMULT: {
+       output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CBV tmp = CONSTANTBV::BitVector_Create(2*inputwidth,true);
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(tmp,tmp0,tmp1);
+      
+      if(0 != e) {
+        BVConstEvaluatorError(e,t);
+      }
+      //FIXME WHAT IS MY OUTPUT???? THE SECOND HALF of tmp?
+      //CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, inputwidth, inputwidth);
+      CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, 0, inputwidth);
+      OutputNode = CreateBVConst(output, outputwidth);
+      CONSTANTBV::BitVector_Destroy(tmp);
+      break;
+    }
+    case BVPLUS: {
+       output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      bool carry = false;
+      ASTVec c = t.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	CBV kk = BVConstEvaluator(*it).GetBVConst();
+	CONSTANTBV::BitVector_add(output,output,kk,&carry);
+	carry = false;
+	//CONSTANTBV::BitVector_Destroy(kk);
+      }
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    //FIXME ANOTHER SPECIAL CASE
+    case SBVDIV:
+    case SBVMOD:{
+      OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
+      break;
+    }
+    case BVDIV: 
+    case BVMOD: {
+      CBV quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CBV remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+      
+      // tmp0 is dividend, tmp1 is the divisor
+      //All parameters to BitVector_Div_Pos must be distinct unlike BitVector_Divide
+      //FIXME the contents of the second parameter to Div_Pos is destroyed
+      //As tmp0 is currently the same as the copy belonging to an ASTNode t[0]
+      //this must be copied.
+      tmp0 = CONSTANTBV::BitVector_Clone(tmp0);      
+      CONSTANTBV::ErrCode e= CONSTANTBV::BitVector_Div_Pos(quotient,tmp0,tmp1,remainder);
+      CONSTANTBV::BitVector_Destroy(tmp0);
+      
+      if(0 != e) {
+	//error printing
+	if(counterexample_checking_during_refinement) {
+          output = CONSTANTBV::BitVector_Create(inputwidth,true);
+	  OutputNode = CreateBVConst(output, outputwidth);
+	  bvdiv_exception_occured = true;
+          
+          //  CONSTANTBV::BitVector_Destroy(output);
+	  break;
+	}
+	else {
+	  BVConstEvaluatorError(e,t);
+	}
+      } //end of error printing
+
+      //FIXME Not very standard in the current scheme
+      if(BVDIV == k){
+        OutputNode = CreateBVConst(quotient, outputwidth);
+        CONSTANTBV::BitVector_Destroy(remainder);
+      }else{
+        OutputNode = CreateBVConst(remainder, outputwidth);
+        CONSTANTBV::BitVector_Destroy(quotient);
+      }
+
+      break;
+    }
+    case ITE:
+      if(ASTTrue == t[0])
+	OutputNode = BVConstEvaluator(t[1]);
+      else if(ASTFalse == t[0])
+	OutputNode = BVConstEvaluator(t[2]);
+      else
+	FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
+      break;
+    case EQ: 
+      if(CONSTANTBV::BitVector_equal(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case NEQ:
+      if(!CONSTANTBV::BitVector_equal(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLT:
+      if(-1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVGT:
+      if(1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    case BVSLT:
+      if(-1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSLE: {
+      signed int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGT:
+      if(1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSGE: {
+      int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    default:
+      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+      break;
+    }
+/*
+    if(BVCONST != k){
+     cerr<<inputwidth<<endl;
+     cerr<<"------------------------"<<endl;
+     t.LispPrint(cerr);
+     cerr<<endl;
+     OutputNode.LispPrint(cerr);
+     cerr<<endl<<"------------------------"<<endl;
+    }
+*/
+    UpdateSolverMap(t,OutputNode);
+    //UpdateSimplifyMap(t,OutputNode,false);
+    return OutputNode;
+  }
+#else
+  //accepts 64 bit BVConst and sign extends it
+  static unsigned long long int SXBVConst64(const ASTNode& t) {
+    unsigned long long int c = t.GetBVConst();
+    unsigned int len = t.GetValueWidth();
+
+    unsigned long long int mask = 1;
+    mask = mask << len-1;
+
+    bool TopBit = (c & mask) ? true : false;
+    if(!TopBit) return c;
+    
+    unsigned long long int sign = 0xffffffffffffffffLL;
+    sign = sign << len-1;
+
+    return (c | sign);
+  }
+
+  //FIXME: Ideally I would like the ASTNodes to be able to operate on
+  //themselves (add, sub, concat, etc.) rather than doing a
+  //GetBVConst() and then do the operation externally. For now,
+  //this is the fastest path to completion.
+  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
+    //cerr << "inside begin bcconstevaluator: " << t << endl;
+
+    ASTNode OutputNode;
+    if(CheckSolverMap(t,OutputNode))
+      return OutputNode;
+    OutputNode = ASTUndefined;
+
+    Kind k = t.GetKind();
+    unsigned long long int output = 0;
+    unsigned inputwidth = t.GetValueWidth();
+    ASTNode t0 = ASTUndefined;
+    ASTNode t1 = ASTUndefined;
+    if(2 == t.Degree()) {
+      t0 = BVConstEvaluator(t[0]);
+      t1 = BVConstEvaluator(t[1]);
+    }
+    switch(k) {
+    case READ:
+    case UNDEFINED:
+    case WRITE:
+    case SYMBOL:
+      cerr << t;
+      FatalError("BVConstEvaluator: term is not a constant-term",t);
+      break;
+    case BVCONST:
+      return t;
+      break;
+    case BVNEG:
+      //compute bitwise negation in C
+      output = ~(BVConstEvaluator(t[0]).GetBVConst());
+      break;
+    case BVSX:
+      output = SXBVConst64(BVConstEvaluator(t[0]));    
+      break;
+    case BVAND:
+      output = t0.GetBVConst() & t1.GetBVConst();
+      break;
+    case BVOR:
+      output = t0.GetBVConst() | t1.GetBVConst();
+      break;
+    case BVXOR:
+      output = t0.GetBVConst() ^ t1.GetBVConst();
+      break;
+    case BVSUB:
+      output = t0.GetBVConst() - t1.GetBVConst();
+      break;
+    case BVUMINUS:
+      output = ~(BVConstEvaluator(t[0]).GetBVConst()) + 1;
+      break;
+    case BVEXTRACT: {
+      unsigned long long int val = BVConstEvaluator(t[0]).GetBVConst();
+      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+
+      if(!(0 <= hi <= 64))
+	FatalError("ConstantEvaluator: hi bit in BVEXTRACT is > 32bits",t);
+      if(!(0 <= low <= hi <= 64))
+	FatalError("ConstantEvaluator: low bit in BVEXTRACT is > 32bits or hi",t);
+
+      //64 bit mask.
+      unsigned long long int mask1 = 0xffffffffffffffffLL;
+      mask1 >>= 64-(hi+1);
+      
+      //extract val[hi:0]
+      val &= mask1;
+      //extract val[hi:low]
+      val >>= low;
+      output = val;
+      break;
+    }
+    case BVCONCAT: {
+      unsigned long long int q = BVConstEvaluator(t0).GetBVConst();
+      unsigned long long int r = BVConstEvaluator(t1).GetBVConst();
+
+      unsigned int qlen = t[0].GetValueWidth();
+      unsigned int rlen = t[1].GetValueWidth();
+      unsigned int slen = t.GetValueWidth();
+      if(!(0 <  qlen + rlen  <= 64))
+	FatalError("BVConstEvaluator:"
+		   "lengths of childnodes of BVCONCAT are > 64:",t);
+
+      //64 bit mask for q
+      unsigned long long int qmask = 0xffffffffffffffffLL;     
+      qmask >>= 64-qlen;
+      //zero the useless bits of q
+      q &= qmask;
+
+      //64 bit mask for r
+      unsigned long long int rmask = 0xffffffffffffffffLL;     
+      rmask >>= 64-rlen;
+      //zero the useless bits of r
+      r &= rmask;
+      
+      //concatenate
+      q <<= rlen;
+      q |= r;
+
+      //64 bit mask for output s
+      unsigned long long int smask = 0xffffffffffffffffLL;
+      smask >>= 64-slen;
+      
+      //currently q has the output
+      output = q;      
+      output &= smask;
+      break;
+    }
+    case BVMULT: {
+      output = t0.GetBVConst() * t1.GetBVConst();
+
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 - inputwidth);
+      output &= mask;
+      break;
+    }
+    case BVPLUS: {
+      ASTVec c = t.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
+	output += BVConstEvaluator(*it).GetBVConst();
+
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 -inputwidth);
+      output &= mask;
+      break;
+    }
+    case SBVDIV:
+    case SBVMOD: {
+      output = BVConstEvaluator(TranslateSignedDivMod(t)).GetBVConst();
+      break;
+    }
+    case BVDIV: {
+      if(0 == t1.GetBVConst()) {
+	//if denominator is 0 then 
+	//  (if refinement is ON then output is set to 0) 
+	//   (else produce a fatal error)
+	if(counterexample_checking_during_refinement) {
+	  output = 0;
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+	}
+      }
+
+      output = t0.GetBVConst() / t1.GetBVConst();
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 - inputwidth);
+      output &= mask;
+      break;
+    }
+    case BVMOD: {
+      if(0 == t1.GetBVConst()) {
+	//if denominator is 0 then 
+	//  (if refinement is ON then output is set to 0) 
+	//   (else produce a fatal error)
+	if(counterexample_checking_during_refinement) {
+	  output = 0;
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+	}
+      }
+
+      output = t0.GetBVConst() % t1.GetBVConst();
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 - inputwidth);
+      output &= mask;
+      break;
+    }
+    case ITE:
+      if(ASTTrue == t[0])
+	OutputNode = BVConstEvaluator(t[1]);
+      else if(ASTFalse == t[0])
+	OutputNode = BVConstEvaluator(t[2]);
+      else
+	FatalError("BVConstEvaluator:" 
+		   "ITE condiional must be either TRUE or FALSE:",t);
+      break;
+    case EQ:
+      if(t0.GetBVConst() == t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case NEQ:
+      if(t0.GetBVConst() != t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+      break;
+    case BVLT: {
+      unsigned long long n0 = t0.GetBVConst();
+      unsigned long long n1 = t1.GetBVConst();
+      if(n0 < n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVLE:
+      if(t0.GetBVConst() <= t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGT:
+      if(t0.GetBVConst() > t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGE:
+      if(t0.GetBVConst() >= t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSLT: {
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 < n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSLE: {
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 <= n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGT: {   
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 > n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGE: {   
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 >= n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    default:
+      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+      break;
+    }    
+   
+    if(ASTTrue  != OutputNode && ASTFalse != OutputNode)
+      OutputNode = CreateBVConst(inputwidth, output);
+    UpdateSolverMap(t,OutputNode);
+    //UpdateSimplifyMap(t,OutputNode,false);
+    return OutputNode;
+  } //End of BVConstEvaluator
+#endif
+//In the block below is the old string based version
+//It is included here as an easy reference while the current code is being worked on.
+
+/*
+  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
+    ASTNode OutputNode;
+    Kind k = t.GetKind();
+
+    if(CheckSolverMap(t,OutputNode))
+      return OutputNode;
+    OutputNode = t;
+
+    unsigned int inputwidth = t.GetValueWidth();
+    unsigned * output = CONSTANTBV::BitVector_Create(inputwidth,true);
+    unsigned * One = CONSTANTBV::BitVector_Create(inputwidth,true);
+    CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(One, (unsigned char*)"1");
+    //error printing
+    if(0 != e) {
+      std::string ss("BVConstEvaluator:");
+      ss += (const char*)BitVector_Error(e);	
+      FatalError(ss.c_str(), t);
+    }
+
+    unsigned * Zero = CONSTANTBV::BitVector_Create(inputwidth,true);
+    unsigned int * iii = One;
+    unsigned int * jjj = Zero;
+
+    //saving some typing. BVPLUS does not use these variables. if the
+    //input BVPLUS has two nodes, then we want to avoid setting these
+    //variables.
+    if(2 == t.Degree() && k != BVPLUS && k != BVCONCAT) {
+      iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+      jjj = ConvertToCONSTANTBV(BVConstEvaluator(t[1]).GetBVConst());
+    }
+
+    char * cccc;
+    switch(k) {
+    case UNDEFINED:
+    case READ:
+    case WRITE:
+    case SYMBOL:
+      FatalError("BVConstEvaluator: term is not a constant-term",t);
+      break;
+    case BVCONST:
+      OutputNode = t;
+      break;
+    case BVNEG:{
+      //AARON
+      if (iii != One) free(iii);
+      //AARON
+
+      iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());     
+      CONSTANTBV::Set_Complement(output,iii);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+      break;
+    }
+    case BVSX: {
+      unsigned * out0 = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+      unsigned t0_width = t[0].GetValueWidth();
+      if(inputwidth == t0_width) {
+	cccc = (char *)CONSTANTBV::BitVector_to_Bin(out0);
+	OutputNode = CreateBVConst(cccc,2);
+
+	//AARON
+	free(cccc);
+	//AARON
+
+	CONSTANTBV::BitVector_Destroy(out0);     
+      }
+      else {
+	// FIXME: (Dill) I'm guessing that BitVector sign returns 1 if the
+	// number is positive, 0 if 0, and -1 if negative.  But I'm only
+	// guessing.
+	signed int topbit_sign = (CONSTANTBV::BitVector_Sign(out0) < 0);
+	//out1 is the sign-extension bits
+	unsigned * out1 =  CONSTANTBV::BitVector_Create(inputwidth-t0_width,true);      
+	if(topbit_sign)
+	  CONSTANTBV::BitVector_Fill(out1);
+
+	//AARON
+	CONSTANTBV::BitVector_Destroy(output);
+	//AARON
+
+	output = CONSTANTBV::BitVector_Concat(out1,out0);
+	cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+	OutputNode = CreateBVConst(cccc,2);
+
+	//AARON
+	free(cccc);
+	//AARON
+
+	CONSTANTBV::BitVector_Destroy(out0);
+	CONSTANTBV::BitVector_Destroy(out1);
+      }
+      break;
+    }
+    case BVAND: {
+      CONSTANTBV::Set_Intersection(output,iii,jjj);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+      
+      break;
+    }
+    case BVOR: {
+      CONSTANTBV::Set_Union(output,iii,jjj);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVXOR: {
+      CONSTANTBV::Set_ExclusiveOr(output,iii,jjj);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVSUB: {
+      bool carry = false;
+      CONSTANTBV::BitVector_sub(output,iii,jjj,&carry);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVUMINUS: {
+      bool carry = false;
+
+      //AARON
+      if (iii != One) free(iii);
+      //AARON
+
+      iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+      CONSTANTBV::Set_Complement(output,iii);
+      CONSTANTBV::BitVector_add(output,output,One,&carry);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVEXTRACT: {
+      string s(BVConstEvaluator(t[0]).GetBVConst());
+      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+
+      //length of substr to chop
+      unsigned int len = hi-low+1;
+      //distance from MSB
+      hi = s.size()-1 - hi;      
+      string ss = s.substr(hi,len);
+      OutputNode = CreateBVConst(ss.c_str(),2);
+      break;
+    }
+    case BVCONCAT: {
+      string s(BVConstEvaluator(t[0]).GetBVConst());
+      string r(BVConstEvaluator(t[1]).GetBVConst());
+  
+      string q(s+r);
+      OutputNode = CreateBVConst(q.c_str(),2);
+      break;
+    }
+    case BVMULT: {
+      unsigned * output1 = CONSTANTBV::BitVector_Create(2*inputwidth,true);
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(output1,iii,jjj);
+      //error printing
+      if(0 != e) {
+	std::string ss("BVConstEvaluator:");
+	ss += (const char*)BitVector_Error(e);	
+	//destroy all the CONSTANTBV bitvectors
+	CONSTANTBV::BitVector_Destroy(iii);
+	CONSTANTBV::BitVector_Destroy(jjj);       
+	CONSTANTBV::BitVector_Destroy(One);
+	CONSTANTBV::BitVector_Destroy(Zero);
+	FatalError(ss.c_str(), t);
+      }
+
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output1);
+      std::string s(cccc);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      s = s.substr(inputwidth,inputwidth);
+      OutputNode = CreateBVConst(s.c_str(),2);
+      CONSTANTBV::BitVector_Destroy(output1);
+      break;
+    }
+    case BVPLUS: {
+      bool carry = false;
+      ASTVec c = t.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	unsigned int * kk = ConvertToCONSTANTBV(BVConstEvaluator(*it).GetBVConst());
+	CONSTANTBV::BitVector_add(output,output,kk,&carry);
+	carry = false;
+	CONSTANTBV::BitVector_Destroy(kk);
+      }
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case SBVDIV:
+    case SBVMOD: {
+      OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
+      break;
+    }
+    case BVDIV: {      
+      unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+      unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+      // iii is dividend, jjj is the divisor
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
+
+      if(0 != e) {
+	//error printing
+	if(counterexample_checking_during_refinement) {
+	  OutputNode = CreateZeroConst(inputwidth);
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  std::string ss("BVConstEvaluator:");
+	  ss += (const char*)BitVector_Error(e);	
+	  //destroy all the CONSTANTBV bitvectors
+	  CONSTANTBV::BitVector_Destroy(iii);
+	  CONSTANTBV::BitVector_Destroy(jjj);       
+	  CONSTANTBV::BitVector_Destroy(One);
+	  CONSTANTBV::BitVector_Destroy(Zero);
+
+	  //AARON
+	  iii = jjj = One = Zero = NULL;
+	  //AARON
+
+	  FatalError(ss.c_str(), t);
+	}
+      } //end of error printing
+
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(quotient);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      CONSTANTBV::BitVector_Destroy(quotient);
+      CONSTANTBV::BitVector_Destroy(remainder);
+      //AARON
+
+      break;
+    }
+   case BVMOD: {
+      unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+      unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+      // iii is dividend, jjj is the divisor
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
+
+      if(0 != e) {
+	//error printing
+	if(counterexample_checking_during_refinement) {
+	  OutputNode = CreateZeroConst(inputwidth);
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  std::string ss("BVConstEvaluator:");
+	  ss += (const char*)BitVector_Error(e);
+	  //destroy all the CONSTANTBV bitvectors
+	  CONSTANTBV::BitVector_Destroy(iii);
+	  CONSTANTBV::BitVector_Destroy(jjj);       
+	  CONSTANTBV::BitVector_Destroy(One);
+	  CONSTANTBV::BitVector_Destroy(Zero);	
+
+	  //AARON
+	  iii = jjj = One = Zero = NULL;
+	  //AARON
+
+	  FatalError(ss.c_str(), t);
+	}
+      } //end of errory printing
+
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(remainder);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      CONSTANTBV::BitVector_Destroy(quotient);
+      CONSTANTBV::BitVector_Destroy(remainder);
+      //AARON
+
+      break;
+    }
+    case ITE:
+      if(ASTTrue == t[0])
+	OutputNode = BVConstEvaluator(t[1]);
+      else if(ASTFalse == t[0])
+	OutputNode = BVConstEvaluator(t[2]);
+      else
+	FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
+      break;
+    case EQ: 
+      if(CONSTANTBV::BitVector_equal(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case NEQ:
+      if(!CONSTANTBV::BitVector_equal(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLT:
+      if(-1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVGT:
+      if(1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    case BVSLT:
+      if(-1 == CONSTANTBV::BitVector_Compare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSLE: {
+      signed int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGT:
+      if(1 == CONSTANTBV::BitVector_Compare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSGE: {
+      int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    default:
+      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+      break;
+    }
+
+
+
+    // //destroy all the CONSTANTBV bitvectors
+//     CONSTANTBV::BitVector_Destroy(iii);
+//     CONSTANTBV::BitVector_Destroy(jjj);
+//     CONSTANTBV::BitVector_Destroy(output);
+
+//     if(k == BVNEG || k == BVUMINUS)
+//       CONSTANTBV::BitVector_Destroy(One);
+//     else if(k == BVAND   || k == BVOR  || k == BVXOR   || k == BVSUB || 
+// 	    k == BVMULT  || k == EQ    || k == NEQ     || k == BVLT  ||
+// 	    k == BVLE    || k == BVGT  || k == BVGE    || k == BVSLT ||
+// 	    k == BVSLE   || k == BVSGT || k == BVSGE) {
+//       CONSTANTBV::BitVector_Destroy(One);
+//       CONSTANTBV::BitVector_Destroy(Zero);
+//     }    
+
+    //AARON
+    if (output != NULL) CONSTANTBV::BitVector_Destroy(output);
+    if (One != NULL) CONSTANTBV::BitVector_Destroy(One);
+    if (Zero != NULL) CONSTANTBV::BitVector_Destroy(Zero);
+    if (iii != NULL && iii != One) CONSTANTBV::BitVector_Destroy(iii);
+    if (jjj != NULL && jjj != Zero) CONSTANTBV::BitVector_Destroy(jjj);
+    //AARON
+   
+    UpdateSolverMap(t,OutputNode);
+    //UpdateSimplifyMap(t,OutputNode,false);
+    return OutputNode;
+  }
+
+
+  unsigned int * ConvertToCONSTANTBV(const char * s) {
+    unsigned int length = strlen(s);
+    unsigned char * ccc = (unsigned char *)s;
+    unsigned *  iii = CONSTANTBV::BitVector_Create(length,true);
+    CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,ccc);
+    //error printing
+    if(0 != e) {
+      cerr << "ConverToCONSTANTBV: wrong bin value: " << BitVector_Error(e);      
+      FatalError("");
+    }
+    
+    return iii;
+  }
+*/
+}; //end of namespace BEEV

Added: klee/trunk/stp/c_interface/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/c_interface/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/c_interface/Makefile (added)
+++ klee/trunk/stp/c_interface/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,13 @@
+include ../Makefile.common
+
+SRCS = c_interface.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libcinterface.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:	
+	rm -rf *.o *~ *.a .#*
+
+c_interface.o: c_interface.h

Added: klee/trunk/stp/c_interface/c_interface.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/c_interface/c_interface.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/c_interface/c_interface.cpp (added)
+++ klee/trunk/stp/c_interface/c_interface.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,1548 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+#include "c_interface.h"
+
+#include <cstdlib>
+#include <cassert>
+#include <ostream>
+#include <iostream>
+#include "fdstream.h"
+#include "../AST/AST.h"
+
+//These typedefs lower the effort of using the keyboard to type (too
+//many overloaded meanings of the word type)
+typedef BEEV::ASTNode  node;
+typedef BEEV::ASTNode* nodestar;
+typedef BEEV::BeevMgr* bmstar;
+typedef BEEV::ASTVec   nodelist;
+typedef BEEV::CompleteCounterExample* CompleteCEStar;
+BEEV::ASTVec *decls = NULL;
+//vector<BEEV::ASTNode *> created_exprs;
+bool cinterface_exprdelete_on = false;
+
+void vc_setFlags(char c) {
+  std::string helpstring = "Usage: stp [-option] [infile]\n\n";
+  helpstring +=  "-r  : switch refinement off (optimizations are ON by default)\n";
+  helpstring +=  "-w  : switch wordlevel solver off (optimizations are ON by default)\n";
+  helpstring +=  "-a  : switch optimizations off (optimizations are ON by default)\n";
+  helpstring +=  "-s  : print function statistics\n";
+  helpstring +=  "-v  : print nodes \n";
+  helpstring +=  "-c  : construct counterexample\n";
+  helpstring +=  "-d  : check counterexample\n";
+  helpstring +=  "-p  : print counterexample\n";
+  helpstring +=  "-h  : help\n";
+  
+  switch(c) {
+  case 'a' :
+    BEEV::optimize = false;
+    BEEV::wordlevel_solve = false;
+    break;
+  case 'b':
+    BEEV::print_STPinput_back = true;
+    break;
+  case 'c':
+    BEEV::construct_counterexample = true;
+    break;
+  case 'd':
+    BEEV::construct_counterexample = true;
+    BEEV::check_counterexample = true;
+    break;
+  case 'e':
+    BEEV::variable_activity_optimize = true;
+    break;
+  case 'f':
+    BEEV::smtlib_parser_enable = true;
+    break;
+  case 'h':
+    cout << helpstring;
+    BEEV::FatalError("");
+    break;
+  case 'l' :
+    BEEV::linear_search = true;
+    break;
+  case 'n':
+    BEEV::print_output = true;
+    break;
+  case 'p':
+    BEEV::print_counterexample = true;
+    break;
+  case 'q':
+    BEEV::print_arrayval_declaredorder = true;
+    break;
+  case 'r':
+    BEEV::arrayread_refinement = false;
+    break;
+  case 's' :
+    BEEV::stats = true;
+    break;
+  case 'u':
+    BEEV::arraywrite_refinement = true;
+    break;  
+  case 'v' :
+    BEEV::print_nodes = true;
+    break;
+  case 'w':
+    BEEV::wordlevel_solve = false;
+    break;
+  case 'x':
+    cinterface_exprdelete_on = true;
+    break;
+  case 'z':
+    BEEV::print_sat_varorder = true;
+    break;
+  default:
+    std::string s = "C_interface: vc_setFlags: Unrecognized commandline flag:\n";
+    s += helpstring;
+    BEEV::FatalError(s.c_str());
+    break;
+  }
+}
+
+//Create a validity Checker. This is the global BeevMgr
+VC vc_createValidityChecker(void) {
+  vc_setFlags('d');
+#ifdef NATIVE_C_ARITH
+#else
+  CONSTANTBV::ErrCode c = CONSTANTBV::BitVector_Boot(); 
+  if(0 != c) {
+    cout << CONSTANTBV::BitVector_Error(c) << endl;
+    return 0;
+  }
+#endif
+  bmstar bm = new BEEV::BeevMgr();
+  decls = new BEEV::ASTVec();
+  //created_exprs.clear();
+  return (VC)bm;
+}
+
+// Expr I/O
+void vc_printExpr(VC vc, Expr e) {
+  //do not print in lisp mode
+  //bmstar b = (bmstar)vc;
+  BEEV::ASTNode q = (*(nodestar)e);
+  //   b->Begin_RemoveWrites = true;
+  //   BEEV::ASTNode q = b->SimplifyFormula_TopLevel(*((nodestar)e),false);
+  //   b->Begin_RemoveWrites = false;    
+  q.PL_Print(cout);
+}
+
+void vc_printExprFile(VC vc, Expr e, int fd) {
+  fdostream os(fd);
+  ((nodestar)e)->PL_Print(os);
+  //os.flush();
+}
+
+static void vc_printVarDeclsToStream(VC vc, ostream &os) {
+  for(BEEV::ASTVec::iterator i = decls->begin(),iend=decls->end();i!=iend;i++) {
+    node a = *i;
+    switch(a.GetType()) {
+    case BEEV::BITVECTOR_TYPE:
+      a.PL_Print(os);
+      os << " : BITVECTOR(" << a.GetValueWidth() << ");" << endl;
+      break;
+    case BEEV::ARRAY_TYPE:
+      a.PL_Print(os);
+      os << " : ARRAY " << "BITVECTOR(" << a.GetIndexWidth() << ") OF ";
+      os << "BITVECTOR(" << a.GetValueWidth() << ");" << endl;
+      break;
+    case BEEV::BOOLEAN_TYPE:
+      a.PL_Print(os);
+      os << " : BOOLEAN;" << endl;
+      break;
+    default:
+      BEEV::FatalError("vc_printDeclsToStream: Unsupported type",a);
+      break;
+    }
+  }
+}
+
+void vc_printVarDecls(VC vc) {
+  vc_printVarDeclsToStream(vc, cout);
+}
+
+static void vc_printAssertsToStream(VC vc, ostream &os, int simplify_print) {
+  bmstar b = (bmstar)vc;
+  BEEV::ASTVec v = b->GetAsserts();
+  for(BEEV::ASTVec::iterator i=v.begin(),iend=v.end();i!=iend;i++) {
+    b->Begin_RemoveWrites = true;
+    BEEV::ASTNode q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(*i,false) : *i;
+    q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(q,false) : q;
+    b->Begin_RemoveWrites = false;
+    os << "ASSERT( ";
+    q.PL_Print(os);
+    os << ");" << endl;
+  }
+}
+
+void vc_printAsserts(VC vc, int simplify_print) {
+  vc_printAssertsToStream(vc, cout, simplify_print);
+}
+
+void vc_printQueryStateToBuffer(VC vc, Expr e, char **buf, unsigned long *len, int simplify_print){
+  assert(vc);
+  assert(e);
+  assert(buf);
+  assert(len);
+  bmstar b = (bmstar)vc;
+
+  // formate the state of the query
+  stringstream os;
+  vc_printVarDeclsToStream(vc, os);
+  os << "%----------------------------------------------------" << endl;
+  vc_printAssertsToStream(vc, os, simplify_print);
+  os << "%----------------------------------------------------" << endl;
+  os << "QUERY( ";
+  b->Begin_RemoveWrites = true;
+  BEEV::ASTNode q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(*((nodestar)e),false) : *(nodestar)e;
+  b->Begin_RemoveWrites = false;    
+  q.PL_Print(os);
+  os << " );" << endl;
+
+  // convert to a c buffer
+  string s = os.str();
+  const char *cstr = s.c_str();
+  unsigned long size = s.size() + 1; // number of chars + terminating null
+  *buf = (char *)malloc(size);
+  if (!(*buf)) {
+    fprintf(stderr, "malloc(%lu) failed.", size);
+    assert(*buf);
+  }
+  *len = size;
+  memcpy(*buf, cstr, size);
+}
+
+void vc_printCounterExampleToBuffer(VC vc, char **buf, unsigned long *len) {
+  assert(vc);
+  assert(buf);
+  assert(len);
+  bmstar b = (bmstar)vc;
+
+  // formate the state of the query
+  std::ostringstream os;
+  BEEV::print_counterexample = true;
+  os << "COUNTEREXAMPLE BEGIN: \n";
+  b->PrintCounterExample(true,os);
+  os << "COUNTEREXAMPLE END: \n";
+
+  // convert to a c buffer
+  string s = os.str();
+  const char *cstr = s.c_str();
+  unsigned long size = s.size() + 1; // number of chars + terminating null
+  *buf = (char *)malloc(size);
+  if (!(*buf)) {
+    fprintf(stderr, "malloc(%lu) failed.", size);
+    assert(*buf);
+  }
+  *len = size;
+  memcpy(*buf, cstr, size);
+}
+
+void vc_printExprToBuffer(VC vc, Expr e, char **buf, unsigned long * len) {
+  stringstream os;
+  //bmstar b = (bmstar)vc;
+  BEEV::ASTNode q = *((nodestar)e);
+  // b->Begin_RemoveWrites = true;
+  //   BEEV::ASTNode q = b->SimplifyFormula_TopLevel(*((nodestar)e),false);
+  //   b->Begin_RemoveWrites = false;    
+  q.PL_Print(os);
+  //((nodestar)e)->PL_Print(os);
+  string s = os.str();
+  const char * cstr = s.c_str();
+  unsigned long size = s.size() + 1; // number of chars + terminating null
+  *buf = (char *)malloc(size);
+  *len = size;
+  memcpy(*buf, cstr, size);
+}
+
+void vc_printQuery(VC vc){
+  ostream& os = std::cout;
+  bmstar b = (bmstar)vc;
+  os << "QUERY(";
+  //b->Begin_RemoveWrites = true;
+  //BEEV::ASTNode q = b->SimplifyFormula_TopLevel(b->GetQuery(),false);
+  BEEV::ASTNode q = b->GetQuery();
+  //b->Begin_RemoveWrites = false;    
+  q.PL_Print(os);
+  // b->GetQuery().PL_Print(os);
+  os << ");" << endl;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Array-related methods                                                   //
+/////////////////////////////////////////////////////////////////////////////
+//! Create an array type
+Type vc_arrayType(VC vc, Type typeIndex, Type typeData) {
+  bmstar b = (bmstar)vc;
+  nodestar ti = (nodestar)typeIndex;
+  nodestar td = (nodestar)typeData;
+
+  if(!(ti->GetKind() == BEEV::BITVECTOR && (*ti)[0].GetKind() == BEEV::BVCONST))
+    BEEV::FatalError("Tyring to build array whose indextype i is not a BITVECTOR, where i = ",*ti);
+  if(!(td->GetKind()  == BEEV::BITVECTOR && (*td)[0].GetKind() == BEEV::BVCONST))
+    BEEV::FatalError("Trying to build an array whose valuetype v is not a BITVECTOR. where a = ",*td);
+  nodestar output = new node(b->CreateNode(BEEV::ARRAY,(*ti)[0],(*td)[0]));
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return (Type)output;
+}
+
+//! Create an expression for the value of array at the given index
+Expr vc_readExpr(VC vc, Expr array, Expr index) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)array;
+  nodestar i = (nodestar)index;
+  
+  b->BVTypeCheck(*a);
+  b->BVTypeCheck(*i);
+  node o = b->CreateTerm(BEEV::READ,a->GetValueWidth(),*a,*i);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+// //! Array update; equivalent to "array WITH [index] := newValue"
+Expr vc_writeExpr(VC vc, Expr array, Expr index, Expr newValue) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)array;
+  nodestar i = (nodestar)index;
+  nodestar n = (nodestar)newValue;
+
+  b->BVTypeCheck(*a);
+  b->BVTypeCheck(*i);
+  b->BVTypeCheck(*n);
+  node o = b->CreateTerm(BEEV::WRITE,a->GetValueWidth(),*a,*i,*n);
+  o.SetIndexWidth(a->GetIndexWidth());
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Context-related methods                                                 //
+/////////////////////////////////////////////////////////////////////////////
+//! Assert a new formula in the current context.  
+/*! The formula must have Boolean type. */
+void vc_assertFormula(VC vc, Expr e) {
+  nodestar a = (nodestar)e;
+  bmstar b = (bmstar)vc;
+
+  if(!BEEV::is_Form_kind(a->GetKind()))
+    BEEV::FatalError("Trying to assert a NON formula: ",*a);
+
+  b->BVTypeCheck(*a);
+  b->AddAssert(*a);
+}
+
+//! Check validity of e in the current context.
+/*!  If the result is true, then the resulting context is the same as
+ * the starting context.  If the result is false, then the resulting
+ * context is a context in which e is false.  e must have Boolean
+ * type. */
+int vc_query(VC vc, Expr e) {
+  nodestar a = (nodestar)e;
+  bmstar b = (bmstar)vc;
+
+ if(!BEEV::is_Form_kind(a->GetKind()))
+    BEEV::FatalError("CInterface: Trying to QUERY a NON formula: ",*a);
+
+  b->BVTypeCheck(*a);
+  b->AddQuery(*a);
+
+  const BEEV::ASTVec v = b->GetAsserts();
+  node o;
+  if(!v.empty()) {
+    if(v.size()==1)
+      return b->TopLevelSAT(v[0],*a);
+    else 
+      return b->TopLevelSAT(b->CreateNode(BEEV::AND,v),*a);
+  }
+  else
+    return b->TopLevelSAT(b->CreateNode(BEEV::TRUE),*a);
+}
+
+void vc_push(VC vc) {
+  bmstar b = (bmstar)vc;
+  b->ClearAllCaches();
+  b->Push();
+}
+
+void vc_pop(VC vc) {
+  bmstar b = (bmstar)vc;
+  b->Pop();
+}
+
+void vc_printCounterExample(VC vc) {
+  bmstar b = (bmstar)vc;
+  BEEV::print_counterexample = true;    
+  cout << "COUNTEREXAMPLE BEGIN: \n";
+  b->PrintCounterExample(true);
+  cout << "COUNTEREXAMPLE END: \n";
+}
+
+// //! Return the counterexample after a failed query.
+// /*! This method should only be called after a query which returns
+//  * false.  It will try to return the simplest possible set of
+//  * assertions which are sufficient to make the queried expression
+//  * false.  The caller is responsible for freeing the array when
+//  * finished with it.
+//  */
+
+Expr vc_getCounterExample(VC vc, Expr e) {
+  nodestar a = (nodestar)e;
+  bmstar b = (bmstar)vc;    
+
+  bool t = false;
+  if(b->CounterExampleSize())
+    t = true;
+  nodestar output = new node(b->GetCounterExample(t, *a));  
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+int vc_counterexample_size(VC vc) {
+  bmstar b = (bmstar)vc;
+  return b->CounterExampleSize();
+}
+
+WholeCounterExample vc_getWholeCounterExample(VC vc) {
+  bmstar b = (bmstar)vc;
+  CompleteCEStar c = 
+    new BEEV::CompleteCounterExample(b->GetCompleteCounterExample(), b);
+  return c;
+}
+
+Expr vc_getTermFromCounterExample(VC vc, Expr e, CompleteCEStar cc) {
+  //bmstar b = (bmstar)vc;
+  nodestar n = (nodestar)e;
+  CompleteCEStar c = (CompleteCEStar)cc;
+
+  nodestar output = new node(c->GetCounterExample(*n));
+  return output;
+}
+
+int vc_getBVLength(VC vc, Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  if(BEEV::BITVECTOR_TYPE != e->GetType()) {
+    BEEV::FatalError("c_interface: vc_GetBVLength: Input expression must be a bit-vector");
+  }
+
+  return e->GetValueWidth();
+} // end of vc_getBVLength
+
+/////////////////////////////////////////////////////////////////////////////
+// Expr Creation methods                                                   //
+/////////////////////////////////////////////////////////////////////////////
+//! Create a variable with a given name and type 
+/*! The type cannot be a function type. */
+Expr vc_varExpr1(VC vc, char* name, 
+		int indexwidth, int valuewidth) {
+  bmstar b = (bmstar)vc;
+
+  node o = b->CreateSymbol(name);
+  o.SetIndexWidth(indexwidth);
+  o.SetValueWidth(valuewidth);
+  
+  nodestar output = new node(o);
+  ////if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  b->BVTypeCheck(*output);
+
+  //store the decls in a vector for printing purposes
+  decls->push_back(o);
+  return output;
+}
+
+Expr vc_varExpr(VC vc, char * name, Type type) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)type;
+
+  node o = b->CreateSymbol(name);
+  switch(a->GetKind()) {
+  case BEEV::BITVECTOR:
+    o.SetIndexWidth(0);
+    o.SetValueWidth(GetUnsignedConst((*a)[0]));
+    break;
+  case BEEV::ARRAY:
+    o.SetIndexWidth(GetUnsignedConst((*a)[0]));
+    o.SetValueWidth(GetUnsignedConst((*a)[1]));
+    break;
+  case BEEV::BOOLEAN:
+    o.SetIndexWidth(0);
+    o.SetValueWidth(0);
+    break;
+  default:
+    BEEV::FatalError("CInterface: vc_varExpr: Unsupported type",*a);
+    break;
+  }
+  nodestar output = new node(o);
+  ////if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  b->BVTypeCheck(*output);
+
+  //store the decls in a vector for printing purposes
+  decls->push_back(o);
+  return output;
+}
+
+//! Create an equality expression.  The two children must have the
+//same type.
+Expr vc_eqExpr(VC vc, Expr ccc0, Expr ccc1) {
+  bmstar b = (bmstar)vc;
+
+  nodestar a = (nodestar)ccc0;
+  nodestar aa = (nodestar)ccc1;
+  b->BVTypeCheck(*a);
+  b->BVTypeCheck(*aa);
+  node o = b->CreateNode(BEEV::EQ,*a,*aa);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_boolType(VC vc) {
+  bmstar b = (bmstar)vc;
+
+  node o = b->CreateNode(BEEV::BOOLEAN);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// BOOLEAN EXPR Creation methods                                           //
+/////////////////////////////////////////////////////////////////////////////
+// The following functions create Boolean expressions.  The children
+// provided as arguments must be of type Boolean.
+Expr vc_trueExpr(VC vc) {
+  bmstar b = (bmstar)vc;
+  node c = b->CreateNode(BEEV::TRUE);
+  
+  nodestar d = new node(c);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(d);
+  return d;
+}
+
+Expr vc_falseExpr(VC vc) {
+  bmstar b = (bmstar)vc;
+  node c = b->CreateNode(BEEV::FALSE);
+  
+  nodestar d = new node(c);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(d);
+  return d;
+}
+
+Expr vc_notExpr(VC vc, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  
+  node o = b->CreateNode(BEEV::NOT,*a);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_andExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+  
+  node o = b->CreateNode(BEEV::AND,*l,*r);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_orExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  node o = b->CreateNode(BEEV::OR,*l,*r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_andExprN(VC vc, Expr* cc, int n) {
+  bmstar b = (bmstar)vc;
+  nodestar * c = (nodestar *)cc;
+  nodelist d;
+  
+  for(int i =0; i < n; i++)
+    d.push_back(*c[i]);
+  
+  node o = b->CreateNode(BEEV::AND,d);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+
+Expr vc_orExprN(VC vc, Expr* cc, int n) {
+  bmstar b = (bmstar)vc;
+  nodestar * c = (nodestar *)cc;
+  nodelist d;
+  
+  for(int i =0; i < n; i++)
+    d.push_back(*c[i]);
+  
+  node o = b->CreateNode(BEEV::OR,d);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_iteExpr(VC vc, Expr cond, Expr thenpart, Expr elsepart){
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)cond;
+  nodestar t = (nodestar)thenpart;
+  nodestar e = (nodestar)elsepart;
+  
+  b->BVTypeCheck(*c);
+  b->BVTypeCheck(*t);
+  b->BVTypeCheck(*e);
+  node o;
+  //if the user asks for a formula then produce a formula, else
+  //prodcue a term
+  if(BEEV::BOOLEAN_TYPE == t->GetType())
+    o = b->CreateNode(BEEV::ITE,*c,*t,*e);
+  else {
+    o = b->CreateTerm(BEEV::ITE,t->GetValueWidth(),*c,*t,*e);
+    o.SetIndexWidth(t->GetIndexWidth());
+  }
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_impliesExpr(VC vc, Expr antecedent, Expr consequent){
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)antecedent;
+  nodestar t = (nodestar)consequent;
+  
+  b->BVTypeCheck(*c);
+  b->BVTypeCheck(*t);
+  node o;
+
+  o = b->CreateNode(BEEV::IMPLIES,*c,*t);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_iffExpr(VC vc, Expr e0, Expr e1){
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)e0;
+  nodestar t = (nodestar)e1;
+  
+  b->BVTypeCheck(*c);
+  b->BVTypeCheck(*t);
+  node o;
+
+  o = b->CreateNode(BEEV::IFF,*c,*t);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_boolToBVExpr(VC vc, Expr form) {
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)form;
+  
+  b->BVTypeCheck(*c);
+  if(!is_Form_kind(c->GetKind()))
+    BEEV::FatalError("CInterface: vc_BoolToBVExpr: You have input a NON formula:",*c);
+  
+  node o;
+  node one = b->CreateOneConst(1); 
+  node zero = b->CreateZeroConst(1);  
+  o = b->CreateTerm(BEEV::ITE,1,*c,one,zero);
+
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// BITVECTOR EXPR Creation methods                                         //
+/////////////////////////////////////////////////////////////////////////////
+Type vc_bvType(VC vc, int num_bits) {
+  bmstar b = (bmstar)vc;
+  
+  if(!(0 < num_bits))
+    BEEV::FatalError("CInterface: number of bits in a bvtype must be a positive integer:", 
+		     b->CreateNode(BEEV::UNDEFINED));
+
+  node e = b->CreateBVConst(32, num_bits);
+  nodestar output = new node(b->CreateNode(BEEV::BITVECTOR,e));
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Type vc_bv32Type(VC vc) {
+  return vc_bvType(vc,32);
+}
+
+
+Expr vc_bvConstExprFromStr(VC vc, char* binary_repr) {
+  bmstar b = (bmstar)vc;
+
+  node n = b->CreateBVConst(binary_repr,2);
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvConstExprFromInt(VC vc,
+			   int n_bits, 
+			   unsigned int value) {
+  bmstar b = (bmstar)vc;
+
+  unsigned long long int v = (unsigned long long int)value;
+  node n = b->CreateBVConst(n_bits, v);
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvConstExprFromLL(VC vc,
+			  int n_bits, 
+			  unsigned long long value) {
+  bmstar b = (bmstar)vc;
+  
+  node n = b->CreateBVConst(n_bits, value);
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvConcatExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o =
+    b->CreateTerm(BEEV::BVCONCAT,
+		  l->GetValueWidth()+ r->GetValueWidth(),*l,*r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvPlusExpr(VC vc, int n_bits, Expr left, Expr right){
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVPLUS,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+
+Expr vc_bv32PlusExpr(VC vc, Expr left, Expr right) {
+  return vc_bvPlusExpr(vc, 32, left, right);
+}
+
+
+Expr vc_bvMinusExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVSUB,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+
+Expr vc_bv32MinusExpr(VC vc, Expr left, Expr right) {
+  return vc_bvMinusExpr(vc, 32, left, right);
+}
+
+
+Expr vc_bvMultExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVMULT,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvDivExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVDIV,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvModExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVMOD,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvDivExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::SBVDIV,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvModExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::SBVMOD,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bv32MultExpr(VC vc, Expr left, Expr right) {
+  return vc_bvMultExpr(vc, 32, left, right);
+}
+
+
+// unsigned comparators
+Expr vc_bvLtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVLT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvLeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVLE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvGtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVGT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvGeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVGE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+// signed comparators
+Expr vc_sbvLtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSLT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvLeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSLE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvGtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSGT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvGeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSGE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvUMinusExpr(VC vc, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  node o = b->CreateTerm(BEEV::BVUMINUS, a->GetValueWidth(), *a);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+// bitwise operations: these are terms not formulas
+Expr vc_bvAndExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVAND, (*l).GetValueWidth(), *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvOrExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVOR, (*l).GetValueWidth(), *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvXorExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVXOR, (*l).GetValueWidth(), *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvNotExpr(VC vc, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+
+  b->BVTypeCheck(*a);
+  node o = b->CreateTerm(BEEV::BVNEG, a->GetValueWidth(), *a);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvLeftShiftExpr(VC vc, int sh_amt, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  //convert leftshift to bvconcat
+  if(0 != sh_amt) {
+    node len = b->CreateBVConst(sh_amt, 0);
+    node o = b->CreateTerm(BEEV::BVCONCAT, a->GetValueWidth() + sh_amt, *a, len);
+    b->BVTypeCheck(o);
+    nodestar output = new node(o);
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+  else
+    return a;
+}
+
+Expr vc_bvRightShiftExpr(VC vc, int sh_amt, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+  
+  unsigned int w = a->GetValueWidth();  
+  //the amount by which you are rightshifting
+  //is less-than/equal-to the length of input
+  //bitvector  
+  if(0 < (unsigned)sh_amt && (unsigned)sh_amt <= w) {
+    node len = b->CreateBVConst(sh_amt, 0);
+    node hi = b->CreateBVConst(32,w-1);
+    node low = b->CreateBVConst(32,sh_amt);
+    node extract = b->CreateTerm(BEEV::BVEXTRACT,w-sh_amt,*a,hi,low);
+
+    node n = b->CreateTerm(BEEV::BVCONCAT, w,len, extract);
+    b->BVTypeCheck(n);
+    nodestar output = new node(n);
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+  else if(sh_amt == 0)
+    return a;
+  else {
+    if(0== w)
+      BEEV::FatalError("CInterface: vc_bvRightShiftExpr: cannot have a bitvector of length 0:",*a);
+    nodestar output = new node(b->CreateBVConst(w,0));
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+}
+
+/* Same as vc_bvLeftShift only that the answer in 32 bits long */
+Expr vc_bv32LeftShiftExpr(VC vc, int sh_amt, Expr child) {
+  return vc_bvExtract(vc, vc_bvLeftShiftExpr(vc, sh_amt, child), 31, 0);
+}
+
+/* Same as vc_bvRightShift only that the answer in 32 bits long */
+Expr vc_bv32RightShiftExpr(VC vc, int sh_amt, Expr child) {
+  return vc_bvExtract(vc, vc_bvRightShiftExpr(vc, sh_amt, child), 31, 0);
+}
+
+
+Expr vc_bvVar32LeftShiftExpr(VC vc, Expr sh_amt, Expr child) {
+  Expr ifpart;
+  Expr thenpart;
+  Expr elsepart = vc_trueExpr(vc);
+  Expr ite = vc_trueExpr(vc);
+
+  for(int count=32; count >= 0; count--){
+    if(count != 32) {
+      ifpart = vc_eqExpr(vc, sh_amt, 
+			 vc_bvConstExprFromInt(vc, 32, count));
+      thenpart = vc_bvExtract(vc,
+			      vc_bvLeftShiftExpr(vc, count, child),
+			      31, 0);
+
+      ite = vc_iteExpr(vc,ifpart,thenpart,elsepart);
+      elsepart = ite;
+    } 
+    else
+      elsepart = vc_bvConstExprFromInt(vc,32, 0);    
+  }  
+  return ite;  
+}
+
+Expr vc_bvVar32DivByPowOfTwoExpr(VC vc, Expr child, Expr rhs) {
+  Expr ifpart;
+  Expr thenpart;
+  Expr elsepart = vc_trueExpr(vc);
+  Expr ite = vc_trueExpr(vc);
+
+  for(int count=32; count >= 0; count--){
+    if(count != 32) {
+      ifpart = vc_eqExpr(vc, rhs, 
+			 vc_bvConstExprFromInt(vc, 32, 1 << count));      
+      thenpart = vc_bvRightShiftExpr(vc, count, child);      
+      ite = vc_iteExpr(vc,ifpart,thenpart,elsepart);
+      elsepart = ite;
+    } else {
+      elsepart = vc_bvConstExprFromInt(vc,32, 0);
+    }    
+  }  
+  return ite;  
+}
+
+Expr vc_bvVar32RightShiftExpr(VC vc, Expr sh_amt, Expr child) {
+  Expr ifpart;
+  Expr thenpart;
+  Expr elsepart = vc_trueExpr(vc);
+  Expr ite = vc_trueExpr(vc);
+
+  for(int count=32; count >= 0; count--){
+    if(count != 32) {
+      ifpart = vc_eqExpr(vc, sh_amt, 
+			 vc_bvConstExprFromInt(vc, 32, count));      
+      thenpart = vc_bvRightShiftExpr(vc, count, child);      
+      ite = vc_iteExpr(vc,ifpart,thenpart,elsepart);
+      elsepart = ite;
+    } else {
+      elsepart = vc_bvConstExprFromInt(vc,32, 0);
+    }    
+  }  
+  return ite;  
+}
+
+Expr vc_bvExtract(VC vc, Expr ccc, int hi_num, int low_num) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  node hi = b->CreateBVConst(32,hi_num);
+  node low = b->CreateBVConst(32,low_num);
+  node o = b->CreateTerm(BEEV::BVEXTRACT,hi_num-low_num+1,*a,hi,low);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvBoolExtract(VC vc, Expr ccc, int bit_num) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  node bit = b->CreateBVConst(32,bit_num);
+  //node o = b->CreateNode(BEEV::BVGETBIT,*a,bit);  
+  node zero = b->CreateBVConst(1,0);
+  node oo = b->CreateTerm(BEEV::BVEXTRACT,1,*a,bit,bit);
+  node o = b->CreateNode(BEEV::EQ,oo,zero);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output; 
+}
+
+Expr vc_bvSignExtend(VC vc, Expr ccc, int nbits) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  
+  //width of the expr which is being sign extended. nbits is the
+  //resulting length of the signextended expr
+  b->BVTypeCheck(*a);
+  
+  unsigned exprlen = a->GetValueWidth();
+  unsigned outputlen = nbits;
+  node n;
+  if(exprlen >= outputlen) {
+    //extract
+    node hi = b->CreateBVConst(32,outputlen-1);
+    node low = b->CreateBVConst(32,0);
+    n = b->CreateTerm(BEEV::BVEXTRACT,nbits,*a,hi,low);
+    b->BVTypeCheck(n);
+  }
+  else {
+    //sign extend
+    BEEV::ASTNode width = b->CreateBVConst(32,nbits);
+    n = b->CreateTerm(BEEV::BVSX,nbits,*a, width);
+  }
+
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+//! Return an int from a constant bitvector expression
+int getBVInt(Expr e) {
+  //bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BVCONST != a->GetKind())
+    BEEV::FatalError("CInterface: getBVInt: Attempting to extract int value from a NON-constant BITVECTOR: ",*a);
+  return (int)GetUnsignedConst(*a);
+}
+
+//! Return an unsigned int from a constant bitvector expression
+unsigned int getBVUnsigned(Expr e) {
+  //bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BVCONST != a->GetKind())
+    BEEV::FatalError("getBVUnsigned: Attempting to extract int value from a NON-constant BITVECTOR: ",*a);
+  return (unsigned int)GetUnsignedConst(*a);
+}
+
+//! Return an unsigned long long int from a constant bitvector expression
+unsigned long long int getBVUnsignedLongLong(Expr e) {
+  //bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BVCONST != a->GetKind())
+    BEEV::FatalError("getBVUnsigned: Attempting to extract int value from a NON-constant BITVECTOR: ",*a);
+#ifdef NATIVE_C_ARITH
+  return (unsigned long long int)a->GetBVConst();
+#else
+  unsigned* bv = a->GetBVConst();
+
+  char * str_bv  = (char *)CONSTANTBV::BitVector_to_Bin(bv);
+  unsigned long long int tmp = strtoull(str_bv,NULL,2);
+  CONSTANTBV::BitVector_Dispose((unsigned char *)str_bv);
+  return tmp;
+#endif
+}
+
+
+Expr vc_simplify(VC vc, Expr e) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BOOLEAN_TYPE == a->GetType()) {
+    nodestar output = new node(b->SimplifyFormula_TopLevel(*a,false));
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    b->Begin_RemoveWrites = true;
+    output = new node(b->SimplifyFormula_TopLevel(*output,false));
+    b->Begin_RemoveWrites = false;
+    return output;    
+  }
+  else {
+    nodestar output = new node(b->SimplifyTerm(*a));
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    b->Begin_RemoveWrites = true;
+    output = new node(b->SimplifyTerm(*output));
+    b->Begin_RemoveWrites = false;
+    return output;
+  }
+}
+
+/* C pointer support: C interface to support C memory arrays in CVCL */
+Expr vc_bvCreateMemoryArray(VC vc, char * arrayName) {
+  Type bv8  = vc_bvType(vc,8);
+  Type bv32 = vc_bvType(vc,32);
+  
+  Type malloced_mem0 = vc_arrayType(vc,bv32,bv8);
+  return vc_varExpr(vc, arrayName, malloced_mem0);
+}
+
+Expr vc_bvReadMemoryArray(VC vc, 
+			  Expr array, 
+			  Expr byteIndex, int numOfBytes) {
+  if(!(numOfBytes > 0))
+    BEEV::FatalError("numOfBytes must be greater than 0");
+
+  if(numOfBytes == 1)
+    return vc_readExpr(vc,array,byteIndex);
+  else {
+    int count = 1;
+    Expr a = vc_readExpr(vc,array,byteIndex);
+    while(--numOfBytes > 0) {
+      Expr b = vc_readExpr(vc,array,
+			   /*vc_simplify(vc, */
+				       vc_bvPlusExpr(vc, 32, 
+						     byteIndex,
+						     vc_bvConstExprFromInt(vc,32,count)))/*)*/;
+      a = vc_bvConcatExpr(vc,b,a);
+      count++;
+    }
+    return a;
+  }    
+}
+
+Expr vc_bvWriteToMemoryArray(VC vc, 
+			     Expr array, Expr byteIndex, 
+			     Expr element, int numOfBytes) {
+  if(!(numOfBytes > 0))
+    BEEV::FatalError("numOfBytes must be greater than 0");
+	    
+  int newBitsPerElem = numOfBytes*8;
+  if(numOfBytes == 1)
+    return vc_writeExpr(vc, array, byteIndex, element);
+  else {
+    int count = 1;
+    int hi = newBitsPerElem - 1;
+    int low = newBitsPerElem - 8;
+    int low_elem = 0;
+    int hi_elem = low_elem + 7;
+    Expr c = vc_bvExtract(vc, element, hi_elem, low_elem);
+    Expr newarray = vc_writeExpr(vc, array, byteIndex, c);
+    while(--numOfBytes > 0) {
+      hi = low-1;
+      low = low-8;      
+
+      low_elem = low_elem + 8;
+      hi_elem = low_elem + 7;
+
+      c = vc_bvExtract(vc, element, hi_elem, low_elem);
+      newarray = 
+	vc_writeExpr(vc, newarray,
+		     vc_bvPlusExpr(vc, 32, byteIndex, vc_bvConstExprFromInt(vc,32,count)),
+		     c);
+      count++;
+    }
+    return newarray;
+  }    
+}
+
+Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value){
+  return vc_bvConstExprFromInt(vc, 32, value);
+}
+
+
+#if 0
+static char *val_to_binary_str(unsigned nbits, unsigned long long val) {
+        char s[65];
+
+	assert(nbits < sizeof s);
+        strcpy(s, "");
+        while(nbits-- > 0) {
+                if((val >> nbits) & 1)
+                        strcat(s, "1");
+                else
+                        strcat(s, "0");
+        }
+        return strdup(s);
+}
+#endif
+
+char* exprString(Expr e){
+  stringstream ss;
+  ((nodestar)e)->PL_Print(ss,0);
+  string s = ss.str();
+  char *copy = strdup(s.c_str());
+  return copy;
+}
+
+char* typeString(Type t){
+  stringstream ss;
+  ((nodestar)t)->PL_Print(ss,0);
+
+  string s = ss.str();
+  char *copy = strdup(s.c_str());
+  return copy;
+}
+
+Expr getChild(Expr e, int i){
+  nodestar a = (nodestar)e;
+
+  BEEV::ASTVec c = a->GetChildren();
+  if(0 <=  (unsigned)i && (unsigned)i < c.size()) {
+    BEEV::ASTNode o = c[i];
+    nodestar output = new node(o);
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+  else 
+    BEEV::FatalError("getChild: Error accessing childNode in expression: ",*a);
+  return a;
+}
+
+void vc_registerErrorHandler(void (*error_hdlr)(const char* err_msg)) {
+  BEEV::vc_error_hdlr = error_hdlr;
+}
+
+
+int vc_getHashQueryStateToBuffer(VC vc, Expr query) {
+  assert(vc);
+  assert(query);
+  bmstar b = (bmstar)vc;
+  nodestar qry = (nodestar)query;
+  BEEV::ASTVec v = b->GetAsserts(); 
+  BEEV::ASTNode out = b->CreateNode(BEEV::AND,b->CreateNode(BEEV::NOT,*qry),v);
+  return out.Hash();
+}
+
+Type vc_getType(VC vc, Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  switch(e->GetType()) {
+  case BEEV::BOOLEAN_TYPE:
+    return vc_boolType(vc);
+    break;      
+  case BEEV::BITVECTOR_TYPE:
+    return vc_bvType(vc,e->GetValueWidth());
+    break;
+  case BEEV::ARRAY_TYPE: {
+    Type typeindex = vc_bvType(vc,e->GetIndexWidth());
+    Type typedata = vc_bvType(vc,e->GetValueWidth());
+    return vc_arrayType(vc,typeindex,typedata);
+    break;
+  }
+  default:
+    BEEV::FatalError("c_interface: vc_GetType: expression with bad typing: please check your expression construction");
+    return vc_boolType(vc);
+    break;
+  }
+}// end of vc_gettype()
+
+//!if e is TRUE then return 1; if e is FALSE then return 0; otherwise
+//return -1
+int vc_isBool(Expr e) {
+  nodestar input = (nodestar)e;
+  if(BEEV::TRUE == input->GetKind()) {
+    return 1;
+  }
+
+  if(BEEV::FALSE == input->GetKind()) {
+    return 0;
+  }
+
+  return -1;
+}
+
+void vc_Destroy(VC vc) {
+  bmstar b = (bmstar)vc;
+  // for(std::vector<BEEV::ASTNode *>::iterator it=created_exprs.begin(),
+  // 	itend=created_exprs.end();it!=itend;it++) {
+  //     BEEV::ASTNode * aaa = *it;
+  //     delete aaa;
+  //   }
+  delete decls;
+  delete b;
+}
+
+void vc_DeleteExpr(Expr e) {
+  nodestar input = (nodestar)e;
+  //bmstar b = (bmstar)vc;
+  delete input;
+}
+
+exprkind_t getExprKind(Expr e) {
+  nodestar input = (nodestar)e;
+  return (exprkind_t)(input->GetKind());  
+}
+
+int getDegree (Expr e) {
+  nodestar input = (nodestar)e;
+  return input->Degree();
+}
+
+int getBVLength(Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  if(BEEV::BITVECTOR_TYPE != e->GetType()) {
+    BEEV::FatalError("c_interface: vc_GetBVLength: Input expression must be a bit-vector");
+  }
+
+  return e->GetValueWidth();
+} 
+
+type_t getType (Expr ex) {
+  nodestar e = (nodestar)ex;
+    
+  return (type_t)(e->GetType());
+}
+
+int getVWidth (Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  return e->GetValueWidth();
+}
+
+int getIWidth (Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  return e->GetIndexWidth();
+}
+
+void vc_printCounterExampleFile(VC vc, int fd) {
+  fdostream os(fd);
+  bmstar b = (bmstar)vc;
+  BEEV::print_counterexample = true;    
+  os << "COUNTEREXAMPLE BEGIN: \n";
+  b->PrintCounterExample(true, os);
+  os << "COUNTEREXAMPLE END: \n";
+}
+
+const char* exprName(Expr e){
+    return ((nodestar)e)->GetName();
+}
+
+int getExprID (Expr ex) {
+    BEEV::ASTNode q = (*(nodestar)ex);
+
+    return q.GetNodeNum();
+}

Added: klee/trunk/stp/c_interface/c_interface.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/c_interface/c_interface.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/c_interface/c_interface.h (added)
+++ klee/trunk/stp/c_interface/c_interface.h Wed May 20 23:36:41 2009
@@ -0,0 +1,401 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * License to use, copy, modify, sell and/or distribute this software
+ * and its documentation for any purpose is hereby granted without
+ * royalty, subject to the terms and conditions defined in the \ref
+ * LICENSE file provided with this distribution.  In particular:
+ *
+ * - The above copyright notice and this permission notice must appear
+ * in all copies of the software and related documentation.
+ *
+ * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
+ * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
+ ********************************************************************/
+// -*- c++ -*-
+#ifndef _cvcl__include__c_interface_h_
+#define _cvcl__include__c_interface_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+#ifdef STP_STRONG_TYPING
+#else
+  //This gives absolutely no pointer typing at compile-time. Most C
+  //users prefer this over stronger typing. User is the king. A
+  //stronger typed interface is in the works.
+  typedef void* VC;
+  typedef void* Expr;
+  typedef void* Type;
+  typedef void* WholeCounterExample;
+#endif
+
+  // o  : optimizations
+  // c  : check counterexample
+  // p  : print counterexample
+  // h  : help
+  // s  : stats
+  // v  : print nodes
+  void vc_setFlags(char c);
+  
+  //! Flags can be NULL
+  VC vc_createValidityChecker(void);
+  
+  // Basic types
+  Type vc_boolType(VC vc);
+  
+  //! Create an array type
+  Type vc_arrayType(VC vc, Type typeIndex, Type typeData);
+
+  /////////////////////////////////////////////////////////////////////////////
+  // Expr manipulation methods                                               //
+  /////////////////////////////////////////////////////////////////////////////
+
+  //! Create a variable with a given name and type 
+  /*! The type cannot be a function type. The var name can contain
+    only variables, numerals and underscore. If you use any other
+    symbol, you will get a segfault. */  
+  Expr vc_varExpr(VC vc, char * name, Type type);
+
+  //The var name can contain only variables, numerals and
+  //underscore. If you use any other symbol, you will get a segfault.
+  Expr vc_varExpr1(VC vc, char* name, 
+		  int indexwidth, int valuewidth);
+
+  //! Get the expression and type associated with a name.
+  /*!  If there is no such Expr, a NULL Expr is returned. */
+  //Expr vc_lookupVar(VC vc, char* name, Type* type);
+  
+  //! Get the type of the Expr.
+  Type vc_getType(VC vc, Expr e);
+  
+  int vc_getBVLength(VC vc, Expr e);
+
+  //! Create an equality expression.  The two children must have the same type.
+  Expr vc_eqExpr(VC vc, Expr child0, Expr child1);
+  
+  // Boolean expressions
+  
+  // The following functions create Boolean expressions.  The children
+  // provided as arguments must be of type Boolean (except for the
+  // function vc_iteExpr(). In the case of vc_iteExpr() the
+  // conditional must always be Boolean, but the ifthenpart
+  // (resp. elsepart) can be bit-vector or Boolean type. But, the
+  // ifthenpart and elsepart must be both of the same type)
+  Expr vc_trueExpr(VC vc);
+  Expr vc_falseExpr(VC vc);
+  Expr vc_notExpr(VC vc, Expr child);
+  Expr vc_andExpr(VC vc, Expr left, Expr right);
+  Expr vc_andExprN(VC vc, Expr* children, int numOfChildNodes);
+  Expr vc_orExpr(VC vc, Expr left, Expr right);
+  Expr vc_orExprN(VC vc, Expr* children, int numOfChildNodes);
+  Expr vc_impliesExpr(VC vc, Expr hyp, Expr conc);
+  Expr vc_iffExpr(VC vc, Expr left, Expr right);
+  //The output type of vc_iteExpr can be Boolean (formula-level ite)
+  //or bit-vector (word-level ite)
+  Expr vc_iteExpr(VC vc, Expr conditional, Expr ifthenpart, Expr elsepart);
+  
+  //Boolean to single bit BV Expression
+  Expr vc_boolToBVExpr(VC vc, Expr form);
+
+  // Arrays
+  
+  //! Create an expression for the value of array at the given index
+  Expr vc_readExpr(VC vc, Expr array, Expr index);
+
+  //! Array update; equivalent to "array WITH [index] := newValue"
+  Expr vc_writeExpr(VC vc, Expr array, Expr index, Expr newValue);
+  
+  // Expr I/O
+  //! Expr vc_parseExpr(VC vc, char* s);
+
+  //! Prints 'e' to stdout.
+  void vc_printExpr(VC vc, Expr e);
+
+  //! Prints 'e' into an open file descriptor 'fd'
+  void vc_printExprFile(VC vc, Expr e, int fd);
+
+  //! Prints state of 'vc' into malloc'd buffer '*buf' and stores the 
+  //  length into '*len'.  It is the responsibility of the caller to 
+  //  free the buffer.
+  //void vc_printStateToBuffer(VC vc, char **buf, unsigned long *len);
+
+  //! Prints 'e' to malloc'd buffer '*buf'.  Sets '*len' to the length of 
+  //  the buffer. It is the responsibility of the caller to free the buffer.
+  void vc_printExprToBuffer(VC vc, Expr e, char **buf, unsigned long * len);
+
+  //! Prints counterexample to stdout.
+  void vc_printCounterExample(VC vc);
+
+  //! Prints variable declarations to stdout.
+  void vc_printVarDecls(VC vc);
+
+  //! Prints asserts to stdout. The flag simplify_print must be set to
+  //"1" if you wish simplification to occur dring printing. It must be
+  //set to "0" otherwise
+  void vc_printAsserts(VC vc, int simplify_print);
+
+  //! Prints the state of the query to malloc'd buffer '*buf' and
+  //stores ! the length of the buffer to '*len'.  It is the
+  //responsibility of the caller to free the buffer. The flag
+  //simplify_print must be set to "1" if you wish simplification to
+  //occur dring printing. It must be set to "0" otherwise
+  void vc_printQueryStateToBuffer(VC vc, Expr e, 
+				  char **buf, unsigned long *len, int simplify_print);
+
+  //! Similar to vc_printQueryStateToBuffer()
+  void vc_printCounterExampleToBuffer(VC vc, char **buf,unsigned long *len);
+
+  //! Prints query to stdout.
+  void vc_printQuery(VC vc);
+
+  /////////////////////////////////////////////////////////////////////////////
+  // Context-related methods                                                 //
+  /////////////////////////////////////////////////////////////////////////////
+  
+  //! Assert a new formula in the current context.  
+  /*! The formula must have Boolean type. */
+  void vc_assertFormula(VC vc, Expr e);
+  
+  //! Simplify e with respect to the current context
+  Expr vc_simplify(VC vc, Expr e);
+
+  //! Check validity of e in the current context. e must be a FORMULA
+  //
+  //if returned 0 then input is INVALID. 
+  //
+  //if returned 1 then input is VALID
+  //
+  //if returned 2 then ERROR
+  int vc_query(VC vc, Expr e);
+  
+  //! Return the counterexample after a failed query.
+  Expr vc_getCounterExample(VC vc, Expr e);
+
+  //! get size of counterexample, i.e. the number of variables/array
+  //locations in the counterexample.
+  int vc_counterexample_size(VC vc);
+  
+  //! Checkpoint the current context and increase the scope level
+  void vc_push(VC vc);
+  
+  //! Restore the current context to its state at the last checkpoint
+  void vc_pop(VC vc);
+  
+  //! Return an int from a constant bitvector expression
+  int getBVInt(Expr e);
+  //! Return an unsigned int from a constant bitvector expression
+  unsigned int getBVUnsigned(Expr e);
+  //! Return an unsigned long long int from a constant bitvector expressions
+  unsigned long long int getBVUnsignedLongLong(Expr e);
+  
+  /**************************/
+  /* BIT VECTOR OPERATIONS  */
+  /**************************/
+  Type vc_bvType(VC vc, int no_bits);
+  Type vc_bv32Type(VC vc);
+  
+  Expr vc_bvConstExprFromStr(VC vc, char* binary_repr);
+  Expr vc_bvConstExprFromInt(VC vc, int n_bits, unsigned int value);
+  Expr vc_bvConstExprFromLL(VC vc, int n_bits, unsigned long long value);
+  Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value);
+  
+  Expr vc_bvConcatExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvPlusExpr(VC vc, int n_bits, Expr left, Expr right);
+  Expr vc_bv32PlusExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvMinusExpr(VC vc, int n_bits, Expr left, Expr right);
+  Expr vc_bv32MinusExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvMultExpr(VC vc, int n_bits, Expr left, Expr right);
+  Expr vc_bv32MultExpr(VC vc, Expr left, Expr right);
+  // left divided by right i.e. left/right
+  Expr vc_bvDivExpr(VC vc, int n_bits, Expr left, Expr right);
+  // left modulo right i.e. left%right
+  Expr vc_bvModExpr(VC vc, int n_bits, Expr left, Expr right);
+  // signed left divided by right i.e. left/right
+  Expr vc_sbvDivExpr(VC vc, int n_bits, Expr left, Expr right);
+  // signed left modulo right i.e. left%right
+  Expr vc_sbvModExpr(VC vc, int n_bits, Expr left, Expr right);
+  
+  Expr vc_bvLtExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvLeExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvGtExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvGeExpr(VC vc, Expr left, Expr right);
+  
+  Expr vc_sbvLtExpr(VC vc, Expr left, Expr right);
+  Expr vc_sbvLeExpr(VC vc, Expr left, Expr right);
+  Expr vc_sbvGtExpr(VC vc, Expr left, Expr right);
+  Expr vc_sbvGeExpr(VC vc, Expr left, Expr right);
+  
+  Expr vc_bvUMinusExpr(VC vc, Expr child);
+
+  // bitwise operations: these are terms not formulas  
+  Expr vc_bvAndExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvOrExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvXorExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvNotExpr(VC vc, Expr child);
+  
+  Expr vc_bvLeftShiftExpr(VC vc, int sh_amt, Expr child);
+  Expr vc_bvRightShiftExpr(VC vc, int sh_amt, Expr child);
+  /* Same as vc_bvLeftShift only that the answer in 32 bits long */
+  Expr vc_bv32LeftShiftExpr(VC vc, int sh_amt, Expr child);
+  /* Same as vc_bvRightShift only that the answer in 32 bits long */
+  Expr vc_bv32RightShiftExpr(VC vc, int sh_amt, Expr child);
+  Expr vc_bvVar32LeftShiftExpr(VC vc, Expr sh_amt, Expr child);
+  Expr vc_bvVar32RightShiftExpr(VC vc, Expr sh_amt, Expr child);
+  Expr vc_bvVar32DivByPowOfTwoExpr(VC vc, Expr child, Expr rhs);
+
+  Expr vc_bvExtract(VC vc, Expr child, int high_bit_no, int low_bit_no);
+  
+  //accepts a bitvector and position, and returns a boolean
+  //corresponding to that position. More precisely, it return the
+  //equation (x[bit_no:bit_no] = 0)
+  //FIXME  = 1 ?
+  Expr vc_bvBoolExtract(VC vc, Expr x, int bit_no);  
+  Expr vc_bvSignExtend(VC vc, Expr child, int nbits);
+  
+  /*C pointer support:  C interface to support C memory arrays in CVCL */
+  Expr vc_bvCreateMemoryArray(VC vc, char * arrayName);
+  Expr vc_bvReadMemoryArray(VC vc, 
+			  Expr array, Expr byteIndex, int numOfBytes);
+  Expr vc_bvWriteToMemoryArray(VC vc, 
+			       Expr array, Expr  byteIndex, 
+			       Expr element, int numOfBytes);
+  Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value);
+  
+  // return a string representation of the Expr e. The caller is responsible
+  // for deallocating the string with free()
+  char* exprString(Expr e);
+  
+  // return a string representation of the Type t. The caller is responsible
+  // for deallocating the string with free()
+  char* typeString(Type t);
+
+  Expr getChild(Expr e, int i);
+
+  //1.if input expr is TRUE then the function returns 1;
+  //
+  //2.if input expr is FALSE then function returns 0;
+  //
+  //3.otherwise the function returns -1
+  int vc_isBool(Expr e);
+
+  /* Register the given error handler to be called for each fatal error.*/
+  void vc_registerErrorHandler(void (*error_hdlr)(const char* err_msg));
+
+  int vc_getHashQueryStateToBuffer(VC vc, Expr query);
+
+  //destroys the STP instance, and removes all the created expressions
+  void vc_Destroy(VC vc);
+
+  //deletes the expression e
+  void vc_DeleteExpr(Expr e);
+
+  //Get the whole counterexample from the current context
+  WholeCounterExample vc_getWholeCounterExample(VC vc);
+
+  //Get the value of a term expression from the CounterExample
+  Expr vc_getTermFromCounterExample(VC vc, Expr e, WholeCounterExample c);
+
+  //Kinds of Expr
+  enum exprkind_t{
+      UNDEFINED,
+      SYMBOL,
+      BVCONST,
+      BVNEG,
+      BVCONCAT,
+      BVOR,
+      BVAND,
+      BVXOR,
+      BVNAND,
+      BVNOR,
+      BVXNOR,
+      BVEXTRACT,
+      BVLEFTSHIFT,
+      BVRIGHTSHIFT,
+      BVSRSHIFT,
+      BVVARSHIFT,
+      BVPLUS,
+      BVSUB,
+      BVUMINUS,
+      BVMULTINVERSE,
+      BVMULT,
+      BVDIV,
+      BVMOD,
+      SBVDIV,
+      SBVMOD,
+      BVSX,
+      BOOLVEC,
+      ITE,
+      BVGETBIT,
+      BVLT,
+      BVLE,
+      BVGT,
+      BVGE,
+      BVSLT,
+      BVSLE,
+      BVSGT,
+      BVSGE,
+      EQ,
+      NEQ,
+      FALSE,
+      TRUE,
+      NOT,
+      AND,
+      OR,
+      NAND,
+      NOR,
+      XOR,
+      IFF,
+      IMPLIES,
+      READ,
+      WRITE,
+      ARRAY,
+      BITVECTOR,
+      BOOLEAN
+  };
+
+  // type of expression
+  enum type_t {
+      BOOLEAN_TYPE = 0,
+      BITVECTOR_TYPE,
+      ARRAY_TYPE,
+      UNKNOWN_TYPE
+  };
+
+  // get the kind of the expression
+  exprkind_t getExprKind (Expr e);
+
+  // get the number of children nodes
+  int getDegree (Expr e);
+
+  // get the bv length
+  int getBVLength(Expr e);
+
+  // get expression type
+  type_t getType (Expr e);
+
+  // get value bit width
+  int getVWidth (Expr e);
+
+  // get index bit width
+  int getIWidth (Expr e);
+
+  // Prints counterexample to an open file descriptor 'fd'
+  void vc_printCounterExampleFile(VC vc, int fd);
+
+  // get name of expression. must be a variable.
+  const char* exprName(Expr e);
+  
+  // get the node ID of an Expr.
+  int getExprID (Expr ex);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+

Added: klee/trunk/stp/c_interface/fdstream.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/c_interface/fdstream.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/c_interface/fdstream.h (added)
+++ klee/trunk/stp/c_interface/fdstream.h Wed May 20 23:36:41 2009
@@ -0,0 +1,186 @@
+/*! @brief The following code declares classes to read from and write to
+ * file descriptore or file handles.
+ *
+ * See
+ *      http://www.josuttis.com/cppcode
+ * for details and the latest version.
+ *
+ * - open:
+ *      - integrating BUFSIZ on some systems?
+ *      - optimized reading of multiple characters
+ *      - stream for reading AND writing
+ *      - i18n
+ *
+ * (C) Copyright Nicolai M. Josuttis 2001.
+ * Permission to copy, use, modify, sell and distribute this software
+ * is granted provided this copyright notice appears in all copies.
+ * This software is provided "as is" without express or implied
+ * warranty, and with no claim as to its suitability for any purpose.
+ *
+ * Version: Jul 28, 2002
+ * History:
+ *  Jul 28, 2002: bugfix memcpy() => memmove()
+ *                fdinbuf::underflow(): cast for return statements
+ *  Aug 05, 2001: first public version
+ */
+#ifndef BOOST_FDSTREAM_HPP
+#define BOOST_FDSTREAM_HPP
+
+#include <istream>
+#include <ostream>
+#include <streambuf>
+
+
+// for EOF:
+#include <cstdio>
+// for memmove():
+#include <cstring>
+
+
+// low-level read and write functions
+#ifdef _MSC_VER
+# include <io.h>
+#else
+# include <unistd.h>
+//extern "C" {
+//    int write (int fd, const char* buf, int num);
+//    int read (int fd, char* buf, int num);
+//}
+#endif
+
+
+// BEGIN namespace BOOST
+namespace std {
+
+
+/************************************************************
+ * fdostream
+ * - a stream that writes on a file descriptor
+ ************************************************************/
+
+
+class fdoutbuf : public std::streambuf {
+  protected:
+    int fd;    // file descriptor
+  public:
+    // constructor
+    fdoutbuf (int _fd) : fd(_fd) {
+    }
+  protected:
+    // write one character
+    virtual int_type overflow (int_type c) {
+        if (c != EOF) {
+            char z = c;
+            if (write (fd, &z, 1) != 1) {
+                return EOF;
+            }
+        }
+        return c;
+    }
+    // write multiple characters
+    virtual
+    std::streamsize xsputn (const char* s,
+                            std::streamsize num) {
+        return write(fd,s,num);
+    }
+};
+
+class fdostream : public std::ostream {
+  protected:
+    fdoutbuf buf;
+  public:
+    fdostream (int fd) : std::ostream(0), buf(fd) {
+        rdbuf(&buf);
+    }
+};
+
+
+/************************************************************
+ * fdistream
+ * - a stream that reads on a file descriptor
+ ************************************************************/
+
+class fdinbuf : public std::streambuf {
+  protected:
+    int fd;    // file descriptor
+  protected:
+    /* data buffer:
+     * - at most, pbSize characters in putback area plus
+     * - at most, bufSize characters in ordinary read buffer
+     */
+    static const int pbSize = 4;        // size of putback area
+    static const int bufSize = 1024;    // size of the data buffer
+    char buffer[bufSize+pbSize];        // data buffer
+
+  public:
+    /* constructor
+     * - initialize file descriptor
+     * - initialize empty data buffer
+     * - no putback area
+     * => force underflow()
+     */
+    fdinbuf (int _fd) : fd(_fd) {
+        setg (buffer+pbSize,     // beginning of putback area
+              buffer+pbSize,     // read position
+              buffer+pbSize);    // end position
+    }
+
+  protected:
+    // insert new characters into the buffer
+    virtual int_type underflow () {
+#ifndef _MSC_VER
+        using std::memmove;
+#endif
+
+        // is read position before end of buffer?
+        if (gptr() < egptr()) {
+            return traits_type::to_int_type(*gptr());
+        }
+
+        /* process size of putback area
+         * - use number of characters read
+         * - but at most size of putback area
+         */
+        int numPutback;
+        numPutback = gptr() - eback();
+        if (numPutback > pbSize) {
+            numPutback = pbSize;
+        }
+
+        /* copy up to pbSize characters previously read into
+         * the putback area
+         */
+        memmove (buffer+(pbSize-numPutback), gptr()-numPutback,
+                numPutback);
+
+        // read at most bufSize new characters
+        int num;
+        num = read (fd, buffer+pbSize, bufSize);
+        if (num <= 0) {
+            // ERROR or EOF
+            return EOF;
+        }
+
+        // reset buffer pointers
+        setg (buffer+(pbSize-numPutback),   // beginning of putback area
+              buffer+pbSize,                // read position
+              buffer+pbSize+num);           // end of buffer
+
+        // return next character
+        return traits_type::to_int_type(*gptr());
+    }
+};
+
+class fdistream : public std::istream {
+  protected:
+    fdinbuf buf;
+  public:
+    fdistream (int fd) : std::istream(0), buf(fd) {
+        rdbuf(&buf);
+    }
+};
+
+
+} // END namespace boost
+
+#endif /*BOOST_FDSTREAM_HPP*/

Added: klee/trunk/stp/constantbv/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/constantbv/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/constantbv/Makefile (added)
+++ klee/trunk/stp/constantbv/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,13 @@
+include ../Makefile.common
+
+SRCS = constantbv.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libconstantbv.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:	
+	rm -rf *.o *~ *.a .#*
+
+constantbv.o: constantbv.h

Added: klee/trunk/stp/constantbv/constantbv.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/constantbv/constantbv.cpp?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/constantbv/constantbv.cpp (added)
+++ klee/trunk/stp/constantbv/constantbv.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,3571 @@
+/*****************************************************************************/
+/*  AUTHOR:                                                                  */
+/*****************************************************************************/
+/*                                                                           */
+/*    Steffen Beyer                                                          */
+/*    mailto:sb at engelschall.com                                              */
+/*    http://www.engelschall.com/u/sb/download/                              */
+/*                                                                           */
+/*****************************************************************************/
+/*  COPYRIGHT:                                                               */
+/*****************************************************************************/
+/*                                                                           */
+/*    Copyright (c) 1995 - 2004 by Steffen Beyer.                            */
+/*    All rights reserved.                                                   */
+/*                                                                           */
+/*****************************************************************************/
+/*  LICENSE:                                                                 */
+/*****************************************************************************/
+/*                                                                           */
+/*    This library is free software; you can redistribute it and/or          */
+/*    modify it under the terms of the GNU Library General Public            */
+/*    License as published by the Free Software Foundation; either           */
+/*    version 2 of the License, || (at your option) any later version.       */
+/*                                                                           */
+/*    This library is distributed in the hope that it will be useful,        */
+/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*    MERCHANTABILITY || FITNESS FOR A PARTICULAR PURPOSE. See the GNU       */
+/*    Library General Public License for more details.                       */
+/*                                                                           */
+/*    You should have received a copy of the GNU Library General Public      */
+/*    License along with this library; if not, write to the                  */
+/*    Free Software Foundation, Inc.,                                        */
+/*    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                  */
+/*                                                                           */
+/*    || download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0      */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*  MODULE NAME:  constantbv.cpp                       MODULE TYPE:constantbv*/
+/*****************************************************************************/
+/*  MODULE IMPORTS:                                                          */
+/*****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <limits.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <string.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <ctype.h>                                  /*  MODULE TYPE:  (sys)  */
+#include "constantbv.h"
+
+namespace CONSTANTBV {
+/*****************************************************************************/
+/*  MODULE IMPLEMENTATION:                                                   */
+/*****************************************************************************/
+    /**********************************************/
+    /* global implementation-intrinsic constants: */
+    /**********************************************/
+
+#define BIT_VECTOR_HIDDEN_WORDS 3
+
+    /*****************************************************************/
+    /* global machine-dependent constants (set by "BitVector_Boot"): */
+    /*****************************************************************/
+
+static unsigned int BITS;     /* = # of bits in machine word (must be power of 2)  */
+static unsigned int MODMASK;  /* = BITS - 1 (mask for calculating modulo BITS)     */
+static unsigned int LOGBITS;  /* = ld(BITS) (logarithmus dualis)                   */
+static unsigned int FACTOR;   /* = ld(BITS / 8) (ld of # of bytes)                 */
+
+static unsigned int LSB = 1;  /* = mask for least significant bit                  */
+static unsigned int MSB;      /* = mask for most significant bit                   */
+
+static unsigned int LONGBITS; /* = # of bits in unsigned long                      */
+
+static unsigned int LOG10;    /* = logarithm to base 10 of BITS - 1                */
+static unsigned int EXP10;    /* = largest possible power of 10 in signed int      */
+
+    /********************************************************************/
+    /* global bit mask table for fast access (set by "BitVector_Boot"): */
+    /********************************************************************/
+
+static unsigned int *  BITMASKTAB;
+
+    /*****************************/
+    /* global macro definitions: */
+    /*****************************/
+
+#define BIT_VECTOR_ZERO_WORDS(target,count) \
+    while (count-- > 0) *target++ = 0;
+
+#define BIT_VECTOR_FILL_WORDS(target,fill,count) \
+    while (count-- > 0) *target++ = fill;
+
+#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
+    while (count-- > 0) *target++ ^= flip;
+
+#define BIT_VECTOR_COPY_WORDS(target,source,count) \
+    while (count-- > 0) *target++ = *source++;
+
+#define BIT_VECTOR_BACK_WORDS(target,source,count) \
+    { target += count; source += count; while (count-- > 0) *--target = *--source; }
+
+#define BIT_VECTOR_CLR_BIT(address,index) \
+    *(address+(index>>LOGBITS)) &= ~ BITMASKTAB[index & MODMASK];
+
+#define BIT_VECTOR_SET_BIT(address,index) \
+    *(address+(index>>LOGBITS)) |= BITMASKTAB[index & MODMASK];
+
+#define BIT_VECTOR_TST_BIT(address,index) \
+    ((*(address+(index>>LOGBITS)) & BITMASKTAB[index & MODMASK]) != 0)
+
+#define BIT_VECTOR_FLP_BIT(address,index,mask) \
+    (mask = BITMASKTAB[index & MODMASK]), \
+    (((*(addr+(index>>LOGBITS)) ^= mask) & mask) != 0)
+
+#define BIT_VECTOR_DIGITIZE(type,value,digit) \
+    value = (type) ((digit = value) / 10); \
+    digit -= value * 10; \
+    digit += (type) '0';
+
+    /*********************************************************/
+    /* private low-level functions (potentially dangerous!): */
+    /*********************************************************/
+
+static unsigned int power10(unsigned int x) {
+    unsigned int y = 1;
+
+    while (x-- > 0) y *= 10;
+    return(y);
+}
+
+static void BIT_VECTOR_zro_words(unsigned int *  addr, unsigned int count) {
+    BIT_VECTOR_ZERO_WORDS(addr,count)
+}
+
+static void BIT_VECTOR_cpy_words(unsigned int *  target, 
+				 unsigned int *  source, unsigned int count) {
+    BIT_VECTOR_COPY_WORDS(target,source,count)
+}
+
+static void BIT_VECTOR_mov_words(unsigned int *  target, 
+				 unsigned int *  source, unsigned int count) {
+    if (target != source) {
+        if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
+        else                 BIT_VECTOR_BACK_WORDS(target,source,count)
+    }
+}
+
+static void BIT_VECTOR_ins_words(unsigned int *  addr, 
+				 unsigned int total, unsigned int count, boolean clear) {
+    unsigned int length;
+
+    if ((total > 0) && (count > 0)) {
+        if (count > total) count = total;
+        length = total - count;
+        if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
+        if (clear)      BIT_VECTOR_zro_words(addr,count);
+    }
+}
+
+static void BIT_VECTOR_del_words(unsigned int *  addr, 
+				 unsigned int total, unsigned int count, boolean clear) {
+    unsigned int length;
+
+    if ((total > 0) && (count > 0)) {
+        if (count > total) count = total;
+        length = total - count;
+        if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
+        if (clear)      BIT_VECTOR_zro_words(addr+length,count);
+    }
+}
+
+static void BIT_VECTOR_reverse(unsigned char * string, unsigned int length) {
+    unsigned char * last;
+    unsigned char  temp;
+
+    if (length > 1) {
+        last = string + length - 1;
+        while (string < last) {
+            temp = *string;
+            *string = *last;
+            *last = temp;
+            string++;
+            last--;
+        }
+    }
+}
+
+static unsigned int BIT_VECTOR_int2str(unsigned char * string, unsigned int value) {
+    unsigned int  length;
+    unsigned int  digit;
+    unsigned char * work;
+
+    work = string;
+    if (value > 0) {
+        length = 0;
+        while (value > 0) {
+            BIT_VECTOR_DIGITIZE(unsigned int,value,digit)
+            *work++ = (unsigned char) digit;
+            length++;
+        }
+        BIT_VECTOR_reverse(string,length);
+    }
+    else {
+        length = 1;
+        *work++ = (unsigned char) '0';
+    }
+    return(length);
+}
+
+static unsigned int BIT_VECTOR_str2int(unsigned char * string, unsigned int *value) {
+    unsigned int  length;
+    unsigned int  digit;
+
+    *value = 0;
+    length = 0;
+    digit = (unsigned int) *string++;
+    /* separate because isdigit() is likely a macro! */
+    while (isdigit((int)digit) != 0) {
+        length++;
+        digit -= (unsigned int) '0';
+        if (*value) *value *= 10;
+        *value += digit;
+        digit = (unsigned int) *string++;
+    }
+    return(length);
+}
+
+    /********************************************/
+    /* routine to convert error code to string: */
+    /********************************************/
+
+unsigned char * BitVector_Error(ErrCode error) {
+    switch (error) {
+        case ErrCode_Ok:   return( (unsigned char *)     NULL     ); break;
+        case ErrCode_Type: return( (unsigned char *) ERRCODE_TYPE ); break;
+        case ErrCode_Bits: return( (unsigned char *) ERRCODE_BITS ); break;
+        case ErrCode_Word: return( (unsigned char *) ERRCODE_WORD ); break;
+        case ErrCode_Long: return( (unsigned char *) ERRCODE_LONG ); break;
+        case ErrCode_Powr: return( (unsigned char *) ERRCODE_POWR ); break;
+        case ErrCode_Loga: return( (unsigned char *) ERRCODE_LOGA ); break;
+        case ErrCode_Null: return( (unsigned char *) ERRCODE_NULL ); break;
+        case ErrCode_Indx: return( (unsigned char *) ERRCODE_INDX ); break;
+        case ErrCode_Ordr: return( (unsigned char *) ERRCODE_ORDR ); break;
+        case ErrCode_Size: return( (unsigned char *) ERRCODE_SIZE ); break;
+        case ErrCode_Pars: return( (unsigned char *) ERRCODE_PARS ); break;
+        case ErrCode_Ovfl: return( (unsigned char *) ERRCODE_OVFL ); break;
+        case ErrCode_Same: return( (unsigned char *) ERRCODE_SAME ); break;
+        case ErrCode_Expo: return( (unsigned char *) ERRCODE_EXPO ); break;
+        case ErrCode_Zero: return( (unsigned char *) ERRCODE_ZERO ); break;
+        default:           return( (unsigned char *) ERRCODE_OOPS ); break;
+    }
+}
+
+    /*****************************************/
+    /* automatic self-configuration routine: */
+    /*****************************************/
+
+    /*******************************************************/
+    /*                                                     */
+    /*   MUST be called once prior to any other function   */
+    /*   to initialize the machine dependent constants     */
+    /*   of this package! (But call only ONCE, or you      */
+    /*   will suffer memory leaks!)                        */
+    /*                                                     */
+    /*******************************************************/
+
+ErrCode BitVector_Boot(void) {
+    unsigned long longsample = 1L;
+    unsigned int sample = LSB;
+    unsigned int lsb;
+
+    if (sizeof(unsigned int) > sizeof(size_t)) return(ErrCode_Type);
+
+    BITS = 1;
+    while (sample <<= 1) BITS++;    /* determine # of bits in a machine word */
+
+    if (BITS != (sizeof(unsigned int) << 3)) return(ErrCode_Bits);
+
+    if (BITS < 16) return(ErrCode_Word);
+
+    LONGBITS = 1;
+    while (longsample <<= 1) LONGBITS++;  /* = # of bits in an unsigned long */
+
+    if (BITS > LONGBITS) return(ErrCode_Long);
+
+    LOGBITS = 0;
+    sample = BITS;
+    lsb = (sample & LSB);
+    while ((sample >>= 1) && (! lsb)) {
+        LOGBITS++;
+        lsb = (sample & LSB);
+    }
+
+    if (sample) return(ErrCode_Powr);      /* # of bits is not a power of 2! */
+
+    if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga);
+
+    MODMASK = BITS - 1;
+    FACTOR = LOGBITS - 3;  /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */
+    MSB = (LSB << MODMASK);
+
+    BITMASKTAB = (unsigned int * ) malloc((size_t) (BITS << FACTOR));
+
+    if (BITMASKTAB == NULL) return(ErrCode_Null);
+
+    for ( sample = 0; sample < BITS; sample++ ) {
+        BITMASKTAB[sample] = (LSB << sample);
+    }
+
+    LOG10 = (unsigned int) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */
+    EXP10 = power10(LOG10);
+
+    return(ErrCode_Ok);
+}
+
+unsigned int BitVector_Size(unsigned int bits) {          /* bit vector size (# of words)  */
+    unsigned int size;
+
+    size = bits >> LOGBITS;
+    if (bits & MODMASK) size++;
+    return(size);
+}
+
+unsigned int BitVector_Mask(unsigned int bits)           /* bit vector mask (unused bits) */
+{
+    unsigned int mask;
+
+    mask = bits & MODMASK;
+    if (mask) mask = (unsigned int) ~(~0L << mask); else mask = (unsigned int) ~0L;
+    return(mask);
+}
+
+unsigned char * BitVector_Version(void)
+{
+    return((unsigned char *)"6.4");
+}
+
+unsigned int BitVector_Word_Bits(void)
+{
+    return(BITS);
+}
+
+unsigned int BitVector_Long_Bits(void)
+{
+    return(LONGBITS);
+}
+
+/********************************************************************/
+/*                                                                  */
+/*  WARNING: Do not "free()" constant character strings, i.e.,      */
+/*           don't call "BitVector_Dispose()" for strings returned  */
+/*           by "BitVector_Error()" or "BitVector_Version()"!       */
+/*                                                                  */
+/*  ONLY call this function for strings allocated with "malloc()",  */
+/*  i.e., the strings returned by the functions "BitVector_to_*()"  */
+/*  and "BitVector_Block_Read()"!                                   */
+/*                                                                  */
+/********************************************************************/
+
+void BitVector_Dispose(unsigned char * string)                      /* free string   */
+{
+    if (string != NULL) free((void *) string);
+}
+
+void BitVector_Destroy(unsigned int *  addr)                        /* free bitvec   */
+{
+    if (addr != NULL)
+    {
+        addr -= BIT_VECTOR_HIDDEN_WORDS;
+        free((void *) addr);
+    }
+}
+
+void BitVector_Destroy_List(unsigned int *  *  list, unsigned int count)      /* free list     */
+{
+    unsigned int *  *  slot;
+
+    if (list != NULL)
+    {
+        slot = list;
+        while (count-- > 0)
+        {
+            BitVector_Destroy(*slot++);
+        }
+        free((void *) list);
+    }
+}
+
+unsigned int *  BitVector_Create(unsigned int bits, boolean clear)         /* malloc        */
+{
+    unsigned int  size;
+    unsigned int  mask;
+    unsigned int  bytes;
+    unsigned int *  addr;
+    unsigned int *  zero;
+
+    size = BitVector_Size(bits);
+    mask = BitVector_Mask(bits);
+    bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+    addr = (unsigned int * ) malloc((size_t) bytes);
+    if (addr != NULL)
+    {
+        *addr++ = bits;
+        *addr++ = size;
+        *addr++ = mask;
+        if (clear)
+        {
+            zero = addr;
+            BIT_VECTOR_ZERO_WORDS(zero,size)
+        }
+    }
+    return(addr);
+}
+
+unsigned int *  *  BitVector_Create_List(unsigned int bits, boolean clear, unsigned int count)
+{
+    unsigned int *  *  list = NULL;
+    unsigned int *  *  slot;
+    unsigned int *  addr;
+    unsigned int   i;
+
+    if (count > 0)
+    {
+        list = (unsigned int *  * ) malloc(sizeof(unsigned int * ) * count);
+        if (list != NULL)
+        {
+            slot = list;
+            for ( i = 0; i < count; i++ )
+            {
+                addr = BitVector_Create(bits,clear);
+                if (addr == NULL)
+                {
+                    BitVector_Destroy_List(list,i);
+                    return(NULL);
+                }
+                *slot++ = addr;
+            }
+        }
+    }
+    return(list);
+}
+
+unsigned int *  BitVector_Resize(unsigned int *  oldaddr, unsigned int bits)       /* realloc       */
+{
+    unsigned int  bytes;
+    unsigned int  oldsize;
+    unsigned int  oldmask;
+    unsigned int  newsize;
+    unsigned int  newmask;
+    unsigned int *  newaddr;
+    unsigned int *  source;
+    unsigned int *  target;
+
+    oldsize = size_(oldaddr);
+    oldmask = mask_(oldaddr);
+    newsize = BitVector_Size(bits);
+    newmask = BitVector_Mask(bits);
+    if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
+    if (newsize <= oldsize)
+    {
+        newaddr = oldaddr;
+        bits_(newaddr) = bits;
+        size_(newaddr) = newsize;
+        mask_(newaddr) = newmask;
+        if (newsize > 0) *(newaddr+newsize-1) &= newmask;
+    }
+    else
+    {
+        bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+        newaddr = (unsigned int * ) malloc((size_t) bytes);
+        if (newaddr != NULL)
+        {
+            *newaddr++ = bits;
+            *newaddr++ = newsize;
+            *newaddr++ = newmask;
+            target = newaddr;
+            source = oldaddr;
+            newsize -= oldsize;
+            BIT_VECTOR_COPY_WORDS(target,source,oldsize)
+            BIT_VECTOR_ZERO_WORDS(target,newsize)
+        }
+        BitVector_Destroy(oldaddr);
+    }
+    return(newaddr);
+}
+
+unsigned int *  BitVector_Shadow(unsigned int *  addr)     /* makes new, same size but empty */
+{
+    return( BitVector_Create(bits_(addr),true) );
+}
+
+unsigned int *  BitVector_Clone(unsigned int *  addr)               /* makes exact duplicate */
+{
+    unsigned int  bits;
+    unsigned int *  twin;
+
+    bits = bits_(addr);
+    twin = BitVector_Create(bits,false);
+    if ((twin != NULL) && (bits > 0))
+        BIT_VECTOR_cpy_words(twin,addr,size_(addr));
+    return(twin);
+}
+
+unsigned int *  BitVector_Concat(unsigned int *  X, unsigned int *  Y)      /* returns concatenation */
+{
+    /* BEWARE that X = most significant part, Y = least significant part! */
+
+    unsigned int  bitsX;
+    unsigned int  bitsY;
+    unsigned int  bitsZ;
+    unsigned int *  Z;
+
+    bitsX = bits_(X);
+    bitsY = bits_(Y);
+    bitsZ = bitsX + bitsY;
+    Z = BitVector_Create(bitsZ,false);
+    if ((Z != NULL) && (bitsZ > 0))
+    {
+        BIT_VECTOR_cpy_words(Z,Y,size_(Y));
+        BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
+        *(Z+size_(Z)-1) &= mask_(Z);
+    }
+    return(Z);
+}
+
+void BitVector_Copy(unsigned int *  X, unsigned int *  Y)                           /* X = Y */
+{
+    unsigned int  sizeX = size_(X);
+    unsigned int  sizeY = size_(Y);
+    unsigned int  maskX = mask_(X);
+    unsigned int  maskY = mask_(Y);
+    unsigned int  fill  = 0;
+    unsigned int *  lastX;
+    unsigned int *  lastY;
+
+    if ((X != Y) && (sizeX > 0))
+    {
+        lastX = X + sizeX - 1;
+        if (sizeY > 0)
+        {
+            lastY = Y + sizeY - 1;
+            if ( (*lastY & (maskY & ~ (maskY >> 1))) == 0 ) *lastY &= maskY;
+            else
+            {
+                fill = (unsigned int) ~0L;
+                *lastY |= ~ maskY;
+            }
+            while ((sizeX > 0) && (sizeY > 0))
+            {
+                *X++ = *Y++;
+                sizeX--;
+                sizeY--;
+            }
+            *lastY &= maskY;
+        }
+        while (sizeX-- > 0) *X++ = fill;
+        *lastX &= maskX;
+    }
+}
+
+void BitVector_Empty(unsigned int *  addr)                        /* X = {}  clr all */
+{
+    unsigned int size = size_(addr);
+
+    BIT_VECTOR_ZERO_WORDS(addr,size)
+}
+
+void BitVector_Fill(unsigned int *  addr)                         /* X = ~{} set all */
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+    unsigned int fill = (unsigned int) ~0L;
+
+    if (size > 0)
+    {
+        BIT_VECTOR_FILL_WORDS(addr,fill,size)
+        *(--addr) &= mask;
+    }
+}
+
+void BitVector_Flip(unsigned int *  addr)                         /* X = ~X flip all */
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+    unsigned int flip = (unsigned int) ~0L;
+
+    if (size > 0)
+    {
+        BIT_VECTOR_FLIP_WORDS(addr,flip,size)
+        *(--addr) &= mask;
+    }
+}
+
+void BitVector_Primes(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int *  work;
+    unsigned int  temp;
+    unsigned int  i,j;
+
+    if (size > 0)
+    {
+        temp = 0xAAAA;
+        i = BITS >> 4;
+        while (--i > 0)
+        {
+            temp <<= 16;
+            temp |= 0xAAAA;
+        }
+        i = size;
+        work = addr;
+        *work++ = temp ^ 0x0006;
+        while (--i > 0) *work++ = temp;
+        for ( i = 3; (j = i * i) < bits; i += 2 )
+        {
+            for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
+        }
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+void BitVector_Reverse(unsigned int *  X, unsigned int *  Y)
+{
+    unsigned int bits = bits_(X);
+    unsigned int mask;
+    unsigned int bit;
+    unsigned int value;
+
+    if (bits > 0)
+    {
+        if (X == Y) BitVector_Interval_Reverse(X,0,bits-1);
+        else if (bits == bits_(Y))
+        {
+/*          mask = mask_(Y);  */
+/*          mask &= ~ (mask >> 1);  */
+            mask = BITMASKTAB[(bits-1) & MODMASK];
+            Y += size_(Y) - 1;
+            value = 0;
+            bit = LSB;
+            while (bits-- > 0)
+            {
+                if ((*Y & mask) != 0)
+                {
+                    value |= bit;
+                }
+                if (! (mask >>= 1))
+                {
+                    Y--;
+                    mask = MSB;
+                }
+                if (! (bit <<= 1))
+                {
+                    *X++ = value;
+                    value = 0;
+                    bit = LSB;
+                }
+            }
+            if (bit > LSB) *X = value;
+        }
+    }
+}
+
+void BitVector_Interval_Empty(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{                                                  /* X = X \ [lower..upper] */
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lobase;
+    unsigned int  hibase;
+    unsigned int  lomask;
+    unsigned int  himask;
+    unsigned int  diff;
+
+    if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper))
+    {
+        lobase = lower >> LOGBITS;
+        hibase = upper >> LOGBITS;
+        diff = hibase - lobase;
+        loaddr = addr + lobase;
+        hiaddr = addr + hibase;
+
+        lomask = (unsigned int)   (~0L << (lower & MODMASK));
+        himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1);
+
+        if (diff == 0)
+        {
+            *loaddr &= ~ (lomask & himask);
+        }
+        else
+        {
+            *loaddr++ &= ~ lomask;
+            while (--diff > 0)
+            {
+                *loaddr++ = 0;
+            }
+            *hiaddr &= ~ himask;
+        }
+    }
+}
+
+void BitVector_Interval_Fill(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{                                                  /* X = X + [lower..upper] */
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int  fill = (unsigned int) ~0L;
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lobase;
+    unsigned int  hibase;
+    unsigned int  lomask;
+    unsigned int  himask;
+    unsigned int  diff;
+
+    if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper))
+    {
+        lobase = lower >> LOGBITS;
+        hibase = upper >> LOGBITS;
+        diff = hibase - lobase;
+        loaddr = addr + lobase;
+        hiaddr = addr + hibase;
+
+        lomask = (unsigned int)   (~0L << (lower & MODMASK));
+        himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1);
+
+        if (diff == 0)
+        {
+            *loaddr |= (lomask & himask);
+        }
+        else
+        {
+            *loaddr++ |= lomask;
+            while (--diff > 0)
+            {
+                *loaddr++ = fill;
+            }
+            *hiaddr |= himask;
+        }
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+void BitVector_Interval_Flip(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{                                                  /* X = X ^ [lower..upper] */
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int  flip = (unsigned int) ~0L;
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lobase;
+    unsigned int  hibase;
+    unsigned int  lomask;
+    unsigned int  himask;
+    unsigned int  diff;
+
+    if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper))
+    {
+        lobase = lower >> LOGBITS;
+        hibase = upper >> LOGBITS;
+        diff = hibase - lobase;
+        loaddr = addr + lobase;
+        hiaddr = addr + hibase;
+
+        lomask = (unsigned int)   (~0L << (lower & MODMASK));
+        himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1);
+
+        if (diff == 0)
+        {
+            *loaddr ^= (lomask & himask);
+        }
+        else
+        {
+            *loaddr++ ^= lomask;
+            while (--diff > 0)
+            {
+                *loaddr++ ^= flip;
+            }
+            *hiaddr ^= himask;
+        }
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+void BitVector_Interval_Reverse(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lomask;
+    unsigned int  himask;
+
+    if ((bits > 0) && (lower < bits) && (upper < bits) && (lower < upper))
+    {
+        loaddr = addr + (lower >> LOGBITS);
+        hiaddr = addr + (upper >> LOGBITS);
+        lomask = BITMASKTAB[lower & MODMASK];
+        himask = BITMASKTAB[upper & MODMASK];
+        for ( bits = upper - lower + 1; bits > 1; bits -= 2 )
+        {
+            if (((*loaddr & lomask) != 0) ^ ((*hiaddr & himask) != 0))
+            {
+                *loaddr ^= lomask;  /* swap bits only if they differ! */
+                *hiaddr ^= himask;
+            }
+            if (! (lomask <<= 1))
+            {
+                lomask = LSB;
+                loaddr++;
+            }
+            if (! (himask >>= 1))
+            {
+                himask = MSB;
+                hiaddr--;
+            }
+        }
+    }
+}
+
+boolean BitVector_interval_scan_inc(unsigned int *  addr, unsigned int start,
+                                    unsigned int * min, unsigned int * max)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  offset;
+    unsigned int  bitmask;
+    unsigned int  value;
+    boolean empty;
+
+    if ((size == 0) || (start >= bits_(addr))) return(false);
+
+    *min = start;
+    *max = start;
+
+    offset = start >> LOGBITS;
+
+    *(addr+size-1) &= mask;
+
+    addr += offset;
+    size -= offset;
+
+    bitmask = BITMASKTAB[start & MODMASK];
+    mask = ~ (bitmask | (bitmask - 1));
+
+    value = *addr++;
+    if ((value & bitmask) == 0)
+    {
+        value &= mask;
+        if (value == 0)
+        {
+            offset++;
+            empty = true;
+            while (empty && (--size > 0))
+            {
+                if ((value = *addr++)) empty = false; else offset++;
+            }
+            if (empty) return(false);
+        }
+        start = offset << LOGBITS;
+        bitmask = LSB;
+        mask = value;
+        while (! (mask & LSB))
+        {
+            bitmask <<= 1;
+            mask >>= 1;
+            start++;
+        }
+        mask = ~ (bitmask | (bitmask - 1));
+        *min = start;
+        *max = start;
+    }
+    value = ~ value;
+    value &= mask;
+    if (value == 0)
+    {
+        offset++;
+        empty = true;
+        while (empty && (--size > 0))
+        {
+            if ((value = ~ *addr++)) empty = false; else offset++;
+        }
+        if (empty) value = LSB;
+    }
+    start = offset << LOGBITS;
+    while (! (value & LSB))
+    {
+        value >>= 1;
+        start++;
+    }
+    *max = --start;
+    return(true);
+}
+
+boolean BitVector_interval_scan_dec(unsigned int *  addr, unsigned int start,
+                                    unsigned int * min, unsigned int * max)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int offset;
+    unsigned int bitmask;
+    unsigned int value;
+    boolean empty;
+
+    if ((size == 0) || (start >= bits_(addr))) return(false);
+
+    *min = start;
+    *max = start;
+
+    offset = start >> LOGBITS;
+
+    if (offset >= size) return(false);
+
+    *(addr+size-1) &= mask;
+
+    addr += offset;
+    size = ++offset;
+
+    bitmask = BITMASKTAB[start & MODMASK];
+    mask = (bitmask - 1);
+
+    value = *addr--;
+    if ((value & bitmask) == 0)
+    {
+        value &= mask;
+        if (value == 0)
+        {
+            offset--;
+            empty = true;
+            while (empty && (--size > 0))
+            {
+                if ((value = *addr--)) empty = false; else offset--;
+            }
+            if (empty) return(false);
+        }
+        start = offset << LOGBITS;
+        bitmask = MSB;
+        mask = value;
+        while (! (mask & MSB))
+        {
+            bitmask >>= 1;
+            mask <<= 1;
+            start--;
+        }
+        mask = (bitmask - 1);
+        *max = --start;
+        *min = start;
+    }
+    value = ~ value;
+    value &= mask;
+    if (value == 0)
+    {
+        offset--;
+        empty = true;
+        while (empty && (--size > 0))
+        {
+            if ((value = ~ *addr--)) empty = false; else offset--;
+        }
+        if (empty) value = MSB;
+    }
+    start = offset << LOGBITS;
+    while (! (value & MSB))
+    {
+        value <<= 1;
+        start--;
+    }
+    *min = start;
+    return(true);
+}
+
+void BitVector_Interval_Copy(unsigned int *  X, unsigned int *  Y, unsigned int Xoffset,
+                             unsigned int Yoffset, unsigned int length)
+{
+    unsigned int  bitsX = bits_(X);
+    unsigned int  bitsY = bits_(Y);
+    unsigned int  source = 0;        /* silence compiler warning */
+    unsigned int  target = 0;        /* silence compiler warning */
+    unsigned int  s_lo_base;
+    unsigned int  s_hi_base;
+    unsigned int  s_lo_bit;
+    unsigned int  s_hi_bit;
+    unsigned int  s_base;
+    unsigned int  s_lower = 0;       /* silence compiler warning */
+    unsigned int  s_upper = 0;       /* silence compiler warning */
+    unsigned int  s_bits;
+    unsigned int  s_min;
+    unsigned int  s_max;
+    unsigned int  t_lo_base;
+    unsigned int  t_hi_base;
+    unsigned int  t_lo_bit;
+    unsigned int  t_hi_bit;
+    unsigned int  t_base;
+    unsigned int  t_lower = 0;       /* silence compiler warning */
+    unsigned int  t_upper = 0;       /* silence compiler warning */
+    unsigned int  t_bits;
+    unsigned int  t_min;
+    unsigned int  mask;
+    unsigned int  bits;
+    unsigned int  select;
+    boolean ascending;
+    boolean notfirst;
+    unsigned int *  Z = X;
+
+    if ((length > 0) && (Xoffset < bitsX) && (Yoffset < bitsY))
+    {
+        if ((Xoffset + length) > bitsX) length = bitsX - Xoffset;
+        if ((Yoffset + length) > bitsY) length = bitsY - Yoffset;
+
+        ascending = (Xoffset <= Yoffset);
+
+        s_lo_base = Yoffset >> LOGBITS;
+        s_lo_bit = Yoffset & MODMASK;
+        Yoffset += --length;
+        s_hi_base = Yoffset >> LOGBITS;
+        s_hi_bit = Yoffset & MODMASK;
+
+        t_lo_base = Xoffset >> LOGBITS;
+        t_lo_bit = Xoffset & MODMASK;
+        Xoffset += length;
+        t_hi_base = Xoffset >> LOGBITS;
+        t_hi_bit = Xoffset & MODMASK;
+
+        if (ascending)
+        {
+            s_base = s_lo_base;
+            t_base = t_lo_base;
+        }
+        else
+        {
+            s_base = s_hi_base;
+            t_base = t_hi_base;
+        }
+        s_bits = 0;
+        t_bits = 0;
+        Y += s_base;
+        X += t_base;
+        notfirst = false;
+        while (true)
+        {
+            if (t_bits == 0)
+            {
+                if (notfirst)
+                {
+                    *X = target;
+                    if (ascending)
+                    {
+                        if (t_base == t_hi_base) break;
+                        t_base++;
+                        X++;
+                    }
+                    else
+                    {
+                        if (t_base == t_lo_base) break;
+                        t_base--;
+                        X--;
+                    }
+                }
+                select = ((t_base == t_hi_base) << 1) | (t_base == t_lo_base);
+                switch (select)
+                {
+                    case 0:
+                        t_lower = 0;
+                        t_upper = BITS - 1;
+                        t_bits = BITS;
+                        target = 0;
+                        break;
+                    case 1:
+                        t_lower = t_lo_bit;
+                        t_upper = BITS - 1;
+                        t_bits = BITS - t_lo_bit;
+                        mask = (unsigned int) (~0L << t_lower);
+                        target = *X & ~ mask;
+                        break;
+                    case 2:
+                        t_lower = 0;
+                        t_upper = t_hi_bit;
+                        t_bits = t_hi_bit + 1;
+                        mask = (unsigned int) ((~0L << t_upper) << 1);
+                        target = *X & mask;
+                        break;
+                    case 3:
+                        t_lower = t_lo_bit;
+                        t_upper = t_hi_bit;
+                        t_bits = t_hi_bit - t_lo_bit + 1;
+                        mask = (unsigned int) (~0L << t_lower);
+                        mask &= (unsigned int) ~((~0L << t_upper) << 1);
+                        target = *X & ~ mask;
+                        break;
+                }
+            }
+            if (s_bits == 0)
+            {
+                if (notfirst)
+                {
+                    if (ascending)
+                    {
+                        if (s_base == s_hi_base) break;
+                        s_base++;
+                        Y++;
+                    }
+                    else
+                    {
+                        if (s_base == s_lo_base) break;
+                        s_base--;
+                        Y--;
+                    }
+                }
+                source = *Y;
+                select = ((s_base == s_hi_base) << 1) | (s_base == s_lo_base);
+                switch (select)
+                {
+                    case 0:
+                        s_lower = 0;
+                        s_upper = BITS - 1;
+                        s_bits = BITS;
+                        break;
+                    case 1:
+                        s_lower = s_lo_bit;
+                        s_upper = BITS - 1;
+                        s_bits = BITS - s_lo_bit;
+                        break;
+                    case 2:
+                        s_lower = 0;
+                        s_upper = s_hi_bit;
+                        s_bits = s_hi_bit + 1;
+                        break;
+                    case 3:
+                        s_lower = s_lo_bit;
+                        s_upper = s_hi_bit;
+                        s_bits = s_hi_bit - s_lo_bit + 1;
+                        break;
+                }
+            }
+            notfirst = true;
+            if (s_bits > t_bits)
+            {
+                bits = t_bits - 1;
+                if (ascending)
+                {
+                    s_min = s_lower;
+                    s_max = s_lower + bits;
+                }
+                else
+                {
+                    s_max = s_upper;
+                    s_min = s_upper - bits;
+                }
+                t_min = t_lower;
+            }
+            else
+            {
+                bits = s_bits - 1;
+                if (ascending) t_min = t_lower;
+                else           t_min = t_upper - bits;
+                s_min = s_lower;
+                s_max = s_upper;
+            }
+            bits++;
+            mask = (unsigned int) (~0L << s_min);
+            mask &= (unsigned int) ~((~0L << s_max) << 1);
+            if (s_min == t_min) target |= (source & mask);
+            else
+            {
+                if (s_min < t_min) target |= (source & mask) << (t_min-s_min);
+                else               target |= (source & mask) >> (s_min-t_min);
+            }
+            if (ascending)
+            {
+                s_lower += bits;
+                t_lower += bits;
+            }
+            else
+            {
+                s_upper -= bits;
+                t_upper -= bits;
+            }
+            s_bits -= bits;
+            t_bits -= bits;
+        }
+        *(Z+size_(Z)-1) &= mask_(Z);
+    }
+}
+
+
+unsigned int *  BitVector_Interval_Substitute(unsigned int *  X, unsigned int *  Y,
+                                      unsigned int Xoffset, unsigned int Xlength,
+                                      unsigned int Yoffset, unsigned int Ylength)
+{
+    unsigned int Xbits = bits_(X);
+    unsigned int Ybits = bits_(Y);
+    unsigned int limit;
+    unsigned int diff;
+
+    if ((Xoffset <= Xbits) && (Yoffset <= Ybits))
+    {
+        limit = Xoffset + Xlength;
+        if (limit > Xbits)
+        {
+            limit = Xbits;
+            Xlength = Xbits - Xoffset;
+        }
+        if ((Yoffset + Ylength) > Ybits)
+        {
+            Ylength = Ybits - Yoffset;
+        }
+        if (Xlength == Ylength)
+        {
+            if ((Ylength > 0) && ((X != Y) || (Xoffset != Yoffset)))
+            {
+                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+            }
+        }
+        else /* Xlength != Ylength */
+        {
+            if (Xlength > Ylength)
+            {
+                diff = Xlength - Ylength;
+                if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,false);
+                if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL);
+            }
+            else /* Ylength > Xlength  ==>  Ylength > 0 */
+            {
+                diff = Ylength - Xlength;
+                if (X != Y)
+                {
+                    if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+                    if (limit < Xbits) BitVector_Insert(X,limit,diff,false);
+                    BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                }
+                else /* in-place */
+                {
+                    if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+                    if (limit >= Xbits)
+                    {
+                        BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                    }
+                    else /* limit < Xbits */
+                    {
+                        BitVector_Insert(X,limit,diff,false);
+                        if ((Yoffset+Ylength) <= limit)
+                        {
+                            BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                        }
+                        else /* overlaps or lies above critical area */
+                        {
+                            if (limit <= Yoffset)
+                            {
+                                Yoffset += diff;
+                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                            }
+                            else /* Yoffset < limit */
+                            {
+                                Xlength = limit - Yoffset;
+                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
+                                Yoffset = Xoffset + Ylength; /* = limit + diff */
+                                Xoffset += Xlength;
+                                Ylength -= Xlength;
+                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return(X);
+}
+
+boolean BitVector_is_empty(unsigned int *  addr)                    /* X == {} ?     */
+{
+    unsigned int  size = size_(addr);
+    boolean r = true;
+
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while (r && (size-- > 0)) r = ( *addr++ == 0 );
+    }
+    return(r);
+}
+
+boolean BitVector_is_full(unsigned int *  addr)                     /* X == ~{} ?    */
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean r = false;
+    unsigned int *  last;
+
+    if (size > 0)
+    {
+        r = true;
+        last = addr + size - 1;
+        *last |= ~ mask;
+        while (r && (size-- > 0)) r = ( ~ *addr++ == 0 );
+        *last &= mask;
+    }
+    return(r);
+}
+
+boolean BitVector_equal(unsigned int *  X, unsigned int *  Y)               /* X == Y ?      */
+{
+    unsigned int  size = size_(X);
+    unsigned int  mask = mask_(X);
+    boolean r = false;
+
+    if (bits_(X) == bits_(Y))
+    {
+        r = true;
+        if (size > 0)
+        {
+            *(X+size-1) &= mask;
+            *(Y+size-1) &= mask;
+            while (r && (size-- > 0)) r = (*X++ == *Y++);
+        }
+    }
+    return(r);
+}
+
+/* X <,=,> Y ?     : unsigned     */
+signed int BitVector_Lexicompare(unsigned int *  X, unsigned int *  Y) {
+    unsigned int  bitsX = bits_(X);
+    unsigned int  bitsY = bits_(Y);
+    unsigned int  size  = size_(X);
+    boolean r = true;
+
+    if (bitsX == bitsY) {
+        if (size > 0) {
+            X += size;
+            Y += size;
+            while (r && (size-- > 0)) r = (*(--X) == *(--Y));
+        }
+        if (r) return((signed int) 0);
+        else {
+            if (*X < *Y) return((signed int) -1); else return((signed int) 1);
+        }
+    }
+    else {
+        if (bitsX < bitsY) return((signed int) -1); else return((signed int) 1);
+    }
+}
+
+signed int BitVector_Compare(unsigned int *  X, unsigned int *  Y)               /* X <,=,> Y ?   */
+{                                                           /*   signed      */
+    unsigned int  bitsX = bits_(X);
+    unsigned int  bitsY = bits_(Y);
+    unsigned int  size  = size_(X);
+    unsigned int  mask  = mask_(X);
+    unsigned int  sign;
+    boolean r = true;
+
+    if (bitsX == bitsY)
+    {
+        if (size > 0)
+        {
+            X += size;
+            Y += size;
+            mask &= ~ (mask >> 1);
+            if ((sign = (*(X-1) & mask)) != (*(Y-1) & mask))
+            {
+                if (sign) return((signed int) -1); else return((signed int) 1);
+            }
+            while (r && (size-- > 0)) r = (*(--X) == *(--Y));
+        }
+        if (r) return((signed int) 0);
+        else
+        {
+            if (*X < *Y) return((signed int) -1); else return((signed int) 1);
+        }
+    }
+    else
+    {
+        if (bitsX < bitsY) return((signed int) -1); else return((signed int) 1);
+    }
+}
+
+size_t BitVector_Hash(unsigned int * addr)
+{
+  unsigned int  bits = bits_(addr);
+  unsigned int  size = size_(addr);
+  unsigned int  value;
+  unsigned int  count;
+  unsigned int  digit;
+  unsigned int  length;
+    
+  size_t result = 0;
+
+  length = bits >> 2;
+  if (bits & 0x0003) length++;
+  if (size > 0)
+    {
+      *(addr+size-1) &= mask_(addr);
+      while ((size-- > 0) && (length > 0))
+        {
+          value = *addr++;
+          count = BITS >> 2;
+          while ((count-- > 0) && (length > 0))
+            {
+              digit = value & 0x000F;
+              if (digit > 9) digit += (unsigned int) 'A' - 10;
+              else           digit += (unsigned int) '0';
+              result = 5*result + digit; length--;
+              if ((count > 0) && (length > 0)) value >>= 4;
+            }
+        }
+    }
+  return result;
+}
+
+
+unsigned char * BitVector_to_Hex(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int  value;
+    unsigned int  count;
+    unsigned int  digit;
+    unsigned int  length;
+    unsigned char * string;
+
+    length = bits >> 2;
+    if (bits & 0x0003) length++;
+    string = (unsigned char *) malloc((size_t) (length+1));
+    if (string == NULL) return(NULL);
+    string += length;
+    *string = (unsigned char) '\0';
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while ((size-- > 0) && (length > 0))
+        {
+            value = *addr++;
+            count = BITS >> 2;
+            while ((count-- > 0) && (length > 0))
+            {
+                digit = value & 0x000F;
+                if (digit > 9) digit += (unsigned int) 'A' - 10;
+                else           digit += (unsigned int) '0';
+                *(--string) = (unsigned char) digit; length--;
+                if ((count > 0) && (length > 0)) value >>= 4;
+            }
+        }
+    }
+    return(string);
+}
+
+ErrCode BitVector_from_Hex(unsigned int *  addr, unsigned char * string)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean ok = true;
+    unsigned int  length;
+    unsigned int  value;
+    unsigned int  count;
+    int     digit;
+
+    if (size > 0)
+    {
+        length = strlen((char *) string);
+        string += length;
+        while (size-- > 0)
+        {
+            value = 0;
+            for ( count = 0; (ok && (length > 0) && (count < BITS)); count += 4 )
+            {
+                digit = (int) *(--string); length--;
+                /* separate because toupper() is likely a macro! */
+                digit = toupper(digit);
+                if ((ok = (isxdigit(digit) != 0)))
+                {
+		  if (digit >= (int) 'A') digit -= (int) 'A' - 10;
+		  else                    digit -= (int) '0';
+		  value |= (((unsigned int) digit) << count);
+                }
+            }
+            *addr++ = value;
+        }
+        *(--addr) &= mask;
+    }
+    if (ok) return(ErrCode_Ok);
+    else    return(ErrCode_Pars);
+}
+
+unsigned char * BitVector_to_Bin(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  value;
+    unsigned int  count;
+    unsigned int  digit;
+    unsigned int  length;
+    unsigned char * string;
+
+    length = bits_(addr);
+    string = (unsigned char *) malloc((size_t) (length+1));
+    if (string == NULL) return(NULL);
+    string += length;
+    *string = (unsigned char) '\0';
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while (size-- > 0)
+        {
+            value = *addr++;
+            count = BITS;
+            if (count > length) count = length;
+            while (count-- > 0)
+            {
+                digit = value & 0x0001;
+                digit += (unsigned int) '0';
+                *(--string) = (unsigned char) digit; length--;
+                if (count > 0) value >>= 1;
+            }
+        }
+    }
+    return(string);
+}
+
+ErrCode BitVector_from_Bin(unsigned int *  addr, unsigned char * string)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean ok = true;
+    unsigned int  length;
+    unsigned int  value;
+    unsigned int  count;
+    int     digit;
+
+    if (size > 0)
+    {
+        length = strlen((char *) string);
+        string += length;
+        while (size-- > 0)
+        {
+            value = 0;
+            for ( count = 0; (ok && (length > 0) && (count < BITS)); count++ )
+            {
+                digit = (int) *(--string); length--;
+                switch (digit)
+                {
+                    case (int) '0':
+                        break;
+                    case (int) '1':
+                        value |= BITMASKTAB[count];
+                        break;
+                    default:
+                        ok = false;
+                        break;
+                }
+            }
+            *addr++ = value;
+        }
+        *(--addr) &= mask;
+    }
+    if (ok) return(ErrCode_Ok);
+    else    return(ErrCode_Pars);
+}
+
+unsigned char * BitVector_to_Dec(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  length;
+    unsigned int  digits;
+    unsigned int  count;
+    unsigned int  q;
+    unsigned int  r;
+    boolean loop;
+    unsigned char * result;
+    unsigned char * string;
+    unsigned int *  quot;
+    unsigned int *  rest;
+    unsigned int *  temp;
+    unsigned int *  base;
+    signed int   sign;
+
+    length = (unsigned int) (bits / 3.3);        /* digits = bits * ln(2) / ln(10) */
+    length += 2; /* compensate for truncating & provide space for minus sign */
+    result = (unsigned char *) malloc((size_t) (length+1));    /* remember the '\0'! */
+    if (result == NULL) return(NULL);
+    string = result;
+    sign = BitVector_Sign(addr);
+    if ((bits < 4) || (sign == 0))
+    {
+        if (bits > 0) digits = *addr; else digits = (unsigned int) 0;
+        if (sign < 0) digits = ((unsigned int)(-((signed int)digits))) & mask_(addr);
+        *string++ = (unsigned char) digits + (unsigned char) '0';
+        digits = 1;
+    }
+    else
+    {
+        quot = BitVector_Create(bits,false);
+        if (quot == NULL)
+        {
+            BitVector_Dispose(result);
+            return(NULL);
+        }
+        rest = BitVector_Create(bits,false);
+        if (rest == NULL)
+        {
+            BitVector_Dispose(result);
+            BitVector_Destroy(quot);
+            return(NULL);
+        }
+        temp = BitVector_Create(bits,false);
+        if (temp == NULL)
+        {
+            BitVector_Dispose(result);
+            BitVector_Destroy(quot);
+            BitVector_Destroy(rest);
+            return(NULL);
+        }
+        base = BitVector_Create(bits,true);
+        if (base == NULL)
+        {
+            BitVector_Dispose(result);
+            BitVector_Destroy(quot);
+            BitVector_Destroy(rest);
+            BitVector_Destroy(temp);
+            return(NULL);
+        }
+        if (sign < 0) BitVector_Negate(quot,addr);
+        else           BitVector_Copy(quot,addr);
+        digits = 0;
+        *base = EXP10;
+        loop = (bits >= BITS);
+        do
+        {
+            if (loop)
+            {
+                BitVector_Copy(temp,quot);
+                if (BitVector_Div_Pos(quot,temp,base,rest))
+                {
+                    BitVector_Dispose(result); /* emergency exit */
+                    BitVector_Destroy(quot);
+                    BitVector_Destroy(rest);   /* should never occur */
+                    BitVector_Destroy(temp);   /* under normal operation */
+                    BitVector_Destroy(base);
+                    return(NULL);
+                }
+                loop = ! BitVector_is_empty(quot);
+                q = *rest;
+            }
+            else q = *quot;
+            count = LOG10;
+            while (((loop && (count-- > 0)) || ((! loop) && (q != 0))) &&
+                (digits < length))
+            {
+                if (q != 0)
+                {
+                    BIT_VECTOR_DIGITIZE(unsigned int,q,r)
+                }
+                else r = (unsigned int) '0';
+                *string++ = (unsigned char) r;
+                digits++;
+            }
+        }
+        while (loop && (digits < length));
+        BitVector_Destroy(quot);
+        BitVector_Destroy(rest);
+        BitVector_Destroy(temp);
+        BitVector_Destroy(base);
+    }
+    if ((sign < 0) && (digits < length))
+    {
+        *string++ = (unsigned char) '-';
+        digits++;
+    }
+    *string = (unsigned char) '\0';
+    BIT_VECTOR_reverse(result,digits);
+    return(result);
+}
+
+ErrCode BitVector_from_Dec(unsigned int *  addr, unsigned char * string)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean init = (bits > BITS);
+    boolean minus;
+    boolean shift;
+    boolean carry;
+    unsigned int *  term;
+    unsigned int *  base;
+    unsigned int *  prod;
+    unsigned int *  rank;
+    unsigned int *  temp;
+    unsigned int  accu;
+    unsigned int  powr;
+    unsigned int  count;
+    unsigned int  length;
+    int     digit;
+
+    if (bits > 0)
+    {
+        length = strlen((char *) string);
+        if (length == 0) return(ErrCode_Pars);
+        digit = (int) *string;
+        if ((minus = (digit == (int) '-')) ||
+                     (digit == (int) '+'))
+        {
+            string++;
+            if (--length == 0) return(ErrCode_Pars);
+        }
+        string += length;
+        term = BitVector_Create(BITS,false);
+        if (term == NULL)
+        {
+            return(ErrCode_Null);
+        }
+        base = BitVector_Create(BITS,false);
+        if (base == NULL)
+        {
+            BitVector_Destroy(term);
+            return(ErrCode_Null);
+        }
+        prod = BitVector_Create(bits,init);
+        if (prod == NULL)
+        {
+            BitVector_Destroy(term);
+            BitVector_Destroy(base);
+            return(ErrCode_Null);
+        }
+        rank = BitVector_Create(bits,init);
+        if (rank == NULL)
+        {
+            BitVector_Destroy(term);
+            BitVector_Destroy(base);
+            BitVector_Destroy(prod);
+            return(ErrCode_Null);
+        }
+        temp = BitVector_Create(bits,false);
+        if (temp == NULL)
+        {
+            BitVector_Destroy(term);
+            BitVector_Destroy(base);
+            BitVector_Destroy(prod);
+            BitVector_Destroy(rank);
+            return(ErrCode_Null);
+        }
+        BitVector_Empty(addr);
+        *base = EXP10;
+        shift = false;
+        while ((! error) && (length > 0))
+        {
+            accu = 0;
+            powr = 1;
+            count = LOG10;
+            while ((! error) && (length > 0) && (count-- > 0))
+            {
+                digit = (int) *(--string); length--;
+                /* separate because isdigit() is likely a macro! */
+                if (isdigit(digit) != 0)
+                {
+                    accu += ((unsigned int) digit - (unsigned int) '0') * powr;
+                    powr *= 10;
+                }
+                else error = ErrCode_Pars;
+            }
+            if (! error)
+            {
+                if (shift)
+                {
+                    *term = accu;
+                    BitVector_Copy(temp,rank);
+                    error = BitVector_Mul_Pos(prod,temp,term,false);
+                }
+                else
+                {
+                    *prod = accu;
+                    if ((! init) && ((accu & ~ mask) != 0)) error = ErrCode_Ovfl;
+                }
+                if (! error)
+                {
+                    carry = false;
+                    BitVector_compute(addr,addr,prod,false,&carry);
+                    /* ignores sign change (= overflow) but ! */
+                    /* numbers too large (= carry) for resulting bit vector */
+                    if (carry) error = ErrCode_Ovfl;
+                    else
+                    {
+                        if (length > 0)
+                        {
+                            if (shift)
+                            {
+                                BitVector_Copy(temp,rank);
+                                error = BitVector_Mul_Pos(rank,temp,base,false);
+                            }
+                            else
+                            {
+                                *rank = *base;
+                                shift = true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        BitVector_Destroy(term);
+        BitVector_Destroy(base);
+        BitVector_Destroy(prod);
+        BitVector_Destroy(rank);
+        BitVector_Destroy(temp);
+        if (! error && minus)
+        {
+            BitVector_Negate(addr,addr);
+            if ((*(addr + size_(addr) - 1) & mask & ~ (mask >> 1)) == 0)
+                error = ErrCode_Ovfl;
+        }
+    }
+    return(error);
+}
+
+unsigned char * BitVector_to_Enum(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  sample;
+    unsigned int  length;
+    unsigned int  digits;
+    unsigned int  factor;
+    unsigned int  power;
+    unsigned int  start;
+    unsigned int  min;
+    unsigned int  max;
+    unsigned char * string;
+    unsigned char * target;
+    boolean comma;
+
+    if (bits > 0)
+    {
+        sample = bits - 1;  /* greatest possible index */
+        length = 2;         /* account for index 0 && terminating '\0' */
+        digits = 1;         /* account for intervening dashes && commas */
+        factor = 1;
+        power = 10;
+        while (sample >= (power-1))
+        {
+            length += ++digits * factor * 6;  /* 9,90,900,9000,... (9*2/3 = 6) */
+            factor = power;
+            power *= 10;
+        }
+        if (sample > --factor)
+        {
+            sample -= factor;
+            factor = (unsigned int) ( sample / 3 );
+            factor = (factor << 1) + (sample - (factor * 3));
+            length += ++digits * factor;
+        }
+    }
+    else length = 1;
+    string = (unsigned char *) malloc((size_t) length);
+    if (string == NULL) return(NULL);
+    start = 0;
+    comma = false;
+    target = string;
+    while ((start < bits) && BitVector_interval_scan_inc(addr,start,&min,&max))
+    {
+        start = max + 2;
+        if (comma) *target++ = (unsigned char) ',';
+        if (min == max)
+        {
+            target += BIT_VECTOR_int2str(target,min);
+        }
+        else
+        {
+            if (min+1 == max)
+            {
+                target += BIT_VECTOR_int2str(target,min);
+                *target++ = (unsigned char) ',';
+                target += BIT_VECTOR_int2str(target,max);
+            }
+            else
+            {
+                target += BIT_VECTOR_int2str(target,min);
+                *target++ = (unsigned char) '-';
+                target += BIT_VECTOR_int2str(target,max);
+            }
+        }
+        comma = true;
+    }
+    *target = (unsigned char) '\0';
+    return(string);
+}
+
+ErrCode BitVector_from_Enum(unsigned int *  addr, unsigned char * string)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(addr);
+    unsigned int  state = 1;
+    unsigned int  token;
+    unsigned int  index = 0;
+    unsigned int  start = 0;         /* silence compiler warning */
+
+    if (bits > 0)
+    {
+        BitVector_Empty(addr);
+        while ((! error) && (state != 0))
+        {
+            token = (unsigned int) *string;
+            /* separate because isdigit() is likely a macro! */
+            if (isdigit((int)token) != 0)
+            {
+                string += BIT_VECTOR_str2int(string,&index);
+                if (index < bits) token = (unsigned int) '0';
+                else error = ErrCode_Indx;
+            }
+            else string++;
+            if (! error)
+            switch (state)
+            {
+                case 1:
+                    switch (token)
+                    {
+                        case (unsigned int) '0':
+                            state = 2;
+                            break;
+                        case (unsigned int) '\0':
+                            state = 0;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 2:
+                    switch (token)
+                    {
+                        case (unsigned int) '-':
+                            start = index;
+                            state = 3;
+                            break;
+                        case (unsigned int) ',':
+                            BIT_VECTOR_SET_BIT(addr,index)
+                            state = 5;
+                            break;
+                        case (unsigned int) '\0':
+                            BIT_VECTOR_SET_BIT(addr,index)
+                            state = 0;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 3:
+                    switch (token)
+                    {
+                        case (unsigned int) '0':
+                            if (start < index)
+                                BitVector_Interval_Fill(addr,start,index);
+                            else if (start == index)
+                                BIT_VECTOR_SET_BIT(addr,index)
+                            else error = ErrCode_Ordr;
+                            state = 4;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 4:
+                    switch (token)
+                    {
+                        case (unsigned int) ',':
+                            state = 5;
+                            break;
+                        case (unsigned int) '\0':
+                            state = 0;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 5:
+                    switch (token)
+                    {
+                        case (unsigned int) '0':
+                            state = 2;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+            }
+        }
+    }
+    return(error);
+}
+
+void BitVector_Bit_Off(unsigned int *  addr, unsigned int index)           /* X = X \ {x}   */
+{
+    if (index < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,index)
+}
+
+void BitVector_Bit_On(unsigned int *  addr, unsigned int index)            /* X = X + {x}   */
+{
+    if (index < bits_(addr)) BIT_VECTOR_SET_BIT(addr,index)
+}
+
+boolean BitVector_bit_flip(unsigned int *  addr, unsigned int index)   /* X=(X+{x})\(X*{x}) */
+{
+    unsigned int mask;
+
+    if (index < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,index,mask) );
+    else                     return( false );
+}
+
+boolean BitVector_bit_test(unsigned int *  addr, unsigned int index)       /* {x} in X ?    */
+{
+    if (index < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,index) );
+    else                     return( false );
+}
+
+void BitVector_Bit_Copy(unsigned int *  addr, unsigned int index, boolean bit)
+{
+    if (index < bits_(addr))
+    {
+        if (bit) BIT_VECTOR_SET_BIT(addr,index)
+        else     BIT_VECTOR_CLR_BIT(addr,index)
+    }
+}
+
+void BitVector_LSB(unsigned int *  addr, boolean bit)
+{
+    if (bits_(addr) > 0)
+    {
+        if (bit) *addr |= LSB;
+        else     *addr &= ~ LSB;
+    }
+}
+
+void BitVector_MSB(unsigned int *  addr, boolean bit)
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+
+    if (size-- > 0)
+    {
+        if (bit) *(addr+size) |= mask & ~ (mask >> 1);
+        else     *(addr+size) &= ~ mask | (mask >> 1);
+    }
+}
+
+boolean BitVector_lsb_(unsigned int *  addr)
+{
+    if (size_(addr) > 0) return( (*addr & LSB) != 0 );
+    else                 return( false );
+}
+
+boolean BitVector_msb_(unsigned int *  addr)
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+
+    if (size-- > 0)
+        return( (*(addr+size) & (mask & ~ (mask >> 1))) != 0 );
+    else
+        return( false );
+}
+
+boolean BitVector_rotate_left(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_in;
+    boolean carry_out = false;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        carry_in = ((*(addr+size-1) & msb) != 0);
+        while (size-- > 1)
+        {
+            carry_out = ((*addr & MSB) != 0);
+            *addr <<= 1;
+            if (carry_in) *addr |= LSB;
+            carry_in = carry_out;
+            addr++;
+        }
+        carry_out = ((*addr & msb) != 0);
+        *addr <<= 1;
+        if (carry_in) *addr |= LSB;
+        *addr &= mask;
+    }
+    return(carry_out);
+}
+
+boolean BitVector_rotate_right(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_in;
+    boolean carry_out = false;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        carry_in = ((*addr & LSB) != 0);
+        addr += size-1;
+        *addr &= mask;
+        carry_out = ((*addr & LSB) != 0);
+        *addr >>= 1;
+        if (carry_in) *addr |= msb;
+        carry_in = carry_out;
+        addr--;
+        size--;
+        while (size-- > 0)
+        {
+            carry_out = ((*addr & LSB) != 0);
+            *addr >>= 1;
+            if (carry_in) *addr |= MSB;
+            carry_in = carry_out;
+            addr--;
+        }
+    }
+    return(carry_out);
+}
+
+boolean BitVector_shift_left(unsigned int *  addr, boolean carry_in)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_out = carry_in;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        while (size-- > 1)
+        {
+            carry_out = ((*addr & MSB) != 0);
+            *addr <<= 1;
+            if (carry_in) *addr |= LSB;
+            carry_in = carry_out;
+            addr++;
+        }
+        carry_out = ((*addr & msb) != 0);
+        *addr <<= 1;
+        if (carry_in) *addr |= LSB;
+        *addr &= mask;
+    }
+    return(carry_out);
+}
+
+boolean BitVector_shift_right(unsigned int *  addr, boolean carry_in)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_out = carry_in;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        addr += size-1;
+        *addr &= mask;
+        carry_out = ((*addr & LSB) != 0);
+        *addr >>= 1;
+        if (carry_in) *addr |= msb;
+        carry_in = carry_out;
+        addr--;
+        size--;
+        while (size-- > 0)
+        {
+            carry_out = ((*addr & LSB) != 0);
+            *addr >>= 1;
+            if (carry_in) *addr |= MSB;
+            carry_in = carry_out;
+            addr--;
+        }
+    }
+    return(carry_out);
+}
+
+void BitVector_Move_Left(unsigned int *  addr, unsigned int bits)
+{
+    unsigned int count;
+    unsigned int words;
+
+    if (bits > 0)
+    {
+        count = bits & MODMASK;
+        words = bits >> LOGBITS;
+        if (bits >= bits_(addr)) BitVector_Empty(addr);
+        else
+        {
+            while (count-- > 0) BitVector_shift_left(addr,0);
+            BitVector_Word_Insert(addr,0,words,true);
+        }
+    }
+}
+
+void BitVector_Move_Right(unsigned int *  addr, unsigned int bits)
+{
+    unsigned int count;
+    unsigned int words;
+
+    if (bits > 0)
+    {
+        count = bits & MODMASK;
+        words = bits >> LOGBITS;
+        if (bits >= bits_(addr)) BitVector_Empty(addr);
+        else
+        {
+            while (count-- > 0) BitVector_shift_right(addr,0);
+            BitVector_Word_Delete(addr,0,words,true);
+        }
+    }
+}
+
+void BitVector_Insert(unsigned int *  addr, unsigned int offset, unsigned int count, boolean clear)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int last;
+
+    if ((count > 0) && (offset < bits))
+    {
+        last = offset + count;
+        if (last < bits)
+        {
+            BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
+        }
+        else last = bits;
+        if (clear) BitVector_Interval_Empty(addr,offset,(last-1));
+    }
+}
+
+void BitVector_Delete(unsigned int *  addr, unsigned int offset, unsigned int count, boolean clear)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int last;
+
+    if ((count > 0) && (offset < bits))
+    {
+        last = offset + count;
+        if (last < bits)
+        {
+            BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
+        }
+        else count = bits - offset;
+        if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
+    }
+}
+
+boolean BitVector_increment(unsigned int *  addr)                   /* X++           */
+{
+    unsigned int  size  = size_(addr);
+    unsigned int  mask  = mask_(addr);
+    unsigned int *  last  = addr + size - 1;
+    boolean carry = true;
+
+    if (size > 0)
+    {
+        *last |= ~ mask;
+        while (carry && (size-- > 0))
+        {
+            carry = (++(*addr++) == 0);
+        }
+        *last &= mask;
+    }
+    return(carry);
+}
+
+boolean BitVector_decrement(unsigned int *  addr)                   /* X--           */
+{
+    unsigned int  size  = size_(addr);
+    unsigned int  mask  = mask_(addr);
+    unsigned int *  last  = addr + size - 1;
+    boolean carry = true;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        while (carry && (size-- > 0))
+        {
+            carry = (*addr == 0);
+            --(*addr++);
+        }
+        *last &= mask;
+    }
+    return(carry);
+}
+
+boolean BitVector_compute(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean minus, boolean *carry)
+{
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+    unsigned int vv = 0;
+    unsigned int cc;
+    unsigned int mm;
+    unsigned int yy;
+    unsigned int zz;
+    unsigned int lo;
+    unsigned int hi;
+
+    if (size > 0)
+    {
+        if (minus) cc = (*carry == 0);
+        else       cc = (*carry != 0);
+        /* deal with (size-1) least significant full words first: */
+        while (--size > 0)
+        {
+            yy = *Y++;
+            if (minus) zz = (unsigned int) ~ ( Z ? *Z++ : 0 );
+            else       zz = (unsigned int)     ( Z ? *Z++ : 0 );
+            lo = (yy & LSB) + (zz & LSB) + cc;
+            hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
+            cc = ((hi & MSB) != 0);
+            *X++ = (hi << 1) | (lo & LSB);
+        }
+        /* deal with most significant word (may be used only partially): */
+        yy = *Y & mask;
+        if (minus) zz = (unsigned int) ~ ( Z ? *Z : 0 );
+        else       zz = (unsigned int)     ( Z ? *Z : 0 );
+        zz &= mask;
+        if (mask == LSB) /* special case, only one bit used */
+        {
+            vv = cc;
+            lo = yy + zz + cc;
+            cc = (lo >> 1);
+            vv ^= cc;
+            *X = lo & LSB;
+        }
+        else
+        {
+            if (~ mask) /* not all bits are used, but more than one */
+            {
+                mm = (mask >> 1);
+                vv = (yy & mm) + (zz & mm) + cc;
+                mm = mask & ~ mm;
+                lo = yy + zz + cc;
+                cc = (lo >> 1);
+                vv ^= cc;
+                vv &= mm;
+                cc &= mm;
+                *X = lo & mask;
+            }
+            else /* other special case, all bits are used */
+            {
+                mm = ~ MSB;
+                lo = (yy & mm) + (zz & mm) + cc;
+                vv = lo & MSB;
+                hi = ((yy & MSB) >> 1) + ((zz & MSB) >> 1) + (vv >> 1);
+                cc = hi & MSB;
+                vv ^= cc;
+                *X = (hi << 1) | (lo & mm);
+            }
+        }
+        if (minus) *carry = (cc == 0);
+        else       *carry = (cc != 0);
+    }
+    return(vv != 0);
+}
+
+boolean BitVector_add(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean *carry)
+{
+    return(BitVector_compute(X,Y,Z,false,carry));
+}
+
+boolean BitVector_sub(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean *carry)
+{
+    return(BitVector_compute(X,Y,Z,true,carry));
+}
+
+boolean BitVector_inc(unsigned int *  X, unsigned int *  Y)
+{
+    boolean carry = true;
+
+    return(BitVector_compute(X,Y,NULL,false,&carry));
+}
+
+boolean BitVector_dec(unsigned int *  X, unsigned int *  Y)
+{
+    boolean carry = true;
+
+    return(BitVector_compute(X,Y,NULL,true,&carry));
+}
+
+void BitVector_Negate(unsigned int *  X, unsigned int *  Y)
+{
+    unsigned int  size  = size_(X);
+    unsigned int  mask  = mask_(X);
+    boolean carry = true;
+
+    if (size > 0)
+    {
+        while (size-- > 0)
+        {
+            *X = ~ *Y++;
+            if (carry)
+            {
+                carry = (++(*X) == 0);
+            }
+            X++;
+        }
+        *(--X) &= mask;
+    }
+}
+
+void BitVector_Absolute(unsigned int *  X, unsigned int *  Y)
+{
+    unsigned int size = size_(Y);
+    unsigned int mask = mask_(Y);
+
+    if (size > 0)
+    {
+        if (*(Y+size-1) & (mask & ~ (mask >> 1))) BitVector_Negate(X,Y);
+        else                                             BitVector_Copy(X,Y);
+    }
+}
+
+// FIXME:  What the hell does the return value of this mean?
+// It returns 0, 1, or -1 under mysterious circumstances.
+signed int BitVector_Sign(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int *  last = addr + size - 1;
+    boolean r    = true;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        while (r && (size-- > 0)) r = ( *addr++ == 0 );
+    }
+    if (r) return((signed int) 0);
+    else
+    {
+        if (*last & (mask & ~ (mask >> 1))) return((signed int) -1);
+        else                                      return((signed int)  1);
+    }
+}
+
+ErrCode BitVector_Mul_Pos(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean strict)
+{
+    unsigned int  mask;
+    unsigned int  limit;
+    unsigned int  count;
+    signed long  last;
+    unsigned int *  sign;
+    boolean carry;
+    boolean overflow;
+    boolean ok = true;
+
+    /*
+       Requirements:
+         -  X, Y && Z must be distinct
+         -  X && Y must have equal sizes (whereas Z may be any size!)
+         -  Z should always contain the SMALLER of the two factors Y && Z
+       Constraints:
+         -  The contents of Y (&& of X, of course) are destroyed
+            (only Z is preserved!)
+    */
+
+    if ((X == Y) || (X == Z) || (Y == Z)) return(ErrCode_Same);
+    if (bits_(X) != bits_(Y)) return(ErrCode_Size);
+    BitVector_Empty(X);
+    if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */
+    if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok);
+    limit = (unsigned int) last;
+    sign = Y + size_(Y) - 1;
+    mask = mask_(Y);
+    *sign &= mask;
+    mask &= ~ (mask >> 1);
+    for ( count = 0; (ok && (count <= limit)); count++ )
+    {
+        if ( BIT_VECTOR_TST_BIT(Z,count) )
+        {
+            carry = false;
+            overflow = BitVector_compute(X,X,Y,false,&carry);
+            if (strict) ok = ! (carry || overflow);
+            else        ok = !  carry;
+        }
+        if (ok && (count < limit))
+        {
+            carry = BitVector_shift_left(Y,0);
+            if (strict)
+            {
+                overflow = ((*sign & mask) != 0);
+                ok = ! (carry || overflow);
+            }
+            else ok = ! carry;
+        }
+    }
+    if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl);
+}
+
+ErrCode BitVector_Multiply(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bit_x = bits_(X);
+    unsigned int  bit_y = bits_(Y);
+    unsigned int  bit_z = bits_(Z);
+    unsigned int  size;
+    unsigned int  mask;
+    unsigned int  msb;
+    unsigned int *  ptr_y;
+    unsigned int *  ptr_z;
+    boolean sgn_x;
+    boolean sgn_y;
+    boolean sgn_z;
+    boolean zero;
+    unsigned int *  A;
+    unsigned int *  B;
+
+    /*
+       Requirements:
+         -  Y && Z must have equal sizes
+         -  X must have at least the same size as Y && Z but may be larger (!)
+       Features:
+         -  The contents of Y && Z are preserved
+         -  X may be identical with Y or Z (or both!)
+            (in-place multiplication is possible!)
+    */
+
+    if ((bit_y != bit_z) || (bit_x < bit_y)) return(ErrCode_Size);
+    if (BitVector_is_empty(Y) || BitVector_is_empty(Z))
+    {
+        BitVector_Empty(X);
+    }
+    else
+    {
+        A = BitVector_Create(bit_y,false);
+        if (A == NULL) return(ErrCode_Null);
+        B = BitVector_Create(bit_z,false);
+        if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+        size  = size_(Y);
+        mask  = mask_(Y);
+        msb   = (mask & ~ (mask >> 1));
+        sgn_y = (((*(Y+size-1) &= mask) & msb) != 0);
+        sgn_z = (((*(Z+size-1) &= mask) & msb) != 0);
+        sgn_x = sgn_y ^ sgn_z;
+        if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+        if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+        ptr_y = A + size;
+        ptr_z = B + size;
+        zero = true;
+        while (zero && (size-- > 0))
+        {
+            zero &= (*(--ptr_y) == 0);
+            zero &= (*(--ptr_z) == 0);
+        }
+        if (*ptr_y > *ptr_z)
+        {
+            if (bit_x > bit_y)
+            {
+                A = BitVector_Resize(A,bit_x);
+                if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); }
+            }
+            error = BitVector_Mul_Pos(X,A,B,true);
+        }
+        else
+        {
+            if (bit_x > bit_z)
+            {
+                B = BitVector_Resize(B,bit_x);
+                if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+            }
+            error = BitVector_Mul_Pos(X,B,A,true);
+        }
+        if ((! error) && sgn_x) BitVector_Negate(X,X);
+        BitVector_Destroy(A);
+        BitVector_Destroy(B);
+    }
+    return(error);
+}
+
+ErrCode BitVector_Div_Pos(unsigned int *  Q, unsigned int *  X, unsigned int *  Y, unsigned int *  R)
+{
+    unsigned int  bits = bits_(Q);
+    unsigned int  mask;
+    unsigned int *  addr;
+    signed long  last;
+    boolean flag;
+    boolean copy = false; /* flags whether valid rest is in R (0) || X (1) */
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+         -  Q, X, Y && R must all be distinct bit vectors
+         -  Y must be non-zero (of course!)
+       Constraints:
+         -  The contents of X (&& Q && R, of course) are destroyed
+            (only Y is preserved!)
+    */
+
+    if ((bits != bits_(X)) || (bits != bits_(Y)) || (bits != bits_(R)))
+        return(ErrCode_Size);
+    if ((Q == X) || (Q == Y) || (Q == R) || (X == Y) || (X == R) || (Y == R))
+        return(ErrCode_Same);
+    if (BitVector_is_empty(Y))
+        return(ErrCode_Zero);
+
+    BitVector_Empty(R);
+    BitVector_Copy(Q,X);
+    if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok);
+    bits = (unsigned int) ++last;
+    while (bits-- > 0)
+    {
+        addr = Q + (bits >> LOGBITS);
+        mask = BITMASKTAB[bits & MODMASK];
+        flag = ((*addr & mask) != 0);
+        if (copy)
+        {
+            BitVector_shift_left(X,flag);
+            flag = false;
+            BitVector_compute(R,X,Y,true,&flag);
+        }
+        else
+        {
+            BitVector_shift_left(R,flag);
+            flag = false;
+            BitVector_compute(X,R,Y,true,&flag);
+        }
+        if (flag) *addr &= ~ mask;
+        else
+        {
+            *addr |= mask;
+            copy = ! copy;
+        }
+    }
+    if (copy) BitVector_Copy(R,X);
+    return(ErrCode_Ok);
+}
+
+ErrCode BitVector_Divide(unsigned int *  Q, unsigned int *  X, unsigned int *  Y, unsigned int *  R)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(Q);
+    unsigned int  size = size_(Q);
+    unsigned int  mask = mask_(Q);
+    unsigned int  msb = (mask & ~ (mask >> 1));
+    boolean sgn_q;
+    boolean sgn_x;
+    boolean sgn_y;
+    unsigned int *  A;
+    unsigned int *  B;
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+         -  Q && R must be two distinct bit vectors
+         -  Y must be non-zero (of course!)
+       Features:
+         -  The contents of X && Y are preserved
+         -  Q may be identical with X || Y (or both)
+            (in-place division is possible!)
+         -  R may be identical with X || Y (or both)
+            (but not identical with Q!)
+    */
+
+    if ((bits != bits_(X)) || (bits != bits_(Y)) || (bits != bits_(R)))
+        return(ErrCode_Size);
+    if (Q == R)
+        return(ErrCode_Same);
+    if (BitVector_is_empty(Y))
+        return(ErrCode_Zero);
+
+    if (BitVector_is_empty(X))
+    {
+        BitVector_Empty(Q);
+        BitVector_Empty(R);
+    }
+    else
+    {
+        A = BitVector_Create(bits,false);
+        if (A == NULL) return(ErrCode_Null);
+        B = BitVector_Create(bits,false);
+        if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+        size--;
+        sgn_x = (((*(X+size) &= mask) & msb) != 0);
+        sgn_y = (((*(Y+size) &= mask) & msb) != 0);
+        sgn_q = sgn_x ^ sgn_y;
+        if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+        if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+        if (! (error = BitVector_Div_Pos(Q,A,B,R)))
+        {
+            if (sgn_q) BitVector_Negate(Q,Q);
+            if (sgn_x) BitVector_Negate(R,R);
+        }
+        BitVector_Destroy(A);
+        BitVector_Destroy(B);
+    }
+    return(error);
+}
+
+ErrCode BitVector_GCD(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(X);
+    unsigned int  size = size_(X);
+    unsigned int  mask = mask_(X);
+    unsigned int  msb = (mask & ~ (mask >> 1));
+    boolean sgn_a;
+    boolean sgn_b;
+    boolean sgn_r;
+    unsigned int *  Q;
+    unsigned int *  R;
+    unsigned int *  A;
+    unsigned int *  B;
+    unsigned int *  T;
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+       Features:
+         -  The contents of Y && Z are preserved
+         -  X may be identical with Y || Z (or both)
+            (in-place is possible!)
+         -  GCD(0,z) == GCD(z,0) == z
+         -  negative values are h&&led correctly
+    */
+
+    if ((bits != bits_(Y)) || (bits != bits_(Z))) return(ErrCode_Size);
+    if (BitVector_is_empty(Y))
+    {
+        if (X != Z) BitVector_Copy(X,Z);
+        return(ErrCode_Ok);
+    }
+    if (BitVector_is_empty(Z))
+    {
+        if (X != Y) BitVector_Copy(X,Y);
+        return(ErrCode_Ok);
+    }
+    Q = BitVector_Create(bits,false);
+    if (Q == NULL)
+    {
+        return(ErrCode_Null);
+    }
+    R = BitVector_Create(bits,false);
+    if (R == NULL)
+    {
+        BitVector_Destroy(Q);
+        return(ErrCode_Null);
+    }
+    A = BitVector_Create(bits,false);
+    if (A == NULL)
+    {
+        BitVector_Destroy(Q);
+        BitVector_Destroy(R);
+        return(ErrCode_Null);
+    }
+    B = BitVector_Create(bits,false);
+    if (B == NULL)
+    {
+        BitVector_Destroy(Q);
+        BitVector_Destroy(R);
+        BitVector_Destroy(A);
+        return(ErrCode_Null);
+    }
+    size--;
+    sgn_a = (((*(Y+size) &= mask) & msb) != 0);
+    sgn_b = (((*(Z+size) &= mask) & msb) != 0);
+    if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+    if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+    while (! error)
+    {
+        if (! (error = BitVector_Div_Pos(Q,A,B,R)))
+        {
+            if (BitVector_is_empty(R)) break;
+            T = A; sgn_r = sgn_a;
+            A = B; sgn_a = sgn_b;
+            B = R; sgn_b = sgn_r;
+            R = T;
+        }
+    }
+    if (! error)
+    {
+        if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B);
+    }
+    BitVector_Destroy(Q);
+    BitVector_Destroy(R);
+    BitVector_Destroy(A);
+    BitVector_Destroy(B);
+    return(error);
+}
+
+ErrCode BitVector_GCD2(unsigned int *  U, unsigned int *  V, unsigned int *  W, unsigned int *  X, unsigned int *  Y)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(U);
+    unsigned int  size = size_(U);
+    unsigned int  mask = mask_(U);
+    unsigned int  msb = (mask & ~ (mask >> 1));
+    boolean minus;
+    boolean carry;
+    boolean sgn_q;
+    boolean sgn_r;
+    boolean sgn_a;
+    boolean sgn_b;
+    boolean sgn_x;
+    boolean sgn_y;
+    unsigned int *  *  L;
+    unsigned int *  Q;
+    unsigned int *  R;
+    unsigned int *  A;
+    unsigned int *  B;
+    unsigned int *  T;
+    unsigned int *  X1;
+    unsigned int *  X2;
+    unsigned int *  X3;
+    unsigned int *  Y1;
+    unsigned int *  Y2;
+    unsigned int *  Y3;
+    unsigned int *  Z;
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+         -  U, V, && W must all be distinct bit vectors
+       Features:
+         -  The contents of X && Y are preserved
+         -  U, V && W may be identical with X || Y (or both,
+            provided that U, V && W are mutually distinct)
+            (i.e., in-place is possible!)
+         -  GCD(0,z) == GCD(z,0) == z
+         -  negative values are h&&led correctly
+    */
+
+    if ((bits != bits_(V)) ||
+        (bits != bits_(W)) ||
+        (bits != bits_(X)) ||
+        (bits != bits_(Y)))
+    {
+        return(ErrCode_Size);
+    }
+    if ((U == V) || (U == W) || (V == W))
+    {
+        return(ErrCode_Same);
+    }
+    if (BitVector_is_empty(X))
+    {
+        if (U != Y) BitVector_Copy(U,Y);
+        BitVector_Empty(V);
+        BitVector_Empty(W);
+        *W = 1;
+        return(ErrCode_Ok);
+    }
+    if (BitVector_is_empty(Y))
+    {
+        if (U != X) BitVector_Copy(U,X);
+        BitVector_Empty(V);
+        BitVector_Empty(W);
+        *V = 1;
+        return(ErrCode_Ok);
+    }
+    if ((L = BitVector_Create_List(bits,false,11)) == NULL)
+    {
+        return(ErrCode_Null);
+    }
+    Q  = L[0];
+    R  = L[1];
+    A  = L[2];
+    B  = L[3];
+    X1 = L[4];
+    X2 = L[5];
+    X3 = L[6];
+    Y1 = L[7];
+    Y2 = L[8];
+    Y3 = L[9];
+    Z  = L[10];
+    size--;
+    sgn_a = (((*(X+size) &= mask) & msb) != 0);
+    sgn_b = (((*(Y+size) &= mask) & msb) != 0);
+    if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+    if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+    BitVector_Empty(X1);
+    BitVector_Empty(X2);
+    *X1 = 1;
+    BitVector_Empty(Y1);
+    BitVector_Empty(Y2);
+    *Y2 = 1;
+    sgn_x = false;
+    sgn_y = false;
+    while (! error)
+    {
+        if ((error = BitVector_Div_Pos(Q,A,B,R)))
+        {
+            break;
+        }
+        if (BitVector_is_empty(R))
+        {
+            break;
+        }
+        sgn_q = sgn_a ^ sgn_b;
+
+        if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2);
+        if ((error = BitVector_Mul_Pos(X3,Z,Q,true)))
+        {
+            break;
+        }
+        minus = ! (sgn_x ^ sgn_q);
+        carry = 0;
+        if (BitVector_compute(X3,X1,X3,minus,&carry))
+        {
+            error = ErrCode_Ovfl;
+            break;
+        }
+        sgn_x = (((*(X3+size) &= mask) & msb) != 0);
+
+        if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2);
+        if ((error = BitVector_Mul_Pos(Y3,Z,Q,true)))
+        {
+            break;
+        }
+        minus = ! (sgn_y ^ sgn_q);
+        carry = 0;
+        if (BitVector_compute(Y3,Y1,Y3,minus,&carry))
+        {
+            error = ErrCode_Ovfl;
+            break;
+        }
+        sgn_y = (((*(Y3+size) &= mask) & msb) != 0);
+
+        T = A; sgn_r = sgn_a;
+        A = B; sgn_a = sgn_b;
+        B = R; sgn_b = sgn_r;
+        R = T;
+
+        T = X1;
+        X1 = X2;
+        X2 = X3;
+        X3 = T;
+
+        T = Y1;
+        Y1 = Y2;
+        Y2 = Y3;
+        Y3 = T;
+    }
+    if (! error)
+    {
+        if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B);
+        BitVector_Copy(V,X2);
+        BitVector_Copy(W,Y2);
+    }
+    BitVector_Destroy_List(L,11);
+    return(error);
+}
+
+ErrCode BitVector_Power(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits  = bits_(X);
+    boolean first = true;
+    signed long  last;
+    unsigned int  limit;
+    unsigned int  count;
+    unsigned int *  T;
+
+    /*
+       Requirements:
+         -  X must have at least the same size as Y but may be larger (!)
+         -  X may not be identical with Z
+         -  Z must be positive
+       Features:
+         -  The contents of Y && Z are preserved
+    */
+
+    if (X == Z) return(ErrCode_Same);
+    if (bits < bits_(Y)) return(ErrCode_Size);
+    if (BitVector_msb_(Z)) return(ErrCode_Expo);
+    if ((last = Set_Max(Z)) < 0L)
+    {
+        if (bits < 2) return(ErrCode_Ovfl);
+        BitVector_Empty(X);
+        *X |= LSB;
+        return(ErrCode_Ok);                             /* anything ^ 0 == 1 */
+    }
+    if (BitVector_is_empty(Y))
+    {
+        if (X != Y) BitVector_Empty(X);
+        return(ErrCode_Ok);                    /* 0 ^ anything ! zero == 0 */
+    }
+    T = BitVector_Create(bits,false);
+    if (T == NULL) return(ErrCode_Null);
+    limit = (unsigned int) last;
+    for ( count = 0; ((!error) && (count <= limit)); count++ )
+    {
+        if ( BIT_VECTOR_TST_BIT(Z,count) )
+        {
+            if (first)
+            {
+                first = false;
+                if (count) {             BitVector_Copy(X,T); }
+                else       { if (X != Y) BitVector_Copy(X,Y); }
+            }
+            else error = BitVector_Multiply(X,T,X); /* order important because T > X */
+        }
+        if ((!error) && (count < limit))
+        {
+            if (count) error = BitVector_Multiply(T,T,T);
+            else       error = BitVector_Multiply(T,Y,Y);
+        }
+    }
+    BitVector_Destroy(T);
+    return(error);
+}
+
+void BitVector_Block_Store(unsigned int *  addr, unsigned char * buffer, unsigned int length)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  value;
+    unsigned int  count;
+
+    /* provide translation for independence of endian-ness: */
+    if (size > 0)
+    {
+        while (size-- > 0)
+        {
+            value = 0;
+            for ( count = 0; (length > 0) && (count < BITS); count += 8 )
+            {
+                value |= (((unsigned int) *buffer++) << count); length--;
+            }
+            *addr++ = value;
+        }
+        *(--addr) &= mask;
+    }
+}
+
+unsigned char * BitVector_Block_Read(unsigned int *  addr, unsigned int * length)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  value;
+    unsigned int  count;
+    unsigned char * buffer;
+    unsigned char * target;
+
+    /* provide translation for independence of endian-ness: */
+    *length = size << FACTOR;
+    buffer = (unsigned char *) malloc((size_t) ((*length)+1));
+    if (buffer == NULL) return(NULL);
+    target = buffer;
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while (size-- > 0)
+        {
+            value = *addr++;
+            count = BITS >> 3;
+            while (count-- > 0)
+            {
+                *target++ = (unsigned char) (value & 0x00FF);
+                if (count > 0) value >>= 8;
+            }
+        }
+    }
+    *target = (unsigned char) '\0';
+    return(buffer);
+}
+
+void BitVector_Word_Store(unsigned int *  addr, unsigned int offset, unsigned int value)
+{
+    unsigned int size = size_(addr);
+
+    if (size > 0)
+    {
+        if (offset < size) *(addr+offset) = value;
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+unsigned int BitVector_Word_Read(unsigned int *  addr, unsigned int offset)
+{
+    unsigned int size = size_(addr);
+
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        if (offset < size) return( *(addr+offset) );
+    }
+    return( (unsigned int) 0 );
+}
+
+void BitVector_Word_Insert(unsigned int *  addr, unsigned int offset, unsigned int count,
+                           boolean clear)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int *  last = addr+size-1;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        if (offset > size) offset = size;
+        BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
+        *last &= mask;
+    }
+}
+
+void BitVector_Word_Delete(unsigned int *  addr, unsigned int offset, unsigned int count,
+                           boolean clear)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int *  last = addr+size-1;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        if (offset > size) offset = size;
+        BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
+        *last &= mask;
+    }
+}
+
+void BitVector_Chunk_Store(unsigned int *  addr, unsigned int chunksize, unsigned int offset,
+                           unsigned long value)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int mask;
+    unsigned int temp;
+
+    if ((chunksize > 0) && (offset < bits))
+    {
+        if (chunksize > LONGBITS) chunksize = LONGBITS;
+        if ((offset + chunksize) > bits) chunksize = bits - offset;
+        addr += offset >> LOGBITS;
+        offset &= MODMASK;
+        while (chunksize > 0)
+        {
+            mask = (unsigned int) (~0L << offset);
+            bits = offset + chunksize;
+            if (bits < BITS)
+            {
+                mask &= (unsigned int) ~(~0L << bits);
+                bits = chunksize;
+            }
+            else bits = BITS - offset;
+            temp = (unsigned int) (value << offset);
+            temp &= mask;
+            *addr &= ~ mask;
+            *addr++ |= temp;
+            value >>= bits;
+            chunksize -= bits;
+            offset = 0;
+        }
+    }
+}
+
+unsigned long BitVector_Chunk_Read(unsigned int *  addr, unsigned int chunksize, unsigned int offset)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int chunkbits = 0;
+    unsigned long value = 0L;
+    unsigned long temp;
+    unsigned int mask;
+
+    if ((chunksize > 0) && (offset < bits))
+    {
+        if (chunksize > LONGBITS) chunksize = LONGBITS;
+        if ((offset + chunksize) > bits) chunksize = bits - offset;
+        addr += offset >> LOGBITS;
+        offset &= MODMASK;
+        while (chunksize > 0)
+        {
+            bits = offset + chunksize;
+            if (bits < BITS)
+            {
+                mask = (unsigned int) ~(~0L << bits);
+                bits = chunksize;
+            }
+            else
+            {
+                mask = (unsigned int) ~0L;
+                bits = BITS - offset;
+            }
+            temp = (unsigned long) ((*addr++ & mask) >> offset);
+            value |= temp << chunkbits;
+            chunkbits += bits;
+            chunksize -= bits;
+            offset = 0;
+        }
+    }
+    return(value);
+}
+
+    /*******************/
+    /* set operations: */
+    /*******************/
+
+void Set_Union(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)             /* X = Y + Z     */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ | *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_Intersection(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)      /* X = Y * Z     */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ & *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_Difference(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)        /* X = Y \ Z     */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ & ~ *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_ExclusiveOr(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)       /* X=(Y+Z)\(Y*Z) */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ ^ *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_Complement(unsigned int *  X, unsigned int *  Y)                   /* X = ~Y        */
+{
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits_(X) == bits_(Y)))
+    {
+        while (size-- > 0) *X++ = ~ *Y++;
+        *(--X) &= mask;
+    }
+}
+
+    /******************/
+    /* set functions: */
+    /******************/
+
+boolean Set_subset(unsigned int *  X, unsigned int *  Y)                    /* X subset Y ?  */
+{
+    unsigned int size = size_(X);
+    boolean r = false;
+
+    if ((size > 0) && (bits_(X) == bits_(Y)))
+    {
+        r = true;
+        while (r && (size-- > 0)) r = ((*X++ & ~ *Y++) == 0);
+    }
+    return(r);
+}
+
+unsigned int Set_Norm(unsigned int *  addr)                                /* = | X |       */
+{
+    unsigned char * byte;
+    unsigned int  bytes;
+    unsigned int   n;
+
+    byte = (unsigned char *) addr;
+    bytes = size_(addr) << FACTOR;
+    n = 0;
+    while (bytes-- > 0)
+    {
+        n += BitVector_BYTENORM[*byte++];
+    }
+    return(n);
+}
+
+unsigned int Set_Norm2(unsigned int *  addr)                               /* = | X |       */
+{
+    unsigned int  size = size_(addr);
+    unsigned int  w0,w1;
+    unsigned int   n,k;
+
+    n = 0;
+    while (size-- > 0)
+    {
+        k = 0;
+        w1 = ~ (w0 = *addr++);
+        while (w0 && w1)
+        {
+            w0 &= w0 - 1;
+            w1 &= w1 - 1;
+            k++;
+        }
+        if (w0 == 0) n += k;
+        else         n += BITS - k;
+    }
+    return(n);
+}
+
+unsigned int Set_Norm3(unsigned int *  addr)                               /* = | X |       */
+{
+    unsigned int  size  = size_(addr);
+    unsigned int   count = 0;
+    unsigned int  c;
+
+    while (size-- > 0)
+    {
+        c = *addr++;
+        while (c)
+        {
+            c &= c - 1;
+            count++;
+        }
+    }
+    return(count);
+}
+
+signed long Set_Min(unsigned int *  addr)                                /* = min(X)      */
+{
+    boolean empty = true;
+    unsigned int  size  = size_(addr);
+    unsigned int  i     = 0;
+    unsigned int  c     = 0;         /* silence compiler warning */
+
+    while (empty && (size-- > 0))
+    {
+        if ((c = *addr++)) empty = false; else i++;
+    }
+    if (empty) return((signed long) LONG_MAX);                  /* plus infinity  */
+    i <<= LOGBITS;
+    while (! (c & LSB))
+    {
+        c >>= 1;
+        i++;
+    }
+    return((signed long) i);
+}
+
+signed long Set_Max(unsigned int *  addr)                                /* = max(X)      */
+{
+    boolean empty = true;
+    unsigned int  size  = size_(addr);
+    unsigned int  i     = size;
+    unsigned int  c     = 0;         /* silence compiler warning */
+
+    addr += size-1;
+    while (empty && (size-- > 0))
+    {
+        if ((c = *addr--)) empty = false; else i--;
+    }
+    if (empty) return((signed long) LONG_MIN);                  /* minus infinity */
+    i <<= LOGBITS;
+    while (! (c & MSB))
+    {
+        c <<= 1;
+        i--;
+    }
+    return((signed long) --i);
+}
+
+    /**********************************/
+    /* matrix-of-booleans operations: */
+    /**********************************/
+
+void Matrix_Multiplication(unsigned int *  X, unsigned int rowsX, unsigned int colsX,
+                           unsigned int *  Y, unsigned int rowsY, unsigned int colsY,
+                           unsigned int *  Z, unsigned int rowsZ, unsigned int colsZ)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int k;
+    unsigned int indxX;
+    unsigned int indxY;
+    unsigned int indxZ;
+    unsigned int termX;
+    unsigned int termY;
+    unsigned int sum;
+
+  if ((colsY == rowsZ) && (rowsX == rowsY) && (colsX == colsZ) &&
+      (bits_(X) == rowsX*colsX) &&
+      (bits_(Y) == rowsY*colsY) &&
+      (bits_(Z) == rowsZ*colsZ))
+  {
+    for ( i = 0; i < rowsY; i++ )
+    {
+        termX = i * colsX;
+        termY = i * colsY;
+        for ( j = 0; j < colsZ; j++ )
+        {
+            indxX = termX + j;
+            sum = 0;
+            for ( k = 0; k < colsY; k++ )
+            {
+                indxY = termY + k;
+                indxZ = k * colsZ + j;
+                if ( BIT_VECTOR_TST_BIT(Y,indxY) &
+                     BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
+            }
+            if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+            else     BIT_VECTOR_CLR_BIT(X,indxX)
+        }
+    }
+  }
+}
+
+void Matrix_Product(unsigned int *  X, unsigned int rowsX, unsigned int colsX,
+                    unsigned int *  Y, unsigned int rowsY, unsigned int colsY,
+                    unsigned int *  Z, unsigned int rowsZ, unsigned int colsZ)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int k;
+    unsigned int indxX;
+    unsigned int indxY;
+    unsigned int indxZ;
+    unsigned int termX;
+    unsigned int termY;
+    unsigned int sum;
+
+  if ((colsY == rowsZ) && (rowsX == rowsY) && (colsX == colsZ) &&
+      (bits_(X) == rowsX*colsX) &&
+      (bits_(Y) == rowsY*colsY) &&
+      (bits_(Z) == rowsZ*colsZ))
+  {
+    for ( i = 0; i < rowsY; i++ )
+    {
+        termX = i * colsX;
+        termY = i * colsY;
+        for ( j = 0; j < colsZ; j++ )
+        {
+            indxX = termX + j;
+            sum = 0;
+            for ( k = 0; k < colsY; k++ )
+            {
+                indxY = termY + k;
+                indxZ = k * colsZ + j;
+                if ( BIT_VECTOR_TST_BIT(Y,indxY) &
+                     BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
+            }
+            if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+            else     BIT_VECTOR_CLR_BIT(X,indxX)
+        }
+    }
+  }
+}
+
+void Matrix_Closure(unsigned int *  addr, unsigned int rows, unsigned int cols)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int k;
+    unsigned int ii;
+    unsigned int ij;
+    unsigned int ik;
+    unsigned int kj;
+    unsigned int termi;
+    unsigned int termk;
+
+  if ((rows == cols) && (bits_(addr) == rows*cols))
+  {
+    for ( i = 0; i < rows; i++ )
+    {
+        ii = i * cols + i;
+        BIT_VECTOR_SET_BIT(addr,ii)
+    }
+    for ( k = 0; k < rows; k++ )
+    {
+        termk = k * cols;
+        for ( i = 0; i < rows; i++ )
+        {
+            termi = i * cols;
+            ik = termi + k;
+            for ( j = 0; j < rows; j++ )
+            {
+                ij = termi + j;
+                kj = termk + j;
+                if ( BIT_VECTOR_TST_BIT(addr,ik) &
+                     BIT_VECTOR_TST_BIT(addr,kj) )
+                     BIT_VECTOR_SET_BIT(addr,ij)
+            }
+        }
+    }
+  }
+}
+
+void Matrix_Transpose(unsigned int *  X, unsigned int rowsX, unsigned int colsX,
+                      unsigned int *  Y, unsigned int rowsY, unsigned int colsY)
+{
+    unsigned int  i;
+    unsigned int  j;
+    unsigned int  ii;
+    unsigned int  ij;
+    unsigned int  ji;
+    unsigned int  addii;
+    unsigned int  addij;
+    unsigned int  addji;
+    unsigned int  bitii;
+    unsigned int  bitij;
+    unsigned int  bitji;
+    unsigned int  termi;
+    unsigned int  termj;
+    boolean swap;
+
+  /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */
+
+  if ((rowsX == colsY) && (colsX == rowsY) &&
+      (bits_(X) == rowsX*colsX) &&
+      (bits_(Y) == rowsY*colsY))
+  {
+    if (rowsY == colsY) /* in-place is possible! */
+    {
+        for ( i = 0; i < rowsY; i++ )
+        {
+            termi = i * colsY;
+            for ( j = 0; j < i; j++ )
+            {
+                termj = j * colsX;
+                ij = termi + j;
+                ji = termj + i;
+                addij = ij >> LOGBITS;
+                addji = ji >> LOGBITS;
+                bitij = BITMASKTAB[ij & MODMASK];
+                bitji = BITMASKTAB[ji & MODMASK];
+                swap = ((*(Y+addij) & bitij) != 0);
+                if ((*(Y+addji) & bitji) != 0)
+                     *(X+addij) |=     bitij;
+                else
+                     *(X+addij) &= ~ bitij;
+                if (swap)
+                     *(X+addji) |=     bitji;
+                else
+                     *(X+addji) &= ~ bitji;
+            }
+            ii = termi + i;
+            addii = ii >> LOGBITS;
+            bitii = BITMASKTAB[ii & MODMASK];
+            if ((*(Y+addii) & bitii) != 0)
+                 *(X+addii) |=     bitii;
+            else
+                 *(X+addii) &= ~ bitii;
+        }
+    }
+    else /* rowsX != colsX, in-place is ~ possible! */
+    {
+        for ( i = 0; i < rowsY; i++ )
+        {
+            termi = i * colsY;
+            for ( j = 0; j < colsY; j++ )
+            {
+                termj = j * colsX;
+                ij = termi + j;
+                ji = termj + i;
+                addij = ij >> LOGBITS;
+                addji = ji >> LOGBITS;
+                bitij = BITMASKTAB[ij & MODMASK];
+                bitji = BITMASKTAB[ji & MODMASK];
+                if ((*(Y+addij) & bitij) != 0)
+                     *(X+addji) |=     bitji;
+                else
+                     *(X+addji) &= ~ bitji;
+            }
+        }
+    }
+  }
+}
+}; //end of namespace CONSTANTBV

Added: klee/trunk/stp/constantbv/constantbv.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/constantbv/constantbv.h?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/constantbv/constantbv.h (added)
+++ klee/trunk/stp/constantbv/constantbv.h Wed May 20 23:36:41 2009
@@ -0,0 +1,316 @@
+#ifndef MODULE_BIT_VECTOR
+#define MODULE_BIT_VECTOR
+/*****************************************************************************/
+/*  AUTHOR:                                                                  */
+/*****************************************************************************/
+/*                                                                           */
+/*    Steffen Beyer                                                          */
+/*    mailto:sb at engelschall.com                                              */
+/*    http://www.engelschall.com/u/sb/download/                              */
+/*                                                                           */
+/*****************************************************************************/
+/*  COPYRIGHT:                                                               */
+/*****************************************************************************/
+/*                                                                           */
+/*    Copyright (c) 1995 - 2004 by Steffen Beyer.                            */
+/*    All rights reserved.                                                   */
+/*                                                                           */
+/*****************************************************************************/
+/*  LICENSE:                                                                 */
+/*****************************************************************************/
+/*                                                                           */
+/*    This library is free software; you can redistribute it and/or          */
+/*    modify it under the terms of the GNU Library General Public            */
+/*    License as published by the Free Software Foundation; either           */
+/*    version 2 of the License, or (at your option) any later version.       */
+/*                                                                           */
+/*    This library 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       */
+/*    Library General Public License for more details.                       */
+/*                                                                           */
+/*    You should have received a copy of the GNU Library General Public      */
+/*    License along with this library; if not, write to the                  */
+/*    Free Software Foundation, Inc.,                                        */
+/*    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                  */
+/*                                                                           */
+/*    or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0      */
+/*                                                                           */
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+/*  MODULE NAME:  BitVector.h                           MODULE TYPE:  (adt)  */
+/*****************************************************************************/
+/*  MODULE IMPORTS:                                                          */
+/*****************************************************************************/
+#include <stdlib.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <limits.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <string.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <ctype.h>                                  /*  MODULE TYPE:  (sys)  */
+/*****************************************************************************/
+/*  MODULE INTERFACE:                                                        */
+/*****************************************************************************/
+
+namespace CONSTANTBV {
+
+#ifdef __cplusplus
+  extern "C" {
+    typedef bool boolean;
+#else
+    typedef enum { false = (0!=0), true = (0==0) } boolean;
+#endif
+
+    typedef enum {
+        ErrCode_Ok = 0,    /* everything went allright                       */	
+        ErrCode_Type,      /* types word and size_t have incompatible sizes  */
+        ErrCode_Bits,      /* bits of word and sizeof(word) are inconsistent */
+        ErrCode_Word,      /* size of word is less than 16 bits              */
+        ErrCode_Long,      /* size of word is greater than size of long      */
+        ErrCode_Powr,      /* number of bits of word is not a power of two   */
+        ErrCode_Loga,      /* error in calculation of logarithm              */	
+        ErrCode_Null,      /* unable to allocate memory                      */	
+        ErrCode_Indx,      /* index out of range                             */
+        ErrCode_Ordr,      /* minimum > maximum index                        */
+        ErrCode_Size,      /* bit vector size mismatch                       */
+        ErrCode_Pars,      /* input string syntax error                      */
+        ErrCode_Ovfl,      /* numeric overflow error                         */
+        ErrCode_Same,      /* operands must be distinct                      */
+        ErrCode_Expo,      /* exponent must be positive                      */
+        ErrCode_Zero       /* division by zero error                         */
+      } ErrCode;
+
+
+    /* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */
+    unsigned char * BitVector_Error(ErrCode error);     /* return string for err code */
+    ErrCode         BitVector_Boot (void);              /* 0 = ok, 1..7 = error */
+    unsigned int    BitVector_Size(unsigned int bits);  /* bit vector size (# of words)  */
+    unsigned int    BitVector_Mask(unsigned int bits);  /* bit vector mask (unused bits) */
+    
+    /* ===> CLASS METHODS: <=== */
+    unsigned char * BitVector_Version(void);           /* return version string */
+    unsigned int    BitVector_Word_Bits(void);         /* return # of bits in machine word */
+    unsigned int    BitVector_Long_Bits(void);         /* return # of bits in unsigned long */
+
+    /* ===> CONSTRUCTOR METHODS: <=== */
+    unsigned int *  BitVector_Create      (unsigned int bits, boolean clear);                /* malloc */
+    unsigned int ** BitVector_Create_List (unsigned int bits, boolean clear, unsigned int count);
+    unsigned int *  BitVector_Resize      (unsigned int * oldaddr, unsigned int bits);       /* realloc */
+    unsigned int *  BitVector_Shadow      (unsigned int * addr);                             /* make new same size but empty */
+    unsigned int *  BitVector_Clone       (unsigned int * addr);                             /* make exact duplicate */
+    unsigned int *  BitVector_Concat      (unsigned int * X, unsigned int * Y);              /* return concatenation */
+
+    /* ===> DESTRUCTOR METHODS: <=== */
+    void    BitVector_Dispose             (unsigned char * string);                     /* string */
+    void    BitVector_Destroy             (unsigned int * addr);                        /* bitvec */
+    void    BitVector_Destroy_List        (unsigned int * * list, unsigned int count);  /* list   */
+
+    /* ===> OBJECT METHODS: <=== */
+
+    /* ===> bit vector hash: */
+    size_t  BitVector_Hash                (unsigned int * X);
+
+    /* ===> bit vector copy function: */
+    void    BitVector_Copy                (unsigned int * X, unsigned int * Y);              /* X := Y   */
+
+    /* ===> bit vector initialization: */
+    void    BitVector_Empty               (unsigned int * addr);                      /* X = {}  */
+    void    BitVector_Fill                (unsigned int * addr);                      /* X = ~{} */
+    void    BitVector_Flip                (unsigned int * addr);                      /* X = ~X  */
+    void    BitVector_Primes              (unsigned int * addr);
+
+    /* ===> miscellaneous functions: */
+    void    BitVector_Reverse             (unsigned int * X, unsigned int * Y);
+    
+    /* ===> bit vector interval operations and functions: */
+    void    BitVector_Interval_Empty      (unsigned int * addr, unsigned int lower, unsigned int upper);
+    void    BitVector_Interval_Fill       (unsigned int * addr, unsigned int lower, unsigned int upper);
+    void    BitVector_Interval_Flip       (unsigned int * addr, unsigned int lower, unsigned int upper);
+    void    BitVector_Interval_Reverse    (unsigned int * addr, unsigned int lower, unsigned int upper);
+    
+    boolean BitVector_interval_scan_inc   (unsigned int * addr, unsigned int start,
+					   unsigned int * min, unsigned int * max);
+    boolean BitVector_interval_scan_dec   (unsigned int * addr, unsigned int start,
+					   unsigned int * min, unsigned int * max);
+    void    BitVector_Interval_Copy       (unsigned int * X, unsigned int * Y, 
+					   unsigned int Xoffset, unsigned int Yoffset, unsigned int length);
+    unsigned int * BitVector_Interval_Substitute(unsigned int * X, unsigned int * Y,
+						 unsigned int Xoffset, unsigned int Xlength,
+						 unsigned int Yoffset, unsigned int Ylength);
+
+    /* ===> bit vector test functions: */
+    boolean BitVector_is_empty            (unsigned int * addr);                         /* X == {} ?   */
+    boolean BitVector_is_full             (unsigned int * addr);                         /* X == ~{} ?  */
+    boolean BitVector_equal               (unsigned int * X, unsigned int * Y);          /* X == Y ?    */
+    signed int   BitVector_Lexicompare    (unsigned int * X, unsigned int * Y);          /* X <,=,> Y ? */
+    signed int   BitVector_Compare        (unsigned int * X, unsigned int * Y);          /* X <,=,> Y ? */
+    
+    /* ===> bit vector string conversion functions: */
+    unsigned char * BitVector_to_Hex      (unsigned int * addr);
+    ErrCode BitVector_from_Hex            (unsigned int * addr, unsigned char * string);
+    unsigned char * BitVector_to_Bin      (unsigned int * addr);
+    ErrCode BitVector_from_Bin            (unsigned int * addr, unsigned char * string);
+    unsigned char * BitVector_to_Dec      (unsigned int * addr);
+    ErrCode BitVector_from_Dec            (unsigned int * addr, unsigned char * string);
+    unsigned char * BitVector_to_Enum     (unsigned int * addr);
+    ErrCode BitVector_from_Enum           (unsigned int * addr, unsigned char * string);
+    
+    /* ===> bit vector bit operations, functions & tests: */
+    void    BitVector_Bit_Off             (unsigned int * addr, unsigned int index); /*  X = X \ {x}    */
+    void    BitVector_Bit_On              (unsigned int * addr, unsigned int index); /*  X = X + {x}    */
+    boolean BitVector_bit_flip            (unsigned int * addr, unsigned int index); /* (X+{x})\(X*{x}) */
+    boolean BitVector_bit_test            (unsigned int * addr, unsigned int index); /*  {x} in X ?     */
+    void    BitVector_Bit_Copy            (unsigned int * addr, unsigned int index, boolean bit);
+    
+    /* ===> bit vector bit shift & rotate functions: */
+    void    BitVector_LSB                 (unsigned int * addr, boolean bit);
+    void    BitVector_MSB                 (unsigned int * addr, boolean bit);
+    boolean BitVector_lsb_                (unsigned int * addr);
+    boolean BitVector_msb_                (unsigned int * addr);
+    boolean BitVector_rotate_left         (unsigned int * addr);
+    boolean BitVector_rotate_right        (unsigned int * addr);
+    boolean BitVector_shift_left          (unsigned int * addr, boolean carry_in);
+    boolean BitVector_shift_right         (unsigned int * addr, boolean carry_in);
+    void    BitVector_Move_Left           (unsigned int * addr, unsigned int bits);
+    void    BitVector_Move_Right          (unsigned int * addr, unsigned int bits);
+    
+    /* ===> bit vector insert/delete bits: */
+    void    BitVector_Insert              (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    void    BitVector_Delete              (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    
+    /* ===> bit vector arithmetic: */
+    boolean BitVector_increment           (unsigned int * addr);                        /*  X++  */
+    boolean BitVector_decrement           (unsigned int * addr);                        /*  X--  */
+    boolean BitVector_compute             (unsigned int * X, unsigned int * Y, 
+					   unsigned int * Z, boolean minus, boolean *carry);
+    boolean BitVector_add                 (unsigned int * X, 
+					   unsigned int * Y, unsigned int * Z, boolean *carry);
+    boolean BitVector_sub                 (unsigned int * X, 
+					   unsigned int * Y, unsigned int * Z, boolean *carry); /* X = Y-Z*/
+    boolean BitVector_inc                 (unsigned int * X, unsigned int * Y);
+    boolean BitVector_dec                 (unsigned int * X, unsigned int * Y);
+    
+    void    BitVector_Negate              (unsigned int * X, unsigned int * Y);
+    void    BitVector_Absolute            (unsigned int * X, unsigned int * Y);
+    signed int   BitVector_Sign           (unsigned int * addr);
+    ErrCode BitVector_Mul_Pos             (unsigned int * X, 
+					   unsigned int * Y, unsigned int * Z, boolean strict);
+    ErrCode BitVector_Multiply            (unsigned int * X, unsigned int * Y, unsigned int * Z);
+    ErrCode BitVector_Div_Pos             (unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R);
+    ErrCode BitVector_Divide              (unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R);
+    ErrCode BitVector_GCD                 (unsigned int * X, unsigned int * Y, unsigned int * Z);
+    ErrCode BitVector_GCD2                (unsigned int * U, unsigned int * V, unsigned int * W,      /*   O   */
+					   unsigned int * X, unsigned int * Y);     /*   I   */
+    ErrCode BitVector_Power               (unsigned int * X, unsigned int * Y, unsigned int * Z);
+    
+    /* ===> direct memory access functions: */
+    void    BitVector_Block_Store         (unsigned int * addr, 
+					   unsigned char * buffer, unsigned int length);
+    unsigned char * BitVector_Block_Read  (unsigned int * addr, unsigned int * length);
+    
+    /* ===> word array functions: */
+    void    BitVector_Word_Store          (unsigned int * addr, unsigned int offset, unsigned int value);
+    unsigned int   BitVector_Word_Read    (unsigned int * addr, unsigned int offset);
+    void    BitVector_Word_Insert         (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    void    BitVector_Word_Delete         (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    
+    /* ===> arbitrary size chunk functions: */
+    void    BitVector_Chunk_Store         (unsigned int * addr, unsigned int chunksize,
+					   unsigned int offset, unsigned long value);
+    unsigned long  BitVector_Chunk_Read   (unsigned int * addr, 
+					   unsigned int chunksize,unsigned int offset);
+    
+    /* ===> set operations: */
+    void    Set_Union                     (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y + Z */
+    void    Set_Intersection              (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y * Z */
+    void    Set_Difference                (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y \ Z */
+    void    Set_ExclusiveOr               (unsigned int * X, unsigned int * Y, unsigned int * Z); /*(Y+Z)\(Y*Z)*/
+    void    Set_Complement                (unsigned int * X, unsigned int * Y);                   /* X = ~Y    */
+    
+    /* ===> set functions: */
+    boolean        Set_subset             (unsigned int * X, unsigned int * Y);     /* X in Y ?  */
+    unsigned int   Set_Norm               (unsigned int * addr);                    /* = | X |   */
+    unsigned int   Set_Norm2              (unsigned int * addr);                    /* = | X |   */
+    unsigned int   Set_Norm3              (unsigned int * addr);                    /* = | X |   */
+    signed long    Set_Min                (unsigned int * addr);                    /* = min(X)  */
+    signed long    Set_Max                (unsigned int * addr);                    /* = max(X)  */
+    
+    /* ===> matrix-of-booleans operations: */
+    void    Matrix_Multiplication         (unsigned int * X, unsigned int rowsX, unsigned int colsX,
+					   unsigned int * Y, unsigned int rowsY, unsigned int colsY,
+					   unsigned int * Z, unsigned int rowsZ, unsigned int colsZ);
+    void    Matrix_Product                (unsigned int * X, unsigned int rowsX, unsigned int colsX,
+					   unsigned int * Y, unsigned int rowsY, unsigned int colsY,
+					   unsigned int * Z, unsigned int rowsZ, unsigned int colsZ);
+    void    Matrix_Closure                (unsigned int * addr, unsigned int rows, unsigned int cols);
+    void    Matrix_Transpose              (unsigned int * X, unsigned int rowsX, unsigned int colsX,
+					   unsigned int * Y, unsigned int rowsY, unsigned int colsY);
+    
+    /*****************************************************************************/
+    /*  MODULE RESOURCES:                                                        */
+    /*****************************************************************************/
+#define bits_(BitVector) *(BitVector-3)
+#define size_(BitVector) *(BitVector-2)
+#define mask_(BitVector) *(BitVector-1)
+    
+#define  ERRCODE_TYPE  "sizeof(word) > sizeof(size_t)"
+#define  ERRCODE_BITS  "bits(word) != sizeof(word)*8"
+#define  ERRCODE_WORD  "bits(word) < 16"
+#define  ERRCODE_LONG  "bits(word) > bits(long)"
+#define  ERRCODE_POWR  "bits(word) != 2^x"
+#define  ERRCODE_LOGA  "bits(word) != 2^ld(bits(word))"
+#define  ERRCODE_NULL  "unable to allocate memory"
+#define  ERRCODE_INDX  "index out of range"
+#define  ERRCODE_ORDR  "minimum > maximum index"
+#define  ERRCODE_SIZE  "bit vector size mismatch"
+#define  ERRCODE_PARS  "input string syntax error"
+#define  ERRCODE_OVFL  "numeric overflow error"
+#define  ERRCODE_SAME  "result vector(s) must be distinct"
+#define  ERRCODE_EXPO  "exponent must be positive"
+#define  ERRCODE_ZERO  "division by zero error"
+#define  ERRCODE_OOPS  "unexpected internal error - please contact author"
+        
+    const unsigned int BitVector_BYTENORM[256] = {
+      0x00, 0x01, 0x01, 0x02,  0x01, 0x02, 0x02, 0x03,
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04, /* 0x00 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x10 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x20 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x30 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x40 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x50 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x60 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0x70 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x80 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x90 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xA0 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xB0 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xC0 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xD0 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xE0 */
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07,
+      0x05, 0x06, 0x06, 0x07,  0x06, 0x07, 0x07, 0x08  /* 0xF0 */
+    };
+#ifdef __cplusplus
+  };
+#endif
+}; //end of namespace CONSTANTBV
+#endif
+

Added: klee/trunk/stp/parser/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/parser/Makefile?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/parser/Makefile (added)
+++ klee/trunk/stp/parser/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,27 @@
+include ../Makefile.common
+
+SRCS = lexPL.cpp parsePL.cpp let-funcs.cpp main.cpp
+OBJS = $(SRCS:.cpp=.o)
+LIBS = -L../AST -last -L../sat -lsatsolver -L../simplifier -lsimplifier -L../bitvec -lconsteval -L../constantbv -lconstantbv
+
+all: parser 
+
+parser: lexPL.o parsePL.o let-funcs.o main.o 
+		$(CXX) $(CFLAGS) $(LDFLAGS) lexPL.o parsePL.o main.o let-funcs.o $(LIBS) -o parser
+
+main.o: parsePL_defs.h
+
+lexPL.cpp:	PL.lex parsePL_defs.h ../AST/AST.h
+		$(LEX) -o lexPL.cpp PL.lex
+
+parsePL_defs.h: y.tab.h
+		@cp y.tab.h parsePL_defs.h
+parsePL.cpp: y.tab.c
+		@cp y.tab.c parsePL.cpp
+
+y.tab.c y.tab.h:	PL.y
+		$(YACC) PL.y
+
+
+clean:	
+		rm -rf *.o parsePL_defs.h *~ lexPL.cpp parsePL.cpp *.output parser y.tab.* lex.yy.c .#*

Added: klee/trunk/stp/parser/PL.lex
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/parser/PL.lex?rev=72205&view=auto

==============================================================================
--- klee/trunk/stp/parser/PL.lex (added)
+++ klee/trunk/stp/parser/PL.lex Wed May 20 23:36:41 2009
@@ -0,0 +1,128 @@
+%{
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+#include <iostream>
+#include "../AST/AST.h"
+#include "parsePL_defs.h"
+
+extern char *yytext;
+extern int yyerror (const char *msg);
+%}
+
+%option noyywrap
+%option nounput
+%option noreject
+%option noyymore
+%option yylineno
+%x	COMMENT
+%x	STRING_LITERAL
+LETTER	([a-zA-Z])
+HEX     ([0-9a-fA-F])
+BITS    ([0-1])
+DIGIT	([0-9])
+OPCHAR	(['?\_$])
+ANYTHING ({LETTER}|{DIGIT}|{OPCHAR})
+%%
+
+[()[\]{},.;:'!#?_=]  { return yytext[0];}
+
+[\n]             { /*Skip new line */ }
+[ \t\r\f]	 { /* skip whitespace */ }
+0b{BITS}+	 { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+2,  2)); return BVCONST_TOK;}
+0bin{BITS}+	 { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+4,  2)); return BVCONST_TOK;}
+0h{HEX}+         { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+2, 16)); return BVCONST_TOK;}
+0hex{HEX}+       { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+4, 16)); return BVCONST_TOK;}
+{DIGIT}+	 { yylval.uintval = strtoul(yytext, NULL, 10); return NUMERAL_TOK;}
+
+"%"		 { BEGIN COMMENT;}
+<COMMENT>"\n"	 { BEGIN INITIAL; /* return to normal mode */}
+<COMMENT>.	 { /* stay in comment mode */}
+
+"ARRAY"		 { return ARRAY_TOK; }
+"OF"		 { return OF_TOK; }
+"WITH"		 { return WITH_TOK; }
+"AND"		 { return AND_TOK;}
+"NAND"		 { return NAND_TOK;}
+"NOR"		 { return NOR_TOK;}
+"NOT"		 { return NOT_TOK; }
+"OR"		 { return OR_TOK; }
+"/="		 { return NEQ_TOK; }
+ ":="            { return ASSIGN_TOK;}
+"=>"		 { return IMPLIES_TOK; }
+"<=>"		 { return IFF_TOK; }
+"XOR"		 { return XOR_TOK; }
+"IF"		 { return IF_TOK; }
+"THEN"		 { return THEN_TOK; }
+"ELSE"		 { return ELSE_TOK; }
+"ELSIF"		 { return ELSIF_TOK; }
+"END"		 { return END_TOK; }
+"ENDIF"		 { return ENDIF_TOK; }
+"BV"             { return BV_TOK;}
+"BITVECTOR"      { return BV_TOK;}
+"BOOLEAN"        { return BOOLEAN_TOK;}
+"<<"             { return BVLEFTSHIFT_TOK;}
+">>"             { return BVRIGHTSHIFT_TOK;}
+"BVPLUS"         { return BVPLUS_TOK;}
+"BVSUB"          { return BVSUB_TOK;}
+"BVUMINUS"       { return BVUMINUS_TOK;}
+"BVMULT"         { return BVMULT_TOK;}
+"BVDIV"          { return BVDIV_TOK;}
+"BVMOD"          { return BVMOD_TOK;}
+"SBVDIV"         { return SBVDIV_TOK;}
+"SBVMOD"         { return SBVMOD_TOK;}
+"~"              { return BVNEG_TOK;}
+"&"              { return BVAND_TOK;}
+"|"              { return BVOR_TOK;}
+"BVXOR"          { return BVXOR_TOK;}
+"BVNAND"         { return BVNAND_TOK;}
+"BVNOR"          { return BVNOR_TOK;}
+"BVXNOR"         { return BVXNOR_TOK;}
+"@"              { return BVCONCAT_TOK;}
+"BVLT"           { return BVLT_TOK;}
+"BVGT"           { return BVGT_TOK;}
+"BVLE"           { return BVLE_TOK;}
+"BVGE"           { return BVGE_TOK;}
+"BVSLT"          { return BVSLT_TOK;}
+"BVSGT"          { return BVSGT_TOK;}
+"BVSLE"          { return BVSLE_TOK;}
+"BVSGE"          { return BVSGE_TOK;}
+"BVSX"           { return BVSX_TOK;} 
+"SBVLT"          { return BVSLT_TOK;}
+"SBVGT"          { return BVSGT_TOK;}
+"SBVLE"          { return BVSLE_TOK;}
+"SBVGE"          { return BVSGE_TOK;}
+"SX"             { return BVSX_TOK;} 
+"BOOLEXTRACT"    { return BOOLEXTRACT_TOK;}
+"BOOLBV"         { return BOOL_TO_BV_TOK;}
+"ASSERT"	 { return ASSERT_TOK; }
+"QUERY"	         { return QUERY_TOK; }
+"FALSE"          { return FALSELIT_TOK;}
+"TRUE"           { return TRUELIT_TOK;}
+"IN"             { return IN_TOK;}
+"LET"            { return LET_TOK;}
+"COUNTEREXAMPLE" { return COUNTEREXAMPLE_TOK;}
+"COUNTERMODEL"   { return COUNTEREXAMPLE_TOK;}
+ "PUSH"          { return PUSH_TOK;}
+ "POP"           { return POP_TOK;}
+
+(({LETTER})|(_)({ANYTHING}))({ANYTHING})*	{
+  BEEV::ASTNode nptr = BEEV::globalBeevMgr_for_parser->CreateSymbol(yytext); 
+
+  // Check valuesize to see if it's a prop var.  I don't like doing
+  // type determination in the lexer, but it's easier than rewriting
+  // the whole grammar to eliminate the term/formula distinction.  
+  yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(nptr));
+  //yylval.node = new BEEV::ASTNode(nptr);
+  if ((yylval.node)->GetType() == BEEV::BOOLEAN_TYPE)
+    return FORMID_TOK;
+  else 
+    return TERMID_TOK;  
+}
+
+.                { yyerror("Illegal input character."); }
+%%





More information about the llvm-commits mailing list