#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)
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++)
if (content == NULL)
return 0;
- return content->length ();
+ return content->allocated ();
}
}
+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. */
/* 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);
}
{
/* 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);
}
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);
}
/* 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 ());
}
delete result;
}
else
- shift_left_sym_values (arg1, arg2, dest);
+ operate (arg1, arg2, nullptr, dest, &state::shift_left_sym_bits);
}
}
}
else
- shift_right_sym_values (arg1, arg2, dest);
+ operate (arg1, arg2, nullptr, dest, &state::shift_right_sym_bits);
}
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;
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;
}
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);
{
value *neg_arg2 = additive_inverse (arg2);
do_add (arg1, neg_arg2, dest);
-
free_val (neg_arg2);
delete neg_arg2;
}
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;
}
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);
/* 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 ());
}
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;
}
-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
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:
/* 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,
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);
/* 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);
const value &polynomial);
public:
- state ();
+ state () = default;
~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. */