|
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>
|
@@ -3173,44 +3174,87 @@ irep_idt java_bytecode_convert_methodt::get_static_field(
|
3173 | 3174 | return inherited_method.get_full_component_identifier();
|
3174 | 3175 | }
|
3175 | 3176 |
|
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. |
3178 | 3184 | void java_bytecode_convert_methodt::save_stack_entries(
|
3179 | 3185 | const std::string &tmp_var_prefix,
|
3180 | 3186 | const typet &tmp_var_type,
|
3181 | 3187 | code_blockt &block,
|
3182 | 3188 | const bytecode_write_typet write_type,
|
3183 | 3189 | const irep_idt &identifier)
|
3184 | 3190 | {
|
| 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 | + |
3185 | 3233 | for(auto &stack_entry : stack)
|
3186 | 3234 | {
|
3187 |
| - // remove typecasts if existing |
3188 |
| - while(stack_entry.id()==ID_typecast) |
3189 |
| - stack_entry=to_typecast_expr(stack_entry).op(); |
3190 |
| - |
3191 | 3235 | // 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)) |
3195 | 3240 | {
|
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); |
3199 | 3242 | }
|
3200 | 3243 |
|
3201 | 3244 | // 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 | + { |
3204 | 3249 | create_stack_tmp_var(tmp_var_prefix, tmp_var_type, block, stack_entry);
|
| 3250 | + } |
3205 | 3251 |
|
3206 | 3252 | // 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)) |
3209 | 3256 | {
|
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); |
3214 | 3258 | }
|
3215 | 3259 | }
|
3216 | 3260 | }
|
|
0 commit comments