Skip to content

Commit f0c59b5

Browse files
author
Daniel Kroening
authored
Merge pull request #3461 from diffblue/smt2_solver_get-value
SMT2 solver: implement get-value
2 parents aec39d5 + d6f7c5a commit f0c59b5

File tree

7 files changed

+187
-46
lines changed

7 files changed

+187
-46
lines changed

scripts/delete_failing_smt2_solver_tests

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ rm Float4/test.desc
3939
rm Float5/test.desc
4040
rm Float6/test.desc
4141
rm Float8/test.desc
42-
rm Free2/test.desc
4342
rm Function1/test.desc
4443
rm Initialization6/test.desc
4544
rm Linking4/test.desc
@@ -51,14 +50,12 @@ rm Malloc19/test.desc
5150
rm Malloc21/test.desc
5251
rm Malloc23/test.desc
5352
rm Malloc24/test.desc
54-
rm Memory_leak1/test.desc
5553
rm Memory_leak2/test.desc
5654
rm Multi_Dimensional_Array1/test.desc
5755
rm Multi_Dimensional_Array2/test.desc
5856
rm Multi_Dimensional_Array3/test.desc
5957
rm Multi_Dimensional_Array4/test.desc
6058
rm Multi_Dimensional_Array6/test.desc
61-
rm Multiple_Properties1/test.desc
6259
rm Overflow_Leftshift1/test.desc
6360
rm Overflow_Multiplication1/test.desc
6461
rm Overflow_Subtraction1/test.desc
@@ -92,14 +89,12 @@ rm Quantifiers-not-exists/test.desc
9289
rm Quantifiers-two-dimension-array/test.desc
9390
rm Quantifiers-type/test.desc
9491
rm Quantifiers1/test.desc
95-
rm Recursion5/test.desc
9692
rm String2/test.desc
9793
rm Struct_Bytewise1/test.desc
9894
rm Struct_Bytewise2/test.desc
9995
rm Struct_Initialization2/test.desc
10096
rm Struct_Padding1/test.desc
10197
rm Typecast1/test.desc
102-
rm Undefined_Shift1/test.desc
10398
rm Union_Initialization1/test.desc
10499
rm Unwinding_Locality1/test.desc
105100
rm address_space_size_limit1/test.desc
@@ -117,7 +112,6 @@ rm byte_update6/test.desc
117112
rm byte_update7/test.desc
118113
rm byte_update8/test.desc
119114
rm byte_update9/test.desc
120-
rm compact-trace/test.desc
121115
rm dynamic_size1/stack_object.desc
122116
rm equality_through_array1/test.desc
123117
rm equality_through_array2/test.desc
@@ -134,19 +128,14 @@ rm equality_through_struct_containing_arrays2/test.desc
134128
rm equality_through_union1/test.desc
135129
rm equality_through_union2/test.desc
136130
rm equality_through_union3/test.desc
137-
rm full_slice1/test.desc
138-
rm full_slice2/test.desc
139131
rm gcc_bswap1/test.desc
140132
rm gcc_c99-bool-1/test.desc
141133
rm gcc_statement_expression4/test.desc
142-
rm gcc_switch_case_range1/test.desc
143-
rm gcc_switch_case_range2/test.desc
144134
rm gcc_vector1/test.desc
145135
rm gcc_vector2/test.desc
146136
rm graphml_witness1/test.desc
147137
rm havoc_object1/test.desc
148138
rm hex_trace/test.desc
149-
rm if2/test.desc
150139
rm integer-assignments1/test.desc
151140
rm little-endian-array1/test.desc
152141
rm memory_allocation1/test.desc

src/solvers/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ SRC = $(BOOLEFORCE_SRC) \
185185
sat/resolution_proof.cpp \
186186
smt2/smt2_conv.cpp \
187187
smt2/smt2_dec.cpp \
188+
smt2/smt2_format.cpp \
188189
smt2/smt2_parser.cpp \
189190
smt2/smt2_tokenizer.cpp \
190191
smt2/smt2irep.cpp \

