[gcc/devel/jlaw/crc] sym-exec v12: - Made expression to work with various argument sizes - Fixed bits creation for consta

Jeff Law law@gcc.gnu.org
Tue Mar 21 15:09:23 GMT 2023


https://gcc.gnu.org/g:5eff99fb3fbeab877740d75c2861983463618483

commit 5eff99fb3fbeab877740d75c2861983463618483
Author: matevos <matevosmehrabyan@gmail.com>
Date:   Thu Jan 5 16:33:03 2023 +0400

    sym-exec v12: - Made expression to work with various argument sizes - Fixed bits creation for constants - Some code refactored and fixed

Diff:
---
 gcc/crc_verification.cc   |   4 +-
 gcc/sym-exec/condition.cc |   4 +-
 gcc/sym-exec/condition.h  |   2 +-
 gcc/sym-exec/expression.h |   5 +-
 gcc/sym-exec/state.cc     | 139 ++++++++++++++++++++--------------------------
 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.  */


More information about the Gcc-cvs mailing list