Skip to content

Commit 5dd3f48

Browse files
smowtontautschnig
authored andcommitted
Implement Java array.clone (#774)
This simply duplicates the contents of an array. Regrettably it uses a loop to do so at this point because if we use ARRAY_COPY the backend dies when it can't conclusively establish that the actual parameters have like type. Some sort of copy-type-from intrinsic would do this, but is more effort than is sensible to make right now.
1 parent 3ffd57c commit 5dd3f48

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed

regression/cbmc-java/enum1/test.desc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
CORE
22
enum1.class
33
--java-unwind-enum-static --unwind 3
4-
^EXIT=10$
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
56
^SIGNAL=0$
67
^Unwinding loop java::enum1.<clinit>:\(\)V.0 iteration 5 \(6 max\) file enum1.java line 6 function java::enum1.<clinit>:\(\)V bytecode_index 78 thread 0$
78
--

src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening, [email protected]
1919
#include "java_bytecode_convert_method.h"
2020
#include "java_bytecode_language.h"
2121

22+
#include <util/arith_tools.h>
2223
#include <util/namespace.h>
2324
#include <util/std_expr.h>
2425

@@ -311,6 +312,122 @@ void java_bytecode_convert_classt::add_array_types()
311312
symbol.is_type=true;
312313
symbol.type=struct_type;
313314
symbol_table.add(symbol);
315+
316+
// Also provide a clone method:
317+
// ----------------------------
318+
319+
const irep_idt clone_name=
320+
id2string(symbol_type.get_identifier())+".clone:()Ljava/lang/Object;";
321+
code_typet clone_type;
322+
clone_type.return_type()=
323+
pointer_typet(symbol_typet("java::java.lang.Object"));
324+
code_typet::parametert this_param;
325+
this_param.set_identifier(id2string(clone_name)+"::this");
326+
this_param.set_base_name("this");
327+
this_param.set_this();
328+
this_param.type()=pointer_typet(symbol_type);
329+
clone_type.parameters().push_back(this_param);
330+
331+
parameter_symbolt this_symbol;
332+
this_symbol.name=this_param.get_identifier();
333+
this_symbol.base_name=this_param.get_base_name();
334+
this_symbol.pretty_name=this_symbol.base_name;
335+
this_symbol.type=this_param.type();
336+
this_symbol.mode=ID_java;
337+
symbol_table.add(this_symbol);
338+
339+
const irep_idt local_name=
340+
id2string(clone_name)+"::cloned_array";
341+
auxiliary_symbolt local_symbol;
342+
local_symbol.name=local_name;
343+
local_symbol.base_name="cloned_array";
344+
local_symbol.pretty_name=local_symbol.base_name;
345+
local_symbol.type=pointer_typet(symbol_type);
346+
local_symbol.mode=ID_java;
347+
symbol_table.add(local_symbol);
348+
const auto &local_symexpr=local_symbol.symbol_expr();
349+
350+
code_blockt clone_body;
351+
352+
code_declt declare_cloned(local_symexpr);
353+
clone_body.move_to_operands(declare_cloned);
354+
355+
side_effect_exprt java_new_array(
356+
ID_java_new_array,
357+
pointer_typet(symbol_type));
358+
dereference_exprt old_array(this_symbol.symbol_expr(), symbol_type);
359+
dereference_exprt new_array(local_symexpr, symbol_type);
360+
member_exprt old_length(old_array, comp1.get_name(), comp1.type());
361+
java_new_array.copy_to_operands(old_length);
362+
code_assignt create_blank(local_symexpr, java_new_array);
363+
clone_body.move_to_operands(create_blank);
364+
365+
366+
member_exprt old_data(old_array, comp2.get_name(), comp2.type());
367+
member_exprt new_data(new_array, comp2.get_name(), comp2.type());
368+
369+
/*
370+
// TODO use this instead of a loop.
371+
codet array_copy;
372+
array_copy.set_statement(ID_array_copy);
373+
array_copy.move_to_operands(new_data);
374+
array_copy.move_to_operands(old_data);
375+
clone_body.move_to_operands(array_copy);
376+
*/
377+
378+
// Begin for-loop to replace:
379+
380+
const irep_idt index_name=
381+
id2string(clone_name)+"::index";
382+
auxiliary_symbolt index_symbol;
383+
index_symbol.name=index_name;
384+
index_symbol.base_name="index";
385+
index_symbol.pretty_name=index_symbol.base_name;
386+
index_symbol.type=comp1.type();
387+
index_symbol.mode=ID_java;
388+
symbol_table.add(index_symbol);
389+
const auto &index_symexpr=index_symbol.symbol_expr();
390+
391+
code_declt declare_index(index_symexpr);
392+
clone_body.move_to_operands(declare_index);
393+
394+
code_fort copy_loop;
395+
396+
copy_loop.init()=
397+
code_assignt(index_symexpr, from_integer(0, index_symexpr.type()));
398+
copy_loop.cond()=
399+
binary_relation_exprt(index_symexpr, ID_lt, old_length);
400+
401+
side_effect_exprt inc(ID_assign);
402+
inc.operands().resize(2);
403+
inc.op0()=index_symexpr;
404+
inc.op1()=plus_exprt(index_symexpr, from_integer(1, index_symexpr.type()));
405+
copy_loop.iter()=inc;
406+
407+
dereference_exprt old_cell(
408+
plus_exprt(old_data, index_symexpr), old_data.type().subtype());
409+
dereference_exprt new_cell(
410+
plus_exprt(new_data, index_symexpr), new_data.type().subtype());
411+
code_assignt copy_cell(new_cell, old_cell);
412+
copy_loop.body()=copy_cell;
413+
414+
// End for-loop
415+
clone_body.move_to_operands(copy_loop);
416+
417+
member_exprt new_base_class(new_array, comp0.get_name(), comp0.type());
418+
address_of_exprt retval(new_base_class);
419+
code_returnt return_inst(retval);
420+
clone_body.move_to_operands(return_inst);
421+
422+
symbolt clone_symbol;
423+
clone_symbol.name=clone_name;
424+
clone_symbol.pretty_name=
425+
id2string(symbol_type.get_identifier())+".clone:()";
426+
clone_symbol.base_name="clone";
427+
clone_symbol.type=clone_type;
428+
clone_symbol.value=clone_body;
429+
clone_symbol.mode=ID_java;
430+
symbol_table.add(clone_symbol);
314431
}
315432
}
316433

0 commit comments

Comments
 (0)