]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
sym-exec v12: - Made expression to work with various argument sizes - Fixed bits...
authormatevos <matevosmehrabyan@gmail.com>
Thu, 5 Jan 2023 12:33:03 +0000 (16:33 +0400)
committerJeff Law <jlaw@ventanamicro>
Tue, 21 Mar 2023 15:03:20 +0000 (09:03 -0600)
gcc/crc_verification.cc
gcc/sym-exec/condition.cc
gcc/sym-exec/condition.h
gcc/sym-exec/expression.h
gcc/sym-exec/state.cc
gcc/sym-exec/state.h

index c261a7510e0e75a9865f84b26fac13011f9cbdd3..eee3cb8f68afe9ca3065daa85c0a55310dcbe13a 100644 (file)
@@ -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;
        }
index 637cb763d36617751bda30baae0d01c3e7cf397d..eb4ecf908be182def83050af82289ebc6568d188 100644 (file)
@@ -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;
 }
index 0bcaf372a8c1bec0bbc1c25be329c22fa08078bc..85d5938009c66deb93bca9565251243475b8733d 100644 (file)
@@ -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;
 };
index 9fdbdad08f3e4d5373be24d479e782690b14fc39..d81e45983922ae8856b85b7458cacfbce11e1494 100644 (file)
@@ -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.  */
index f2aae1d619ff7dda31de44bc9d94d34d9b4424d2..8b0560a1d144cbe6e1692ed57a3df86ac79decd4 100644 (file)
@@ -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
index 67913e9f934ef85102beefd7c4b62561323bf462..e83b47806bea391ef0d25870709f36df9da85882 100644 (file)
@@ -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.  */