Skip to content

Commit cb0f310

Browse files
author
Matthias Güdemann
committed
Add nondet.{h.cpp}
1 parent 82a1bd3 commit cb0f310

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed

jbmc/src/java_bytecode/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ SRC = bytecode_info.cpp \
3535
java_utils.cpp \
3636
load_method_by_regex.cpp \
3737
mz_zip_archive.cpp \
38+
nondet.cpp \
3839
remove_exceptions.cpp \
3940
remove_instanceof.cpp \
4041
remove_java_new.cpp \

jbmc/src/java_bytecode/nondet.cpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*******************************************************************\
2+
3+
Module: Non-deterministic object init and choice for JBMC
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#include "nondet.h"
10+
11+
#include <java_bytecode/java_types.h>
12+
#include <util/arith_tools.h>
13+
#include <util/c_types.h>
14+
#include <util/fresh_symbol.h>
15+
#include <util/symbol.h>
16+
17+
/// Gets a fresh nondet choice in range (min_value, max_value). GOTO generated
18+
/// resembles:
19+
/// ```
20+
/// int_type name_prefix::nondet_int = NONDET(int_type)
21+
/// ASSUME(name_prefix::nondet_int >= min_value)
22+
/// ASSUME(name_prefix::nondet_int <= max_value)
23+
/// ```
24+
/// \param min_value: Minimum value (inclusive) of returned int.
25+
/// \param max_value: Maximum value (inclusive) of returned int.
26+
/// \param name_prefix: Prefix for the fresh symbol name generated.
27+
/// \param int_type: The type of the int used to non-deterministically choose
28+
/// one of the switch cases.
29+
/// \param source_location: The location to mark the generated int with.
30+
/// \param symbol_table: The global symbol table.
31+
/// \param instructions [out]: Output instructions are written to
32+
/// 'instructions'. These declare, nondet-initialise and range-constrain (with
33+
/// assume statements) a fresh integer.
34+
/// \return Returns a symbol expression for the resulting integer.
35+
symbol_exprt generate_nondet_int(
36+
const int64_t min_value,
37+
const int64_t max_value,
38+
const std::string &name_prefix,
39+
const typet &int_type,
40+
const source_locationt &source_location,
41+
symbol_table_baset &symbol_table,
42+
code_blockt &instructions)
43+
{
44+
PRECONDITION(min_value < max_value);
45+
46+
// Declare a symbol for the non deterministic integer.
47+
const symbol_exprt &nondet_symbol = get_fresh_aux_symbol(
48+
int_type,
49+
name_prefix + "::nondet_int",
50+
"nondet_int",
51+
source_location,
52+
ID_java,
53+
symbol_table)
54+
.symbol_expr();
55+
instructions.add(code_declt(nondet_symbol));
56+
57+
// Assign the symbol any non deterministic integer value.
58+
// int_type name_prefix::nondet_int = NONDET(int_type)
59+
instructions.add(
60+
code_assignt(nondet_symbol, side_effect_expr_nondett(int_type)));
61+
62+
// Constrain the non deterministic integer with a lower bound of `min_value`.
63+
// ASSUME(name_prefix::nondet_int >= min_value)
64+
instructions.add(
65+
code_assumet(
66+
binary_predicate_exprt(
67+
nondet_symbol, ID_ge, from_integer(min_value, int_type))));
68+
69+
// Constrain the non deterministic integer with an upper bound of `max_value`.
70+
// ASSUME(name_prefix::nondet_int <= max_value)
71+
instructions.add(
72+
code_assumet(
73+
binary_predicate_exprt(
74+
nondet_symbol, ID_le, from_integer(max_value, int_type))));
75+
76+
return nondet_symbol;
77+
}
78+
79+
/// Pick nondeterministically between imperative actions 'switch_cases'.
80+
/// \param name_prefix: Name prefix for fresh symbols
81+
/// \param switch_cases: List of codet objects to execute in each switch case.
82+
/// \param int_type: The type of the int used to non-deterministically choose
83+
/// one of the switch cases.
84+
/// \param source_location: The location to mark the generated int with.
85+
/// \param symbol_table: The global symbol table.
86+
/// \return Returns a nondet-switch choosing between switch_cases. The resulting
87+
/// switch block has no default case.
88+
code_blockt generate_nondet_switch(
89+
const irep_idt &name_prefix,
90+
const alternate_casest &switch_cases,
91+
const typet &int_type,
92+
const source_locationt &source_location,
93+
symbol_table_baset &symbol_table)
94+
{
95+
PRECONDITION(!switch_cases.empty());
96+
97+
if(switch_cases.size() == 1)
98+
return code_blockt({switch_cases[0]});
99+
100+
code_switcht result_switch;
101+
code_blockt result_block;
102+
103+
const symbol_exprt &switch_value = generate_nondet_int(
104+
0,
105+
switch_cases.size() - 1,
106+
id2string(name_prefix),
107+
int_type,
108+
source_location,
109+
symbol_table,
110+
result_block);
111+
112+
result_switch.value() = switch_value;
113+
114+
code_blockt switch_block;
115+
int64_t case_number = 0;
116+
for(const auto &switch_case : switch_cases)
117+
{
118+
code_blockt this_block;
119+
this_block.add(switch_case);
120+
this_block.add(code_breakt());
121+
code_switch_caset this_case;
122+
this_case.case_op() = from_integer(case_number, switch_value.type());
123+
this_case.code() = this_block;
124+
switch_block.move(this_case);
125+
++case_number;
126+
}
127+
128+
result_switch.body() = switch_block;
129+
result_block.move(result_switch);
130+
return result_block;
131+
}

jbmc/src/java_bytecode/nondet.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*******************************************************************\
2+
3+
Module: Non-deterministic object init and choice for JBMC
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_JAVA_BYTECODE_NONDET_H
10+
#define CPROVER_JAVA_BYTECODE_NONDET_H
11+
12+
#include <util/std_code.h>
13+
#include <util/std_expr.h>
14+
#include <util/symbol_table.h>
15+
16+
symbol_exprt generate_nondet_int(
17+
int64_t min_value,
18+
int64_t max_value,
19+
const std::string &name_prefix,
20+
const typet &int_type,
21+
const source_locationt &source_location,
22+
symbol_table_baset &symbol_table,
23+
code_blockt &instructions);
24+
25+
typedef std::vector<codet> alternate_casest;
26+
27+
code_blockt generate_nondet_switch(
28+
const irep_idt &name_prefix,
29+
const alternate_casest &switch_cases,
30+
const typet &int_type,
31+
const source_locationt &source_location,
32+
symbol_table_baset &symbol_table);
33+
34+
#endif // CPROVER_JAVA_BYTECODE_NONDET_H

0 commit comments

Comments
 (0)