@@ -1214,169 +1214,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
1214
1214
statement==" invokevirtual" ||
1215
1215
statement==" invokestatic" )
1216
1216
{
1217
- const bool use_this (statement!=" invokestatic" );
1218
- const bool is_virtual (
1219
- statement==" invokevirtual" || statement==" invokeinterface" );
1220
-
1221
- code_typet &code_type=to_code_type (arg0.type ());
1222
- code_typet::parameterst ¶meters (code_type.parameters ());
1223
-
1224
- if (use_this)
1225
- {
1226
- if (parameters.empty () || !parameters[0 ].get_this ())
1227
- {
1228
- irep_idt classname=arg0.get (ID_C_class);
1229
- typet thistype=symbol_typet (classname);
1230
- // Note invokespecial is used for super-method calls as well as
1231
- // constructors.
1232
- if (statement==" invokespecial" )
1233
- {
1234
- if (is_constructor (arg0.get (ID_identifier)))
1235
- {
1236
- if (needed_lazy_methods)
1237
- needed_lazy_methods->add_needed_class (classname);
1238
- code_type.set_is_constructor ();
1239
- }
1240
- else
1241
- code_type.set (ID_java_super_method_call, true );
1242
- }
1243
- reference_typet object_ref_type=java_reference_type (thistype);
1244
- code_typet::parametert this_p (object_ref_type);
1245
- this_p.set_this ();
1246
- this_p.set_base_name (" this" );
1247
- parameters.insert (parameters.begin (), this_p);
1248
- }
1249
- }
1250
-
1251
- code_function_callt call;
1252
- source_locationt loc=i_it->source_location ;
1253
- loc.set_function (method_id);
1254
-
1255
- call.add_source_location ()=loc;
1256
- call.arguments ()=pop (parameters.size ());
1257
-
1258
- // double-check a bit
1259
- if (use_this)
1260
- {
1261
- const exprt &this_arg=call.arguments ().front ();
1262
- INVARIANT (this_arg.type ().id ()==ID_pointer,
1263
- " first argument must be a pointer" );
1264
- }
1265
-
1266
- // do some type adjustment for the arguments,
1267
- // as Java promotes arguments
1268
- // Also cast pointers since intermediate locals
1269
- // can be void*.
1270
-
1271
- for (std::size_t i=0 ; i<parameters.size (); i++)
1272
- {
1273
- const typet &type=parameters[i].type ();
1274
- if (type==java_boolean_type () ||
1275
- type==java_char_type () ||
1276
- type==java_byte_type () ||
1277
- type==java_short_type () ||
1278
- type.id ()==ID_pointer)
1279
- {
1280
- assert (i<call.arguments ().size ());
1281
- if (type!=call.arguments ()[i].type ())
1282
- call.arguments ()[i].make_typecast (type);
1283
- }
1284
- }
1285
-
1286
- // do some type adjustment for return values
1287
-
1288
- const typet &return_type=code_type.return_type ();
1289
-
1290
- if (return_type.id ()!=ID_empty)
1291
- {
1292
- // return types are promoted in Java
1293
- call.lhs ()=tmp_variable (" return" , return_type);
1294
- exprt promoted=java_bytecode_promotion (call.lhs ());
1295
- results.resize (1 );
1296
- results[0 ]=promoted;
1297
- }
1298
-
1299
- assert (arg0.id ()==ID_virtual_function);
1300
-
1301
- // If we don't have a definition for the called symbol, and we won't
1302
- // inherit a definition from a super-class, we create a new symbol and
1303
- // insert it in the symbol table. The name and type of the method are
1304
- // derived from the information we have in the call.
1305
- // We fix the access attribute to ID_public, because of the following
1306
- // reasons:
1307
- // - We don't know the orignal access attribute and since the .class file
1308
- // unavailable, we have no way to know.
1309
- // - Whatever it was, we assume that the bytecode we are translating
1310
- // compiles correctly, so such a method has to be accessible from this
1311
- // method.
1312
- // - We will never generate code that calls that method unless we
1313
- // translate bytecode that calls that method. As a result we will never
1314
- // generate code that may wrongly assume that such a method is
1315
- // accessible if we assume that its access attribute is "more
1316
- // accessible" than it actually is.
1317
- irep_idt id=arg0.get (ID_identifier);
1318
- if (symbol_table.symbols .find (id)==symbol_table.symbols .end () &&
1319
- !(is_virtual && is_method_inherited (arg0.get (ID_C_class), arg0.get (ID_component_name))))
1320
- {
1321
- symbolt symbol;
1322
- symbol.name =id;
1323
- symbol.base_name =arg0.get (ID_C_base_name);
1324
- symbol.pretty_name =
1325
- id2string (arg0.get (ID_C_class)).substr (6 )+" ." +
1326
- id2string (symbol.base_name )+" ()" ;
1327
- symbol.type =arg0.type ();
1328
- symbol.type .set (ID_access, ID_public);
1329
- symbol.value .make_nil ();
1330
- symbol.mode =ID_java;
1331
- assign_parameter_names (
1332
- to_code_type (symbol.type ),
1333
- symbol.name ,
1334
- symbol_table);
1335
-
1336
- debug ()
1337
- << " Generating codet: new opaque symbol: method '"
1338
- << symbol.name << " '" << eom;
1339
- symbol_table.add (symbol);
1340
- }
1341
-
1342
- if (is_virtual)
1343
- {
1344
- // dynamic binding
1345
- assert (use_this);
1346
- assert (!call.arguments ().empty ());
1347
- call.function ()=arg0;
1348
- // Populate needed methods later,
1349
- // once we know what object types can exist.
1350
- }
1351
- else
1352
- {
1353
- // static binding
1354
- call.function ()=symbol_exprt (arg0.get (ID_identifier), arg0.type ());
1355
- if (needed_lazy_methods)
1356
- {
1357
- needed_lazy_methods->add_needed_method (arg0.get (ID_identifier));
1358
- // Calling a static method causes static initialization:
1359
- needed_lazy_methods->add_needed_class (arg0.get (ID_C_class));
1360
- }
1361
- }
1362
-
1363
- call.function ().add_source_location ()=loc;
1364
-
1365
- // Replacing call if it is a function of the Character library,
1366
- // returning the same call otherwise
1367
- c=string_preprocess.replace_character_call (call);
1368
-
1369
- if (!use_this)
1370
- {
1371
- codet clinit_call=get_clinit_call (arg0.get (ID_C_class));
1372
- if (clinit_call.get_statement ()!=ID_skip)
1373
- {
1374
- code_blockt ret_block;
1375
- ret_block.move_to_operands (clinit_call);
1376
- ret_block.move_to_operands (c);
1377
- c=std::move (ret_block);
1378
- }
1379
- }
1217
+ convert_invoke (i_it, statement, arg0, c, results);
1380
1218
}
1381
1219
else if (statement==" return" )
1382
1220
{
@@ -2136,6 +1974,176 @@ codet java_bytecode_convert_methodt::convert_instructions(
2136
1974
return code;
2137
1975
}
2138
1976
1977
+ void java_bytecode_convert_methodt::convert_invoke (
1978
+ const std::vector<java_bytecode_parse_treet::instructiont>::const_iterator
1979
+ &i_it,
1980
+ const irep_idt &statement,
1981
+ exprt &arg0,
1982
+ codet &c,
1983
+ exprt::operandst &results)
1984
+ {
1985
+ const bool use_this (statement != " invokestatic" );
1986
+ const bool is_virtual (
1987
+ statement == " invokevirtual" || statement == " invokeinterface" );
1988
+
1989
+ code_typet &code_type = to_code_type (arg0.type ());
1990
+ code_typet::parameterst ¶meters (code_type.parameters ());
1991
+
1992
+ if (use_this)
1993
+ {
1994
+ if (parameters.empty () || !parameters[0 ].get_this ())
1995
+ {
1996
+ irep_idt classname = arg0.get (ID_C_class);
1997
+ typet thistype = symbol_typet (classname);
1998
+ // Note invokespecial is used for super-method calls as well as
1999
+ // constructors.
2000
+ if (statement == " invokespecial" )
2001
+ {
2002
+ if (is_constructor (arg0.get (ID_identifier)))
2003
+ {
2004
+ if (needed_lazy_methods)
2005
+ needed_lazy_methods->add_needed_class (classname);
2006
+ code_type.set_is_constructor ();
2007
+ }
2008
+ else
2009
+ code_type.set (ID_java_super_method_call, true );
2010
+ }
2011
+ reference_typet object_ref_type = java_reference_type (thistype);
2012
+ code_typet::parametert this_p (object_ref_type);
2013
+ this_p.set_this ();
2014
+ this_p.set_base_name (" this" );
2015
+ parameters.insert (parameters.begin (), this_p);
2016
+ }
2017
+ }
2018
+
2019
+ code_function_callt call;
2020
+ source_locationt loc = i_it->source_location ;
2021
+ loc.set_function (method_id);
2022
+
2023
+ call.add_source_location () = loc;
2024
+ call.arguments () = pop (parameters.size ());
2025
+
2026
+ // double-check a bit
2027
+ if (use_this)
2028
+ {
2029
+ const exprt &this_arg = call.arguments ().front ();
2030
+ INVARIANT (
2031
+ this_arg.type ().id () == ID_pointer, " first argument must be a pointer" );
2032
+ }
2033
+
2034
+ // do some type adjustment for the arguments,
2035
+ // as Java promotes arguments
2036
+ // Also cast pointers since intermediate locals
2037
+ // can be void*.
2038
+
2039
+ for (std::size_t i = 0 ; i < parameters.size (); i++)
2040
+ {
2041
+ const typet &type = parameters[i].type ();
2042
+ if (
2043
+ type == java_boolean_type () || type == java_char_type () ||
2044
+ type == java_byte_type () || type == java_short_type () ||
2045
+ type.id () == ID_pointer)
2046
+ {
2047
+ assert (i < call.arguments ().size ());
2048
+ if (type != call.arguments ()[i].type ())
2049
+ call.arguments ()[i].make_typecast (type);
2050
+ }
2051
+ }
2052
+
2053
+ // do some type adjustment for return values
2054
+
2055
+ const typet &return_type = code_type.return_type ();
2056
+
2057
+ if (return_type.id () != ID_empty)
2058
+ {
2059
+ // return types are promoted in Java
2060
+ call.lhs () = tmp_variable (" return" , return_type);
2061
+ exprt promoted = java_bytecode_promotion (call.lhs ());
2062
+ results.resize (1 );
2063
+ results[0 ] = promoted;
2064
+ }
2065
+
2066
+ assert (arg0.id () == ID_virtual_function);
2067
+
2068
+ // If we don't have a definition for the called symbol, and we won't
2069
+ // inherit a definition from a super-class, we create a new symbol and
2070
+ // insert it in the symbol table. The name and type of the method are
2071
+ // derived from the information we have in the call.
2072
+ // We fix the access attribute to ID_public, because of the following
2073
+ // reasons:
2074
+ // - We don't know the orignal access attribute and since the .class file
2075
+ // unavailable, we have no way to know.
2076
+ // - Whatever it was, we assume that the bytecode we are translating
2077
+ // compiles correctly, so such a method has to be accessible from this
2078
+ // method.
2079
+ // - We will never generate code that calls that method unless we
2080
+ // translate bytecode that calls that method. As a result we will never
2081
+ // generate code that may wrongly assume that such a method is
2082
+ // accessible if we assume that its access attribute is "more
2083
+ // accessible" than it actually is.
2084
+ irep_idt id = arg0.get (ID_identifier);
2085
+ if (
2086
+ symbol_table.symbols .find (id) == symbol_table.symbols .end () &&
2087
+ !(is_virtual &&
2088
+ is_method_inherited (arg0.get (ID_C_class), arg0.get (ID_component_name))))
2089
+ {
2090
+ symbolt symbol;
2091
+ symbol.name = id;
2092
+ symbol.base_name = arg0.get (ID_C_base_name);
2093
+ symbol.pretty_name = id2string (arg0.get (ID_C_class)).substr (6 ) + " ." +
2094
+ id2string (symbol.base_name ) + " ()" ;
2095
+ symbol.type = arg0.type ();
2096
+ symbol.type .set (ID_access, ID_public);
2097
+ symbol.value .make_nil ();
2098
+ symbol.mode = ID_java;
2099
+ assign_parameter_names (
2100
+ to_code_type (symbol.type ), symbol.name , symbol_table);
2101
+
2102
+ debug () << " Generating codet: new opaque symbol: method '" << symbol.name
2103
+ << " '" << eom;
2104
+ symbol_table.add (symbol);
2105
+ }
2106
+
2107
+ if (is_virtual)
2108
+ {
2109
+ // dynamic binding
2110
+ assert (use_this);
2111
+ assert (!call.arguments ().empty ());
2112
+ call.function () = arg0;
2113
+ // Populate needed methods later,
2114
+ // once we know what object types can exist.
2115
+ }
2116
+ else
2117
+ {
2118
+ // static binding
2119
+ call.function () = symbol_exprt (arg0.get (ID_identifier), arg0.type ());
2120
+ if (needed_lazy_methods)
2121
+ {
2122
+ needed_lazy_methods->add_needed_method (arg0.get (ID_identifier));
2123
+ // Calling a static method causes static initialization:
2124
+ needed_lazy_methods->add_needed_class (arg0.get (ID_C_class));
2125
+ }
2126
+ }
2127
+
2128
+ call.function ().add_source_location () = loc;
2129
+
2130
+ // Replacing call if it is a function of the Character library,
2131
+ // returning the same call otherwise
2132
+ c = string_preprocess.replace_character_call (call);
2133
+
2134
+ if (!use_this)
2135
+ {
2136
+ codet clinit_call = get_clinit_call (arg0.get (ID_C_class));
2137
+ if (clinit_call.get_statement () != ID_skip)
2138
+ {
2139
+ code_blockt ret_block;
2140
+ ret_block.move_to_operands (clinit_call);
2141
+ ret_block.move_to_operands (c);
2142
+ c = std::move (ret_block);
2143
+ }
2144
+ }
2145
+ }
2146
+
2139
2147
codet &java_bytecode_convert_methodt::replace_call_to_cprover_assume (
2140
2148
const std::vector<java_bytecode_parse_treet::instructiont>::const_iterator
2141
2149
&i_it,
0 commit comments