Skip to content

Commit d9bac49

Browse files
committed
Fix multinewarray
* Always init subarrays with correct type, rather than trying to use a member of (void**)data to do init. * Use a for-loop, not array-set, for zero init. This is how C memset gets implemented anyhow, and array_set depends on the symex pass lowering the array to a static global object, which is likely not to happen for subarrays.
1 parent 475a7e1 commit d9bac49

File tree

3 files changed

+36
-25
lines changed

3 files changed

+36
-25
lines changed

src/goto-programs/builtin_functions.cpp

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9+
#include <iostream>
910
#include <cassert>
1011

1112
#include <util/i2string.h>
@@ -675,7 +676,7 @@ void goto_convertt::do_java_new_array(
675676
{
676677
if(lhs.is_nil())
677678
throw "do_java_new_array without lhs is yet to be implemented";
678-
679+
679680
source_locationt location=rhs.source_location();
680681

681682
assert(rhs.operands().size()>=1); // one per dimension
@@ -718,7 +719,7 @@ void goto_convertt::do_java_new_array(
718719

719720
// Allocate a (struct realtype**) instead of a (void**) if possible,
720721
// to avoid confusing the trace due to dynamic type aliasing.
721-
const irept& given_element_type=rhs.find(ID_C_element_type);
722+
const irept& given_element_type=object_type.find(ID_C_element_type);
722723
typet allocate_data_type;
723724
exprt cast_data_member;
724725
if(given_element_type!=get_nil_irep())
@@ -745,22 +746,16 @@ void goto_convertt::do_java_new_array(
745746
t_p->code=code_assignt(data,cast_cpp_new);
746747
t_p->source_location=location;
747748

748-
// zero-initialize the data
749+
// zero-initialize the data, or create subarrays if specified:
749750
if(!rhs.get_bool("skip_initialise"))
750-
{
751-
exprt zero_element=gen_zero(data.type().subtype());
752-
codet array_set(ID_array_set);
753-
array_set.copy_to_operands(data, zero_element);
754-
goto_programt::targett t_d=dest.add_instruction(OTHER);
755-
t_d->code=array_set;
756-
t_d->source_location=location;
757-
}
758-
759-
if(rhs.operands().size()>=2)
760751
{
761752
// produce
762-
// for(int i=0; i<size; i++) tmp[i]=java_new(dim-1);
753+
// for(int i=0; i<size; i++) { init=java_new(dim-1); tmp[i]=init; }
754+
// or init=0 if this is the last dimension.
763755
// This will be converted recursively.
756+
757+
// Since reference arrays carry void*, init using a local variable
758+
// before assigning to the array.
764759

765760
goto_programt tmp;
766761

@@ -769,21 +764,38 @@ void goto_convertt::do_java_new_array(
769764

770765
code_fort for_loop;
771766

772-
side_effect_exprt sub_java_new=rhs;
773-
sub_java_new.operands().erase(sub_java_new.operands().begin());
774-
775767
side_effect_exprt inc(ID_assign);
776768
inc.operands().resize(2);
777769
inc.op0()=tmp_i;
778770
inc.op1()=plus_exprt(tmp_i, gen_one(tmp_i.type()));
779771

780-
dereference_exprt deref_expr(plus_exprt(data, tmp_i), data.type().subtype());
781-
782772
for_loop.init()=code_assignt(tmp_i, gen_zero(tmp_i.type()));
783773
for_loop.cond()=binary_relation_exprt(tmp_i, ID_lt, rhs.op0());
784774
for_loop.iter()=inc;
785-
for_loop.body()=code_skipt();
786-
for_loop.body()=code_assignt(deref_expr, sub_java_new);
775+
776+
code_blockt for_body;
777+
dereference_exprt deref_expr(plus_exprt(data, tmp_i), data.type().subtype());
778+
779+
if(rhs.operands().size() >= 2)
780+
{
781+
side_effect_exprt sub_java_new=rhs;
782+
sub_java_new.operands().erase(sub_java_new.operands().begin());
783+
sub_java_new.type()=static_cast<const typet &>(given_element_type);
784+
exprt next_array_init=
785+
new_tmp_symbol(sub_java_new.type(), "multiarray_init", tmp, location).symbol_expr();
786+
for_body.copy_to_operands(code_assignt(next_array_init, sub_java_new));
787+
788+
if(deref_expr.type()!=next_array_init.type())
789+
next_array_init=typecast_exprt(next_array_init, deref_expr.type());
790+
for_body.copy_to_operands(code_assignt(deref_expr, next_array_init));
791+
}
792+
else
793+
{
794+
exprt zero_element=gen_zero(deref_expr.type());
795+
for_body.copy_to_operands(code_assignt(deref_expr,zero_element));
796+
}
797+
798+
for_loop.body()=for_body;
787799

788800
convert(for_loop, tmp);
789801
dest.destructive_append(tmp);

src/java_bytecode/java_bytecode_convert.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,16 +1448,15 @@ codet java_bytecode_convertt::convert_instructions(
14481448
}
14491449
else if(statement=="multianewarray")
14501450
{
1451-
// The first argument is the type, the second argument is the dimension.
1451+
// The first argument is the type, the second argument is the number of dimensions.
14521452
// The size of each dimension is on the stack.
14531453
irep_idt number=to_constant_expr(arg1).get_value();
14541454
unsigned dimension=safe_c_str2unsigned(number.c_str());
14551455

14561456
op=pop(dimension);
14571457
assert(results.size()==1);
14581458

1459-
// arg0.type()
1460-
const pointer_typet ref_type=java_array_type('a');
1459+
const pointer_typet ref_type=pointer_typet(arg0.type());
14611460

14621461
side_effect_exprt java_new_array(ID_java_new_array, ref_type);
14631462
java_new_array.operands()=op;

src/java_bytecode/java_object_factory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ void gen_nondet_array_init(const exprt &expr,
310310
side_effect_exprt java_new_array(ID_java_new_array,expr.type());
311311
java_new_array.copy_to_operands(length_sym_expr);
312312
java_new_array.set("skip_initialise",true);
313-
java_new_array.set(ID_C_element_type,element_type);
313+
java_new_array.type().subtype().set(ID_C_element_type,element_type);
314314
init_code.copy_to_operands(code_assignt(expr,java_new_array));
315315

316316
exprt init_array_expr=member_exprt(dereference_exprt(expr, expr.type().subtype()),

0 commit comments

Comments
 (0)