|
| 1 | +/*******************************************************************\ |
| 2 | +
|
| 3 | +Module: Unwind loops in array clone for enums |
| 4 | +
|
| 5 | +Author: Diffblue |
| 6 | +
|
| 7 | +\*******************************************************************/ |
| 8 | + |
| 9 | +/// \file |
| 10 | +/// Unwind loops in array.clone for enums |
| 11 | +#include "java_enum_array_clone_unwind_handler.h" |
| 12 | + |
| 13 | +#include <util/invariant.h> |
| 14 | +#include <util/suffix.h> |
| 15 | + |
| 16 | +#include <java_bytecode/java_utils.h> |
| 17 | + |
| 18 | +/// Unwind handler that special-cases the clone functions of arrays of |
| 19 | +/// enumeration classes. This forces unwinding of the copy loop in the clone |
| 20 | +/// method with as many iterations as enum elements exist. |
| 21 | +/// \param function_id: function the loop is in |
| 22 | +/// \param loop_number: ordinal number of the loop (ignored) |
| 23 | +/// \param unwind_count: iteration count that is about to begin |
| 24 | +/// \param [out] unwind_max: may be set to an advisory (unenforced) maximum when |
| 25 | +/// we know the total iteration count |
| 26 | +/// \param symbol_table: global symbol table |
| 27 | +/// \return false if loop_id belongs to an enumeration's array clone method and |
| 28 | +/// unwind_count is <= the enumeration size, or unknown (defer / no decision) |
| 29 | +/// otherwise. |
| 30 | +tvt java_enum_array_clone_unwind_handler( |
| 31 | + const irep_idt &function_id, |
| 32 | + unsigned loop_number, |
| 33 | + unsigned unwind_count, |
| 34 | + unsigned &unwind_max, |
| 35 | + const symbol_tablet &symbol_table) |
| 36 | +{ |
| 37 | + const std::string method_name = id2string(function_id); |
| 38 | + const std::string java_array_prefix = "java::array["; |
| 39 | + const size_t java_array_prefix_start = method_name.find(java_array_prefix); |
| 40 | + const size_t java_array_prefix_end = |
| 41 | + method_name.find("].clone:()Ljava/lang/Object;"); |
| 42 | + if(java_array_prefix_end == std::string::npos || java_array_prefix_start != 0) |
| 43 | + return tvt::unknown(); |
| 44 | + |
| 45 | + const java_enum_elements_mapt java_enum_elements = |
| 46 | + get_java_enum_elements_map(symbol_table); |
| 47 | + |
| 48 | + std::string enum_name = "java::" + |
| 49 | + method_name.substr( |
| 50 | + java_array_prefix.size(), |
| 51 | + java_array_prefix_end - java_array_prefix.size()); |
| 52 | + std::replace(enum_name.begin(), enum_name.end(), '/', '.'); |
| 53 | + const auto entry = java_enum_elements.find(enum_name); |
| 54 | + |
| 55 | + if(entry != java_enum_elements.end()) |
| 56 | + { |
| 57 | + const size_t bound = entry->second; |
| 58 | + if(unwind_count < bound) |
| 59 | + { |
| 60 | + unwind_max = bound; |
| 61 | + return tvt(false); |
| 62 | + } |
| 63 | + } |
| 64 | + return tvt::unknown(); |
| 65 | +} |
0 commit comments