Skip to content

Commit 731c69e

Browse files
author
Matthias Güdemann
committed
Keep expressions unchanged when adding temporary variables
Search recursively through expressions instead of only removing outer typecast expressions.
1 parent d10e44d commit 731c69e

File tree

1 file changed

+64
-20
lines changed

1 file changed

+64
-20
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Author: Daniel Kroening, [email protected]
3333
#include <util/std_expr.h>
3434
#include <util/string2int.h>
3535
#include <util/string_constant.h>
36+
#include <util/threeval.h>
3637

3738
#include <goto-programs/cfg.h>
3839
#include <goto-programs/class_hierarchy.h>
@@ -3176,44 +3177,87 @@ irep_idt java_bytecode_convert_methodt::get_static_field(
31763177
return inherited_method.get_full_component_identifier();
31773178
}
31783179

3179-
/// create temporary variables if a write instruction can have undesired side-
3180-
/// effects
3180+
/// Create temporary variables if a write instruction can have undesired side-
3181+
/// effects.
3182+
/// \param tmp_var_prefix: The prefix string to use for new temporary variables
3183+
/// \param tmp_var_type: The type of the temporary variable.
3184+
/// \param[out] block: The code block the assignment is added to if required.
3185+
/// \param write_type: The enumeration type of the write instruction.
3186+
/// \param identifier: The identifier of the symbol in the write instruction.
31813187
void java_bytecode_convert_methodt::save_stack_entries(
31823188
const std::string &tmp_var_prefix,
31833189
const typet &tmp_var_type,
31843190
code_blockt &block,
31853191
const bytecode_write_typet write_type,
31863192
const irep_idt &identifier)
31873193
{
3194+
const std::function<bool(
3195+
const std::function<tvt(const exprt &expr)>, const exprt &expr)>
3196+
entry_matches = [&entry_matches](
3197+
const std::function<tvt(const exprt &expr)> predicate,
3198+
const exprt &expr) {
3199+
const tvt &tvres = predicate(expr);
3200+
if(tvres.is_unknown())
3201+
{
3202+
return std::any_of(
3203+
expr.operands().begin(),
3204+
expr.operands().end(),
3205+
[&predicate, &entry_matches](const exprt &expr) {
3206+
return entry_matches(predicate, expr);
3207+
});
3208+
}
3209+
else
3210+
{
3211+
return tvres.is_true();
3212+
}
3213+
};
3214+
3215+
const std::function<tvt(const exprt &expr)> has_member_entry = [&identifier](
3216+
const exprt &expr) {
3217+
const auto member_expr = expr_try_dynamic_cast<member_exprt>(expr);
3218+
return !member_expr ? tvt::unknown()
3219+
: tvt(member_expr->get_component_name() == identifier);
3220+
};
3221+
3222+
const std::function<tvt(const exprt &expr)> is_symbol_entry =
3223+
[&identifier](const exprt &expr) {
3224+
const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(expr);
3225+
return !symbol_expr ? tvt::unknown()
3226+
: tvt(symbol_expr->get_identifier() == identifier);
3227+
};
3228+
3229+
const std::function<tvt(const exprt &expr)> is_dereference_entry =
3230+
[](const exprt &expr) {
3231+
const auto dereference_expr =
3232+
expr_try_dynamic_cast<dereference_exprt>(expr);
3233+
return !dereference_expr ? tvt::unknown() : tvt(true);
3234+
};
3235+
31883236
for(auto &stack_entry : stack)
31893237
{
3190-
// remove typecasts if existing
3191-
while(stack_entry.id()==ID_typecast)
3192-
stack_entry=to_typecast_expr(stack_entry).op();
3193-
31943238
// variables or static fields and symbol -> save symbols with same id
3195-
if((write_type==bytecode_write_typet::VARIABLE ||
3196-
write_type==bytecode_write_typet::STATIC_FIELD) &&
3197-
stack_entry.id()==ID_symbol)
3239+
if(
3240+
(write_type == bytecode_write_typet::VARIABLE ||
3241+
write_type == bytecode_write_typet::STATIC_FIELD) &&
3242+
entry_matches(is_symbol_entry, stack_entry))
31983243
{
3199-
const symbol_exprt &var=to_symbol_expr(stack_entry);
3200-
if(var.get_identifier()==identifier)
3201-
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
3244+
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
32023245
}
32033246

32043247
// array reference and dereference -> save all references on the stack
3205-
else if(write_type==bytecode_write_typet::ARRAY_REF &&
3206-
stack_entry.id()==ID_dereference)
3248+
else if(
3249+
write_type == bytecode_write_typet::ARRAY_REF &&
3250+
entry_matches(is_dereference_entry, stack_entry))
3251+
{
32073252
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
3253+
}
32083254

32093255
// field and member access -> compare component name
3210-
else if(write_type==bytecode_write_typet::FIELD &&
3211-
stack_entry.id()==ID_member)
3256+
else if(
3257+
write_type == bytecode_write_typet::FIELD &&
3258+
entry_matches(has_member_entry, stack_entry))
32123259
{
3213-
const irep_idt &entry_id=
3214-
to_member_expr(stack_entry).get_component_name();
3215-
if(entry_id==identifier)
3216-
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
3260+
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
32173261
}
32183262
}
32193263
}

0 commit comments

Comments
 (0)