Skip to content

Commit 7161f17

Browse files
author
Daniel Kroening
authored
Merge pull request diffblue#1879 from diffblue/smt2-frontend
An SMT2 frontend plus solver binary
2 parents d83fa17 + ab68848 commit 7161f17

25 files changed

+1720
-232
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ src/goto-instrument/goto-instrument.exe
104104
src/jbmc/jbmc
105105
src/musketeer/musketeer
106106
src/musketeer/musketeer.exe
107+
src/solvers/smt2/smt2_solver
108+
src/solvers/smt2/smt2_solver.exe
107109
src/symex/symex
108110
src/symex/symex.exe
109111
src/goto-diff/goto-diff

regression/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ DIRS = cbmc \
1111
strings-smoke-tests \
1212
cbmc-cover \
1313
goto-instrument-typedef \
14+
smt2_solver \
1415
strings \
1516
invariants \
1617
goto-diff \

regression/smt2_solver/Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
default: tests.log
2+
3+
test:
4+
@../test.pl -p -c ../../../src/solvers/smt2_solver
5+
6+
tests.log: ../test.pl
7+
@../test.pl -p -c ../../../src/solvers/smt2_solver
8+
9+
show:
10+
@for dir in *; do \
11+
if [ -d "$$dir" ]; then \
12+
vim -o "$$dir/*.c" "$$dir/*.out"; \
13+
fi; \
14+
done;
15+
16+
clean:
17+
find -name '*.out' -execdir $(RM) '{}' \;
18+
$(RM) tests.log
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
(set-logic QF_BV)
2+
3+
; From https://rise4fun.com/z3/tutorialcontent/guide
4+
5+
; Basic Bitvector Arithmetic
6+
(define-fun b01 () Bool (= (bvadd #x07 #x03) #x0a)) ; addition
7+
(define-fun b02 () Bool (= (bvsub #x07 #x03) #x04)) ; subtraction
8+
(define-fun b03 () Bool (= (bvneg #x07) #xf9)) ; unary minus
9+
(define-fun b04 () Bool (= (bvmul #x07 #x03) #x15)) ; multiplication
10+
(define-fun b05 () Bool (= (bvurem #x07 #x03) #x01)) ; unsigned remainder
11+
(define-fun b06 () Bool (= (bvsrem #x07 #x03) #x01)) ; signed remainder
12+
(define-fun b07 () Bool (= (bvsmod #x07 #x03) #x01)) ; signed modulo
13+
(define-fun b08 () Bool (= (bvshl #x07 #x03) #x38)) ; shift left
14+
(define-fun b09 () Bool (= (bvlshr #xf0 #x03) #x1e)) ; unsigned (logical) shift right
15+
(define-fun b10 () Bool (= (bvashr #xf0 #x03) #xfe)) ; signed (arithmetical) shift right#x0a
16+
17+
; Bitwise Operations
18+
19+
(define-fun w1 () Bool (= (bvor #x6 #x3) #x7)) ; bitwise or
20+
(define-fun w2 () Bool (= (bvand #x6 #x3) #x2)) ; bitwise and
21+
(define-fun w3 () Bool (= (bvnot #x6) #x9)) ; bitwise not
22+
(define-fun w4 () Bool (= (bvnand #x6 #x3) #xd)) ; bitwise nand
23+
(define-fun w5 () Bool (= (bvnor #x6 #x3) #x8)) ; bitwise nor
24+
(define-fun w6 () Bool (= (bvxnor #x6 #x3) #xa)) ; bitwise xnor
25+
26+
; We can prove a bitwise version of deMorgan's law
27+
28+
(declare-const x (_ BitVec 64))
29+
(declare-const y (_ BitVec 64))
30+
(define-fun d01 () Bool (= (bvand (bvnot x) (bvnot y)) (bvnot (bvor x y))))
31+
32+
; There is a fast way to check that fixed size numbers are powers of two
33+
34+
(define-fun is-power-of-two ((x (_ BitVec 4))) Bool
35+
(= #x0 (bvand x (bvsub x #x1))))
36+
(declare-const a (_ BitVec 4))
37+
(define-fun power-test () Bool
38+
(= (is-power-of-two a)
39+
(or (= a #x0)
40+
(= a #x1)
41+
(= a #x2)
42+
(= a #x4)
43+
(= a #x8))))
44+
45+
; Predicates over Bitvectors
46+
47+
(define-fun p1 () Bool (= (bvule #x0a #xf0) true)) ; unsigned less or equal
48+
(define-fun p2 () Bool (= (bvult #x0a #xf0) true)) ; unsigned less than
49+
(define-fun p3 () Bool (= (bvuge #x0a #xf0) false)) ; unsigned greater or equal
50+
(define-fun p4 () Bool (= (bvugt #x0a #xf0) false)) ; unsigned greater than
51+
(define-fun p5 () Bool (= (bvsle #x0a #xf0) false)) ; signed less or equal
52+
(define-fun p6 () Bool (= (bvslt #x0a #xf0) false)) ; signed less than
53+
(define-fun p7 () Bool (= (bvsge #x0a #xf0) true)) ; signed greater or equal
54+
(define-fun p8 () Bool (= (bvsgt #x0a #xf0) true)) ; signed greater than
55+
56+
; all must be true
57+
58+
(assert (not (and
59+
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
60+
d01
61+
power-test
62+
p1 p2 p3 p4 p5 p6 p7 p8)))
63+
64+
(check-sat)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
basic-bv1.smt2
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^unsat$
7+
--
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
(set-logic QF_BV)
2+
3+
; try 'let' on bitvectors
4+
5+
(define-fun x () (_ BitVec 4) #x0)
6+
7+
; very simple
8+
(define-fun let0 () Bool (= (let ((x #x0)) #x1) #x1))
9+
10+
; let hides the function 'x'
11+
(define-fun let1 () Bool (= (let ((x #x1)) x) #x1))
12+
13+
; the binding isn't visible immediately
14+
(define-fun let2 () Bool (= (let ((x x)) x) #x0))
15+
16+
; parallel let
17+
(define-fun let3 () Bool (= (let ((x #x1) (y x)) y) #x0))
18+
19+
; limited scope
20+
(define-fun let4 () Bool (and (= (let ((x #x1)) x) #x1) (= x #x0)))
21+
22+
; all must be true
23+
24+
(assert (not (and
25+
let0
26+
let1
27+
let2
28+
let3
29+
let4
30+
)))
31+
32+
(check-sat)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
let-with-bv1.smt2
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^unsat$
7+
--

regression/smt2_solver/let1/let1.smt2

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
(set-logic QF_BV)
2+
3+
(define-fun x () Bool false)
4+
5+
; very simple
6+
(define-fun let0 () Bool (let ((x false)) true))
7+
8+
; let hides the function 'x'
9+
(define-fun let1 () Bool (let ((x true)) x))
10+
11+
; the binding isn't visible immediately
12+
(define-fun let2 () Bool (not (let ((x x)) x)))
13+
14+
; parallel let
15+
(define-fun let3 () Bool (let ((x true) (y x)) (not y)))
16+
17+
; limited scope
18+
(define-fun let4 () Bool (and (let ((x true)) x) (not x)))
19+
20+
; all must be true
21+
22+
(assert (not (and
23+
let0
24+
let1
25+
let2
26+
let3
27+
let4
28+
)))
29+
30+
(check-sat)

regression/smt2_solver/let1/test.desc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
let1.smt2
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^unsat$
7+
--

src/ansi-c/expr2c.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,26 @@ std::string expr2ct::convert_with(
944944
return dest;
945945
}
946946

947+
std::string expr2ct::convert_let(
948+
const let_exprt &src,
949+
unsigned precedence)
950+
{
951+
if(src.operands().size()<3)
952+
return convert_norep(src, precedence);
953+
954+
unsigned p0;
955+
std::string op0=convert_with_precedence(src.op0(), p0);
956+
957+
std::string dest="LET ";
958+
dest+=convert(src.symbol());
959+
dest+='=';
960+
dest+=convert(src.value());
961+
dest+=" IN ";
962+
dest+=convert(src.where());
963+
964+
return dest;
965+
}
966+
947967
std::string expr2ct::convert_update(
948968
const exprt &src,
949969
unsigned precedence)
@@ -3936,6 +3956,9 @@ std::string expr2ct::convert_with_precedence(
39363956
else if(src.id()==ID_sizeof)
39373957
return convert_sizeof(src, precedence);
39383958

3959+
else if(src.id()==ID_let)
3960+
return convert_let(to_let_expr(src), precedence=16);
3961+
39393962
else if(src.id()==ID_type)
39403963
return convert(src.type());
39413964

src/ansi-c/expr2c_class.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ class expr2ct
253253
std::string convert_designated_initializer(const exprt &src, unsigned &precedence);
254254
std::string convert_concatenation(const exprt &src, unsigned &precedence);
255255
std::string convert_sizeof(const exprt &src, unsigned &precedence);
256+
std::string convert_let(const let_exprt &, unsigned precedence);
256257

257258
std::string convert_struct(
258259
const exprt &src,

src/solvers/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
set(CMAKE_CXX_STANDARD 11)
2+
set(CMAKE_CXX_STANDARD_REQUIRED true)
3+
14
# We may use one of several different solver libraries.
25
# The following files wrap the chosen solver library.
36
# We remove them all from the solver-library sources list, and then add the
@@ -104,6 +107,10 @@ elseif("${sat_impl}" STREQUAL "glucose")
104107
target_link_libraries(solvers glucose-condensed)
105108
endif()
106109

107-
target_link_libraries(solvers java_bytecode util)
110+
target_link_libraries(solvers util)
111+
112+
# Executable
113+
add_executable(smt2_solver smt2/smt2_solver.cpp)
114+
target_link_libraries(smt2_solver solvers)
108115

109116
generic_includes(solvers)

src/solvers/Makefile

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ SRC = $(BOOLEFORCE_SRC) \
125125
flattening/boolbv_ieee_float_rel.cpp \
126126
flattening/boolbv_if.cpp \
127127
flattening/boolbv_index.cpp \
128+
flattening/boolbv_let.cpp \
128129
flattening/boolbv_map.cpp \
129130
flattening/boolbv_member.cpp \
130131
flattening/boolbv_mod.cpp \
@@ -215,9 +216,9 @@ INCLUDES += -I .. \
215216
$(SMVSAT_INCLUDE) $(SQUOLEM2_INC) $(CUDD_INCLUDE) $(GLUCOSE_INCLUDE) \
216217
$(PRECOSAT_INCLUDE) $(PICOSAT_INCLUDE) $(LINGELING_INCLUDE)
217218

218-
CLEANFILES = solvers$(LIBEXT)
219+
CLEANFILES = solvers$(LIBEXT) smt2_solver$(EXEEXT)
219220

220-
all: solvers$(LIBEXT)
221+
all: solvers$(LIBEXT) smt2_solver$(EXEEXT)
221222

222223
ifneq ($(SQUOLEM2),)
223224
CP_CXXFLAGS += -DHAVE_QBF_CORE
@@ -231,9 +232,15 @@ endif
231232

232233
-include $(SRC:.cpp=.d)
233234

234-
###############################################################################
235-
236-
solvers$(LIBEXT): $(OBJ) $(CHAFF_LIB) $(BOOLEFORCE_LIB) $(MINISAT_LIB) \
235+
SOLVER_LIB = $(CHAFF_LIB) $(BOOLEFORCE_LIB) $(MINISAT_LIB) \
237236
$(MINISAT2_LIB) $(SMVSAT_LIB) $(SQUOLEM2_LIB) $(CUDD_LIB) \
238237
$(PRECOSAT_LIB) $(PICOSAT_LIB) $(LINGELING_LIB) $(GLUCOSE_LIB)
238+
239+
###############################################################################
240+
241+
solvers$(LIBEXT): $(OBJ) $(SOLVER_LIB)
239242
$(LINKLIB) $(LIBSOLVER)
243+
244+
smt2_solver$(EXEEXT): $(OBJ) smt2/smt2_solver$(OBJEXT) \
245+
../util/util$(LIBEXT) ../langapi/langapi$(LIBEXT) ../big-int/big-int$(LIBEXT) $(SOLVER_LIB)
246+
$(LINKBIN) $(LIBSOLVER)

src/solvers/flattening/boolbv.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,10 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
278278
else if(expr.id()==ID_array_of)
279279
return convert_array_of(to_array_of_expr(expr));
280280
else if(expr.id()==ID_let)
281-
{
282-
// const let_exprt &let_expr=to_let_expr(expr);
283-
throw "let is todo";
284-
}
281+
return convert_let(to_let_expr(expr));
285282
else if(expr.id()==ID_function_application)
286-
{
287-
return convert_function_application(to_function_application_expr(expr));
288-
}
283+
return convert_function_application(
284+
to_function_application_expr(expr));
289285
else if(expr.id()==ID_reduction_or || expr.id()==ID_reduction_and ||
290286
expr.id()==ID_reduction_nor || expr.id()==ID_reduction_nand ||
291287
expr.id()==ID_reduction_xor || expr.id()==ID_reduction_xnor)
@@ -463,6 +459,15 @@ literalt boolbvt::convert_rest(const exprt &expr)
463459
return convert_quantifier(expr);
464460
else if(expr.id()==ID_exists)
465461
return convert_quantifier(expr);
462+
else if(expr.id()==ID_let)
463+
{
464+
bvt bv=convert_let(to_let_expr(expr));
465+
466+
DATA_INVARIANT(bv.size()==1,
467+
"convert_let must return 1-bit vector for boolean let");
468+
469+
return bv[0];
470+
}
466471
else if(expr.id()==ID_index)
467472
{
468473
bvt bv=convert_index(to_index_expr(expr));

src/solvers/flattening/boolbv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ class boolbvt:public arrayst
145145
virtual bvt convert_complex_real(const exprt &expr);
146146
virtual bvt convert_complex_imag(const exprt &expr);
147147
virtual bvt convert_lambda(const exprt &expr);
148+
virtual bvt convert_let(const let_exprt &);
148149
virtual bvt convert_array_of(const array_of_exprt &expr);
149150
virtual bvt convert_union(const union_exprt &expr);
150151
virtual bvt convert_bv_typecast(const typecast_exprt &expr);

src/solvers/flattening/boolbv_let.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "boolbv.h"
10+
11+
#include <util/std_expr.h>
12+
#include <util/std_types.h>
13+
14+
bvt boolbvt::convert_let(const let_exprt &expr)
15+
{
16+
const bvt value_bv=convert_bv(expr.value());
17+
18+
// We expect the identifiers of the bound symbols to be unique,
19+
// and thus, these can go straight into the symbol to literal map.
20+
// This property also allows us to cache any subexpressions.
21+
const irep_idt &id=expr.symbol().get_identifier();
22+
23+
// the symbol shall be visible during the recursive call
24+
// to convert_bv
25+
map.set_literals(id, expr.symbol().type(), value_bv);
26+
bvt result_bv=convert_bv(expr.where());
27+
28+
// now remove, no longer needed
29+
map.erase_literals(id, expr.symbol().type());
30+
31+
return result_bv;
32+
}

src/solvers/flattening/boolbv_map.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,10 @@ void boolbv_mapt::set_literals(
146146
mb.l=literal;
147147
}
148148
}
149+
150+
void boolbv_mapt::erase_literals(
151+
const irep_idt &identifier,
152+
const typet &)
153+
{
154+
mapping.erase(identifier);
155+
}

src/solvers/flattening/boolbv_map.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ class boolbv_mapt
7575
const typet &type,
7676
const bvt &literals);
7777

78+
void erase_literals(
79+
const irep_idt &identifier,
80+
const typet &type);
81+
7882
protected:
7983
propt &prop;
8084
const namespacet &ns;

0 commit comments

Comments
 (0)