Skip to content

Commit 1871331

Browse files
Move replace_java_nondet to java_bytecode
1 parent dba5c4f commit 1871331

File tree

5 files changed

+94
-121
lines changed

5 files changed

+94
-121
lines changed

src/goto-programs/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ SRC = basic_blocks.cpp \
5050
remove_unused_functions.cpp \
5151
remove_vector.cpp \
5252
remove_virtual_functions.cpp \
53-
replace_java_nondet.cpp \
5453
generate_function_bodies.cpp \
5554
resolve_inherited_component.cpp \
5655
safety_checker.cpp \

src/java_bytecode/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ SRC = bytecode_info.cpp \
3131
java_types.cpp \
3232
java_utils.cpp \
3333
mz_zip_archive.cpp \
34+
replace_java_nondet.cpp \
3435
remove_exceptions.cpp \
3536
remove_instanceof.cpp \
3637
select_pointer_type.cpp \

src/goto-programs/replace_java_nondet.cpp renamed to src/java_bytecode/replace_java_nondet.cpp

Lines changed: 89 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,51 @@ Author: Reuben Thomas, [email protected]
99
/// \file
1010
/// Replace Java Nondet expressions
1111

12-
#include "goto-programs/replace_java_nondet.h"
13-
#include "goto-programs/goto_convert.h"
14-
#include "goto-programs/goto_model.h"
15-
#include "goto-programs/remove_skip.h"
16-
17-
#include "util/irep_ids.h"
12+
#include "replace_java_nondet.h"
1813

1914
#include <algorithm>
2015
#include <regex>
2116

