about summary refs log tree commit diff homepage
path: root/lib/Solver
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Solver')
-rw-r--r--lib/Solver/STPBuilder.cpp31
1 files changed, 22 insertions, 9 deletions
diff --git a/lib/Solver/STPBuilder.cpp b/lib/Solver/STPBuilder.cpp
index 2c03c483..2e313fb0 100644
--- a/lib/Solver/STPBuilder.cpp
+++ b/lib/Solver/STPBuilder.cpp
@@ -465,17 +465,30 @@ ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out) {
 
   switch (e->getKind()) {
   case Expr::Constant: {
-    uint64_t asUInt64 = cast<ConstantExpr>(e)->getConstantValue();
-    *width_out = e->getWidth();
-
-    if (*width_out > 64)
-      assert(0 && "constructActual: width > 64");
+    ConstantExpr *CE = cast<ConstantExpr>(e);
+    *width_out = CE->getWidth();
 
+    // Coerce to bool if necessary.
     if (*width_out == 1)
-      return asUInt64 ? getTrue() : getFalse();
-    else if (*width_out <= 32) 
-      return bvConst32(*width_out, asUInt64);
-    else return bvConst64(*width_out, asUInt64);
+      return CE->isTrue() ? getTrue() : getFalse();
+
+    // Fast path.
+    if (*width_out <= 32)
+      return bvConst32(*width_out, CE->getZExtValue(32));
+    if (*width_out <= 64)
+      return bvConst64(*width_out, CE->getZExtValue());
+
+    // FIXME: Optimize?
+    assert(0 && "FIXME: Not tested!");
+    ref<ConstantExpr> Tmp = CE;
+    ExprHandle Res = bvConst64(64, Tmp->Extract(0, 64)->getZExtValue());
+    for (unsigned i = (*width_out / 64) - 1; i; --i) {
+      Tmp = Tmp->LShr(ConstantExpr::alloc(64, Tmp->getWidth()));
+      Res = vc_bvConcatExpr(vc, bvConst64(std::min(64U, Tmp->getWidth()),
+                                          Tmp->Extract(0, 64)->getZExtValue()),
+                            Res);
+    }
+    return Res;
   }
     
   // Special