@@ -33,6 +33,7 @@ Author: Daniel Kroening, kroening@kroening.com
33
33
#include < util/std_expr.h>
34
34
#include < util/string2int.h>
35
35
#include < util/string_constant.h>
36
+ #include < util/threeval.h>
36
37
37
38
#include < goto-programs/cfg.h>
38
39
#include < goto-programs/class_hierarchy.h>
@@ -3176,44 +3177,90 @@ irep_idt java_bytecode_convert_methodt::get_static_field(
3176
3177
return inherited_method.get_full_component_identifier ();
3177
3178
}
3178
3179
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.
3181
3187
void java_bytecode_convert_methodt::save_stack_entries (
3182
3188
const std::string &tmp_var_prefix,
3183
3189
const typet &tmp_var_type,
3184
3190
code_blockt &block,
3185
3191
const bytecode_write_typet write_type,
3186
3192
const irep_idt &identifier)
3187
3193
{
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
+ // Function that checks whether the expression accesses a member with the
3216
+ // given identifier name. These accesses are created in the case of `iinc`, or
3217
+ // non-array `?store` instructions.
3218
+ const std::function<tvt (const exprt &expr)> has_member_entry = [&identifier](
3219
+ const exprt &expr) {
3220
+ const auto member_expr = expr_try_dynamic_cast<member_exprt>(expr);
3221
+ return !member_expr ? tvt::unknown ()
3222
+ : tvt (member_expr->get_component_name () == identifier);
3223
+ };
3224
+
3225
+ // Function that checks whether the expression is a symbol with the given
3226
+ // identifier name. These accesses are created in the case of `putstatic` or
3227
+ // `putfield` instructions.
3228
+ const std::function<tvt (const exprt &expr)> is_symbol_entry =
3229
+ [&identifier](const exprt &expr) {
3230
+ const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(expr);
3231
+ return !symbol_expr ? tvt::unknown ()
3232
+ : tvt (symbol_expr->get_identifier () == identifier);
3233
+ };
3234
+
3235
+ // Function that checks whether the expression is a dereference
3236
+ // expression. These accesses are created in `?astore` array write
3237
+ // instructions.
3238
+ const std::function<tvt (const exprt &expr)> is_dereference_entry =
3239
+ [](const exprt &expr) {
3240
+ const auto dereference_expr =
3241
+ expr_try_dynamic_cast<dereference_exprt>(expr);
3242
+ return !dereference_expr ? tvt::unknown () : tvt (true );
3243
+ };
3244
+
3188
3245
for (auto &stack_entry : stack)
3189
3246
{
3190
- // remove typecasts if existing
3191
- while (stack_entry.id ()==ID_typecast)
3192
- stack_entry=to_typecast_expr (stack_entry).op ();
3193
-
3194
- // 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)
3247
+ bool replace = false ;
3248
+ switch (write_type)
3249
+ {
3250
+ case bytecode_write_typet::VARIABLE:
3251
+ case bytecode_write_typet::STATIC_FIELD:
3252
+ replace = entry_matches (is_symbol_entry, stack_entry);
3253
+ break ;
3254
+ case bytecode_write_typet::ARRAY_REF:
3255
+ replace = entry_matches (is_dereference_entry, stack_entry);
3256
+ break ;
3257
+ case bytecode_write_typet::FIELD:
3258
+ replace = entry_matches (has_member_entry, stack_entry);
3259
+ break ;
3260
+ }
3261
+ if (replace)
3198
3262
{
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);
3202
- }
3203
-
3204
- // 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)
3207
3263
create_stack_tmp_var (tmp_var_prefix, tmp_var_type, block, stack_entry);
3208
-
3209
- // field and member access -> compare component name
3210
- else if (write_type==bytecode_write_typet::FIELD &&
3211
- stack_entry.id ()==ID_member)
3212
- {
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);
3217
3264
}
3218
3265
}
3219
3266
}
0 commit comments