17+
#include <goto-programs/goto_convert.h>
18+
#include <goto-programs/goto_model.h>
19+
#include <goto-programs/remove_skip.h>
20+
21+
#include <util/irep_ids.h>
22+
2223
/// Holds information about any discovered nondet methods, with extreme type-
2324
/// safety.
2425
class nondet_instruction_infot final
2526
{
2627
public:
27-
enum class is_nondett:bool { FALSE, TRUE };
28-
enum class is_nullablet:bool { FALSE, TRUE };
28+
enum class is_nondett : bool
29+
{
30+
FALSE,
31+
TRUE
32+
};
33+
enum class is_nullablet : bool
34+
{
35+
FALSE,
36+
TRUE
37+
};
2938

30-
nondet_instruction_infot():
31-
is_nondet(is_nondett::FALSE),
32-
is_nullable(is_nullablet::FALSE)
39+
nondet_instruction_infot()
40+
: is_nondet(is_nondett::FALSE), is_nullable(is_nullablet::FALSE)
3341
{
3442
}
3543

36-
explicit nondet_instruction_infot(is_nullablet is_nullable):
37-
is_nondet(is_nondett::TRUE),
38-
is_nullable(is_nullable)
44+
explicit nondet_instruction_infot(is_nullablet is_nullable)
45+
: is_nondet(is_nondett::TRUE), is_nullable(is_nullable)
3946
{
4047
}
4148

42-
is_nondett get_instruction_type() const { return is_nondet; }
43-
is_nullablet get_nullable_type() const { return is_nullable; }
49+
is_nondett get_instruction_type() const
50+
{
51+
return is_nondet;
52+
}
53+
is_nullablet get_nullable_type() const
54+
{
55+
return is_nullable;
56+
}
4457

4558
private:
4659
is_nondett is_nondet;
@@ -52,11 +65,11 @@ class nondet_instruction_infot final
5265
/// \return A structure detailing whether the function call appears to be one of
5366
/// our nondet library methods, and if so, whether or not it allows null
5467
/// results.
55-
static nondet_instruction_infot is_nondet_returning_object(
56-
const code_function_callt &function_call)
68+
static nondet_instruction_infot
69+
is_nondet_returning_object(const code_function_callt &function_call)
5770
{
58-
const auto &function_symbol=to_symbol_expr(function_call.function());
59-
const auto function_name=id2string(function_symbol.get_identifier());
71+
const auto &function_symbol = to_symbol_expr(function_call.function());
72+
const auto function_name = id2string(function_symbol.get_identifier());
6073
const std::regex reg(
6174
R"(.*org\.cprover\.CProver\.nondet)"
6275
R"((?:Boolean|Byte|Char|Short|Int|Long|Float|Double|With(out)?Null.*))");
@@ -74,51 +87,51 @@ static nondet_instruction_infot is_nondet_returning_object(
7487
/// recognised nondet library methods, and return some information about it.
7588
/// \param instr: A goto-program instruction to check.
7689
/// \return A structure detailing the properties of the nondet method.
77-
static nondet_instruction_infot get_nondet_instruction_info(
78-
const goto_programt::const_targett &instr)
90+
static nondet_instruction_infot
91+
get_nondet_instruction_info(const goto_programt::const_targett &instr)
7992
{
80-
if(!(instr->is_function_call() && instr->code.id()==ID_code))
93+
if(!(instr->is_function_call() && instr->code.id() == ID_code))
8194
{
8295
return nondet_instruction_infot();
8396
}
84-
const auto &code=to_code(instr->code);
85-
if(code.get_statement()!=ID_function_call)
97+
const auto &code = to_code(instr->code);
98+
if(code.get_statement() != ID_function_call)
8699
{
87100
return nondet_instruction_infot();
88101
}
89-
const auto &function_call=to_code_function_call(code);
102+
const auto &function_call = to_code_function_call(code);
90103
return is_nondet_returning_object(function_call);
91104
}
92105

93106
/// Return whether the expression is a symbol with the specified identifier.
94107
/// \param expr: The expression which may be a symbol.
95108
/// \param identifier: Some identifier.
96109
/// \return True if the expression is a symbol with the specified identifier.
97-
static bool is_symbol_with_id(const exprt& expr, const irep_idt& identifier)
110+
static bool is_symbol_with_id(const exprt &expr, const irep_idt &identifier)
98111
{
99-
return expr.id()==ID_symbol &&
100-
to_symbol_expr(expr).get_identifier()==identifier;
112+
return expr.id() == ID_symbol &&
113+
to_symbol_expr(expr).get_identifier() == identifier;
101114
}
102115

103116
/// Return whether the expression is a typecast with the specified identifier.
104117
/// \param expr: The expression which may be a typecast.
105118
/// \param identifier: Some identifier.
106119
/// \return True if the expression is a typecast with one operand, and the
107120
/// typecast's identifier matches the specified identifier.
108-
static bool is_typecast_with_id(const exprt& expr, const irep_idt& identifier)
121+
static bool is_typecast_with_id(const exprt &expr, const irep_idt &identifier)
109122
{
110-
if(!(expr.id()==ID_typecast && expr.operands().size()==1))
123+
if(!(expr.id() == ID_typecast && expr.operands().size() == 1))
111124
{
112125
return false;
113126
}
114-
const auto &typecast=to_typecast_expr(expr);
115-
if(!(typecast.op().id()==ID_symbol && !typecast.op().has_operands()))
127+
const auto &typecast = to_typecast_expr(expr);
128+
if(!(typecast.op().id() == ID_symbol && !typecast.op().has_operands()))
116129
{
117130
return false;
118131
}
119-
const auto &op_symbol=to_symbol_expr(typecast.op());
132+
const auto &op_symbol = to_symbol_expr(typecast.op());
120133
// Return whether the typecast has the expected operand
121-
return op_symbol.get_identifier()==identifier;
134+
return op_symbol.get_identifier() == identifier;
122135
}
123136

124137
/// Return whether the instruction is an assignment, and the rhs is a symbol or
@@ -136,26 +149,14 @@ static bool is_assignment_from(
136149
{
137150
return false;
138151
}
139-
const auto &rhs=to_code_assign(instr.code).rhs();
152+
const auto &rhs = to_code_assign(instr.code).rhs();
140153
return is_symbol_with_id(rhs, identifier) ||
141154
is_typecast_with_id(rhs, identifier);
142155
}
143156

144157
/// Given an iterator into a list of instructions, modify the list to replace
145158
/// 'nondet' library functions with CBMC-native nondet expressions, and return
146-
/// an iterator to the next instruction to check. It's important to note that
147-
/// this method also deals with the fact that in the GOTO program it assigns
148-
/// function return values to temporary variables, performs validation and then
149-
/// assigns the value into the actual variable.
150-
///
151-
/// Example:
152-
///
153-
/// return_tmp0=org.cprover.CProver.nondetWithoutNull:()Ljava/lang/Object;();
154-
/// ... Various validations of type and value here.
155-
/// obj = (<type-of-obj>)return_tmp0;
156-
///
157-
/// We're going to replace all of these lines with
158-
/// return_tmp0 = NONDET(<type-of-obj>)
159+
/// an iterator to the next instruction to check.
159160
/// \param goto_program: The goto program to modify.
160161
/// \param target: A single step of the goto program which may be erased and
161162
/// replaced.
@@ -165,94 +166,67 @@ static goto_programt::targett check_and_replace_target(
165166
const goto_programt::targett &target)
166167
{
167168
// Check whether this is a nondet library method, and return if not
168-
const auto instr_info=get_nondet_instruction_info(target);
169-
const auto next_instr=std::next(target);
170-
if(instr_info.get_instruction_type()==
171-
nondet_instruction_infot::is_nondett::FALSE)
169+
const auto instr_info = get_nondet_instruction_info(target);
170+
const auto next_instr = std::next(target);
171+
if(
172+
instr_info.get_instruction_type() ==
173+
nondet_instruction_infot::is_nondett::FALSE)
172174
{
173175
return next_instr;
174176
}
175177

176-
// If we haven't removed returns yet, our function call will have a variable
177-
// on its left hand side.
178-
const bool remove_returns_not_run =
179-
to_code_function_call(target->code).lhs().is_not_nil();
180-
181-
irep_idt return_identifier;
182-
if(remove_returns_not_run)
178+
// Look at the next instruction, ensure that it is an assignment
179+
assert(next_instr->is_assign());
180+
// Get the name of the LHS of the assignment
181+
const auto &next_instr_assign_lhs = to_code_assign(next_instr->code).lhs();
182+
if(
183+
!(next_instr_assign_lhs.id() == ID_symbol &&
184+
!next_instr_assign_lhs.has_operands()))
183185
{
184-
return_identifier =
185-
to_symbol_expr(to_code_function_call(target->code).lhs())
186-
.get_identifier();
187-
}
188-
else
189-
{
190-
// If not, we need to look at the next line instead.
191-
DATA_INVARIANT(
192-
next_instr->is_assign(),
193-
"the code_function_callt for a nondet-returning library function should "
194-
"either have a variable for the return value in its lhs() or the next "
195-
"instruction should be an assignment of the return value to a temporary "
196-
"variable");
197-
const exprt &return_value_assignment =
198-
to_code_assign(next_instr->code).lhs();
199-
200-
// If the assignment is null, return.
201-
if(
202-
!(return_value_assignment.id() == ID_symbol &&
203-
!return_value_assignment.has_operands()))
204-
{
205-
return next_instr;
206-
}
207-
208-
// Otherwise it's the temporary variable.
209-
return_identifier =
210-
to_symbol_expr(return_value_assignment).get_identifier();
186+
return next_instr;
211187
}
188+
const auto return_identifier =
189+
to_symbol_expr(next_instr_assign_lhs).get_identifier();
190+
191+
auto &instructions = goto_program.instructions;
192+
const auto end = instructions.end();
212193

213-
// Look for the assignment of the temporary return variable into our target
214-
// variable.
215-
const auto end = goto_program.instructions.end();
216-
auto assignment_instruction = std::find_if(
194+
// Look for an instruction where this name is on the RHS of an assignment
195+
const auto matching_assignment = std::find_if(
217196
next_instr,
218197
end,
219-
[&return_identifier](const goto_programt::instructiont &instr) {
198+
[&return_identifier](
199+
const goto_programt::instructiont &instr) { // NOLINT (*)
220200
return is_assignment_from(instr, return_identifier);
221201
});
222202

223-
INVARIANT(
224-
assignment_instruction != end,
225-
"failed to find assignment of the temporary return variable into our "
226-
"target variable");
203+
assert(matching_assignment != end);
227204

228205
// Assume that the LHS of *this* assignment is the actual nondet variable
229-
const auto &code_assign = to_code_assign(assignment_instruction->code);
230-
const auto nondet_var=code_assign.lhs();
231-
const auto source_loc=target->source_location;
206+
const auto &code_assign = to_code_assign(matching_assignment->code);
207+
const auto nondet_var = code_assign.lhs();
208+
const auto source_loc = target->source_location;
232209

233210
// Erase from the nondet function call to the assignment
234-
const auto after_matching_assignment = std::next(assignment_instruction);
235-
INVARIANT(
236-
after_matching_assignment != end,
237-
"goto_program missing END_FUNCTION instruction");
211+
const auto after_matching_assignment = std::next(matching_assignment);
212+
assert(after_matching_assignment != end);
238213

239214
std::for_each(
240215
target,
241216
after_matching_assignment,
242-
[](goto_programt::instructiont &instr)
243-
{
217+
[](goto_programt::instructiont &instr) { // NOLINT (*)
244218
instr.make_skip();
245219
});
246220

247-
const auto inserted=goto_program.insert_before(after_matching_assignment);
221+
const auto inserted = goto_program.insert_before(after_matching_assignment);
248222
inserted->make_assignment();
249223
side_effect_expr_nondett inserted_expr(nondet_var.type());
250224
inserted_expr.set_nullable(
251-
instr_info.get_nullable_type()==
225+
instr_info.get_nullable_type() ==
252226
nondet_instruction_infot::is_nullablet::TRUE);
253-
inserted->code=code_assignt(nondet_var, inserted_expr);
254-
inserted->code.add_source_location()=source_loc;
255-
inserted->source_location=source_loc;
227+
inserted->code = code_assignt(nondet_var, inserted_expr);
228+
inserted->code.add_source_location() = source_loc;
229+
inserted->source_location = source_loc;
256230

257231
goto_program.update();
258232

@@ -265,13 +239,12 @@ static goto_programt::targett check_and_replace_target(
265239
/// \param goto_program: The goto program to modify.
266240
static void replace_java_nondet(goto_programt &goto_program)
267241
{
268-
for(auto instruction_iterator=goto_program.instructions.begin(),
269-
end=goto_program.instructions.end();
270-
instruction_iterator!=end;)
242+
for(auto instruction_iterator = goto_program.instructions.begin(),
243+
end = goto_program.instructions.end();
244+
instruction_iterator != end;)
271245
{
272-
instruction_iterator=check_and_replace_target(
273-
goto_program,
274-
instruction_iterator);
246+
instruction_iterator =
247+
check_and_replace_target(goto_program, instruction_iterator);
275248
}
276249
}
277250

src/goto-programs/replace_java_nondet.h renamed to src/java_bytecode/replace_java_nondet.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ Author: Reuben Thomas, [email protected]
99
/// \file
1010
/// Replace Java Nondet expressions
1111

12-
#ifndef CPROVER_GOTO_PROGRAMS_REPLACE_JAVA_NONDET_H
13-
#define CPROVER_GOTO_PROGRAMS_REPLACE_JAVA_NONDET_H
12+
#ifndef CPROVER_JAVA_BYTECODE_REPLACE_JAVA_NONDET_H
13+
#define CPROVER_JAVA_BYTECODE_REPLACE_JAVA_NONDET_H
1414

1515
class goto_modelt;
1616
class goto_functionst;
@@ -28,4 +28,4 @@ void replace_java_nondet(goto_functionst &);
2828
/// \param function: The goto program to modify.
2929
void replace_java_nondet(goto_model_functiont &function);
3030

31-
#endif
31+
#endif // CPROVER_JAVA_BYTECODE_REPLACE_JAVA_NONDET_H

src/jbmc/jbmc_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ Author: Daniel Kroening, [email protected]
3636
#include <goto-programs/remove_asm.h>
3737
#include <goto-programs/remove_unused_functions.h>
3838
#include <goto-programs/remove_skip.h>
39-
#include <goto-programs/replace_java_nondet.h>
4039
#include <goto-programs/set_properties.h>
4140
#include <goto-programs/show_goto_functions.h>
4241
#include <goto-programs/show_symbol_table.h>
@@ -56,6 +55,7 @@ Author: Daniel Kroening, [email protected]
5655
#include <java_bytecode/java_enum_static_init_unwind_handler.h>
5756
#include <java_bytecode/remove_instanceof.h>
5857
#include <java_bytecode/remove_exceptions.h>
58+
#include <java_bytecode/replace_java_nondet.h>
5959

6060
#include <cbmc/version.h>
6161

0 commit comments

Comments
 (0)