Skip to content

Commit 0e71658

Browse files
Initialise string solver function parameter names
Get the names of the parameters for string solver functions from bytecode if we have the bytecode for them
1 parent d556380 commit 0e71658

5 files changed

+138
-16
lines changed

src/java_bytecode/java_bytecode_convert_method.cpp

+90
Original file line numberDiff line numberDiff line change
@@ -2844,6 +2844,96 @@ codet java_bytecode_convert_methodt::convert_instructions(
28442844
return code;
28452845
}
28462846

2847+
/// This uses a cut-down version of the logic in
2848+
/// java_bytecode_convert_methodt::convert to initialize symbols for the
2849+
/// parameters and update the parameters in the type of method_symbol with
2850+
/// names read from the local_variable_table read from the bytecode
2851+
/// \remarks This is useful for pre-initialization for methods generated by
2852+
/// the string solver
2853+
/// \param method_symbol: The symbol for the method for which to initialize the
2854+
/// parameters
2855+
/// \param local_variable_table: The local variable table containing the
2856+
/// bytecode for the parameters
2857+
/// \param symbol_table: The symbol table into which to insert symbols for the
2858+
/// parameters
2859+
void java_bytecode_initialize_parameter_names(
2860+
symbolt &method_symbol,
2861+
const java_bytecode_parse_treet::methodt::local_variable_tablet
2862+
&local_variable_table,
2863+
symbol_table_baset &symbol_table)
2864+
{
2865+
// Obtain a std::vector of code_typet::parametert objects from the
2866+
// (function) type of the symbol
2867+
code_typet &code_type = to_code_type(method_symbol.type);
2868+
code_typet::parameterst &parameters = code_type.parameters();
2869+
2870+
// Find number of parameters
2871+
unsigned slots_for_parameters = java_method_parameter_slots(code_type);
2872+
2873+
// Find parameter names in the local variable table:
2874+
typedef std::pair<irep_idt, irep_idt> base_name_and_identifiert;
2875+
std::map<std::size_t, base_name_and_identifiert> param_names;
2876+
for(const auto &v : local_variable_table)
2877+
{
2878+
if(v.index < slots_for_parameters)
2879+
param_names.emplace(
2880+
v.index,
2881+
make_pair(
2882+
v.name, id2string(method_symbol.name) + "::" + id2string(v.name)));
2883+
}
2884+
2885+
// Assign names to parameters
2886+
std::size_t param_index = 0;
2887+
for(auto &param : parameters)
2888+
{
2889+
irep_idt base_name, identifier;
2890+
2891+
// Construct a sensible base name (base_name) and a fully qualified name
2892+
// (identifier) for every parameter of the method under translation,
2893+
// regardless of whether we have an LVT or not; and assign it to the
2894+
// parameter object (which is stored in the type of the symbol, not in the
2895+
// symbol table)
2896+
if(param_index == 0 && param.get_this())
2897+
{
2898+
// my.package.ClassName.myMethodName:(II)I::this
2899+
base_name = "this";
2900+
identifier = id2string(method_symbol.name) + "::" + id2string(base_name);
2901+
}
2902+
else
2903+
{
2904+
auto param_name = param_names.find(param_index);
2905+
if(param_name != param_names.end())
2906+
{
2907+
base_name = param_name->second.first;
2908+
identifier = param_name->second.second;
2909+
}
2910+
else
2911+
{
2912+
// my.package.ClassName.myMethodName:(II)I::argNT, where N is the local
2913+
// variable slot where the parameter is stored and T is a character
2914+
// indicating the type
2915+
const typet &type = param.type();
2916+
char suffix = java_char_from_type(type);
2917+
base_name = "arg" + std::to_string(param_index) + suffix;
2918+
identifier =
2919+
id2string(method_symbol.name) + "::" + id2string(base_name);
2920+
}
2921+
}
2922+
param.set_base_name(base_name);
2923+
param.set_identifier(identifier);
2924+
2925+
// Build a new symbol for the parameter and add it to the symbol table
2926+
parameter_symbolt parameter_symbol;
2927+
parameter_symbol.base_name = base_name;
2928+
parameter_symbol.mode = ID_java;
2929+
parameter_symbol.name = identifier;
2930+
parameter_symbol.type = param.type();
2931+
symbol_table.insert(parameter_symbol);
2932+
2933+
param_index += java_local_variable_slots(param.type());
2934+
}
2935+
}
2936+
28472937
void java_bytecode_convert_method(
28482938
const symbolt &class_symbol,
28492939
const java_bytecode_parse_treet::methodt &method,

src/java_bytecode/java_bytecode_convert_method.h

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ Author: Daniel Kroening, [email protected]
2121

2222
class class_hierarchyt;
2323

24+
void java_bytecode_initialize_parameter_names(
25+
symbolt &method_symbol,
26+
const java_bytecode_parse_treet::methodt::local_variable_tablet
27+
&local_variable_table,
28+
symbol_table_baset &symbol_table);
29+
2430
void java_bytecode_convert_method(
2531
const symbolt &class_symbol,
2632
const java_bytecode_parse_treet::methodt &,

src/java_bytecode/java_bytecode_language.cpp

+18-8
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,9 @@ bool java_bytecode_languaget::typecheck(
256256
convert_single_method(method_sig.first, journalling_symbol_table);
257257
}
258258
// Now convert all newly added string methods
259-
id_sett string_methods;
260-
string_preprocess.get_all_function_names(string_methods);
261259
for(const auto &fn_name : journalling_symbol_table.get_inserted())
262260
{
263-
if(string_methods.count(fn_name) != 0)
261+
if(string_preprocess.implements_function(fn_name))
264262
convert_single_method(fn_name, symbol_table);
265263
}
266264
}
@@ -392,17 +390,29 @@ bool java_bytecode_languaget::convert_single_method(
392390
if(symbol.value.is_not_nil())
393391
return false;
394392

395-
exprt generated_code =
396-
string_preprocess.code_for_function(symbol, symbol_table);
397-
if(generated_code.is_not_nil())
393+
// Get bytecode for specified function if we have it
394+
method_bytecodet::opt_reft cmb = method_bytecode.get(function_id);
395+
396+
// Check if have a string solver implementation
397+
if(string_preprocess.implements_function(function_id))
398398
{
399+
symbolt &symbol = symbol_table.get_writeable_ref(function_id);
400+
// Load parameter names from any extant bytecode before filling in body
401+
if(cmb)
402+
{
403+
java_bytecode_initialize_parameter_names(
404+
symbol, cmb->get().method.local_variable_table, symbol_table);
405+
}
399406
// Populate body of the function with code generated by string preprocess
400-
symbol_table.get_writeable_ref(function_id).value = generated_code;
407+
exprt generated_code =
408+
string_preprocess.code_for_function(symbol, symbol_table);
409+
INVARIANT(
410+
generated_code.is_not_nil(), "Couldn't retrieve code for string method");
411+
symbol.value = generated_code;
401412
return false;
402413
}
403414

404415
// No string solver implementation, check if have bytecode for it
405-
method_bytecodet::opt_reft cmb = method_bytecode.get(function_id);
406416
if(cmb)
407417
{
408418
java_bytecode_convert_method(

src/java_bytecode/java_string_library_preprocess.cpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,16 @@ codet java_string_library_preprocesst::make_string_length_code(
17581758
return code_returnt(get_length(deref, symbol_table));
17591759
}
17601760

1761+
bool java_string_library_preprocesst::implements_function(
1762+
const irep_idt &function_id) const
1763+
{
1764+
for(const id_mapt *map : id_maps)
1765+
if(map->count(function_id) != 0)
1766+
return true;
1767+
1768+
return conversion_table.count(function_id) != 0;
1769+
}
1770+
17611771
template <typename TMap, typename TContainer>
17621772
void add_keys_to_container(const TMap &map, TContainer &container)
17631773
{
@@ -1775,14 +1785,7 @@ void add_keys_to_container(const TMap &map, TContainer &container)
17751785
void java_string_library_preprocesst::get_all_function_names(
17761786
id_sett &methods) const
17771787
{
1778-
const id_mapt *maps[] = {
1779-
&cprover_equivalent_to_java_function,
1780-
&cprover_equivalent_to_java_string_returning_function,
1781-
&cprover_equivalent_to_java_constructor,
1782-
&cprover_equivalent_to_java_assign_and_return_function,
1783-
&cprover_equivalent_to_java_assign_function,
1784-
};
1785-
for(const id_mapt *map : maps)
1788+
for(const id_mapt *map : id_maps)
17861789
add_keys_to_container(*map, methods);
17871790

17881791
add_keys_to_container(conversion_table, methods);

src/java_bytecode/java_string_library_preprocess.h

+13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Date: March 2017
2222

2323
#include <util/ieee_float.h> // should get rid of this
2424

25+
#include <array>
2526
#include <unordered_set>
2627
#include <functional>
2728
#include "character_refine_preprocess.h"
@@ -45,6 +46,7 @@ class java_string_library_preprocesst:public messaget
4546
void initialize_conversion_table();
4647
void initialize_refined_string_type();
4748

49+
bool implements_function(const irep_idt &function_id) const;
4850
void get_all_function_names(id_sett &methods) const;
4951

5052
exprt
@@ -126,6 +128,17 @@ class java_string_library_preprocesst:public messaget
126128
// of returning it
127129
id_mapt cprover_equivalent_to_java_assign_function;
128130

131+
const std::array<id_mapt *, 5> id_maps = std::array<id_mapt *, 5>
132+
{
133+
{
134+
&cprover_equivalent_to_java_function,
135+
&cprover_equivalent_to_java_string_returning_function,
136+
&cprover_equivalent_to_java_constructor,
137+
&cprover_equivalent_to_java_assign_and_return_function,
138+
&cprover_equivalent_to_java_assign_function,
139+
}
140+
};
141+
129142
// A set tells us what java types should be considered as string objects
130143
std::unordered_set<irep_idt, irep_id_hash> string_types;
131144

0 commit comments

Comments
 (0)