Skip to content

Commit 166563f

Browse files
Do lowering of java_new as a function-level pass
1 parent 3779782 commit 166563f

12 files changed

+191
-71
lines changed

src/clobber/clobber_parse_options.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Author: Daniel Kroening, [email protected]
3232
#include <goto-programs/link_to_library.h>
3333
#include <goto-programs/goto_inline.h>
3434
#include <goto-programs/xml_goto_trace.h>
35+
#include <goto-programs/remove_java_new.h>
3536

3637
#include <goto-instrument/dump_c.h>
3738

@@ -207,6 +208,8 @@ bool clobber_parse_optionst::process_goto_program(
207208
goto_modelt &goto_model)
208209
{
209210
{
211+
remove_java_new(goto_model, get_message_handler());
212+
210213
// do partial inlining
211214
status() << "Partial Inlining" << eom;
212215
goto_partial_inline(goto_model, get_message_handler());

src/goto-analyzer/goto_analyzer_parse_options.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Author: Daniel Kroening, [email protected]
3737
#include <goto-programs/read_goto_binary.h>
3838
#include <goto-programs/goto_inline.h>
3939
#include <goto-programs/link_to_library.h>
40+
#include <goto-programs/remove_java_new.h>
4041

4142
#include <analyses/is_threaded.h>
4243
#include <analyses/goto_check.h>
@@ -735,6 +736,8 @@ bool goto_analyzer_parse_optionst::process_goto_program(
735736
link_to_library(goto_model, ui_message_handler);
736737
#endif
737738

739+
remove_java_new(goto_model, get_message_handler());
740+
738741
// remove function pointers
739742
status() << "Removing function pointers and virtual functions" << eom;
740743
remove_function_pointers(

src/goto-diff/goto_diff_parse_options.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Author: Peter Schrammel
3737
#include <goto-programs/string_instrumentation.h>
3838
#include <goto-programs/loop_ids.h>
3939
#include <goto-programs/link_to_library.h>
40+
#include <goto-programs/remove_java_new.h>
4041

4142
#include <pointer-analysis/add_failed_symbols.h>
4243

@@ -394,6 +395,8 @@ bool goto_diff_parse_optionst::process_goto_program(
394395
{
395396
namespacet ns(symbol_table);
396397

398+
remove_java_new(goto_model, get_message_handler());
399+
397400
// Remove inline assembler; this needs to happen before
398401
// adding the library.
399402
remove_asm(goto_model);

src/goto-programs/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ SRC = basic_blocks.cpp \
4545
remove_exceptions.cpp \
4646
remove_function_pointers.cpp \
4747
remove_instanceof.cpp \
48+
remove_java_new.cpp \
4849
remove_returns.cpp \
4950
remove_skip.cpp \
5051
remove_static_init_loops.cpp \

src/goto-programs/builtin_functions.cpp

+1-62
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Author: Daniel Kroening, [email protected]
3333
#include <ansi-c/string_constant.h>
3434

3535
#include "format_strings.h"
36+
#include "class_identifier.h"
3637

3738
void goto_convertt::do_prob_uniform(
3839
const exprt &lhs,
@@ -539,68 +540,6 @@ void goto_convertt::do_cpp_new(
539540
dest.destructive_append(tmp_initializer);
540541
}
541542

542-
void set_class_identifier(
543-
struct_exprt &expr,
544-
const namespacet &ns,
545-
const symbol_typet &class_type)
546-
{
547-
const struct_typet &struct_type=
548-
to_struct_type(ns.follow(expr.type()));
549-
const struct_typet::componentst &components=struct_type.components();
550-
551-
if(components.empty())
552-
return;
553-
assert(!expr.operands().empty());
554-
555-
if(components.front().get_name()=="@class_identifier")
556-
{
557-
assert(expr.op0().id()==ID_constant);
558-
expr.op0()=constant_exprt(class_type.get_identifier(), string_typet());
559-
}
560-
else
561-
{
562-
assert(expr.op0().id()==ID_struct);
563-
set_class_identifier(to_struct_expr(expr.op0()), ns, class_type);
564-
}
565-
}
566-
567-
void goto_convertt::do_java_new(
568-
const exprt &lhs,
569-
const side_effect_exprt &rhs,
570-
goto_programt &dest)
571-
{
572-
PRECONDITION(!lhs.is_nil());
573-
PRECONDITION(rhs.operands().empty());
574-
PRECONDITION(rhs.type().id() == ID_pointer);
575-
source_locationt location=rhs.source_location();
576-
typet object_type=rhs.type().subtype();
577-
578-
// build size expression
579-
exprt object_size=size_of_expr(object_type, ns);
580-
CHECK_RETURN(object_size.is_not_nil());
581-
582-
// we produce a malloc side-effect, which stays
583-
side_effect_exprt malloc_expr(ID_allocate);
584-
malloc_expr.copy_to_operands(object_size);
585-
// could use true and get rid of the code below
586-
malloc_expr.copy_to_operands(false_exprt());
587-
malloc_expr.type()=rhs.type();
588-
589-
goto_programt::targett t_n=dest.add_instruction(ASSIGN);
590-
t_n->code=code_assignt(lhs, malloc_expr);
591-
t_n->source_location=location;
592-
593-
// zero-initialize the object
594-
dereference_exprt deref(lhs, object_type);
595-
exprt zero_object=
596-
zero_initializer(object_type, location, ns, get_message_handler());
597-
set_class_identifier(
598-
to_struct_expr(zero_object), ns, to_symbol_type(object_type));
599-
goto_programt::targett t_i=dest.add_instruction(ASSIGN);
600-
t_i->code=code_assignt(deref, zero_object);
601-
t_i->source_location=location;
602-
}
603-
604543
void goto_convertt::do_java_new_array(
605544
const exprt &lhs,
606545
const side_effect_exprt &rhs,

src/goto-programs/class_identifier.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,39 @@ exprt get_class_identifier_field(
7171
exprt deref=dereference_exprt(this_expr, this_expr.type().subtype());
7272
return build_class_identifier(deref, ns);
7373
}
74+
75+
/// If expr has its components filled in then sets the `@class_identifier`
76+
/// member of the struct
77+
/// \remarks Follows through base class members until it gets to the object
78+
/// type that contains the `@class_identifier` member
79+
/// \param expr: An expression that represents a struct
80+
/// \param ns: The namespace used to resolve symbol referencess in the type of
81+
/// the struct
82+
/// \param class_type: A symbol whose identifier is the name of the class
83+
void set_class_identifier(
84+
struct_exprt &expr,
85+
const namespacet &ns,
86+
const symbol_typet &class_type)
87+
{
88+
const struct_typet &struct_type=to_struct_type(ns.follow(expr.type()));
89+
const struct_typet::componentst &components=struct_type.components();
90+
91+
if(components.empty())
92+
// Presumably this means the type has not yet been determined
93+
return;
94+
PRECONDITION(!expr.operands().empty());
95+
96+
if(components.front().get_name()=="@class_identifier")
97+
{
98+
INVARIANT(
99+
expr.op0().id()==ID_constant, "@class_identifier must be a constant");
100+
expr.op0()=constant_exprt(class_type.get_identifier(), string_typet());
101+
}
102+
else
103+
{
104+
// The first member must be the base class
105+
INVARIANT(
106+
expr.op0().id()==ID_struct, "Non @class_identifier must be a structure");
107+
set_class_identifier(to_struct_expr(expr.op0()), ns, class_type);
108+
}
109+
}

src/goto-programs/class_identifier.h

+6
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ Author: Chris Smowton, [email protected]
1515
class exprt;
1616
class namespacet;
1717
class symbol_typet;
18+
class struct_exprt;
1819

1920
exprt get_class_identifier_field(
2021
const exprt &this_expr,
2122
const symbol_typet &suggested_type,
2223
const namespacet &ns);
2324

25+
void set_class_identifier(
26+
struct_exprt &expr,
27+
const namespacet &ns,
28+
const symbol_typet &class_type);
29+
2430
#endif

src/goto-programs/goto_convert.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -756,10 +756,7 @@ void goto_convertt::convert_assign(
756756
else if(rhs.id()==ID_side_effect &&
757757
rhs.get(ID_statement)==ID_java_new)
758758
{
759-
Forall_operands(it, rhs)
760-
clean_expr(*it, dest);
761-
762-
do_java_new(lhs, to_side_effect_expr(rhs), dest);
759+
copy(code, ASSIGN, dest);
763760
}
764761
else if(rhs.id()==ID_side_effect &&
765762
rhs.get(ID_statement)==ID_java_new_array)

src/goto-programs/goto_convert_class.h

-5
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,6 @@ class goto_convertt:public messaget
142142
const side_effect_exprt &rhs,
143143
goto_programt &dest);
144144

145-
void do_java_new(
146-
const exprt &lhs,
147-
const side_effect_exprt &rhs,
148-
goto_programt &dest);
149-
150145
void do_java_new_array(
151146
const exprt &lhs,
152147
const side_effect_exprt &rhs,

src/goto-programs/remove_java_new.cpp

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2017 Diffblue Limited. All Rights Reserved.
2+
3+
/// \file
4+
/// Function-level/module-level pass to remove java_new and replace with
5+
/// malloc & zero-initialize
6+
7+
#include "remove_java_new.h"
8+
9+
#include <util/message.h>
10+
#include <util/pointer_offset_size.h>
11+
#include <linking/zero_initializer.h>
12+
13+
#include "class_identifier.h"
14+
15+
static bool remove_java_new(
16+
goto_programt &goto_program,
17+
const namespacet &ns,
18+
message_handlert &message_handler)
19+
{
20+
messaget msg(message_handler);
21+
22+
bool changed=false;
23+
for(goto_programt::targett target=goto_program.instructions.begin();
24+
target!=goto_program.instructions.end();
25+
++target)
26+
{
27+
code_assignt *assign=expr_try_dynamic_cast<code_assignt>(target->code);
28+
if(assign==nullptr)
29+
continue;
30+
side_effect_exprt *rhs=
31+
expr_try_dynamic_cast<side_effect_exprt>(assign->rhs());
32+
if(rhs==nullptr)
33+
continue;
34+
if(rhs->get_statement()!=ID_java_new)
35+
continue;
36+
INVARIANT(rhs->operands().empty(), "java_new does not have operands");
37+
INVARIANT(rhs->type().id()==ID_pointer, "java_new returns pointer");
38+
39+
const exprt &lhs=assign->lhs();
40+
INVARIANT(
41+
!lhs.is_nil(), "remove_java_new without lhs is yet to be implemented");
42+
43+
typet object_type=rhs->type().subtype();
44+
45+
// build size expression
46+
exprt object_size=size_of_expr(object_type, ns);
47+
CHECK_RETURN(object_size.is_not_nil());
48+
49+
changed=true;
50+
51+
source_locationt location=rhs->source_location();
52+
53+
// We produce a malloc side-effect
54+
side_effect_exprt malloc_expr(ID_allocate);
55+
malloc_expr.copy_to_operands(object_size);
56+
// could use true and get rid of the code below
57+
malloc_expr.copy_to_operands(false_exprt());
58+
malloc_expr.type()=rhs->type();
59+
*rhs=std::move(malloc_expr);
60+
61+
// zero-initialize the object
62+
dereference_exprt deref(lhs, object_type);
63+
exprt zero_object=
64+
zero_initializer(object_type, location, ns, message_handler);
65+
set_class_identifier(
66+
expr_dynamic_cast<struct_exprt>(zero_object),
67+
ns,
68+
to_symbol_type(object_type));
69+
goto_programt::targett zi_assign=goto_program.insert_after(target);
70+
zi_assign->make_assignment();
71+
zi_assign->code=code_assignt(deref, zero_object);
72+
zi_assign->source_location=location;
73+
}
74+
if(!changed)
75+
return false;
76+
goto_program.update();
77+
return true;
78+
}
79+
80+
bool remove_java_new(
81+
goto_functionst::goto_functiont &goto_function,
82+
const namespacet &ns,
83+
message_handlert &message_handler)
84+
{
85+
return remove_java_new(goto_function.body, ns, message_handler);
86+
}
87+
88+
void remove_java_new(
89+
goto_functionst &goto_functions,
90+
const namespacet &ns,
91+
message_handlert &message_handler)
92+
{
93+
for(auto &named_fn : goto_functions.function_map)
94+
remove_java_new(named_fn.second, ns, message_handler);
95+
}
96+
97+
void remove_java_new(
98+
goto_modelt &goto_model,
99+
message_handlert &message_handler)
100+
{
101+
remove_java_new(
102+
goto_model.goto_functions,
103+
namespacet(goto_model.symbol_table),
104+
message_handler);
105+
}

src/goto-programs/remove_java_new.h

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2017 Diffblue Limited. All Rights Reserved.
2+
3+
/// \file
4+
/// Function-level/module-level pass to remove java_new and replace with
5+
/// malloc & zero-initialize
6+
7+
#ifndef CPROVER_GOTO_PROGRAMS_REMOVE_JAVA_NEW_H
8+
#define CPROVER_GOTO_PROGRAMS_REMOVE_JAVA_NEW_H
9+
10+
#include "goto_model.h"
11+
12+
class message_handlert;
13+
14+
15+
bool remove_java_new(
16+
goto_functionst::goto_functiont &goto_function,
17+
const namespacet &ns,
18+
message_handlert &message_handler);
19+
20+
void remove_java_new(
21+
goto_functionst &goto_functions,
22+
const namespacet &ns,
23+
message_handlert &message_handler);
24+
25+
void remove_java_new(
26+
goto_modelt &goto_model,
27+
message_handlert &message_handler);
28+
29+
#endif // CPROVER_GOTO_PROGRAMS_REMOVE_JAVA_NEW_H

src/jbmc/jbmc_parse_options.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Author: Daniel Kroening, [email protected]
5050
#include <goto-programs/show_properties.h>
5151
#include <goto-programs/string_abstraction.h>
5252
#include <goto-programs/string_instrumentation.h>
53+
#include <goto-programs/remove_java_new.h>
5354

5455
#include <goto-symex/rewrite_union.h>
5556
#include <goto-symex/adjust_float_expressions.h>
@@ -675,6 +676,8 @@ bool jbmc_parse_optionst::process_goto_functions(
675676
{
676677
try
677678
{
679+
remove_java_new(goto_model, get_message_handler());
680+
678681
// add the library
679682
link_to_library(goto_model, get_message_handler());
680683

0 commit comments

Comments
 (0)