Skip to content

Commit d054a5d

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 70887e2 commit d054a5d

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

+64-20
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>
@@ -3173,44 +3174,87 @@ irep_idt java_bytecode_convert_methodt::get_static_field(
31733174
return inherited_method.get_full_component_identifier();
31743175
}
31753176

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

32013244
// array reference and dereference -> save all references on the stack
3202-
else if(write_type==bytecode_write_typet::ARRAY_REF &&
3203-
stack_entry.id()==ID_dereference)
3245+
else if(
3246+
write_type == bytecode_write_typet::ARRAY_REF &&
3247+
entry_matches(is_dereference_entry, stack_entry))
3248+
{
32043249
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
3250+
}
32053251

32063252
// field and member access -> compare component name
3207-
else if(write_type==bytecode_write_typet::FIELD &&
3208-
stack_entry.id()==ID_member)
3253+
else if(
3254+
write_type == bytecode_write_typet::FIELD &&
3255+
entry_matches(has_member_entry, stack_entry))
32093256
{
3210-
const irep_idt &entry_id=
3211-
to_member_expr(stack_entry).get_component_name();
3212-
if(entry_id==identifier)
3213-
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
3257+
create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
32143258
}
32153259
}
32163260
}

0 commit comments

Comments
 (0)