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