Skip to content

Commit 6c09b3e

Browse files
author
Matthias Güdemann
committed
Add nondet.{h.cpp}
1 parent eb71a01 commit 6c09b3e

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed

jbmc/src/java_bytecode/Makefile

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

jbmc/src/java_bytecode/nondet.cpp

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

jbmc/src/java_bytecode/nondet.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// Author: DiffBlue Limited. All Rights Reserved.
2+
3+
#ifndef CPROVER_JAVA_BYTECODE_NONDET_H
4+
#define CPROVER_JAVA_BYTECODE_NONDET_H
5+
6+
#include <util/std_code.h>
7+
#include <util/std_expr.h>
8+
#include <util/symbol_table.h>
9+
10+
symbol_exprt generate_nondet_int(
11+
int64_t min_value,
12+
int64_t max_value,
13+
const std::string &name_prefix,
14+
const typet &int_type,
15+
const source_locationt &source_location,
16+
symbol_table_baset &symbol_table,
17+
code_blockt &instructions);
18+
19+
typedef std::vector<codet> alternate_casest;
20+
21+
code_blockt generate_nondet_switch(
22+
const irep_idt &name_prefix,
23+
const alternate_casest &switch_cases,
24+
const typet &int_type,
25+
const source_locationt &source_location,
26+
symbol_table_baset &symbol_table);
27+
28+
#endif // CPROVER_JAVA_BYTECODE_NONDET_H

0 commit comments

Comments
 (0)