#include "state.h"
#include "vec.h"
#include "hash-set.h"
-#include "expression.h"
+#include "condition.h"
+//#include "expression.h"
/* Checks whether state for variable with specified name already
exists or not. */
bool
-State::is_declared (tree *var)
+State::is_declared (tree var)
{
return var_states.get (var) != NULL;
}
/* Adds an empty state for the given variable. */
bool
-State::decl_var (tree *var, unsigned size)
+State::decl_var (tree var, unsigned size)
{
if (is_declared (var))
return false;
/* Returns size of the given variable. */
unsigned
-State::get_var_size (tree *var)
+State::get_var_size (tree var)
{
vec < value * > *content = var_states.get (var);
if (content == NULL)
represented as sequence of symbolic bits. */
bool
-State::make_symbolic (tree *var, unsigned size)
+State::make_symbolic (tree var, unsigned size)
{
if (is_declared (var))
return false;
/* Does bit-level AND operation for given variables. */
void
-State::do_and (tree* arg1, tree* arg2, tree* dest)
+State::do_and (tree arg1, tree arg2, tree dest)
{
gcc_assert (!(is_declared (arg1) || is_declared (arg2)
|| is_declared (dest)));
for (size_t i = 0; i < get_var_size (dest); i++)
{
value *result = nullptr;
- value *sym_bit1 = dyn_cast<symbolic_bit *> ((*var_states.get (arg1))[i]);
- if (sym_bit1 == nullptr)
- sym_bit1 = dyn_cast<bit_expression *> ((*var_states.get (arg1))[i]);
-
- value *sym_bit2 = dyn_cast<symbolic_bit *> ((*var_states.get (arg2))[i]);
- if (sym_bit2 == nullptr)
- sym_bit2 = dyn_cast<bit_expression *> ((*var_states.get (arg2))[i]);
-
- bit *const_bit1 = dyn_cast<bit *> ((*var_states.get (arg1))[i]);
- bit *const_bit2 = dyn_cast<bit *> ((*var_states.get (arg2))[i]);
-
- if (sym_bit1 && sym_bit2)
- result = and_sym_bits (sym_bit1, sym_bit2);
- else if (sym_bit1 && const_bit2)
- result = and_var_const (sym_bit1, const_bit2);
- else if (const_bit1 && sym_bit2)
- result = and_var_const (sym_bit2, const_bit1);
- else if (const_bit1 && const_bit2)
- result = and_const_bits (const_bit1, const_bit2);
+ value * arg1_bit = (*var_states.get (arg1))[i];
+ value * arg2_bit = (*var_states.get (arg2))[i];
+
+ if (is_a<bit *> (arg1_bit) && is_a<bit *> (arg2_bit))
+ result = and_const_bits (as_a<bit *> (arg1_bit), as_a<bit *> (arg2_bit));
+
+ else if (is_a<bit *> (arg1_bit) && (is_a<symbolic_bit *> (arg2_bit)
+ || (is_a<bit_expression *> (arg2_bit))))
+ result = and_var_const (arg2_bit, as_a<bit *> (arg1_bit));
+
+ else if ((is_a<symbolic_bit *> (arg1_bit)
+ || (is_a<bit_expression *> (arg1_bit))) && is_a<bit *> (arg2_bit))
+ result = and_var_const (arg1_bit, as_a<bit *> (arg2_bit));
+
else
- gcc_assert (true);
+ result = and_sym_bits (arg1_bit, arg2_bit);
delete (*var_states.get (dest))[i];
(*var_states.get (dest))[i] = result;
/* Does bit-level OR operation for given variables. */
void
-State::do_or (tree* arg1, tree* arg2, tree* dest)
+State::do_or (tree arg1, tree arg2, tree dest)
{
gcc_assert (!(is_declared (arg1) || is_declared (arg2)
|| is_declared (dest)));
for (size_t i = 0; i < get_var_size (dest); i++)
{
value *result = nullptr;
- value *sym_bit1 = dyn_cast<symbolic_bit *> ((*var_states.get (arg1))[i]);
- if (sym_bit1 == nullptr)
- sym_bit1 = dyn_cast<bit_expression *> ((*var_states.get (arg1))[i]);
-
- value *sym_bit2 = dyn_cast<symbolic_bit *> ((*var_states.get (arg2))[i]);
- if (sym_bit2 == nullptr)
- sym_bit2 = dyn_cast<bit_expression *> ((*var_states.get (arg2))[i]);
-
- bit *const_bit1 = dyn_cast<bit *> ((*var_states.get (arg1))[i]);
- bit *const_bit2 = dyn_cast<bit *> ((*var_states.get (arg2))[i]);
-
- if (sym_bit1 && sym_bit2)
- result = or_sym_bits (sym_bit1, sym_bit2);
- else if (sym_bit1 && const_bit2)
- result = or_var_const (sym_bit1, const_bit2);
- else if (const_bit1 && sym_bit2)
- result = or_var_const (sym_bit2, const_bit1);
- else if (const_bit1 && const_bit2)
- result = or_const_bits (const_bit1, const_bit2);
+ value * arg1_bit = (*var_states.get (arg1))[i];
+ value * arg2_bit = (*var_states.get (arg2))[i];
+
+ if (is_a<bit *> (arg1_bit) && is_a<bit *> (arg2_bit))
+ result = or_const_bits (as_a<bit *> (arg1_bit), as_a<bit *> (arg2_bit));
+
+ else if (is_a<bit *> (arg1_bit) && (is_a<symbolic_bit *> (arg2_bit)
+ || (is_a<bit_expression *> (arg2_bit))))
+ result = or_var_const (arg2_bit, as_a<bit *> (arg1_bit));
+
+ else if ((is_a<symbolic_bit *> (arg1_bit)
+ || (is_a<bit_expression *> (arg1_bit))) && is_a<bit *> (arg2_bit))
+ result = or_var_const (arg1_bit, as_a<bit *> (arg2_bit));
+
else
- gcc_assert (true);
+ result = or_sym_bits (arg1_bit, arg2_bit);
delete (*var_states.get (dest))[i];
(*var_states.get (dest))[i] = result;
/* Does bit-level XOR operation for given variables. */
void
-State::do_xor (tree *arg1, tree *arg2, tree *dest)
+State::do_xor (tree arg1, tree arg2, tree dest)
{
gcc_assert (!(is_declared (arg1) || is_declared (arg2)
|| is_declared (dest)));
for (size_t i = 0; i < get_var_size (dest); i++)
{
value *result = nullptr;
- value *sym_bit1 = dyn_cast<symbolic_bit *> ((*var_states.get (arg1))[i]);
- if (sym_bit1 == nullptr)
- sym_bit1 = dyn_cast<bit_expression *> ((*var_states.get (arg1))[i]);
-
- value *sym_bit2 = dyn_cast<symbolic_bit *> ((*var_states.get (arg2))[i]);
- if (sym_bit2 == nullptr)
- sym_bit2 = dyn_cast<bit_expression *> ((*var_states.get (arg2))[i]);
-
- bit *const_bit1 = dyn_cast<bit *> ((*var_states.get (arg1))[i]);
- bit *const_bit2 = dyn_cast<bit *> ((*var_states.get (arg2))[i]);
-
- if (sym_bit1 && sym_bit2)
- result = xor_sym_bits (sym_bit1, sym_bit2);
- else if (sym_bit1 && const_bit2)
- result = xor_var_const (sym_bit1, const_bit2);
- else if (const_bit1 && sym_bit2)
- result = xor_var_const (sym_bit2, const_bit1);
- else if (const_bit1 && const_bit2)
- result = xor_const_bits (const_bit1, const_bit2);
+ value * arg1_bit = (*var_states.get (arg1))[i];
+ value * arg2_bit = (*var_states.get (arg2))[i];
+
+ if (is_a<bit *> (arg1_bit) && is_a<bit *> (arg2_bit))
+ result = xor_const_bits (as_a<bit *> (arg1_bit), as_a<bit *> (arg2_bit));
+
+ else if (is_a<bit *> (arg1_bit) && (is_a<symbolic_bit *> (arg2_bit)
+ || (is_a<bit_expression *> (arg2_bit))))
+ result = xor_var_const (arg2_bit, as_a<bit *> (arg1_bit));
+
+ else if ((is_a<symbolic_bit *> (arg1_bit)
+ || (is_a<bit_expression *> (arg1_bit))) && is_a<bit *> (arg2_bit))
+ result = xor_var_const (arg1_bit, as_a<bit *> (arg2_bit));
+
else
- gcc_assert (true);
+ result = xor_sym_bits (arg1_bit, arg2_bit);
delete (*var_states.get (dest))[i];
(*var_states.get (dest))[i] = result;
}
-/* Shifts value_vector left by shift_value bits. */
+/* Shifts value_vector right by shift_value bits. */
vec <value *>
-State::shift_left_by_const (const vec < value * > * value_vector,
- size_t shift_value)
+State::shift_right_by_const (const vec <value *> * value_vector,
+ size_t shift_value)
{
vec <value *> shift_result;
shift_result.create (value_vector->length ());
}
-/* returns the value of the number represented as a bit vector. */
+/* Returns the value of the number represented as a bit vector. */
size_t
State::get_value (vec <value *> * bit_vector)
/* shift_left operation. Case: var2 is a sym_bit. */
void
-State::shift_left_sym_bits (tree * var1, tree * var2, tree * dest)
+State::shift_left_sym_bits (tree var1, tree var2, tree dest)
{
for (size_t i = 0; i < get_var_size (dest); i++)
{
}
-/* Does SHIFT_LEFT operation for given variables. */
+/* Does shift_left operation for given variables. */
void
-State::do_shift_left (tree * arg1, tree * arg2, tree * dest)
+State::do_shift_left (tree arg1, tree arg2, tree dest)
{
gcc_assert (!(is_declared (arg1) || is_declared (arg2)
|| is_declared (dest)));
}
-/* Does SHIFT_RIGHT operation for given variables. */
+/* Does shift_right operation for given variables. */
void
-State::do_shift_right (tree * arg1, tree * arg2, tree * dest)
+State::do_shift_right (tree arg1, tree arg2, tree dest)
{
gcc_assert (!(is_declared (arg1) || is_declared (arg2)
|| is_declared (dest)));
gcc_assert (get_var_size (arg1) == get_var_size (dest)
&& get_var_size (arg2) == get_var_size (dest));
+ /* TODO: Add support for signed var shift. */
if (is_bit_vector (var_states.get (arg2)))
{
size_t shift_value = get_value (var_states.get (arg2));
/* Adds two variables. */
void
-State::do_add (tree *arg1, tree *arg2, tree *dest)
+State::do_add (tree arg1, tree arg2, tree dest)
{
gcc_assert (!(is_declared (arg1) || is_declared (arg2)
|| is_declared (dest)));
/* Does subtraction. */
void
-State::do_sub (tree *arg1, tree *arg2, tree *dest)
+State::do_sub (tree arg1, tree arg2, tree dest)
{
gcc_assert (!(is_declared (arg1) || is_declared (arg2)
|| is_declared (dest)));
/* Negates given variable. */
void
-State::do_complement (tree *arg, tree *dest)
+State::do_complement (tree arg, tree dest)
{
gcc_assert (!(is_declared (arg) || is_declared (dest)));
gcc_assert (get_var_size (arg) == get_var_size (dest));
}
-/* performs NOT operation for constant bit. */
+/* Performs NOT operation for constant bit. */
bit *
State::complement_const_bit (const bit * const_bit) const
{
- return new bit (1u - const_bit->get_val ());
+ return new bit (1u ^ const_bit->get_val ());
}
-/* performs NOT operation for symbolic_bit. */
+/* Performs NOT operation for symbolic_bit. */
value *
State::complement_sym_bit (const value * var) const
}
-/* performs XOR operation for 2 symbolic_bit operands. */
+/* Performs XOR operation for 2 symbolic_bit operands. */
value *
State::xor_sym_bits (const value * var1, const value * var2) const
bit_expression * var1_node_with_const_child
= get_parent_with_const_child (var1_copy);
+ /* If both subtrees have constant bit nodes, we can merge them together. */
if (var1_node_with_const_child != nullptr)
{
+ /* If var1's const bit is in its left subtree. */
value * var1_left = var1_node_with_const_child->get_left ();
- if (var1_left != nullptr && dyn_cast<bit *> (var1_left) != nullptr)
+ if (var1_left != nullptr && is_a<bit *> (var1_left))
{
+ /* If var2's const bit is in its left subtree. */
value * var2_left = var2_node_with_const_child->get_left ();
- if (var2_left != nullptr && dyn_cast<bit *> (var2_left) != nullptr)
+ if (var2_left != nullptr && is_a<bit *> (var2_left))
{
- bit * new_left = xor_const_bits (dyn_cast<bit *> (var1_left),
- dyn_cast<bit *> (var2_left));
+ bit * new_left = xor_const_bits (as_a<bit *> (var1_left),
+ as_a<bit *> (var2_left));
delete var2_left;
var2_node_with_const_child->set_left (nullptr);
delete var1_left;
var1_node_with_const_child->set_left (new_left);
}
- else
+ else /* Var2's const bit is in its right subtree. */
{
value * var2_right = var2_node_with_const_child->get_right ();
- bit * new_left = xor_const_bits (dyn_cast<bit *> (var1_left),
- dyn_cast<bit *> (var2_right));
+ bit * new_left = xor_const_bits (as_a<bit *> (var1_left),
+ as_a<bit *> (var2_right));
delete var2_right;
var2_node_with_const_child->set_right (nullptr);
}
}
- else
+ else /* Var1's const bit is in its right subtree. */
{
value * var1_right = var1_node_with_const_child->get_right ();
value * var2_left = var2_node_with_const_child->get_left ();
- if (var2_left != nullptr && dyn_cast<bit *> (var2_left) != nullptr)
+ /* If var2's const bit is in its left subtree. */
+ if (var2_left != nullptr && is_a<bit *> (var2_left))
{
- bit * new_right = xor_const_bits (dyn_cast<bit *> (var1_left),
- dyn_cast<bit *> (var2_left));
+ bit * new_right = xor_const_bits (as_a<bit *> (var1_left),
+ as_a<bit *> (var2_left));
delete var2_left;
var2_node_with_const_child->set_left (nullptr);
delete var1_right;
var1_node_with_const_child->set_right (new_right);
}
- else
+ else /* Var2's const bit is in its right subtree. */
{
value * var2_right = var2_node_with_const_child->get_right ();
- bit * new_right = xor_const_bits (dyn_cast<bit *> (var1_right),
- dyn_cast<bit *> (var2_right));
+ bit * new_right = xor_const_bits (as_a<bit *> (var1_right),
+ as_a<bit *> (var2_right));
delete var2_right;
var2_node_with_const_child->set_right (nullptr);
}
-/* performs XOR operation for 2 constant bit operands. */
+/* Performs XOR operation for 2 constant bit operands. */
bit *
State::xor_const_bits (const bit * const_bit1, const bit * const_bit2) const
}
-/* performs XOR operation for a symbolic_bit and const_bit operands. */
+/* Performs XOR operation for a symbolic_bit and const_bit operands. */
value *
State::xor_var_const (const value * var, const bit * const_bit) const
if (node_with_const_child != nullptr)
{
value * left = node_with_const_child->get_left ();
- if (left != nullptr && dyn_cast<bit *> (left) != nullptr)
+ if (left != nullptr && is_a<bit *> (left))
{
- bit * new_left = xor_const_bits (dyn_cast<bit *> (left), const_bit);
+ bit * new_left = xor_const_bits (as_a<bit *> (left), const_bit);
delete left;
node_with_const_child->set_left (new_left);
}
else
{
value * right = node_with_const_child->get_right ();
- bit * new_right = xor_const_bits (dyn_cast<bit *> (right), const_bit);
+ bit * new_right = xor_const_bits (as_a<bit *> (right), const_bit);
delete right;
node_with_const_child->set_right (new_right);
}
bit_expression *
State::get_parent_with_const_child (value* root) const
{
- const bit_expression * expr = dyn_cast<const bit_expression *> (root);
- if (expr == nullptr)
+ if (! is_a<bit_expression *> (root))
return nullptr;
- bit_expression* expr_root = dyn_cast<bit_expression *> (expr->copy ());
+ bit_expression* expr_root = as_a<bit_expression *> (root->copy ());
hash_set<bit_expression *> nodes_to_consider;
nodes_to_consider.add (expr_root);
+ /* Traversing expression tree:
+ considering only comutative expression nodes. */
while (!nodes_to_consider.is_empty ())
{
bit_expression* cur_element = *nodes_to_consider.begin ();
value* left = cur_element->get_left ();
value* right = cur_element->get_right ();
- if ((left != nullptr && dyn_cast<bit *> (left) != nullptr)
- || (right != nullptr && dyn_cast<bit *> (right) != nullptr))
+ if ((left != nullptr && is_a<bit *> (left))
+ || (right != nullptr && is_a<bit *> (right)))
return cur_element;
if (left != nullptr && is_safe_branching (left))
- nodes_to_consider.add (dyn_cast<bit_expression *> (left));
+ nodes_to_consider.add (as_a<bit_expression *> (left));
if (right != nullptr && is_safe_branching (right))
- nodes_to_consider.add (dyn_cast<bit_expression *> (right));
+ nodes_to_consider.add (as_a<bit_expression *> (right));
}
+ return nullptr;
}
-/* Checks if node is AND, OR or XOR expression. */
+/* Checks if node is AND, OR or XOR expression as they are comutative. */
bool
State::is_safe_branching (value* node) const
{
- return dyn_cast<bit_and_expression *> (node) != nullptr
- || dyn_cast<bit_or_expression *> (node) != nullptr
- || dyn_cast<bit_xor_expression *> (node) != nullptr;
+ return is_a<bit_and_expression *> (node) || is_a<bit_or_expression *> (node)
+ || is_a<bit_xor_expression *> (node);
}
-/* Shifts value_vector right by shift_value bits. */
+/* Shifts value_vector left by shift_value bits. */
vec <value *>
-State::shift_right_by_const (const vec < value * > * value_vector,
- size_t shift_value)
+State::shift_left_by_const (const vec < value * > * value_vector,
+ size_t shift_value)
{
vec <value *> shift_result;
shift_result.create (value_vector->length ());
if (shift_result.length () <= shift_value)
for (size_t i = 0; i < shift_result.length (); i++)
- {
shift_result[i] = new bit (0);
- }
else
- {
- size_t i = 0;
- for ( ; i < shift_result.length () - shift_value; ++i)
- shift_result[i] = new bit (0);
+ {
+ size_t i = 0;
+ for ( ; i < shift_result.length () - shift_value; ++i)
+ shift_result[i] = new bit (0);
- for (size_t j = 0; i < shift_result.length (); ++i, ++j)
- shift_result[i] = ((*value_vector)[j])->copy ();
- }
+ for (size_t j = 0; i < shift_result.length (); ++i, ++j)
+ shift_result[i] = ((*value_vector)[j])->copy ();
+ }
return shift_result;
}
/* shift_right operation. Case: var2 is a sym_bit. */
void
-State::shift_right_sym_bits (tree * var1, tree * var2, tree * dest)
+State::shift_right_sym_bits (tree var1, tree var2, tree dest)
{
for (size_t i = 0; i < get_var_size (dest); i++)
+ {
+ value * var1_elem = (*var_states.get (var1))[i];
+ value * var2_elem = (*var_states.get (var2))[i];
+ value * new_elem = new shift_right_expression (var1_elem->copy (),
+ var2_elem->copy ());
+ delete (*var_states.get (dest))[i];
+ (*var_states.get (dest))[i] = new_elem;
+ }
+}
+
+
+bool
+State::check_const_bit_equality (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const
+{
+ for (size_t i = 1; i < arg1_bits->length (); i++)
+ if ((*arg1_bits)[i] != (*arg2_bits)[i])
+ return false;
+ return true;
+}
+
+
+void
+State::add_equal_cond (tree arg1, tree arg2)
+{
+ vec<value *> * arg1_bits = var_states.get (arg1);
+ vec<value *> * arg2_bits = var_states.get (arg1);
+
+ if (is_bit_vector (arg1_bits) && is_bit_vector (arg2_bits))
+ {
+ bool result = check_const_bit_equality (arg1_bits, arg2_bits);
+ conditions.add (new bit_condition (nullptr, nullptr,
+ result ? condition_type::IS_TRUE
+ : condition_type::IS_FALSE));
+ return;
+ }
+ else if (is_bit_vector (arg1_bits) && TREE_CODE (arg2) == INTEGER_CST
+ && (integer_onep (arg2) || integer_zerop (arg2)))
+ {
+ size_t i = 0;
+ if (integer_onep (arg2))
{
- value * var1_elem = (*var_states.get (var1))[i];
- value * var2_elem = (*var_states.get (var2))[i];
- value * new_elem = new shift_right_expression (var1_elem->copy (),
- var2_elem->copy ());
- delete (*var_states.get (dest))[i];
- (*var_states.get (dest))[i] = new_elem;
+ conditions.add (new bit_condition ((*arg1_bits)[0]->copy (), new bit (1),
+ condition_type::EQUAL));
+ i++;
}
+
+ for ( ; i < arg1_bits->length (); i++)
+ conditions.add (new bit_condition ((*arg1_bits)[i]->copy (), new bit (0),
+ condition_type::EQUAL));
+ }
+
+ for (size_t i = 0; i < arg1_bits->length (); i++)
+ {
+ conditions.add (new bit_condition ((*arg1_bits)[i]->copy (),
+ (*arg2_bits)[i]->copy (),
+ condition_type::EQUAL));
+ }
+}
+
+
+bool
+State::check_const_bit_are_not_equal (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const
+{
+ for (size_t i = 0; i < arg1_bits->length (); i++)
+ if ((*arg1_bits)[i] != (*arg2_bits)[i])
+ return true;
+ return false;
+}
+
+
+void
+State::add_not_equal_cond (tree arg1, tree arg2)
+{
+ vec<value *> * arg1_bits = var_states.get (arg1);
+ vec<value *> * arg2_bits = var_states.get (arg1);
+
+ if (is_bit_vector (arg1_bits) && is_bit_vector (arg2_bits))
+ {
+ bool result = check_const_bit_are_not_equal (arg1_bits, arg2_bits);
+ conditions.add (new bit_condition (nullptr, nullptr,
+ result ? condition_type::IS_TRUE
+ : condition_type::IS_FALSE));
+ return;
+ }
+
+ /* TODO: add condition when one of arguments is symbolic. */
+}
+
+
+bool
+State::check_const_bit_is_greater_than (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const
+{
+ for (int i = arg1_bits->length () - 1; i >= 0; i--)
+ {
+ if ((*arg1_bits)[i] > (*arg2_bits)[i])
+ return true;
+ else if ((*arg1_bits)[i] < (*arg2_bits)[i])
+ return false;
+ }
+ return false;
+}
+
+
+void
+State::add_greater_than_cond (tree arg1, tree arg2)
+{
+ vec<value *> * arg1_bits = var_states.get (arg1);
+ vec<value *> * arg2_bits = var_states.get (arg1);
+
+ if (is_bit_vector (arg1_bits) && is_bit_vector (arg2_bits))
+ {
+ bool result = check_const_bit_is_greater_than (arg1_bits, arg2_bits);
+ conditions.add (new bit_condition (nullptr, nullptr,
+ result ? condition_type::IS_TRUE
+ : condition_type::IS_FALSE));
+ return;
+ }
+
+ /* TODO: add condition when one of arguments is symbolic. */
+}
+
+
+bool
+State::check_const_bit_is_less_than (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const
+{
+ for (int i = arg1_bits->length () - 1; i >= 0; i--)
+ {
+ if ((*arg1_bits)[i] < (*arg2_bits)[i])
+ return true;
+ else if ((*arg1_bits)[i] > (*arg2_bits)[i])
+ return false;
+ }
+ return false;
+}
+
+
+void
+State::add_less_than_cond (tree arg1, tree arg2)
+{
+ vec<value *> * arg1_bits = var_states.get (arg1);
+ vec<value *> * arg2_bits = var_states.get (arg1);
+
+ if (is_bit_vector (arg1_bits) && is_bit_vector (arg2_bits))
+ {
+ bool result = check_const_bit_is_less_than (arg1_bits, arg2_bits);
+ conditions.add (new bit_condition (nullptr, nullptr,
+ result ? condition_type::IS_TRUE
+ : condition_type::IS_FALSE));
+ return;
+ }
+
+ /* TODO: add condition when one of arguments is symbolic. */
}
+
+
+void
+State::add_greater_or_equal_cond (tree arg1, tree arg2)
+{
+ vec<value *> * arg1_bits = var_states.get (arg1);
+ vec<value *> * arg2_bits = var_states.get (arg1);
+
+ if (is_bit_vector (arg1_bits) && is_bit_vector (arg2_bits))
+ {
+ bool is_greater_than = check_const_bit_is_greater_than (arg1_bits,
+ arg2_bits);
+ bool is_equal = check_const_bit_equality (arg1_bits, arg2_bits);
+ conditions.add (new bit_condition (nullptr, nullptr,
+ (is_greater_than | is_equal)
+ ? condition_type::IS_TRUE
+ : condition_type::IS_FALSE));
+ return;
+ }
+
+ /* TODO: add condition when one of arguments is symbolic. */
+}
+
+
+void
+State::add_less_or_equal_cond (tree arg1, tree arg2)
+{
+ vec<value *> * arg1_bits = var_states.get (arg1);
+ vec<value *> * arg2_bits = var_states.get (arg1);
+
+ if (is_bit_vector (arg1_bits) && is_bit_vector (arg2_bits))
+ {
+ bool is_less_than = check_const_bit_is_less_than (arg1_bits, arg2_bits);
+ bool is_equal = check_const_bit_equality (arg1_bits, arg2_bits);
+ conditions.add (new bit_condition (nullptr, nullptr,
+ (is_less_than | is_equal)
+ ? condition_type::IS_TRUE
+ : condition_type::IS_FALSE));
+ return;
+ }
+
+ /* TODO: add condition when one of arguments is symbolic. */
+}
+
+void
+State::add_bool_cond (tree arg)
+{
+ vec<value *> * arg_bits = var_states.get (arg);
+ condition_type result = condition_type::IS_FALSE;
+ if (is_bit_vector (arg_bits))
+ {
+ for (size_t i = 0; i < arg_bits->length (); i++)
+ if ((*arg_bits)[i] != 0)
+ {
+ result = condition_type::IS_TRUE;
+ break;
+ }
+ }
+ conditions.add (new bit_condition (nullptr, nullptr, result));
+
+ /* TODO: add condition when one of arguments is symbolic. */
+}
\ No newline at end of file
#ifndef SYM_EXEC_STATE_H
#define SYM_EXEC_STATE_H
-#include "expression.h"
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "is-a.h"
#include "vec.h"
#include "hash-map.h"
+#include "hash-set.h"
+#include "expression.h"
/* Stores states of variables' values on bit-level. */
class State {
private:
/* Here is stored values of bit of each variable. */
- hash_map<tree *, vec < value * >> var_states;
+ hash_map<tree, vec < value * >> var_states;
+
+ hash_set<bit_expression *> conditions;
/* Performs AND operation for 2 symbolic_bit operands. */
value *and_sym_bits (const value * var1, const value * var2) const;
/* Checks whether state for variable with specified name already
exists or not. */
- bool is_declared (tree *var);
+ bool is_declared (tree var);
public:
/* Adds an empty state for the given variable. */
- bool decl_var (tree *name, unsigned size);
+ bool decl_var (tree name, unsigned size);
/* Adds a variable with unknown value to state. Such variables are
represented as sequence of symbolic bits. */
- bool make_symbolic (tree *var, unsigned size);
+ bool make_symbolic (tree var, unsigned size);
/* Returns size of the given variable. */
- unsigned get_var_size (tree *var);
+ unsigned get_var_size (tree var);
/* Does bit-level XOR operation for given variables. */
- void do_xor (tree *arg1, tree *arg2, tree *dest);
+ void do_xor (tree arg1, tree arg2, tree dest);
/* Does bit-level AND operation for given variables. */
- void do_and (tree *arg1, tree *arg2, tree *dest);
+ void do_and (tree arg1, tree arg2, tree dest);
/* Does bit-level OR operation for given variables. */
- void do_or (tree *arg1, tree *arg2, tree *dest);
+ void do_or (tree arg1, tree arg2, tree dest);
/* Shifts value_vector left by shift_value bits. */
vec <value *> shift_left_by_const (const vec <value *> * value_vector,
/* Checks if all vector elements are const_bit_expressions. */
bool is_bit_vector (vec <value *> * value_vector);
- /* returns the value of the number represented as a bit vector. */
+ /* Returns the value of the number represented as a bit vector. */
size_t get_value (vec <value *> * bit_vector);
/* shift_left operation. Case: var2 is a sym_bit. */
- void shift_left_sym_bits (tree * var1, tree * var2, tree * dest);
+ void shift_left_sym_bits (tree var1, tree var2, tree dest);
- /* Does SHIFT_LEFT operation for given variables. */
- void do_shift_left (tree *arg1, tree *arg2, tree *dest);
+ /* Does shift_left operation for given variables. */
+ void do_shift_left (tree arg1, tree arg2, tree dest);
/* Shifts value_vector right by shift_value bits. */
vec <value *> shift_right_by_const (const vec <value *> * value_vector,
size_t shift_value);
/* shift_right operation. Case: var2 is a sym_bit. */
- void shift_right_sym_bits (tree * var1, tree * var2, tree * dest);
+ void shift_right_sym_bits (tree var1, tree var2, tree dest);
- /* Does SHIFT_RIGHT operation for given variables. */
- void do_shift_right (tree *arg1, tree *arg2, tree *dest);
+ /* Does shift_right operation for given variables. */
+ void do_shift_right (tree arg1, tree arg2, tree dest);
/* Adds two variables. */
- void do_add (tree *arg1, tree *arg2, tree *dest);
+ void do_add (tree arg1, tree arg2, tree dest);
/* Does subtraction. */
- void do_sub (tree *arg1, tree *arg2, tree *dest);
+ void do_sub (tree arg1, tree arg2, tree dest);
/* Negates given variable. */
- void do_complement (tree *arg, tree *dest);
+ void do_complement (tree arg, tree dest);
+
+ void add_equal_cond (tree arg1, tree arg2);
+
+ void add_not_equal_cond (tree arg1, tree arg2);
+
+ void add_greater_than_cond (tree arg1, tree arg2);
+
+ void add_less_than_cond (tree arg1, tree arg2);
+
+ void add_greater_or_equal_cond (tree arg1, tree arg2);
+
+ void add_less_or_equal_cond (tree arg1, tree arg2);
+
+ void add_bool_cond (tree arg);
+
+ bool check_const_bit_equality (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const;
+
+ bool check_const_bit_are_not_equal (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const;
+
+ bool check_const_bit_is_greater_than (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const;
+
+ bool check_const_bit_is_less_than (vec<value *> * arg1_bits,
+ vec<value *> * arg2_bits) const;
};
#endif /* SYM_EXEC_STATE_H. */