diff options
author | matevos <matevosmehrabyan@gmail.com> | 2023-01-05 16:33:03 +0400 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro> | 2023-03-21 09:03:20 -0600 |
commit | 5eff99fb3fbeab877740d75c2861983463618483 (patch) | |
tree | 437499660b98ec0f9402406063ecc3822a92781c | |
parent | fa7e023c6394d03add3449adc5033a7eb3fa250e (diff) | |
download | gcc-5eff99fb3fbeab877740d75c2861983463618483.tar.gz |
sym-exec v12: - Made expression to work with various argument sizes - Fixed bits creation for constants - Some code refactored and fixed
-rw-r--r-- | gcc/crc_verification.cc | 4 | ||||
-rw-r--r-- | gcc/sym-exec/condition.cc | 4 | ||||
-rw-r--r-- | gcc/sym-exec/condition.h | 2 | ||||
-rw-r--r-- | gcc/sym-exec/expression.h | 5 | ||||
-rw-r--r-- | gcc/sym-exec/state.cc | 139 | ||||
-rw-r--r-- | gcc/sym-exec/state.h | 73 |
6 files changed, 136 insertions, 91 deletions
diff --git a/gcc/crc_verification.cc b/gcc/crc_verification.cc index c261a7510e0..eee3cb8f68a 100644 --- a/gcc/crc_verification.cc +++ b/gcc/crc_verification.cc @@ -1067,9 +1067,9 @@ check_condition (value_bit *symb_exp, unsigned char is_one, unsigned char comparison_val = as_a<bit *> ((*iter)->get_right ()) ->get_val (); - if (condition->get_cond_type () == EQ_EXPR) + if (condition->get_code () == EQ_EXPR) return comparison_val == is_one; - if (condition->get_cond_type () == NE_EXPR) + if (condition->get_code () == NE_EXPR) return comparison_val != is_one; return false; } diff --git a/gcc/sym-exec/condition.cc b/gcc/sym-exec/condition.cc index 637cb763d36..eb4ecf908be 100644 --- a/gcc/sym-exec/condition.cc +++ b/gcc/sym-exec/condition.cc @@ -34,12 +34,12 @@ bit_condition::bit_condition (value_bit *left, value_bit *right, tree_code type) bit_condition::bit_condition (const bit_condition &expr) { bit_expression::copy (&expr); - type = expr.get_cond_type (); + type = expr.get_code (); } tree_code -bit_condition::get_cond_type () const +bit_condition::get_code () const { return type; } diff --git a/gcc/sym-exec/condition.h b/gcc/sym-exec/condition.h index 0bcaf372a8c..85d5938009c 100644 --- a/gcc/sym-exec/condition.h +++ b/gcc/sym-exec/condition.h @@ -18,7 +18,7 @@ class bit_condition : public bit_expression { public: bit_condition (value_bit *left, value_bit *right, tree_code type); bit_condition (const bit_condition &expr); - tree_code get_cond_type () const; + tree_code get_code () const; value_bit *copy () const; value_type get_type () const; }; diff --git a/gcc/sym-exec/expression.h b/gcc/sym-exec/expression.h index 9fdbdad08f3..d81e4598392 100644 --- a/gcc/sym-exec/expression.h +++ b/gcc/sym-exec/expression.h @@ -45,7 +45,7 @@ class value_bit { {}; value_bit (size_t i) : index (i) {}; - value_bit (value_bit &val) : index (val.index) + value_bit (const value_bit &val) : index (val.index) {}; size_t get_index () const; @@ -53,8 +53,7 @@ class value_bit { virtual value_bit *copy () const = 0; virtual value_type get_type () const = 0; virtual void print () = 0; - virtual ~value_bit () - {}; + virtual ~value_bit () = default; }; /* Represents value of a single bit of symbolic marked variables. */ diff --git a/gcc/sym-exec/state.cc b/gcc/sym-exec/state.cc index f2aae1d619f..8b0560a1d14 100644 --- a/gcc/sym-exec/state.cc +++ b/gcc/sym-exec/state.cc @@ -4,10 +4,14 @@ #include "state.h" -state::state () + +size_t min (size_t a, size_t b, size_t c) { + size_t min = (a < b ? a : b); + return min < c ? min : c; } + state::state (const state &s) { for (auto iter = s.var_states.begin (); iter != s.var_states.end (); ++iter) @@ -96,7 +100,8 @@ state::check_args_compatibility (tree arg1, tree arg2, tree dest) value state::create_val_for_const (tree var, size_t size) { - HOST_WIDE_INT val = tree_to_shwi (var); + unsigned HOST_WIDE_INT val = TYPE_UNSIGNED (TREE_TYPE (var)) + ? tree_to_uhwi (var) : tree_to_shwi (var); value result (size, TYPE_UNSIGNED (TREE_TYPE (var))); for (size_t i = 0; i < size; i++) @@ -288,7 +293,7 @@ state::get_var_size (tree var) if (content == NULL) return 0; - return content->length (); + return content->allocated (); } @@ -335,6 +340,22 @@ state::and_two_bits (value_bit *arg1, value_bit *arg2) } +value_bit * +state::operate_bits (bit_func bit_op, value_bit *bit1, value_bit *bit2, + value_bit **bit3) +{ + return (bit_op) (bit1, bit2); +} + + +value_bit * +state::operate_bits (bit_func3 bit_op, value_bit *bit1, value_bit *bit2, + value_bit **bit3) +{ + return (bit_op) (bit1, bit2, bit3); +} + + /* Does preprocessing and postprocessing for expressions with tree operands. Handles value creation for constant and their removement in the end. */ @@ -391,12 +412,7 @@ state::do_and (value *arg1, value *arg2, tree dest) /* Creating AND expressions for every bit pair of given arguments and store them as a new state for given destination. */ - for (size_t i = 0; i < get_var_size (dest); i++) - { - value_bit *temp = (*var_states.get (dest))[i]; - (*var_states.get (dest))[i] = and_two_bits ((*arg1)[i], (*arg2)[i]); - delete temp; - } + operate (arg1, arg2, nullptr, dest, &state::and_two_bits); } @@ -440,12 +456,7 @@ state::do_or (value *arg1, value *arg2, tree dest) { /* Creating OR expressions for every bit pair of given arguments and store them as a new state for given destination. */ - for (size_t i = 0; i < get_var_size (dest); i++) - { - value_bit *temp = (*var_states.get (dest))[i]; - (*var_states.get (dest))[i] = or_two_bits ((*arg1)[i], (*arg2)[i]); - delete temp; - } + operate (arg1, arg2, nullptr, dest, &state::or_two_bits); } @@ -487,12 +498,7 @@ state::do_xor (tree arg1, tree arg2, tree dest) void state::do_xor (value *arg1, value *arg2, tree dest) { - for (size_t i = 0; i < get_var_size (dest); i++) - { - value_bit *temp = (*var_states.get (dest))[i]; - (*var_states.get (dest))[i] = xor_two_bits ((*arg1)[i], (*arg2)[i]); - delete temp; - } + operate (arg1, arg2, nullptr, dest, &state::xor_two_bits); } @@ -555,18 +561,10 @@ state::make_number (const value *var) /* Shift_left operation. Case: var2 is a symbolic value. */ -void -state::shift_left_sym_values (value *arg1, value *arg2, tree dest) +value_bit * +state::shift_left_sym_bits (value_bit *var1, value_bit *var2) { - for (size_t i = 0; i < get_var_size (dest); i++) - { - value_bit *var1_bit = (*arg1)[i]; - value_bit *var2_bit = (*arg2)[i]; - value_bit *new_bit = new shift_left_expression (var1_bit->copy (), - var2_bit->copy ()); - delete (*var_states.get (dest))[i]; - (*var_states.get (dest))[i] = new_bit; - } + return new shift_left_expression (var1->copy (), var2->copy ()); } @@ -594,7 +592,7 @@ state::do_shift_left (value *arg1, value *arg2, tree dest) delete result; } else - shift_left_sym_values (arg1, arg2, dest); + operate (arg1, arg2, nullptr, dest, &state::shift_left_sym_bits); } @@ -621,7 +619,7 @@ state::do_shift_right (value *arg1, value *arg2, tree dest) } } else - shift_right_sym_values (arg1, arg2, dest); + operate (arg1, arg2, nullptr, dest, &state::shift_right_sym_bits); } @@ -629,18 +627,18 @@ state::do_shift_right (value *arg1, value *arg2, tree dest) Resturn result and stores new carry bit in "carry". */ value_bit * -state::full_adder (value_bit *var1, value_bit *var2, value_bit *&carry) +state::full_adder (value_bit *var1, value_bit *var2, value_bit **carry) { value_bit *new_carry = and_two_bits (var1, var2); value_bit *sum = xor_two_bits (var1, var2); - value_bit *result = xor_two_bits (sum, carry); - value_bit *sum_and_carry = and_two_bits (sum, carry); + value_bit *result = xor_two_bits (sum, *carry); + value_bit *sum_and_carry = and_two_bits (sum, *carry); - delete carry; + delete *carry; delete sum; - carry = or_two_bits (sum_and_carry, new_carry); + *carry = or_two_bits (sum_and_carry, new_carry); delete sum_and_carry; delete new_carry; @@ -662,12 +660,7 @@ void state::do_add (value *arg1, value *arg2, tree dest) { value_bit *carry = new bit (0); - for (size_t i = 0; i < get_var_size (dest); ++i) - { - value_bit *temp = (*var_states.get (dest))[i]; - (*var_states.get (dest))[i] = full_adder ((*arg1)[i], (*arg2)[i], carry); - delete temp; - } + operate (arg1, arg2, &carry, dest, &state::full_adder); delete carry; } @@ -692,7 +685,7 @@ state::additive_inverse (const value *number) value_bit *carry = new bit (0); for (size_t i = 0; i < size; ++i) - (*result)[i] = full_adder ((*result)[i], one[i], carry); + (*result)[i] = full_adder ((*result)[i], one[i], &carry); delete carry; free_val (&one); @@ -714,7 +707,6 @@ state::do_sub (value *arg1, value *arg2, tree dest) { value *neg_arg2 = additive_inverse (arg2); do_add (arg1, neg_arg2, dest); - free_val (neg_arg2); delete neg_arg2; } @@ -744,25 +736,31 @@ state::do_complement (tree arg, tree dest) declare_if_needed (dest, tree_to_uhwi (TYPE_SIZE (TREE_TYPE (dest)))); declare_if_needed (arg, var_states.get (dest)->allocated ()); - if (get_var_size (arg) != get_var_size (dest)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Sym-Exec: Incompatible destination" - " and argument sizes.\n"); - - return false; - } - /* Creating complement expressions for every bit the given argument and store it as a new state for given destination. */ - for (size_t i = 0; i < get_var_size (dest); i++) + size_t iter_count = min (get_var_size (dest), get_var_size (arg), + get_var_size (arg)); + + size_t i = 0; + for (; i < iter_count; i++) { value_bit *result = complement_a_bit ((*var_states.get (arg))[i]); - delete (*var_states.get (dest))[i]; (*var_states.get (dest))[i] = result; } + if (i >= get_var_size (dest)) + { + print_value (var_states.get (dest)); + return true; + } + + for (; i < get_var_size (dest); i++) + { + delete (*var_states.get (dest))[i]; + (*var_states.get (dest))[i] = complement_a_bit (new bit (0)); + } + print_value (var_states.get (dest)); return true; } @@ -1047,7 +1045,7 @@ state::get_parent_with_const_child (value_bit *root, bit_expression *&parent, node_to_parent.put (as_a<bit_expression *> (left), cur_element); } - if (right != nullptr && is_a<bit_xor_expression *> (left)) + if (right != nullptr && is_a<bit_xor_expression *> (right)) { nodes_to_consider.add (as_a<bit_expression *> (right)); node_to_parent.put (as_a<bit_expression *> (right), cur_element); @@ -1080,18 +1078,10 @@ state::shift_left_by_const (const value *number, size_t shift_value) /* Shift_right operation. Case: var2 is a symbolic value. */ -void -state::shift_right_sym_values (value *arg1, value *arg2, tree dest) +value_bit * +state::shift_right_sym_bits (value_bit *var1, value_bit *var2) { - for (size_t i = 0; i < get_var_size (dest); i++) - { - value_bit *var1_bit = (*arg1)[i]; - value_bit *var2_bit = (*arg2)[i]; - value_bit *new_bit = new shift_right_expression (var1_bit->copy (), - var2_bit->copy ()); - delete (*var_states.get (dest))[i]; - (*var_states.get (dest))[i] = new_bit; - } + return new shift_right_expression (var1->copy (), var2->copy ()); } @@ -1104,7 +1094,7 @@ state::add_numbers (value *var1, const value *var2) for (unsigned i = 0; i < var1->length (); i++) { value_bit *temp = (*var1)[i]; - (*var1)[i] = full_adder ((*var1)[i], (*var2)[i], carry); + (*var1)[i] = full_adder ((*var1)[i], (*var2)[i], &carry); delete temp; } delete carry; @@ -1952,13 +1942,6 @@ state::print_value (value *var) } -size_t min (size_t a, size_t b, size_t c) -{ - size_t min = (a < b ? a : b); - return min < c ? min : c; -} - - /* Casts arg to cast_size size, stores value in dest. */ bool diff --git a/gcc/sym-exec/state.h b/gcc/sym-exec/state.h index 67913e9f934..e83b47806be 100644 --- a/gcc/sym-exec/state.h +++ b/gcc/sym-exec/state.h @@ -30,7 +30,9 @@ struct value { class state { typedef void (state::*binary_func) (value *arg1, value *arg2, tree dest); - + typedef value_bit *(*bit_func) (value_bit *bit1, value_bit *bit2); + typedef value_bit *(*bit_func3) (value_bit *var1, value_bit *var2, + value_bit **var3); typedef void (state::*binary_cond_func) (value *arg1, value *arg2); private: @@ -87,6 +89,16 @@ class state { /* Constructs expression trees of equal condition for given values. */ bit_expression *construct_equal_cond (value *arg1, value *arg2); + static value_bit *operate_bits (bit_func bit_op, value_bit *bit1, + value_bit *bit2, value_bit **bit3); + + static value_bit *operate_bits (bit_func3 bit_op, value_bit *bit1, + value_bit *bit2, value_bit **bit3); + + template<class func> + void operate (value *arg1, value *arg2, value_bit **bit_arg, tree dest, + func bit_op); + /* Does preprocessing and postprocessing for expressions with tree operands. Handles value creation for constant and their removement in the end. */ bool do_binary_operation (tree arg1, tree arg2, tree dest, @@ -166,10 +178,10 @@ class state { const bit *const_bit); /* Shift_right operation. Case: var2 is a symbolic value. */ - void shift_right_sym_values (value *arg1, value *arg2, tree dest); + static value_bit *shift_right_sym_bits (value_bit *var1, value_bit *var2); /* Shift_left operation. Case: var2 is a symbolic value. */ - void shift_left_sym_values (value *arg1, value *arg2, tree dest); + static value_bit *shift_left_sym_bits (value_bit *var1, value_bit *var2); /* Shifts var right by size of shift_value. */ value *shift_right_by_const (value *var, size_t shift_value); @@ -194,7 +206,8 @@ class state { /* Adds two bits and carry value. Resturn result and stores new carry bit in "carry". */ - value_bit *full_adder (value_bit *var1, value_bit *var2, value_bit *&carry); + static value_bit *full_adder (value_bit *var1, value_bit *var2, + value_bit **carry); /* Returns the additive inverse of the given number. */ value *additive_inverse (const value *number); @@ -215,7 +228,7 @@ class state { const value &polynomial); public: - state (); + state () = default; ~state (); @@ -330,4 +343,54 @@ class state { static value *create_lfsr (tree crc, value *polynomial, bool is_bit_forward); }; + +size_t min (size_t a, size_t b, size_t c); + + +template<class func> +void +state::operate (value *arg1, value *arg2, value_bit **bit_arg, tree dest, + func bit_op) +{ + value *dest_var = var_states.get (dest); + size_t min_iter = min (arg1->length (), arg2->length (), dest_var->length ()); + + size_t i = 0; + for (; i < min_iter; i++) + { + value_bit *temp = (*var_states.get (dest))[i]; + (*var_states.get (dest))[i] = operate_bits (bit_op, (*arg1)[i], + (*arg2)[i], bit_arg); + delete temp; + } + + if (i >= dest_var->length ()) + return; + + value *biggest = arg1; + if (arg2->length () > arg1->length ()) + biggest = arg2; + + min_iter = min (biggest->length (), dest_var->length (), dest_var->length ()); + value_bit *zero_bit = new bit (0); + for (; i < min_iter; i++) + { + value_bit *temp = (*var_states.get (dest))[i]; + (*var_states.get (dest))[i] = operate_bits (bit_op, (*biggest)[i], + zero_bit, bit_arg); + delete temp; + } + + if (i >= dest_var->length ()) + return; + + for (; i < dest_var->length (); i++) + { + value_bit *temp = (*var_states.get (dest))[i]; + (*var_states.get (dest))[i] = operate_bits (bit_op, zero_bit, zero_bit, + bit_arg); + delete temp; + } +} + #endif /* SYM_EXEC_STATE_H. */ |