src/solvers/smt2/smt2_format.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "smt2_format.h"
10+
11+
#include <util/arith_tools.h>
12+
#include <util/std_expr.h>
13+
#include <util/std_types.h>
14+
15+
std::ostream &smt2_format_rec(std::ostream &out, const typet &type)
16+
{
17+
if(type.id() == ID_unsignedbv)
18+
out << "(_ BitVec " << to_unsignedbv_type(type).get_width() << ')';
19+
else if(type.id() == ID_bool)
20+
out << "Bool";
21+
else if(type.id() == ID_integer)
22+
out << "Int";
23+
else if(type.id() == ID_real)
24+
out << "Real";
25+
else
26+
out << "? " << type.id();
27+
28+
return out;
29+
}
30+
31+
std::ostream &smt2_format_rec(std::ostream &out, const exprt &expr)
32+
{
33+
if(expr.id() == ID_constant)
34+
{
35+
const auto &value = to_constant_expr(expr).get_value();
36+
37+
const typet &expr_type = expr.type();
38+
39+
if(expr_type.id() == ID_unsignedbv)
40+
{
41+
const std::size_t width = to_unsignedbv_type(expr_type).get_width();
42+
43+
const auto value = numeric_cast_v<mp_integer>(expr);
44+
45+
out << "(_ bv" << value << " " << width << ")";
46+
}
47+
else if(expr_type.id() == ID_bool)
48+
{
49+
if(expr.is_true())
50+
out << "true";
51+
else if(expr.is_false())
52+
out << "false";
53+
else
54+
DATA_INVARIANT(false, "unknown Boolean constant");
55+
}
56+
else if(expr_type.id() == ID_integer)
57+
{
58+
out << value;
59+
}
60+
else
61+
DATA_INVARIANT(false, "unhandled constant: " + expr_type.id_string());
62+
}
63+
else if(expr.id() == ID_symbol)
64+
{
65+
out << to_symbol_expr(expr).get_identifier();
66+
}
67+
else
68+
out << "? " << expr.id();
69+
70+
return out;
71+
}

src/solvers/smt2/smt2_format.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_SOLVERS_SMT2_SMT2_FORMAT_H
10+
#define CPROVER_SOLVERS_SMT2_SMT2_FORMAT_H
11+
12+
#include <util/expr.h>
13+
14+
template <typename T>
15+
struct smt2_format_containert
16+
{
17+
explicit smt2_format_containert(const T &_o) : o(_o)
18+
{
19+
}
20+
21+
const T &o;
22+
};
23+
24+
template <typename T>
25+
static inline smt2_format_containert<T> smt2_format(const T &_o)
26+
{
27+
return smt2_format_containert<T>(_o);
28+
}
29+
30+
template <typename T>
31+
static inline std::ostream &
32+
operator<<(std::ostream &out, const smt2_format_containert<T> &c)
33+
{
34+
return smt2_format_rec(out, c.o);
35+
}
36+
37+
std::ostream &smt2_format_rec(std::ostream &, const exprt &);
38+
std::ostream &smt2_format_rec(std::ostream &, const typet &);
39+
40+
#endif // CPROVER_SOLVERS_SMT2_SMT2_FORMAT_H

src/solvers/smt2/smt2_parser.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,9 @@ Author: Daniel Kroening, [email protected]
88

99
#include "smt2_parser.h"
1010

11-
#include <util/arith_tools.h>
12-
13-
std::ostream &operator<<(std::ostream &out, const smt2_parsert::smt2_format &f)
14-
{
15-
if(f.type.id() == ID_unsignedbv)
16-
out << "(_ BitVec " << to_unsignedbv_type(f.type).get_width() << ')';
17-
else if(f.type.id() == ID_bool)
18-
out << "Bool";
19-
else if(f.type.id() == ID_integer)
20-
out << "Int";
21-
else if(f.type.id() == ID_real)
22-
out << "Real";
23-
else
24-
out << "? " << f.type.id();
11+
#include "smt2_format.h"
2512

26-
return out;
27-
}
13+
#include <util/arith_tools.h>
2814

2915
void smt2_parsert::command_sequence()
3016
{

src/solvers/smt2/smt2_parser.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ class smt2_parsert:public smt2_tokenizert
4343
using id_mapt=std::map<irep_idt, idt>;
4444
id_mapt id_map;
4545

46-
struct smt2_format
47-
{
48-
explicit smt2_format(const typet &_type) : type(_type)
49-
{
50-
}
51-
52-
const typet type;
53-
};
54-
5546
protected:
5647
bool exit;
5748
void command_sequence();
@@ -91,6 +82,4 @@ class smt2_parsert:public smt2_tokenizert
9182
exprt cast_bv_to_unsigned(const exprt &);
9283
};
9384

94-
std::ostream &operator<<(std::ostream &, const smt2_parsert::smt2_format &);
95-
9685
#endif // CPROVER_SOLVERS_SMT2_SMT2_PARSER_H

