summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatevos <matevosmehrabyan@gmail.com>2023-01-05 16:33:03 +0400
committerJeff Law <jlaw@ventanamicro>2023-03-21 09:03:20 -0600
commit5eff99fb3fbeab877740d75c2861983463618483 (patch)
tree437499660b98ec0f9402406063ecc3822a92781c
parentfa7e023c6394d03add3449adc5033a7eb3fa250e (diff)
downloadgcc-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.cc4
-rw-r--r--gcc/sym-exec/condition.cc4
-rw-r--r--gcc/sym-exec/condition.h2
-rw-r--r--gcc/sym-exec/expression.h5
-rw-r--r--gcc/sym-exec/state.cc139
-rw-r--r--gcc/sym-exec/state.h73
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. */