Skip to content

Commit 1e5fd65

Browse files
Merge pull request #4873 from romainbrenguier/bugfix/java-convert-variable
Avoid unnecessary typecast in java_bytecode_convert_methodt::variable
2 parents cbef420 + 1c93adb commit 1e5fd65

File tree

3 files changed

+412
-42
lines changed

3 files changed

+412
-42
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -164,21 +164,18 @@ symbol_exprt java_bytecode_convert_methodt::tmp_variable(
164164
/// from a bytecode at address `address` a value of type `type_char` stored in
165165
/// the JVM's slot `arg`.
166166
/// \param arg: The local variable slot
167-
/// \param type_char: The type of the value stored in the slot pointed by `arg`
167+
/// \param type_char: The type of the value stored in the slot pointed to by
168+
/// `arg`, this is only used in the case where a new unnamed local variable
169+
/// is created
168170
/// \param address: Bytecode address used to find a variable that the LVT
169171
/// declares to be live and living in the slot pointed by `arg` for this
170172
/// bytecode
171-
/// \param do_cast: Indicates whether we should return the original symbol_exprt
172-
/// or a typecast_exprt if the type of the symbol_exprt does not equal that
173-
/// represented by `type_char`
174173
/// \return symbol_exprt or type-cast symbol_exprt
175174
exprt java_bytecode_convert_methodt::variable(
176175
const exprt &arg,
177176
char type_char,
178-
size_t address,
179-
java_bytecode_convert_methodt::variable_cast_argumentt do_cast)
177+
size_t address)
180178
{
181-
typet t=java_type_from_char(type_char);
182179
const std::size_t number_int =
183180
numeric_cast_v<std::size_t>(to_constant_expr(arg));
184181
variablest &var_list=variables[number_int];
@@ -187,24 +184,17 @@ exprt java_bytecode_convert_methodt::variable(
187184
const variablet &var=
188185
find_variable_for_slot(address, var_list);
189186

190-
if(var.symbol_expr.get_identifier().empty())
191-
{
192-
// an unnamed local variable
193-
irep_idt base_name="anonlocal::"+std::to_string(number_int)+type_char;
194-
irep_idt identifier=id2string(current_method)+"::"+id2string(base_name);
195-
196-
symbol_exprt result(identifier, t);
197-
result.set(ID_C_base_name, base_name);
198-
used_local_names.insert(result);
199-
return std::move(result);
200-
}
201-
else
202-
{
203-
exprt result=var.symbol_expr;
204-
if(do_cast == CAST_AS_NEEDED)
205-
result = typecast_exprt::conditional_cast(result, t);
206-
return result;
207-
}
187+
if(!var.symbol_expr.get_identifier().empty())
188+
return var.symbol_expr;
189+
190+
// an unnamed local variable
191+
irep_idt base_name = "anonlocal::" + std::to_string(number_int) + type_char;
192+
irep_idt identifier = id2string(current_method) + "::" + id2string(base_name);
193+
194+
symbol_exprt result(identifier, java_type_from_char(type_char));
195+
result.set(ID_C_base_name, base_name);
196+
used_local_names.insert(result);
197+
return std::move(result);
208198
}
209199

210200
/// Returns the member type for a method, based on signature or descriptor
@@ -1346,8 +1336,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
13461336
else if(bytecode == patternt("?load") || bytecode == patternt("?load_?"))
13471337
{
13481338
// load a value from a local variable
1349-
results[0]=
1350-
variable(arg0, statement[0], i_it->address, CAST_AS_NEEDED);
1339+
results[0] = convert_load(arg0, statement[0], i_it->address);
13511340
}
13521341
else if(bytecode == BC_ldc || bytecode == BC_ldc_w || bytecode == BC_ldc2_w)
13531342
{
@@ -2710,7 +2699,7 @@ code_blockt java_bytecode_convert_methodt::convert_iinc(
27102699
code_blockt block;
27112700
block.add_source_location() = location;
27122701
// search variable on stack
2713-
const exprt &locvar = variable(arg0, 'i', address, NO_CAST);
2702+
const exprt &locvar = variable(arg0, 'i', address);
27142703
save_stack_entries(
27152704
"stack_iinc",
27162705
block,
@@ -2720,8 +2709,11 @@ code_blockt java_bytecode_convert_methodt::convert_iinc(
27202709
const exprt arg1_int_type =
27212710
typecast_exprt::conditional_cast(arg1, java_int_type());
27222711
code_assignt code_assign(
2723-
variable(arg0, 'i', address, NO_CAST),
2724-
plus_exprt(variable(arg0, 'i', address, CAST_AS_NEEDED), arg1_int_type));
2712+
variable(arg0, 'i', address),
2713+
plus_exprt(
2714+
typecast_exprt::conditional_cast(
2715+
variable(arg0, 'i', address), java_int_type()),
2716+
arg1_int_type));
27252717
block.add(std::move(code_assign));
27262718

27272719
return block;
@@ -2826,7 +2818,7 @@ code_blockt java_bytecode_convert_methodt::convert_ret(
28262818
const method_offsett address)
28272819
{
28282820
code_blockt c;
2829-
auto retvar = variable(arg0, 'a', address, NO_CAST);
2821+
auto retvar = variable(arg0, 'a', address);
28302822
for(size_t idx = 0, idxlim = jsr_ret_targets.size(); idx != idxlim; ++idx)
28312823
{
28322824
irep_idt number = std::to_string(jsr_ret_targets[idx]);
@@ -2888,20 +2880,37 @@ exprt java_bytecode_convert_methodt::convert_aload(
28882880
return java_bytecode_promotion(dereference_exprt{data_plus_offset});
28892881
}
28902882

2883+
exprt java_bytecode_convert_methodt::convert_load(
2884+
const exprt &index,
2885+
char type_char,
2886+
size_t address)
2887+
{
2888+
const exprt var = variable(index, type_char, address);
2889+
if(type_char == 'i')
2890+
{
2891+
INVARIANT(
2892+
can_cast_type<bitvector_typet>(var.type()) &&
2893+
type_try_dynamic_cast<bitvector_typet>(var.type())->get_width() <= 32,
2894+
"iload can be used for boolean, byte, short, int and char");
2895+
return typecast_exprt::conditional_cast(var, java_int_type());
2896+
}
2897+
INVARIANT(
2898+
(type_char == 'a' && can_cast_type<reference_typet>(var.type())) ||
2899+
var.type() == java_type_from_char(type_char),
2900+
"Variable type must match [adflv]load return type");
2901+
return var;
2902+
}
2903+
28912904
code_blockt java_bytecode_convert_methodt::convert_store(
28922905
const irep_idt &statement,
28932906
const exprt &arg0,
28942907
const exprt::operandst &op,
28952908
const method_offsett address,
28962909
const source_locationt &location)
28972910
{
2898-
const exprt var = variable(arg0, statement[0], address, NO_CAST);
2911+
const exprt var = variable(arg0, statement[0], address);
28992912
const irep_idt &var_name = to_symbol_expr(var).get_identifier();
29002913

2901-
exprt toassign = op[0];
2902-
if('a' == statement[0])
2903-
toassign = typecast_exprt::conditional_cast(toassign, var.type());
2904-
29052914
code_blockt block;
29062915
block.add_source_location() = location;
29072916

@@ -2911,7 +2920,9 @@ code_blockt java_bytecode_convert_methodt::convert_store(
29112920
bytecode_write_typet::VARIABLE,
29122921
var_name);
29132922

2914-
block.add(code_assignt{var, toassign}, location);
2923+
block.add(
2924+
code_assignt{var, typecast_exprt::conditional_cast(op[0], var.type())},
2925+
location);
29152926
return block;
29162927
}
29172928

jbmc/src/java_bytecode/java_bytecode_convert_method_class.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,7 @@ class java_bytecode_convert_methodt:public messaget
183183
NO_CAST
184184
};
185185

186-
exprt variable(
187-
const exprt &arg,
188-
char type_char,
189-
size_t address,
190-
variable_cast_argumentt do_cast);
186+
exprt variable(const exprt &arg, char type_char, size_t address);
191187

192188
// temporary variables
193189
std::list<symbol_exprt> tmp_vars;
@@ -369,6 +365,17 @@ class java_bytecode_convert_methodt:public messaget
369365
static exprt
370366
convert_aload(const irep_idt &statement, const exprt::operandst &op);
371367

368+
/// Load reference from local variable.
369+
/// \p index must be an unsigned byte and an index in the local variable array
370+
/// of the current frame. The type of the local variable at index \p index
371+
/// must:
372+
/// - be a reference type if \p type_char is 'a'
373+
/// - be either boolean, byte, short, int, or char if \p type_char is 'i', a
374+
/// typecast to `int` is added if needed
375+
/// - match \c java_type_of_char(type_char) otherwise
376+
/// \return the local variable at \p index
377+
exprt convert_load(const exprt &index, char type_char, size_t address);
378+
372379
code_blockt convert_ret(
373380
const std::vector<method_offsett> &jsr_ret_targets,
374381
const exprt &arg0,

0 commit comments

Comments
 (0)