8 namespace ConstantPropagation
17 BooleanFunction And(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
19 std::vector<BooleanFunction::Value> simplified;
20 simplified.reserve(p0.size());
21 for (
auto i = 0u; i < p0.size(); i++)
23 if ((p0[i] == 0) || (p1[i] == 0))
25 simplified.emplace_back(BooleanFunction::Value::ZERO);
27 else if ((p0[i] == 1) && (p1[i] == 1))
29 simplified.emplace_back(BooleanFunction::Value::ONE);
33 simplified.emplace_back(BooleanFunction::Value::X);
46 BooleanFunction Or(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
48 std::vector<BooleanFunction::Value> simplified;
49 simplified.reserve(p0.size());
50 for (
auto i = 0u; i < p0.size(); i++)
52 if ((p0[i] == 0) && (p1[i] == 0))
54 simplified.emplace_back(BooleanFunction::Value::ZERO);
56 else if ((p0[i] == 1) || (p1[i] == 1))
58 simplified.emplace_back(BooleanFunction::Value::ONE);
62 simplified.emplace_back(BooleanFunction::Value::X);
76 std::vector<BooleanFunction::Value> simplified;
77 simplified.reserve(p.size());
78 for (
const auto& value : p)
80 if (value == BooleanFunction::Value::ZERO)
82 simplified.emplace_back(BooleanFunction::Value::ONE);
84 else if (value == BooleanFunction::Value::ONE)
86 simplified.emplace_back(BooleanFunction::Value::ZERO);
90 simplified.emplace_back(value);
103 BooleanFunction Xor(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
105 std::vector<BooleanFunction::Value> simplified;
106 simplified.reserve(p0.size());
107 for (
auto i = 0u; i < p0.size(); i++)
109 if (((p0[i] == 0) && (p1[i] == 1)) || ((p0[i] == 1) && (p1[i] == 0)))
111 simplified.emplace_back(BooleanFunction::Value::ONE);
113 else if (((p0[i] == 0) && (p1[i] == 0)) || ((p0[i] == 1) && (p1[i] == 1)))
115 simplified.emplace_back(BooleanFunction::Value::ZERO);
119 simplified.emplace_back(BooleanFunction::Value::X);
132 BooleanFunction Add(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
134 if (p0.size() <= 64 && p1.size() <= 64)
139 if (a_res.is_ok() && b_res.is_ok())
141 const auto res = (a_res.get() + b_res.get()) & 0xffffffff;
148 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
149 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
154 std::vector<BooleanFunction::Value> simplified;
155 simplified.reserve(p0.size());
156 auto carry = BooleanFunction::Value::ZERO;
157 for (
auto i = 0u; i < p0.size(); i++)
159 auto res = p0[i] + p1[i] +
carry;
173 BooleanFunction Sub(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
175 if (p0.size() <= 64 && p1.size() <= 64)
180 if (a_res.is_ok() && b_res.is_ok())
182 const auto res = (a_res.get() - b_res.get()) & 0xffffffff;
189 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
190 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
195 std::vector<BooleanFunction::Value> simplified;
196 simplified.reserve(p0.size());
197 auto carry = BooleanFunction::Value::ONE;
198 for (
auto i = 0u; i < p0.size(); i++)
200 auto res = p0[i] + !(p1[i]) +
carry;
214 BooleanFunction Mul(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
216 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
217 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
222 auto bitsize = p0.size();
223 std::vector<BooleanFunction::Value> simplified(bitsize, BooleanFunction::Value::ZERO);
224 for (
auto i = 0u; i < bitsize; i++)
226 auto carry = BooleanFunction::Value::ZERO;
227 for (
auto j = 0u; j < bitsize - i; j++)
229 auto res = simplified[i + j] + (p0[i] & p1[j]) +
carry;
249 return BooleanFunction::Const(std::vector<BooleanFunction::Value>(p0.size(), BooleanFunction::Value::ZERO));
252 std::vector<BooleanFunction::Value> result(p0.size(), BooleanFunction::Value::ZERO);
255 for (
auto i = p1; i < p0.size(); i++)
257 result[i] = p0[i - p1];
275 return BooleanFunction::Const(std::vector<BooleanFunction::Value>(p0.size(), BooleanFunction::Value::ZERO));
278 std::vector<BooleanFunction::Value> result(p0.size(), BooleanFunction::Value::ZERO);
281 for (
auto i = 0u; i < p0.size() - p1; i++)
283 result[i] = p0[i + p1];
298 auto sign_bit = p0.back();
306 std::vector<BooleanFunction::Value> result(p0.size(), sign_bit);
309 for (
auto i = 0u; i < p0.size() - p1; i++)
311 result[i] = p0[i + p1];
326 auto rotate_amount = p1 % p0.
size();
328 if (rotate_amount == 0)
333 std::vector<BooleanFunction::Value> result(p0.size());
336 for (
auto i = 0u; i < p0.size(); i++)
338 auto new_pos = (i + rotate_amount) % p0.size();
339 result[new_pos] = p0[i];
354 auto rotate_amount = p1 % p0.
size();
356 if (rotate_amount == 0)
361 std::vector<BooleanFunction::Value> result(p0.size());
364 for (
auto i = 0u; i < p0.size(); i++)
366 auto new_pos = (i + p0.size() - rotate_amount) % p0.size();
367 result[new_pos] = p0[i];
379 BooleanFunction Sle(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
381 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
382 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
387 auto msb_p0 = p0.back();
388 auto msb_p1 = p1.back();
389 if (msb_p0 == BooleanFunction::Value::ONE && msb_p1 == BooleanFunction::Value::ZERO)
393 else if (msb_p0 == BooleanFunction::Value::ZERO && msb_p1 == BooleanFunction::Value::ONE)
398 std::vector<BooleanFunction::Value> simplified;
402 for (
auto i = 0u; i < p0.size(); i++)
404 res = p0[i] + !(p1[i]) +
carry;
419 BooleanFunction Slt(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
421 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
422 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
427 auto msb_p0 = p0.back();
428 auto msb_p1 = p1.back();
429 if (msb_p0 == BooleanFunction::Value::ONE && msb_p1 == BooleanFunction::Value::ZERO)
433 else if (msb_p0 == BooleanFunction::Value::ZERO && msb_p1 == BooleanFunction::Value::ONE)
438 std::vector<BooleanFunction::Value> simplified;
441 for (
auto i = 0u; i < p0.size(); i++)
443 res = p0[i] + !(p1[i]) +
carry;
444 carry = (res >> 1) & 1;
457 BooleanFunction Ule(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
459 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
460 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
465 for (
i32 i = p0.size() - 1; i >= 0; i--)
467 if (p0[i] == BooleanFunction::Value::ONE && p1[i] == BooleanFunction::Value::ZERO)
471 else if (p0[i] == BooleanFunction::Value::ZERO && p1[i] == BooleanFunction::Value::ONE)
486 BooleanFunction Ult(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
488 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
489 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
494 for (
i32 i = p0.size() - 1; i >= 0; i--)
496 if (p0[i] == BooleanFunction::Value::ONE && p1[i] == BooleanFunction::Value::ZERO)
500 else if (p0[i] == BooleanFunction::Value::ZERO && p1[i] == BooleanFunction::Value::ONE)
516 BooleanFunction Ite(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1,
const std::vector<BooleanFunction::Value>& p2)
518 if (p0.front() == BooleanFunction::Value::ONE)
522 else if (p0.front() == BooleanFunction::Value::ZERO)
554 std::vector<BooleanFunction> stack;
555 for (
const auto& node :
function.get_nodes())
557 std::vector<BooleanFunction> parameters;
558 std::move(stack.end() -
static_cast<i64>(node.get_arity()), stack.end(), std::back_inserter(parameters));
559 stack.erase(stack.end() -
static_cast<i64>(node.get_arity()), stack.end());
561 if (
auto simplified = this->simplify(node, std::move(parameters)); simplified.is_ok())
563 stack.emplace_back(simplified.get());
567 return ERR_APPEND(simplified.get_error(),
"could not evaluate Boolean function within symbolic state: simplification failed");
571 switch (stack.size())
574 return OK(stack.back());
576 return ERR(
"could not evaluate Boolean function within symbolic state: stack is imbalanced");
586 this->state.set(assignment->second.clone(), std::move(rhs));
591 return ERR_APPEND(res.get_error(),
"could not to evaluate assignment constraint within the symbolic state: evaluation failed");
600 const auto&
function = constraint.get_function().get();
601 auto node_type =
function->get_top_level_node().type;
605 return ERR(
"invalid node type in function '" + function->to_string() +
"'");
607 if (
auto res = this->evaluate(*
function); res.is_error())
609 return ERR_APPEND(res.get_error(),
"could not to evaluate function constraint within the symbolic state: evaluation failed");
618 std::vector<BooleanFunction> SymbolicExecution::normalize(std::vector<BooleanFunction>&& p)
625 std::sort(p.begin(), p.end(), [](
const auto& lhs,
const auto& rhs) {
626 if (lhs.get_top_level_node().type == rhs.get_top_level_node().type)
630 return rhs.is_constant();
640 bool is_x_not_y(
const BooleanFunction& x,
const BooleanFunction& y)
642 const BooleanFunction& smaller = (x.get_nodes().size() < y.get_nodes().size()) ? x : y;
643 const BooleanFunction& bigger = (x.get_nodes().size() < y.get_nodes().size()) ? y : x;
646 if (smaller.get_nodes().size() != (bigger.get_nodes().size() - 1))
658 for (
u32 idx = 0; idx < smaller.get_nodes().size(); idx++)
660 if (smaller.get_nodes().at(idx) != bigger.get_nodes().at(idx))
670 Result<BooleanFunction> SymbolicExecution::simplify(
const BooleanFunction::Node& node, std::vector<BooleanFunction>&& p)
const
672 if (!p.empty() && std::all_of(p.begin(), p.end(), [](
const auto&
function) { return function.is_constant() || function.is_index(); }))
674 if (
auto res = SymbolicExecution::constant_propagation(node, std::move(p)); res.is_error())
676 return ERR_APPEND(res.get_error(),
"could not simplify sub-expression in abstract syntax tree: constant propagation failed");
684 if (node.is_commutative())
686 p = SymbolicExecution::normalize(std::move(p));
697 case BooleanFunction::NodeType::Constant: {
698 return OK(BooleanFunction::Const(node.constant));
700 case BooleanFunction::NodeType::Index: {
701 return OK(BooleanFunction::Index(node.index, node.size));
703 case BooleanFunction::NodeType::Variable: {
704 return OK(this->
state.get(BooleanFunction::Var(node.variable, node.size)));
708 if (p[1].has_constant_value(0))
710 return OK(BooleanFunction::Const(0, node.size));
713 if (p[1] == One(node.size))
723 if (is_x_not_y(p[0], p[1]))
725 return OK(BooleanFunction::Const(0, node.size));
730 auto p0_parameter = p[0].get_parameters();
731 auto p1_parameter = p[1].get_parameters();
734 if (p0_parameter[0] == p1_parameter[0])
736 return OK(p0_parameter[0] | (p0_parameter[1] & p1_parameter[1]));
739 if (p0_parameter[0] == p1_parameter[1])
741 return OK(p0_parameter[0] | (p0_parameter[1] & p1_parameter[0]));
745 if (p0_parameter[1] == p1_parameter[0])
747 return OK(p0_parameter[1] | (p0_parameter[0] & p1_parameter[1]));
750 if (p0_parameter[1] == p1_parameter[1])
752 return OK(p0_parameter[1] | (p0_parameter[0] & p1_parameter[0]));
758 auto p1_parameter = p[1].get_parameters();
760 if (p[0] == p1_parameter[1])
765 if (p[0] == p1_parameter[0])
771 if (is_x_not_y(p1_parameter[0], p[0]))
773 return OK(BooleanFunction::Const(0, node.size));
776 if (is_x_not_y(p1_parameter[1], p[0]))
778 return OK(BooleanFunction::Const(0, node.size));
784 auto p1_parameter = p[1].get_parameters();
787 if (p1_parameter[0] == p[0])
792 if (p1_parameter[1] == p[0])
797 if (is_x_not_y(p1_parameter[0], p[0]))
802 if (is_x_not_y(p1_parameter[1], p[0]))
810 auto p0_parameter = p[0].get_parameters();
813 if (p0_parameter[0] == p[1])
819 if (p0_parameter[1] == p[1])
824 if (is_x_not_y(p0_parameter[0], p[1]))
826 return OK(BooleanFunction::Const(0, node.size));
829 if (is_x_not_y(p0_parameter[1], p[1]))
831 return OK(BooleanFunction::Const(0, node.size));
837 auto p0_parameter = p[0].get_parameters();
840 if (p0_parameter[0] == p[1])
845 if (p0_parameter[1] == p[1])
850 if (is_x_not_y(p0_parameter[0], p[1]))
855 if (is_x_not_y(p0_parameter[1], p[1]))
861 return OK(p[0] & p[1]);
867 return OK(p[0].get_parameters()[0]);
873 auto p0_parameter = p[0].get_parameters();
876 return BooleanFunction::Or(p0_parameter[0].get_parameters()[0].clone(), p0_parameter[1].get_parameters()[0].clone(), node.size);
883 auto p0_parameter = p[0].get_parameters();
886 return BooleanFunction::And(p0_parameter[0].get_parameters()[0].clone(), p0_parameter[1].get_parameters()[0].clone(), node.size);
893 auto p0_parameter = p[0].get_parameters();
894 return OK((~p0_parameter[0]) & (~p0_parameter[1]));
900 auto p0_parameter = p[0].get_parameters();
901 return OK((~p0_parameter[0]) | (~p0_parameter[1]));
909 if (p[1].has_constant_value(0))
915 if (p[1] == One(node.size))
927 if (is_x_not_y(p[0], p[1]))
929 return OK(One(node.size));
934 auto p0_parameter = p[0].get_parameters();
935 auto p1_parameter = p[1].get_parameters();
938 if (p0_parameter[0] == p1_parameter[0])
940 return OK(p0_parameter[0] & (p0_parameter[1] | p1_parameter[1]));
943 if (p0_parameter[0] == p1_parameter[1])
945 return OK(p0_parameter[0] & (p0_parameter[1] | p1_parameter[0]));
948 if (p0_parameter[1] == p1_parameter[0])
950 return OK(p0_parameter[1] & (p0_parameter[0] | p1_parameter[1]));
953 if (p0_parameter[1] == p1_parameter[1])
955 return OK(p0_parameter[1] & (p0_parameter[0] | p1_parameter[0]));
961 auto p1_parameter = p[1].get_parameters();
963 if (is_x_not_y(p1_parameter[1], p[0]))
969 if ((p1_parameter[0] == p[0]) || (p1_parameter[1] == p[0]))
975 if (is_x_not_y(p1_parameter[0], p[0]))
980 if (is_x_not_y(p1_parameter[1], p[0]))
988 auto p1_parameter = p[1].get_parameters();
991 if (p1_parameter[0] == p[0])
996 if (p1_parameter[1] == p[0])
1002 if (is_x_not_y(p1_parameter[0], p[0]))
1004 return OK(One(node.size));
1008 if (is_x_not_y(p1_parameter[1], p[0]))
1010 return OK(One(node.size));
1016 auto p0_parameter = p[0].get_parameters();
1019 if (p0_parameter[0] == p[1])
1024 if (p0_parameter[1] == p[1])
1030 if (is_x_not_y(p0_parameter[0], p[1]))
1032 return OK(One(node.size));
1036 if (is_x_not_y(p0_parameter[1], p[1]))
1038 return OK(One(node.size));
1044 auto p0_parameter = p[0].get_parameters();
1047 if (p0_parameter[0] == p[1])
1052 if (p0_parameter[1] == p[1])
1058 if (is_x_not_y(p0_parameter[0], p[1]))
1064 if (is_x_not_y(p0_parameter[1], p[1]))
1074 if (p[1].has_constant_value(0))
1079 if (p[1] == One(node.size))
1086 return OK(BooleanFunction::Const(0, node.size));
1089 if (is_x_not_y(p[0], p[1]))
1091 return OK(One(node.size));
1098 if (p[1].has_constant_value(0))
1107 if (p[1].has_constant_value(0))
1114 return OK(BooleanFunction::Const(0, node.size));
1121 if (p[1].has_constant_value(0))
1123 return OK(BooleanFunction::Const(0, node.size));
1126 if (p[1].has_constant_value(1))
1133 case BooleanFunction::NodeType::Sdiv: {
1135 if (p[1].has_constant_value(1))
1142 return OK(BooleanFunction::Const(1, node.size));
1145 return BooleanFunction::Sdiv(p[0].clone(), p[1].clone(), node.size);
1147 case BooleanFunction::NodeType::Udiv: {
1149 if (p[1].has_constant_value(1))
1156 return OK(BooleanFunction::Const(1, node.size));
1159 return BooleanFunction::Udiv(p[0].clone(), p[1].clone(), node.size);
1161 case BooleanFunction::NodeType::Srem: {
1163 if (p[1].has_constant_value(1))
1165 return OK(BooleanFunction::Const(0, node.size));
1170 return OK(BooleanFunction::Const(0, node.size));
1173 return BooleanFunction::Srem(p[0].clone(), p[1].clone(), node.size);
1175 case BooleanFunction::NodeType::Urem: {
1177 if (p[1].has_constant_value(1))
1179 return OK(BooleanFunction::Const(0, node.size));
1184 return OK(BooleanFunction::Const(0, node.size));
1187 return BooleanFunction::Urem(p[0].clone(), p[1].clone(), node.size);
1189 case BooleanFunction::NodeType::Slice: {
1197 if (node.size == p[0].size() && p[1].has_index_value(0) && p[2].has_index_value(node.size - 1))
1202 return BooleanFunction::Slice(p[0].clone(), p[1].clone(), p[2].clone(), node.size);
1204 case BooleanFunction::NodeType::Concat: {
1206 if (p[0].is_constant() && p[1].is_constant())
1208 if ((p[0].size() + p[1].size()) <= 64)
1210 return OK(BooleanFunction::Const((p[0].get_constant_value_u64().get() << p[1].size()) + p[1].get_constant_value_u64().get(), p[0].size() + p[1].size()));
1215 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Concat))
1217 auto p1_parameter = p[1].get_parameters();
1219 if (p1_parameter[0].is(BooleanFunction::NodeType::Slice))
1221 auto p0_parameter = p[0].get_parameters();
1222 auto p10_parameter = p1_parameter[0].get_parameters();
1224 if (p0_parameter[0] == p10_parameter[0])
1226 if (p1_parameter[1].is(BooleanFunction::NodeType::Slice))
1228 auto p11_parameter = p1_parameter[1].get_parameters();
1231 if (p11_parameter[0] != p10_parameter[0])
1233 if (
auto concatination = BooleanFunction::Concat(p[0].clone(), p1_parameter[0].clone(), p[0].size() + p1_parameter[0].size()); concatination.is_ok())
1235 return BooleanFunction::Concat(concatination.get(), p1_parameter[1].clone(), concatination.get().size() + p1_parameter[1].size());
1239 else if (p1_parameter[1].is(BooleanFunction::NodeType::Concat))
1241 auto p11_parameter = p1_parameter[1].get_parameters();
1243 if (p11_parameter[0].is(BooleanFunction::NodeType::Slice))
1245 auto p110_parameter = p11_parameter[0].get_parameters();
1248 if (p110_parameter[0] != p10_parameter[0])
1250 auto c1 = BooleanFunction::Concat(p[0].clone(), p1_parameter[0].clone(), p[0].size() + p1_parameter[0].size());
1252 return BooleanFunction::Concat(c1.get().clone(), p1_parameter[1].clone(), c1.get().size() + p1_parameter[1].size());
1259 if (
auto concatination = BooleanFunction::Concat(p[0].clone(), p1_parameter[0].clone(), p[0].size() + p1_parameter[0].size()); concatination.is_ok())
1261 return BooleanFunction::Concat(concatination.get(), p1_parameter[1].clone(), concatination.get().size() + p1_parameter[1].size());
1268 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Slice))
1270 auto p0_parameter = p[0].get_parameters();
1271 auto p1_parameter = p[1].get_parameters();
1273 if (p0_parameter[0] == p1_parameter[0])
1276 if ((p1_parameter[2].get_index_value().get() == (p0_parameter[1].get_index_value().get() - 1)))
1278 return BooleanFunction::Slice(p0_parameter[0].clone(), p1_parameter[1].clone(), p0_parameter[2].clone(), p[0].size() + p[1].size());
1282 if ((p1_parameter[2].get_index_value().get() == p0_parameter[1].get_index_value().get())
1283 && (p1_parameter[2].get_index_value().get() == p0_parameter[2].get_index_value().get()))
1285 return BooleanFunction::Sext(p[1].clone(), BooleanFunction::Index(p[1].size() + 1, p[1].size() + 1), p[1].size() + 1);
1291 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Sext))
1293 auto p1_parameter = p[1].get_parameters();
1295 if (p1_parameter[0].is(BooleanFunction::NodeType::Slice))
1297 auto p0_parameter = p[0].get_parameters();
1298 auto p10_parameter = p1_parameter[0].get_parameters();
1300 if ((p0_parameter[0] == p10_parameter[0]) && (p0_parameter[1] == p0_parameter[2]) && (p0_parameter[1].get_index_value().get() == p10_parameter[2].get_index_value().get()))
1302 return BooleanFunction::Sext(p1_parameter[0].clone(), BooleanFunction::Index(p[1].size() + 1, p[1].size() + 1), p[1].size() + 1);
1308 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Concat))
1310 auto p1_parameter = p[1].get_parameters();
1312 if (p1_parameter[0].is(BooleanFunction::NodeType::Sext))
1314 auto p10_parameter = p1_parameter[0].get_parameters();
1316 if (p10_parameter[0].is(BooleanFunction::NodeType::Slice))
1318 auto p0_parameter = p[0].get_parameters();
1319 auto p100_parameter = p10_parameter[0].get_parameters();
1321 if ((p0_parameter[0] == p100_parameter[0]) && (p0_parameter[1] == p0_parameter[2])
1322 && (p0_parameter[1].get_index_value().get() == p100_parameter[2].get_index_value().get()))
1324 if (
auto extension =
1325 BooleanFunction::Sext(p10_parameter[0].clone(), BooleanFunction::Index(p1_parameter[0].size() + 1, p1_parameter[0].size() + 1), p1_parameter[0].size() + 1);
1328 return BooleanFunction::Concat(extension.get(), p1_parameter[1].clone(), extension.get().size() + p1_parameter[1].size());
1335 return BooleanFunction::Concat(p[0].clone(), p[1].clone(), node.size);
1337 case BooleanFunction::NodeType::Zext: {
1338 return BooleanFunction::Zext(p[0].clone(), p[1].clone(), node.size);
1340 case BooleanFunction::NodeType::Sext: {
1341 return BooleanFunction::Sext(p[0].clone(), p[1].clone(), node.size);
1343 case BooleanFunction::NodeType::Eq: {
1347 return OK(BooleanFunction::Const(1, node.size));
1350 return BooleanFunction::Eq(p[0].clone(), p[1].clone(), node.size);
1356 return OK(BooleanFunction::Const(1, node.size));
1365 return OK(BooleanFunction::Const(0, node.size));
1374 return OK(BooleanFunction::Const(1, node.size));
1381 if (p[1].has_constant_value(0))
1383 return OK(BooleanFunction::Const(0, node.size));
1388 return OK(BooleanFunction::Const(0, node.size));
1395 if (p[0].has_constant_value(0))
1400 if (p[0].has_constant_value(1))
1413 return ERR(
"could not simplify sub-expression in abstract syntax tree: not implemented for given node type");
1417 Result<BooleanFunction> SymbolicExecution::constant_propagation(
const BooleanFunction::Node& node, std::vector<BooleanFunction>&& p)
1419 if (node.get_arity() != p.size())
1421 return ERR(
"could not propagate constants: arity does not match number of parameters");
1424 std::vector<std::vector<BooleanFunction::Value>> values;
1425 std::vector<u16> indices;
1427 for (
const auto& parameter : p)
1429 if (parameter.is_index())
1431 indices.push_back(parameter.get_index_value().get());
1435 const auto v = parameter.get_top_level_node().constant;
1436 values.emplace_back(v);
1458 case BooleanFunction::NodeType::Sdiv: {
1460 return ERR(
"could not propagate constants: not implemented for given node type");
1462 case BooleanFunction::NodeType::Udiv: {
1464 return ERR(
"could not propagate constants: not implemented for given node type");
1466 case BooleanFunction::NodeType::Srem: {
1468 return ERR(
"could not propagate constants: not implemented for given node type");
1470 case BooleanFunction::NodeType::Urem: {
1472 return ERR(
"could not propagate constants: not implemented for given node type");
1475 case BooleanFunction::NodeType::Concat: {
1476 values[1].insert(values[1].end(), values[0].begin(), values[0].end());
1477 return OK(BooleanFunction::Const(values[1]));
1479 case BooleanFunction::NodeType::Slice: {
1480 auto start = p[1].get_index_value().get();
1481 auto end = p[2].get_index_value().get();
1482 return OK(BooleanFunction::Const(std::vector<BooleanFunction::Value>(values[0].begin() + start, values[0].begin() + end + 1)));
1484 case BooleanFunction::NodeType::Zext: {
1485 values[0].resize(node.size, BooleanFunction::Value::ZERO);
1486 return OK(BooleanFunction::Const(values[0]));
1488 case BooleanFunction::NodeType::Sext: {
1489 values[0].resize(node.size,
static_cast<BooleanFunction::Value
>(values[0].back()));
1490 return OK(BooleanFunction::Const(values[0]));
1504 case BooleanFunction::NodeType::Eq:
1505 return OK((values[0] == values[1]) ? BooleanFunction::Const(1, 1) : BooleanFunction::Const(0, 1));
1518 return ERR(
"could not propagate constants: not implemented for given node type");
Value
represents the type of the node
static BooleanFunction Const(const BooleanFunction::Value &value)
static Result< u64 > to_u64(const std::vector< BooleanFunction::Value > &value)
SymbolicExecution(const std::vector< BooleanFunction > &variables={})
Result< BooleanFunction > evaluate(const BooleanFunction &function) const
#define ERR_APPEND(prev_error, message)
BooleanFunction Slt(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Or(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Not(const std::vector< BooleanFunction::Value > &p)
BooleanFunction Sle(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Ite(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1, const std::vector< BooleanFunction::Value > &p2)
BooleanFunction Ule(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Rol(const std::vector< BooleanFunction::Value > &p0, const u16 p1)
BooleanFunction Ult(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Shl(const std::vector< BooleanFunction::Value > &p0, const u16 p1)
BooleanFunction Mul(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Ror(const std::vector< BooleanFunction::Value > &p0, const u16 p1)
BooleanFunction Sub(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Add(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Ashr(const std::vector< BooleanFunction::Value > &p0, const u16 p1)
BooleanFunction Xor(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction And(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Lshr(const std::vector< BooleanFunction::Value > &p0, const u16 p1)
bool is_assignment() const
Result< const std::pair< BooleanFunction, BooleanFunction > * > get_assignment() const