src/solvers/smt2/smt2_solver.cpp

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9+
#include "smt2_parser.h"
10+
11+
#include "smt2_format.h"
12+
913
#include <fstream>
1014
#include <iostream>
1115

12-
#include "smt2_parser.h"
13-
1416
#include <util/message.h>
1517
#include <util/namespace.h>
1618
#include <util/replace_symbol.h>
@@ -23,11 +25,8 @@ Author: Daniel Kroening, [email protected]
2325
class smt2_solvert:public smt2_parsert
2426
{
2527
public:
26-
smt2_solvert(
27-
std::istream &_in,
28-
decision_proceduret &_solver):
29-
smt2_parsert(_in),
30-
solver(_solver)
28+
smt2_solvert(std::istream &_in, decision_proceduret &_solver)
29+
: smt2_parsert(_in), solver(_solver), status(NOT_SOLVED)
3130
{
3231
}
3332

@@ -39,6 +38,13 @@ class smt2_solvert:public smt2_parsert
3938
void expand_function_applications(exprt &);
4039

4140
std::set<irep_idt> constants_done;
41+
42+
enum
43+
{
44+
NOT_SOLVED,
45+
SAT,
46+
UNSAT
47+
} status;
4248
};
4349

4450
void smt2_solvert::define_constants(const exprt &expr)
@@ -139,14 +145,17 @@ void smt2_solvert::command(const std::string &c)
139145
{
140146
case decision_proceduret::resultt::D_SATISFIABLE:
141147
std::cout << "sat\n";
148+
status = SAT;
142149
break;
143150

144151
case decision_proceduret::resultt::D_UNSATISFIABLE:
145152
std::cout << "unsat\n";
153+
status = UNSAT;
146154
break;
147155

148156
case decision_proceduret::resultt::D_ERROR:
149157
std::cout << "error\n";
158+
status = NOT_SOLVED;
150159
}
151160
}
152161
else if(c=="check-sat-assuming")
@@ -162,6 +171,63 @@ void smt2_solvert::command(const std::string &c)
162171
std::cout << e.pretty() << '\n'; // need to do an 'smt2_format'
163172
}
164173
}
174+
else if(c == "get-value")
175+
{
176+
std::vector<exprt> ops;
177+
178+
if(next_token() != OPEN)
179+
throw "get-value expects list as argument";
180+
181+
while(peek() != CLOSE && peek() != END_OF_FILE)
182+
ops.push_back(expression()); // any term
183+
184+
if(next_token() != CLOSE)
185+
throw "get-value expects ')' at end of list";
186+
187+
if(status != SAT)
188+
throw "model is not available";
189+
190+
std::vector<exprt> values;
191+
values.reserve(ops.size());
192+
193+
for(const auto &op : ops)
194+
{
195+
if(op.id() != ID_symbol)
196+
throw "get-value expects symbol";
197+
198+
const auto &identifier = to_symbol_expr(op).get_identifier();
199+
200+
const auto id_map_it = id_map.find(identifier);
201+
202+
if(id_map_it == id_map.end())
203+
throw "unexpected symbol " + id2string(identifier);
204+
205+
exprt value;
206+
207+
if(id_map_it->second.definition.is_nil())
208+
value = solver.get(op);
209+
else
210+
value = solver.get(id_map_it->second.definition);
211+
212+
if(value.is_nil())
213+
throw "no value for " + id2string(identifier);
214+
215+
values.push_back(value);
216+
}
217+
218+
std::cout << '(';
219+
220+
for(std::size_t op_nr = 0; op_nr < ops.size(); op_nr++)
221+
{
222+
if(op_nr != 0)
223+
std::cout << "\n ";
224+
225+
std::cout << '(' << smt2_format(ops[op_nr]) << ' '
226+
<< smt2_format(values[op_nr]) << ')';
227+
}
228+
229+
std::cout << ")\n";
230+
}
165231
else if(c=="simplify")
166232
{
167233
// this is a command that Z3 appears to implement
@@ -195,7 +261,6 @@ void smt2_solvert::command(const std::string &c)
195261
| ( get-proof )
196262
| ( get-unsat-assumptions )
197263
| ( get-unsat-core )
198-
| ( get-value ( htermi + ) )
199264
| ( pop hnumerali )
200265
| ( push hnumerali )
201266
| ( reset )

0 commit comments

Comments
 (0)