@@ -109,9 +109,11 @@ static bool operator==(const irep_idt &what, const patternt &pattern)
109
109
110
110
static irep_idt strip_java_namespace_prefix (const irep_idt to_strip)
111
111
{
112
- const auto to_strip_str=id2string (to_strip);
113
- PRECONDITION (has_prefix (to_strip_str, " java::" ));
114
- return to_strip_str.substr (6 , std::string::npos);
112
+ const std::string to_strip_str=id2string (to_strip);
113
+ const std::string prefix=" java::" ;
114
+
115
+ PRECONDITION (has_prefix (to_strip_str, prefix));
116
+ return to_strip_str.substr (prefix.size (), std::string::npos);
115
117
}
116
118
117
119
// name contains <init> or <clinit>
@@ -283,20 +285,26 @@ void java_bytecode_convert_methodt::convert(
283
285
const symbolt &class_symbol,
284
286
const methodt &m)
285
287
{
288
+ // Construct the fully qualified method name
289
+ // (e.g. "my.package.ClassName.myMethodName:(II)I") and query the symbol table
290
+ // to retrieve the symbol (constructed by java_bytecode_convert_method_lazy)
291
+ // associated to the method
286
292
const irep_idt method_identifier=
287
293
id2string (class_symbol.name )+" ." +id2string (m.name )+" :" +m.signature ;
288
294
method_id=method_identifier;
289
295
290
296
const auto &old_sym=symbol_table.lookup (method_identifier);
291
297
298
+ // Obtain a std::vector of code_typet::parametert objects from the
299
+ // (function) type of the symbol
292
300
typet member_type=old_sym.type ;
293
301
code_typet &code_type=to_code_type (member_type);
294
302
method_return_type=code_type.return_type ();
295
303
code_typet::parameterst ¶meters=code_type.parameters ();
296
304
297
305
// Determine the number of local variable slots used by the JVM to maintan the
298
306
// formal parameters
299
- slots_for_parameters = java_method_parameter_slots (code_type);
307
+ slots_for_parameters= java_method_parameter_slots (code_type);
300
308
301
309
debug () << " Generating codet: class "
302
310
<< class_symbol.name << " , method "
@@ -312,49 +320,70 @@ void java_bytecode_convert_methodt::convert(
312
320
if (!is_parameter (v))
313
321
continue ;
314
322
323
+ // Construct a fully qualified name for the parameter v,
324
+ // e.g. my.package.ClassName.myMethodName:(II)I::anIntParam, and then a
325
+ // symbol_exprt with the parameter and its type
315
326
typet t=java_type_from_string (v.signature );
316
327
std::ostringstream id_oss;
317
328
id_oss << method_id << " ::" << v.name ;
318
329
irep_idt identifier (id_oss.str ());
319
330
symbol_exprt result (identifier, t);
320
331
result.set (ID_C_base_name, v.name );
321
332
333
+ // Create a new variablet in the variables vector; in fact this entry will
334
+ // be rewritten below in the loop that iterates through the method
335
+ // parameters; the only field that seem to be useful to write here is the
336
+ // symbol_expr, others will be rewritten
322
337
variables[v.index ].push_back (variablet ());
323
338
auto &newv=variables[v.index ].back ();
324
339
newv.symbol_expr =result;
325
340
newv.start_pc =v.start_pc ;
326
341
newv.length =v.length ;
327
342
}
328
343
329
- // set up variables array
344
+ // The variables is a expanding_vectort, and the loop above may have expanded
345
+ // the vector introducing gaps where the entries are empty vectors. We now
346
+ // make sure that the vector of each LV slot contains exactly one variablet,
347
+ // possibly default-initialized
330
348
std::size_t param_index=0 ;
331
349
for (const auto ¶m : parameters)
332
350
{
333
351
variables[param_index].resize (1 );
334
352
param_index+=java_local_variable_slots (param.type ());
335
353
}
336
- INVARIANT (param_index==slots_for_parameters,
354
+ INVARIANT (
355
+ param_index==slots_for_parameters,
337
356
" java_parameter_count and local computation must agree" );
338
357
339
- // assign names to parameters
358
+ // Assign names to parameters
340
359
param_index=0 ;
341
360
for (auto ¶m : parameters)
342
361
{
343
362
irep_idt base_name, identifier;
344
363
364
+ // Construct a sensible base name (base_name) and a fully qualified name
365
+ // (identifier) for every parameter of the method under translation,
366
+ // regardless of whether we have an LVT or not; and assign it to the
367
+ // parameter object (which is stored in the type of the symbol, not in the
368
+ // symbol table)
345
369
if (param_index==0 && param.get_this ())
346
370
{
371
+ // my.package.ClassName.myMethodName:(II)I::this
347
372
base_name=" this" ;
348
373
identifier=id2string (method_identifier)+" ::" +id2string (base_name);
349
374
}
350
375
else
351
376
{
352
- // in the variable table?
377
+ // if already present in the LVT ...
353
378
base_name=variables[param_index][0 ].symbol_expr .get (ID_C_base_name);
354
379
identifier=variables[param_index][0 ].symbol_expr .get (ID_identifier);
355
380
381
+ // ... then base_name will not be empty
356
382
if (base_name.empty ())
357
383
{
384
+ // my.package.ClassName.myMethodName:(II)I::argNT, where N is the local
385
+ // variable slot where the parameter is stored and T is a character
386
+ // indicating the type
358
387
const typet &type=param.type ();
359
388
char suffix=java_char_from_type (type);
360
389
base_name=" arg" +std::to_string (param_index)+suffix;
@@ -364,7 +393,7 @@ void java_bytecode_convert_methodt::convert(
364
393
param.set_base_name (base_name);
365
394
param.set_identifier (identifier);
366
395
367
- // add to symbol table
396
+ // Build a new symbol for the parameter and add it to the symbol table
368
397
parameter_symbolt parameter_symbol;
369
398
parameter_symbol.base_name =base_name;
370
399
parameter_symbol.mode =ID_java;
@@ -382,7 +411,8 @@ void java_bytecode_convert_methodt::convert(
382
411
383
412
// The parameter slots detected in this function should agree with what
384
413
// java_parameter_count() thinks about this method
385
- INVARIANT (param_index==slots_for_parameters,
414
+ INVARIANT (
415
+ param_index==slots_for_parameters,
386
416
" java_parameter_count and local computation must agree" );
387
417
388
418
const bool is_virtual=!m.is_static && !m.is_final ;
@@ -406,6 +436,10 @@ void java_bytecode_convert_methodt::convert(
406
436
method_symbol.location =m.source_location ;
407
437
method_symbol.location .set_function (method_identifier);
408
438
439
+ // Set up the pretty name for the method entry in the symbol table.
440
+ // The pretty name of a constructor includes the base name of the class
441
+ // instead of the internal method name "<init>". For regular methods, it's
442
+ // just the base name of the method.
409
443
if (method.get_base_name ()==" <init>" )
410
444
method_symbol.pretty_name =id2string (class_symbol.pretty_name )+" ." +
411
445
id2string (class_symbol.base_name )+" ()" ;
@@ -416,17 +450,20 @@ void java_bytecode_convert_methodt::convert(
416
450
method_symbol.type =member_type;
417
451
if (is_constructor (method))
418
452
method_symbol.type .set (ID_constructor, true );
453
+
419
454
current_method=method_symbol.name ;
420
455
method_has_this=code_type.has_this ();
421
456
if ((!m.is_abstract ) && (!m.is_native ))
422
457
method_symbol.value =convert_instructions (m, code_type, method_symbol.name );
423
458
424
459
// Replace the existing stub symbol with the real deal:
425
460
const auto s_it=symbol_table.symbols .find (method.get_name ());
426
- INVARIANT (s_it!=symbol_table.symbols .end (),
461
+ INVARIANT (
462
+ s_it!=symbol_table.symbols .end (),
427
463
" the symbol was there earlier on this function; it must be there now" );
428
464
symbol_table.symbols .erase (s_it);
429
465
466
+ // Insert the method symbol in the symbol table
430
467
symbol_table.add (method_symbol);
431
468
}
432
469
0 commit comments