Skip to content

Commit b113c23

Browse files
author
Lefan Zhang
authored
Merge pull request diffblue#19 from lefanz-amazon/lefan-abstraction
length: add length variable and assumptions
2 parents 7543df9 + 4436aa0 commit b113c23

File tree

6 files changed

+139
-29
lines changed

6 files changed

+139
-29
lines changed

regression/abstraction/abst-funcs.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ size_t sub_conc_from_abs_1(size_t abs_ind, size_t num, size_t a1){
118118
//Cases +c+c*, c+c*, +cc*, c+c*, cc+ can all be
119119
//handled by the same function as long as we are careful with concretization, increment and other funcs.
120120
//If model checking time is affected then we can split into finer cases.
121-
int two_abs(int index, int a1, int a2) {
121+
size_t two_abs(size_t index, size_t a1, size_t a2) {
122122
if (index < a1) return 0;
123123
else if (index == a1) return 1;
124124
else if (index > a1 && index < a2) return 2;
@@ -129,7 +129,7 @@ int two_abs(int index, int a1, int a2) {
129129

130130
//Get the concretization of an index. We assume all args are >= 0
131131
//Shape *c*c*
132-
int concretize_2(int abs_ind, int a1, int a2) {
132+
size_t concretize_2(size_t abs_ind, size_t a1, size_t a2) {
133133
assert(abs_ind >= 0);
134134
assert(a1 >= 0);
135135
assert(a2 > a1);
@@ -155,18 +155,18 @@ int concretize_2(int abs_ind, int a1, int a2) {
155155
else return(nndt_above(a2));
156156
}
157157

158-
int is_precise_2(int abs_ind){
158+
int is_precise_2(size_t abs_ind){
159159
if (abs_ind == 1 || abs_ind == 3) return(1);
160160
else return(0);
161161
}
162162

163-
int is_abstract_2(int abs_ind){
163+
int is_abstract_2(size_t abs_ind){
164164
int pre = is_precise_2(abs_ind);
165165
return(1-pre);
166166
}
167167

168168
// Add a number to an abs_ind
169-
int add_abs_to_conc_2(int abs_ind, int num, int a1, int a2){
169+
size_t add_abs_to_conc_2(size_t abs_ind, size_t num, size_t a1, size_t a2){
170170
if (num == 1){
171171
if(abs_ind == 0 || abs_ind == 2) {
172172
if (nndt_bool() > 0) return(abs_ind);
@@ -190,7 +190,7 @@ int add_abs_to_conc_2(int abs_ind, int num, int a1, int a2){
190190

191191
}
192192

193-
int sub_conc_from_abs_2(int abs_ind, int num, int a1, int a2){
193+
size_t sub_conc_from_abs_2(size_t abs_ind, size_t num, size_t a1, size_t a2){
194194
if (num == 1){
195195
if(abs_ind == 4 || abs_ind == 2) {
196196
if (nndt_bool() > 0) return(abs_ind);

regression/abstraction/specs/aws_array_eq.json

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
"function": "aws_array_eq_harness",
66
"name": "aws_array_eq_harness::1::rhs",
77
"shape": {
8-
"indices": ["cncrt"],
8+
"indices": ["cncrt", "length"],
99
"assumptions": [
1010
],
11-
"shape-type": "*c*"
11+
"shape-type": "*c*l"
1212
},
13-
"abst-function-file": "./abst-funcs.c",
13+
"abst-function-file": "../abst-funcs.c",
1414
"abst-functions":{
15-
"add-abs-conc": "add_abs_to_conc_1",
16-
"sub-abs-conc": "sub_conc_from_abs_1",
17-
"precise-check": "is_precise_1",
18-
"abstract-index": "one_abs",
15+
"add-abs-conc": "add_abs_to_conc_2",
16+
"sub-abs-conc": "sub_conc_from_abs_2",
17+
"precise-check": "is_precise_2",
18+
"abstract-index": "two_abs",
1919
"concretize-index": "concretize",
2020
"multiply-indices": null,
2121
"mod-indices": null
@@ -27,12 +27,7 @@
2727
"name": "aws_array_eq_harness::1::lhs"
2828
},
2929
{
30-
"entity": "scalar",
31-
"function": "aws_array_eq_harness",
32-
"name": "aws_array_eq_harness::1::rhs_len"
33-
},
34-
{
35-
"entity": "scalar",
30+
"entity": "length",
3631
"function": "aws_array_eq_harness",
3732
"name": "aws_array_eq_harness::1::lhs_len"
3833
}

src/goto-instrument/abstraction.cpp

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,10 @@ void complete_abst_spec(const goto_functiont& goto_function, abstraction_spect &
294294
std::tuple<std::unordered_set<irep_idt>, std::unordered_set<irep_idt>> abst_entities = find_index_symbols(goto_function, ent.first);
295295
for(irep_idt index_name: std::get<0>(abst_entities))
296296
if(spec.get_abst_arrays().find(index_name) == spec.get_abst_arrays().end())
297-
spec.insert_entity(index_name, false);
297+
spec.insert_entity(index_name, "array");
298298
for(irep_idt index_name: std::get<1>(abst_entities))
299299
if(spec.get_abst_indices().find(index_name) == spec.get_abst_indices().end())
300-
spec.insert_entity(index_name, true);
300+
spec.insert_entity(index_name, "scalar");
301301
}
302302
}
303303
}
@@ -1235,11 +1235,102 @@ void define_concrete_indices(goto_modelt &goto_model, const abstraction_spect &a
12351235
}
12361236
}
12371237

1238+
void add_length_assumptions(goto_modelt &goto_model, const abstraction_spect &abst_spec)
1239+
{
1240+
for(const auto &spec: abst_spec.get_specs())
1241+
{
1242+
for(const auto &lp: spec.get_abst_lengths())
1243+
{
1244+
const irep_idt func_name = abst_spec.get_func_name();
1245+
1246+
// TODO: currently we are assuming every entities in the
1247+
// json file belong to the same function. That may not be the case.
1248+
auto &function = goto_model.goto_functions.function_map.at(func_name);
1249+
// if this variable is a local varible
1250+
bool is_local = false;
1251+
1252+
// go through each instruction in the function to find the declare
1253+
Forall_goto_program_instructions(it, function.body)
1254+
{
1255+
if(it->is_decl())
1256+
{
1257+
const code_declt &decl = it->get_decl();
1258+
// check if this declares the length variable
1259+
if(decl.get_identifier() == lp.first)
1260+
{
1261+
is_local = true;
1262+
// need to add an assumption after this inst
1263+
INVARIANT(
1264+
goto_model.get_symbol_table().has_symbol(decl.get_identifier()),
1265+
"Symbol " + std::string(decl.get_identifier().c_str()) +
1266+
" not defined");
1267+
INVARIANT(
1268+
goto_model.get_symbol_table().has_symbol(
1269+
spec.get_length_index_name()),
1270+
"Symbol " + std::string(spec.get_length_index_name().c_str()) +
1271+
" not defined");
1272+
1273+
// define the assumption instruction
1274+
const symbolt symb1 = goto_model.get_symbol_table().lookup_ref(decl.get_identifier());
1275+
const symbolt symb2 = goto_model.get_symbol_table().lookup_ref(spec.get_length_index_name());
1276+
equal_exprt assumption_expr(symb1.symbol_expr(), symb2.symbol_expr());
1277+
auto new_assumption = goto_programt::make_assumption(assumption_expr);
1278+
1279+
// insert it
1280+
function.body.insert_after(it, new_assumption);
1281+
std::cout << "Added length assumption after the decl: ";
1282+
format_rec(std::cout, assumption_expr) << std::endl;
1283+
it++;
1284+
}
1285+
}
1286+
}
1287+
1288+
// if it is not a local variable, the assumption should be added at
1289+
// the end of the global INITIAL function
1290+
if(!is_local)
1291+
{
1292+
// find the CPROVER_INITIAL function
1293+
goto_functionst::function_mapt::iterator fct_entry =
1294+
goto_model.goto_functions.function_map.find(INITIALIZE_FUNCTION);
1295+
CHECK_RETURN(fct_entry != goto_model.goto_functions.function_map.end());
1296+
goto_programt &init_function = fct_entry->second.body;
1297+
auto last_instruction = std::prev(init_function.instructions.end());
1298+
DATA_INVARIANT(
1299+
last_instruction->is_end_function(),
1300+
"last instruction in function should be END_FUNCTION");
1301+
1302+
// define the assumption instruction
1303+
INVARIANT(
1304+
goto_model.get_symbol_table().has_symbol(lp.first),
1305+
"Symbol " + std::string(lp.first.c_str()) +
1306+
" not defined");
1307+
INVARIANT(
1308+
goto_model.get_symbol_table().has_symbol(
1309+
spec.get_length_index_name()),
1310+
"Symbol " + std::string(spec.get_length_index_name().c_str()) +
1311+
" not defined");
1312+
const symbolt symb1 = goto_model.get_symbol_table().lookup_ref(lp.first);
1313+
const symbolt symb2 = goto_model.get_symbol_table().lookup_ref(spec.get_length_index_name());
1314+
equal_exprt assumption_expr(symb1.symbol_expr(), symb2.symbol_expr());
1315+
auto new_assumption = goto_programt::make_assumption(assumption_expr);
1316+
1317+
// insert it
1318+
std::cout << "Added length assumption in the beginning of the function: ";
1319+
format_rec(std::cout, assumption_expr);
1320+
init_function.insert_before_swap(last_instruction, new_assumption);
1321+
}
1322+
}
1323+
}
1324+
}
1325+
12381326
void abstract_goto_program(goto_modelt &goto_model, abstraction_spect &abst_spec)
12391327
{
12401328
// Define the global concrete indices to be used
12411329
define_concrete_indices(goto_model, abst_spec);
12421330

1331+
// Add the assumption for len==$clen
1332+
add_length_assumptions(goto_model, abst_spec);
1333+
12431334
// A couple of spects are initialized from the json file. We should go from there and insert spects to other functions
12441335
std::unordered_map<irep_idt, abstraction_spect> function_spec_map =
12451336
calculate_complete_abst_specs_for_funcs(goto_model, abst_spec);

src/goto-instrument/abstraction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ exprt abstract_expr_read(
239239
goto_programt::instructionst &insts_after,
240240
std::vector<symbolt> &new_symbs);
241241

242+
// add the assumption len=$clen for all length variables
243+
void add_length_assumptions(goto_modelt &goto_model, const abstraction_spect &abst_spec);
244+
242245
// define concrete indices globally
243246
void define_concrete_indices(goto_modelt &goto_model, const abstraction_spect &abst_spec);
244247

src/goto-instrument/abstraction_spect.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ abstraction_spect::abstraction_spect(
3030
size_t spec_index = specs.size();
3131
function = entry_obj.find("function")->second.value; // we assume that all entries in the json file are located in the same function
3232
// insert the entity
33-
spec.insert_entity(entry_obj.find("name")->second.value, entry_obj.find("entity")->second.value!="array");
33+
spec.insert_entity(entry_obj.find("name")->second.value, entry_obj.find("entity")->second.value);
3434
const auto &json_re_array = to_json_array(entry_obj.find("related-entities")->second);
3535
for(auto it_r=json_re_array.begin(); it_r != json_re_array.end(); ++it_r)
3636
{
3737
const auto &related_entity = to_json_object(*it_r);
38-
spec.insert_entity(related_entity.find("name")->second.value, related_entity.find("entity")->second.value!="array");
38+
spec.insert_entity(related_entity.find("name")->second.value, related_entity.find("entity")->second.value);
3939
}
4040

4141
// initialize the abst functions

src/goto-instrument/abstraction_spect.h

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ class abstraction_spect
8585
{
8686
return indices;
8787
}
88+
const irep_idt get_length_index_name() const
89+
{
90+
INVARIANT(indices.size()>0, "shape should have at least a length concrete variable");
91+
return *(indices.end()-1);
92+
}
8893
};
8994

9095
struct entityt
@@ -126,11 +131,12 @@ class abstraction_spect
126131

127132
//Arrays to be abstracted
128133
std::unordered_map<irep_idt, entityt> abst_arrays;
129-
// std::vector<entityt> abst_arrays;
130134

131135
//Index vars to be abstracted
132136
std::unordered_map<irep_idt, entityt> abst_indices;
133-
// std::vector<entityt> abst_indices;
137+
138+
//Length vars to be abstracted
139+
std::unordered_map<irep_idt, entityt> abst_lengths;
134140

135141
// Shape of the abstraction
136142
abst_shapet shape;
@@ -156,6 +162,7 @@ class abstraction_spect
156162
: abst_func_file(_spec.abst_func_file),
157163
abst_arrays(_spec.abst_arrays),
158164
abst_indices(_spec.abst_indices),
165+
abst_lengths(_spec.abst_lengths),
159166
shape(_spec.shape),
160167
is_precise_func(_spec.is_precise_func),
161168
compare_indices_func(_spec.compare_indices_func),
@@ -166,14 +173,18 @@ class abstraction_spect
166173
}
167174

168175
//We will have functions for accessing and modifying the above data.
169-
//array_or_index: false-array, true-index
170-
void insert_entity(const irep_idt &_name, bool array_or_index)
176+
//_type: "array", "scalar", "length"
177+
void insert_entity(const irep_idt &_name, const std::string &_type)
171178
{
172179
entityt new_entity(_name);
173-
if(!array_or_index)
180+
if(_type == "array")
174181
abst_arrays.insert({_name, new_entity});
175-
else
182+
else if(_type == "scalar")
176183
abst_indices.insert({_name, new_entity});
184+
else if(_type == "length")
185+
abst_lengths.insert({_name, new_entity});
186+
else
187+
throw "Unknown entity type: " + _type;
177188
}
178189

179190
const std::unordered_map<irep_idt, entityt> &get_abst_arrays() const
@@ -186,6 +197,11 @@ class abstraction_spect
186197
return abst_indices;
187198
}
188199

200+
const std::unordered_map<irep_idt, entityt> &get_abst_lengths() const
201+
{
202+
return abst_lengths;
203+
}
204+
189205
const bool has_entity(const irep_idt &entity_name) const
190206
{
191207
return (abst_arrays.find(entity_name) != abst_arrays.end()) ||
@@ -202,6 +218,11 @@ class abstraction_spect
202218
return (abst_indices.find(entity_name) != abst_indices.end());
203219
}
204220

221+
const irep_idt get_length_index_name() const
222+
{
223+
return shape.get_length_index_name();
224+
}
225+
205226
//set abst func file path
206227
void set_abst_func_file(const std::string &_abst_func_file)
207228
{

0 commit comments

Comments
 (0)