9 namespace ConstantPropagation
18 BooleanFunction And(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
20 std::vector<BooleanFunction::Value> simplified;
21 simplified.reserve(p0.size());
22 for (
auto i = 0u; i < p0.size(); i++)
24 if ((p0[i] == 0) || (p1[i] == 0))
26 simplified.emplace_back(BooleanFunction::Value::ZERO);
28 else if ((p0[i] == 1) && (p1[i] == 1))
30 simplified.emplace_back(BooleanFunction::Value::ONE);
34 simplified.emplace_back(BooleanFunction::Value::X);
47 BooleanFunction Or(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
49 std::vector<BooleanFunction::Value> simplified;
50 simplified.reserve(p0.size());
51 for (
auto i = 0u; i < p0.size(); i++)
53 if ((p0[i] == 0) && (p1[i] == 0))
55 simplified.emplace_back(BooleanFunction::Value::ZERO);
57 else if ((p0[i] == 1) || (p1[i] == 1))
59 simplified.emplace_back(BooleanFunction::Value::ONE);
63 simplified.emplace_back(BooleanFunction::Value::X);
77 std::vector<BooleanFunction::Value> simplified;
78 simplified.reserve(p.size());
79 for (
const auto& value : p)
81 if (value == BooleanFunction::Value::ZERO)
83 simplified.emplace_back(BooleanFunction::Value::ONE);
85 else if (value == BooleanFunction::Value::ONE)
87 simplified.emplace_back(BooleanFunction::Value::ZERO);
91 simplified.emplace_back(value);
104 BooleanFunction Xor(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
106 std::vector<BooleanFunction::Value> simplified;
107 simplified.reserve(p0.size());
108 for (
auto i = 0u; i < p0.size(); i++)
110 if (((p0[i] == 0) && (p1[i] == 1)) || ((p0[i] == 1) && (p1[i] == 0)))
112 simplified.emplace_back(BooleanFunction::Value::ONE);
114 else if (((p0[i] == 0) && (p1[i] == 0)) || ((p0[i] == 1) && (p1[i] == 1)))
116 simplified.emplace_back(BooleanFunction::Value::ZERO);
120 simplified.emplace_back(BooleanFunction::Value::X);
133 BooleanFunction Add(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
135 if (p0.size() <= 64 && p1.size() <= 64)
140 if (a_res.is_ok() && b_res.is_ok())
142 const auto res = (a_res.get() + b_res.get()) & 0xffffffff;
149 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
150 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
155 std::vector<BooleanFunction::Value> simplified;
156 simplified.reserve(p0.size());
157 auto carry = BooleanFunction::Value::ZERO;
158 for (
auto i = 0u; i < p0.size(); i++)
160 auto res = p0[i] + p1[i] +
carry;
174 BooleanFunction Sub(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
176 if (p0.size() <= 64 && p1.size() <= 64)
181 if (a_res.is_ok() && b_res.is_ok())
183 const auto res = (a_res.get() - b_res.get()) & 0xffffffff;
190 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
191 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
196 std::vector<BooleanFunction::Value> simplified;
197 simplified.reserve(p0.size());
198 auto carry = BooleanFunction::Value::ONE;
199 for (
auto i = 0u; i < p0.size(); i++)
201 auto res = p0[i] + !(p1[i]) +
carry;
215 BooleanFunction Mul(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
217 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
218 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
223 auto bitsize = p0.size();
224 std::vector<BooleanFunction::Value> simplified(bitsize, BooleanFunction::Value::ZERO);
225 for (
auto i = 0u; i < bitsize; i++)
227 auto carry = BooleanFunction::Value::ZERO;
228 for (
auto j = 0u; j < bitsize - i; j++)
230 auto res = simplified[i + j] + (p0[i] & p1[j]) +
carry;
245 BooleanFunction Sle(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
247 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
248 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
253 auto msb_p0 = p0.back();
254 auto msb_p1 = p1.back();
255 if (msb_p0 == BooleanFunction::Value::ONE && msb_p1 == BooleanFunction::Value::ZERO)
259 else if (msb_p0 == BooleanFunction::Value::ZERO && msb_p1 == BooleanFunction::Value::ONE)
264 std::vector<BooleanFunction::Value> simplified;
268 for (
auto i = 0u; i < p0.size(); i++)
270 res = p0[i] + !(p1[i]) +
carry;
285 BooleanFunction Slt(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
287 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
288 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
293 auto msb_p0 = p0.back();
294 auto msb_p1 = p1.back();
295 if (msb_p0 == BooleanFunction::Value::ONE && msb_p1 == BooleanFunction::Value::ZERO)
299 else if (msb_p0 == BooleanFunction::Value::ZERO && msb_p1 == BooleanFunction::Value::ONE)
304 std::vector<BooleanFunction::Value> simplified;
307 for (
auto i = 0u; i < p0.size(); i++)
309 res = p0[i] + !(p1[i]) +
carry;
310 carry = (res >> 1) & 1;
323 BooleanFunction Ule(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
325 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
326 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
331 for (
i32 i = p0.size() - 1; i >= 0; i--)
333 if (p0[i] == BooleanFunction::Value::ONE && p1[i] == BooleanFunction::Value::ZERO)
337 else if (p0[i] == BooleanFunction::Value::ZERO && p1[i] == BooleanFunction::Value::ONE)
352 BooleanFunction Ult(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1)
354 if (std::any_of(p0.begin(), p0.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; })
355 || std::any_of(p1.begin(), p1.end(), [](
auto val) { return val == BooleanFunction::Value::X || val == BooleanFunction::Value::Z; }))
360 for (
i32 i = p0.size() - 1; i >= 0; i--)
362 if (p0[i] == BooleanFunction::Value::ONE && p1[i] == BooleanFunction::Value::ZERO)
366 else if (p0[i] == BooleanFunction::Value::ZERO && p1[i] == BooleanFunction::Value::ONE)
382 BooleanFunction Ite(
const std::vector<BooleanFunction::Value>& p0,
const std::vector<BooleanFunction::Value>& p1,
const std::vector<BooleanFunction::Value>& p2)
384 if (p0.front() == BooleanFunction::Value::ONE)
388 else if (p0.front() == BooleanFunction::Value::ZERO)
420 std::vector<BooleanFunction> stack;
421 for (
const auto& node :
function.get_nodes())
423 std::vector<BooleanFunction> parameters;
424 std::move(stack.end() -
static_cast<i64>(node.get_arity()), stack.end(), std::back_inserter(parameters));
425 stack.erase(stack.end() -
static_cast<i64>(node.get_arity()), stack.end());
427 if (
auto simplified = this->simplify(node, std::move(parameters)); simplified.is_ok())
429 stack.emplace_back(simplified.get());
433 return ERR_APPEND(simplified.get_error(),
"could not evaluate Boolean function within symbolic state: simplification failed");
437 switch (stack.size())
440 return OK(stack.back());
442 return ERR(
"could not evaluate Boolean function within symbolic state: stack is imbalanced");
452 this->state.set(assignment->second.clone(), std::move(rhs));
457 return ERR_APPEND(res.get_error(),
"could not to evaluate assignment constraint within the symbolic state: evaluation failed");
466 const auto&
function = constraint.get_function().get();
467 auto node_type =
function->get_top_level_node().type;
471 return ERR(
"invalid node type in function '" + function->to_string() +
"'");
473 if (
auto res = this->evaluate(*
function); res.is_error())
475 return ERR_APPEND(res.get_error(),
"could not to evaluate function constraint within the symbolic state: evaluation failed");
484 std::vector<BooleanFunction> SymbolicExecution::normalize(std::vector<BooleanFunction>&& p)
491 std::sort(p.begin(), p.end(), [](
const auto& lhs,
const auto& rhs) {
492 if (lhs.get_top_level_node().type == rhs.get_top_level_node().type)
496 return rhs.is_constant();
506 bool is_x_not_y(
const BooleanFunction& x,
const BooleanFunction& y)
508 const BooleanFunction& smaller = (x.get_nodes().size() < y.get_nodes().size()) ? x : y;
509 const BooleanFunction& bigger = (x.get_nodes().size() < y.get_nodes().size()) ? y : x;
512 if (smaller.get_nodes().size() != (bigger.get_nodes().size() - 1))
524 for (
u32 idx = 0; idx < smaller.get_nodes().size(); idx++)
526 if (smaller.get_nodes().at(idx) != bigger.get_nodes().at(idx))
536 Result<BooleanFunction> SymbolicExecution::simplify(
const BooleanFunction::Node& node, std::vector<BooleanFunction>&& p)
const
538 if (!p.empty() && std::all_of(p.begin(), p.end(), [](
const auto&
function) { return function.is_constant() || function.is_index(); }))
540 if (
auto res = SymbolicExecution::constant_propagation(node, std::move(p)); res.is_error())
542 return ERR_APPEND(res.get_error(),
"could not simplify sub-expression in abstract syntax tree: constant propagation failed");
550 if (node.is_commutative())
552 p = SymbolicExecution::normalize(std::move(p));
563 case BooleanFunction::NodeType::Constant: {
564 return OK(BooleanFunction::Const(node.constant));
566 case BooleanFunction::NodeType::Index: {
567 return OK(BooleanFunction::Index(node.index, node.size));
569 case BooleanFunction::NodeType::Variable: {
570 return OK(this->
state.get(BooleanFunction::Var(node.variable, node.size)));
574 if (p[1].has_constant_value(0))
576 return OK(BooleanFunction::Const(0, node.size));
579 if (p[1] == One(node.size))
589 if (is_x_not_y(p[0], p[1]))
591 return OK(BooleanFunction::Const(0, node.size));
596 auto p0_parameter = p[0].get_parameters();
597 auto p1_parameter = p[1].get_parameters();
600 if (p0_parameter[0] == p1_parameter[0])
602 return OK(p0_parameter[0] | (p0_parameter[1] & p1_parameter[1]));
605 if (p0_parameter[0] == p1_parameter[1])
607 return OK(p0_parameter[0] | (p0_parameter[1] & p1_parameter[0]));
611 if (p0_parameter[1] == p1_parameter[0])
613 return OK(p0_parameter[1] | (p0_parameter[0] & p1_parameter[1]));
616 if (p0_parameter[1] == p1_parameter[1])
618 return OK(p0_parameter[1] | (p0_parameter[0] & p1_parameter[0]));
624 auto p1_parameter = p[1].get_parameters();
626 if (p[0] == p1_parameter[1])
631 if (p[0] == p1_parameter[0])
637 if (is_x_not_y(p1_parameter[0], p[0]))
639 return OK(BooleanFunction::Const(0, node.size));
642 if (is_x_not_y(p1_parameter[1], p[0]))
644 return OK(BooleanFunction::Const(0, node.size));
650 auto p1_parameter = p[1].get_parameters();
653 if (p1_parameter[0] == p[0])
658 if (p1_parameter[1] == p[0])
663 if (is_x_not_y(p1_parameter[0], p[0]))
668 if (is_x_not_y(p1_parameter[1], p[0]))
676 auto p0_parameter = p[0].get_parameters();
679 if (p0_parameter[0] == p[1])
685 if (p0_parameter[1] == p[1])
690 if (is_x_not_y(p0_parameter[0], p[1]))
692 return OK(BooleanFunction::Const(0, node.size));
695 if (is_x_not_y(p0_parameter[1], p[1]))
697 return OK(BooleanFunction::Const(0, node.size));
703 auto p0_parameter = p[0].get_parameters();
706 if (p0_parameter[0] == p[1])
711 if (p0_parameter[1] == p[1])
716 if (is_x_not_y(p0_parameter[0], p[1]))
721 if (is_x_not_y(p0_parameter[1], p[1]))
727 return OK(p[0] & p[1]);
733 return OK(p[0].get_parameters()[0]);
739 auto p0_parameter = p[0].get_parameters();
742 return BooleanFunction::Or(p0_parameter[0].get_parameters()[0].clone(), p0_parameter[1].get_parameters()[0].clone(), node.size);
749 auto p0_parameter = p[0].get_parameters();
752 return BooleanFunction::And(p0_parameter[0].get_parameters()[0].clone(), p0_parameter[1].get_parameters()[0].clone(), node.size);
759 auto p0_parameter = p[0].get_parameters();
760 return OK((~p0_parameter[0]) & (~p0_parameter[1]));
766 auto p0_parameter = p[0].get_parameters();
767 return OK((~p0_parameter[0]) | (~p0_parameter[1]));
775 if (p[1].has_constant_value(0))
781 if (p[1] == One(node.size))
793 if (is_x_not_y(p[0], p[1]))
795 return OK(One(node.size));
800 auto p0_parameter = p[0].get_parameters();
801 auto p1_parameter = p[1].get_parameters();
804 if (p0_parameter[0] == p1_parameter[0])
806 return OK(p0_parameter[0] & (p0_parameter[1] | p1_parameter[1]));
809 if (p0_parameter[0] == p1_parameter[1])
811 return OK(p0_parameter[0] & (p0_parameter[1] | p1_parameter[0]));
814 if (p0_parameter[1] == p1_parameter[0])
816 return OK(p0_parameter[1] & (p0_parameter[0] | p1_parameter[1]));
819 if (p0_parameter[1] == p1_parameter[1])
821 return OK(p0_parameter[1] & (p0_parameter[0] | p1_parameter[0]));
827 auto p1_parameter = p[1].get_parameters();
829 if (is_x_not_y(p1_parameter[1], p[0]))
835 if ((p1_parameter[0] == p[0]) || (p1_parameter[1] == p[0]))
841 if (is_x_not_y(p1_parameter[0], p[0]))
846 if (is_x_not_y(p1_parameter[1], p[0]))
854 auto p1_parameter = p[1].get_parameters();
857 if (p1_parameter[0] == p[0])
862 if (p1_parameter[1] == p[0])
868 if (is_x_not_y(p1_parameter[0], p[0]))
870 return OK(One(node.size));
874 if (is_x_not_y(p1_parameter[1], p[0]))
876 return OK(One(node.size));
882 auto p0_parameter = p[0].get_parameters();
885 if (p0_parameter[0] == p[1])
890 if (p0_parameter[1] == p[1])
896 if (is_x_not_y(p0_parameter[0], p[1]))
898 return OK(One(node.size));
902 if (is_x_not_y(p0_parameter[1], p[1]))
904 return OK(One(node.size));
910 auto p0_parameter = p[0].get_parameters();
913 if (p0_parameter[0] == p[1])
918 if (p0_parameter[1] == p[1])
924 if (is_x_not_y(p0_parameter[0], p[1]))
930 if (is_x_not_y(p0_parameter[1], p[1]))
940 if (p[1].has_constant_value(0))
945 if (p[1] == One(node.size))
952 return OK(BooleanFunction::Const(0, node.size));
955 if (is_x_not_y(p[0], p[1]))
957 return OK(One(node.size));
964 if (p[1].has_constant_value(0))
973 if (p[1].has_constant_value(0))
980 return OK(BooleanFunction::Const(0, node.size));
987 if (p[1].has_constant_value(0))
989 return OK(BooleanFunction::Const(0, node.size));
992 if (p[1].has_constant_value(1))
999 case BooleanFunction::NodeType::Sdiv: {
1001 if (p[1].has_constant_value(1))
1008 return OK(BooleanFunction::Const(1, node.size));
1011 return BooleanFunction::Sdiv(p[0].clone(), p[1].clone(), node.size);
1013 case BooleanFunction::NodeType::Udiv: {
1015 if (p[1].has_constant_value(1))
1022 return OK(BooleanFunction::Const(1, node.size));
1025 return BooleanFunction::Udiv(p[0].clone(), p[1].clone(), node.size);
1027 case BooleanFunction::NodeType::Srem: {
1029 if (p[1].has_constant_value(1))
1031 return OK(BooleanFunction::Const(0, node.size));
1036 return OK(BooleanFunction::Const(0, node.size));
1039 return BooleanFunction::Srem(p[0].clone(), p[1].clone(), node.size);
1041 case BooleanFunction::NodeType::Urem: {
1043 if (p[1].has_constant_value(1))
1045 return OK(BooleanFunction::Const(0, node.size));
1050 return OK(BooleanFunction::Const(0, node.size));
1053 return BooleanFunction::Urem(p[0].clone(), p[1].clone(), node.size);
1055 case BooleanFunction::NodeType::Slice: {
1063 if (node.size == p[0].size() && p[1].has_index_value(0) && p[2].has_index_value(node.size - 1))
1068 return BooleanFunction::Slice(p[0].clone(), p[1].clone(), p[2].clone(), node.size);
1070 case BooleanFunction::NodeType::Concat: {
1072 if (p[0].is_constant() && p[1].is_constant())
1074 if ((p[0].size() + p[1].size()) <= 64)
1076 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()));
1081 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Concat))
1083 auto p1_parameter = p[1].get_parameters();
1085 if (p1_parameter[0].is(BooleanFunction::NodeType::Slice))
1087 auto p0_parameter = p[0].get_parameters();
1088 auto p10_parameter = p1_parameter[0].get_parameters();
1090 if (p0_parameter[0] == p10_parameter[0])
1092 if (p1_parameter[1].is(BooleanFunction::NodeType::Slice))
1094 auto p11_parameter = p1_parameter[1].get_parameters();
1097 if (p11_parameter[0] != p10_parameter[0])
1099 if (
auto concatination = BooleanFunction::Concat(p[0].clone(), p1_parameter[0].clone(), p[0].size() + p1_parameter[0].size()); concatination.is_ok())
1101 return BooleanFunction::Concat(concatination.get(), p1_parameter[1].clone(), concatination.get().size() + p1_parameter[1].size());
1105 else if (p1_parameter[1].is(BooleanFunction::NodeType::Concat))
1107 auto p11_parameter = p1_parameter[1].get_parameters();
1109 if (p11_parameter[0].is(BooleanFunction::NodeType::Slice))
1111 auto p110_parameter = p11_parameter[0].get_parameters();
1114 if (p110_parameter[0] != p10_parameter[0])
1116 auto c1 = BooleanFunction::Concat(p[0].clone(), p1_parameter[0].clone(), p[0].size() + p1_parameter[0].size());
1118 return BooleanFunction::Concat(c1.get().clone(), p1_parameter[1].clone(), c1.get().size() + p1_parameter[1].size());
1125 if (
auto concatination = BooleanFunction::Concat(p[0].clone(), p1_parameter[0].clone(), p[0].size() + p1_parameter[0].size()); concatination.is_ok())
1127 return BooleanFunction::Concat(concatination.get(), p1_parameter[1].clone(), concatination.get().size() + p1_parameter[1].size());
1134 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Slice))
1136 auto p0_parameter = p[0].get_parameters();
1137 auto p1_parameter = p[1].get_parameters();
1139 if (p0_parameter[0] == p1_parameter[0])
1142 if ((p1_parameter[2].get_index_value().get() == (p0_parameter[1].get_index_value().get() - 1)))
1144 return BooleanFunction::Slice(p0_parameter[0].clone(), p1_parameter[1].clone(), p0_parameter[2].clone(), p[0].size() + p[1].size());
1148 if ((p1_parameter[2].get_index_value().get() == p0_parameter[1].get_index_value().get())
1149 && (p1_parameter[2].get_index_value().get() == p0_parameter[2].get_index_value().get()))
1151 return BooleanFunction::Sext(p[1].clone(), BooleanFunction::Index(p[1].size() + 1, p[1].size() + 1), p[1].size() + 1);
1157 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Sext))
1159 auto p1_parameter = p[1].get_parameters();
1161 if (p1_parameter[0].is(BooleanFunction::NodeType::Slice))
1163 auto p0_parameter = p[0].get_parameters();
1164 auto p10_parameter = p1_parameter[0].get_parameters();
1166 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()))
1168 return BooleanFunction::Sext(p1_parameter[0].clone(), BooleanFunction::Index(p[1].size() + 1, p[1].size() + 1), p[1].size() + 1);
1174 if (p[0].is(BooleanFunction::NodeType::Slice) && p[1].is(BooleanFunction::NodeType::Concat))
1176 auto p1_parameter = p[1].get_parameters();
1178 if (p1_parameter[0].is(BooleanFunction::NodeType::Sext))
1180 auto p10_parameter = p1_parameter[0].get_parameters();
1182 if (p10_parameter[0].is(BooleanFunction::NodeType::Slice))
1184 auto p0_parameter = p[0].get_parameters();
1185 auto p100_parameter = p10_parameter[0].get_parameters();
1187 if ((p0_parameter[0] == p100_parameter[0]) && (p0_parameter[1] == p0_parameter[2])
1188 && (p0_parameter[1].get_index_value().get() == p100_parameter[2].get_index_value().get()))
1190 if (
auto extension =
1191 BooleanFunction::Sext(p10_parameter[0].clone(), BooleanFunction::Index(p1_parameter[0].size() + 1, p1_parameter[0].size() + 1), p1_parameter[0].size() + 1);
1194 return BooleanFunction::Concat(extension.get(), p1_parameter[1].clone(), extension.get().size() + p1_parameter[1].size());
1201 return BooleanFunction::Concat(p[0].clone(), p[1].clone(), node.size);
1203 case BooleanFunction::NodeType::Zext: {
1204 return BooleanFunction::Zext(p[0].clone(), p[1].clone(), node.size);
1206 case BooleanFunction::NodeType::Sext: {
1207 return BooleanFunction::Sext(p[0].clone(), p[1].clone(), node.size);
1209 case BooleanFunction::NodeType::Eq: {
1213 return OK(BooleanFunction::Const(1, node.size));
1216 return BooleanFunction::Eq(p[0].clone(), p[1].clone(), node.size);
1222 return OK(BooleanFunction::Const(1, node.size));
1231 return OK(BooleanFunction::Const(0, node.size));
1240 return OK(BooleanFunction::Const(1, node.size));
1247 if (p[1].has_constant_value(0))
1249 return OK(BooleanFunction::Const(0, node.size));
1254 return OK(BooleanFunction::Const(0, node.size));
1261 if (p[0].has_constant_value(0))
1266 if (p[0].has_constant_value(1))
1279 return ERR(
"could not simplify sub-expression in abstract syntax tree: not implemented for given node type");
1283 Result<BooleanFunction> SymbolicExecution::constant_propagation(
const BooleanFunction::Node& node, std::vector<BooleanFunction>&& p)
1285 if (node.get_arity() != p.size())
1287 return ERR(
"could not propagate constants: arity does not match number of parameters");
1290 std::vector<std::vector<BooleanFunction::Value>> values;
1291 for (
const auto& parameter : p)
1293 values.emplace_back(parameter.get_top_level_node().constant);
1314 case BooleanFunction::NodeType::Slice: {
1315 auto start = p[1].get_index_value().get();
1316 auto end = p[2].get_index_value().get();
1317 return OK(BooleanFunction::Const(std::vector<BooleanFunction::Value>(values[0].begin() + start, values[0].begin() + end + 1)));
1319 case BooleanFunction::NodeType::Concat: {
1320 values[1].insert(values[1].end(), values[0].begin(), values[0].end());
1321 return OK(BooleanFunction::Const(values[1]));
1323 case BooleanFunction::NodeType::Zext: {
1324 values[0].resize(node.size, BooleanFunction::Value::ZERO);
1325 return OK(BooleanFunction::Const(values[0]));
1327 case BooleanFunction::NodeType::Sext: {
1328 values[0].resize(node.size,
static_cast<BooleanFunction::Value
>(values[0].back()));
1329 return OK(BooleanFunction::Const(values[0]));
1332 case BooleanFunction::NodeType::Eq:
1333 return OK((values[0] == values[1]) ? BooleanFunction::Const(1, 1) : BooleanFunction::Const(0, 1));
1345 case BooleanFunction::NodeType::Sdiv:
1347 case BooleanFunction::NodeType::Udiv:
1349 case BooleanFunction::NodeType::Srem:
1351 case BooleanFunction::NodeType::Urem:
1354 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 Ult(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Mul(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &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 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)
bool is_assignment() const
Result< const std::pair< BooleanFunction, BooleanFunction > * > get_assignment() const