@@ -984,13 +984,33 @@ exprt java_bytecode_convert_methodt::get_or_create_clinit_wrapper(
984
984
if (!class_needs_clinit (classname))
985
985
return static_cast <const exprt &>(get_nil_irep ());
986
986
987
+ // if the symbol table already contains the clinit_wrapper() function, return
988
+ // it
987
989
const irep_idt &clinit_wrapper_name=
988
990
id2string (classname)+" ::clinit_wrapper" ;
989
991
auto findit=symbol_table.symbols .find (clinit_wrapper_name);
990
992
if (findit!=symbol_table.symbols .end ())
991
993
return findit->second .symbol_expr ();
992
994
993
- // Create the wrapper now:
995
+ // Otherwise, assume that class C extends class C' and implements interfaces
996
+ // I1, ..., In. We now create the following function (possibly recursively
997
+ // creating the clinit_wrapper functions for C' and I1, ..., In):
998
+ //
999
+ // java::C::clinit_wrapper()
1000
+ // {
1001
+ // if (java::C::clinit_already_run == false)
1002
+ // {
1003
+ // java::C::clinit_already_run = true; // before recursive calls!
1004
+ //
1005
+ // java::C'::clinit_wrapper();
1006
+ // java::I1::clinit_wrapper();
1007
+ // java::I2::clinit_wrapper();
1008
+ // // ...
1009
+ // java::In::clinit_wrapper();
1010
+ //
1011
+ // java::C::<clinit>();
1012
+ // }
1013
+ // }
994
1014
const irep_idt &already_run_name=
995
1015
id2string (classname)+" ::clinit_already_run" ;
996
1016
symbolt already_run_symbol;
@@ -1009,24 +1029,20 @@ exprt java_bytecode_convert_methodt::get_or_create_clinit_wrapper(
1009
1029
already_run_symbol.symbol_expr (),
1010
1030
false_exprt ());
1011
1031
1032
+ // the entire body of the function is an if-then-else
1012
1033
code_ifthenelset wrapper_body;
1034
+
1035
+ // add the condition to the if
1013
1036
wrapper_body.cond ()=check_already_run;
1037
+
1038
+ // add the "already-run = false" statement
1014
1039
code_blockt init_body;
1015
- // Note already-run is set *before* calling clinit, in order to prevent
1016
- // recursion in clinit methods.
1017
1040
code_assignt set_already_run (already_run_symbol.symbol_expr (), true_exprt ());
1018
1041
init_body.move_to_operands (set_already_run);
1019
- const irep_idt &real_clinit_name=id2string (classname)+" .<clinit>:()V" ;
1020
- const symbolt &class_symbol=*symbol_table.lookup (classname);
1021
-
1022
- auto findsymit=symbol_table.symbols .find (real_clinit_name);
1023
- if (findsymit!=symbol_table.symbols .end ())
1024
- {
1025
- code_function_callt call_real_init;
1026
- call_real_init.function ()=findsymit->second .symbol_expr ();
1027
- init_body.move_to_operands (call_real_init);
1028
- }
1029
1042
1043
+ // iterate through the base types and add recursive calls to the
1044
+ // clinit_wrapper()
1045
+ const symbolt &class_symbol=*symbol_table.lookup (classname);
1030
1046
for (const auto &base : to_class_type (class_symbol.type ).bases ())
1031
1047
{
1032
1048
const auto base_name=to_symbol_type (base.type ()).get_identifier ();
@@ -1038,8 +1054,18 @@ exprt java_bytecode_convert_methodt::get_or_create_clinit_wrapper(
1038
1054
init_body.move_to_operands (call_base);
1039
1055
}
1040
1056
1057
+ // call java::C::<clinit>(), if the class has one static initializer
1058
+ const irep_idt &real_clinit_name=id2string (classname)+" .<clinit>:()V" ;
1059
+ auto find_sym_it=symbol_table.symbols .find (real_clinit_name);
1060
+ if (find_sym_it!=symbol_table.symbols .end ())
1061
+ {
1062
+ code_function_callt call_real_init;
1063
+ call_real_init.function ()=find_sym_it->second .symbol_expr ();
1064
+ init_body.move_to_operands (call_real_init);
1065
+ }
1041
1066
wrapper_body.then_case ()=init_body;
1042
1067
1068
+ // insert symbol in the symbol table
1043
1069
symbolt wrapper_method_symbol;
1044
1070
code_typet wrapper_method_type;
1045
1071
wrapper_method_type.return_type ()=void_typet ();
0 commit comments