State: change precondition, axioms, return domain to dedicated and/or exprs
TODO: switch BB constraint as well
MODIFY
ir/state.cpp
ir/state.cpp
@@ -14,7 +14,7 @@ using namespace std;
namespace IR {
State::State(const Function &f, bool source)
- : f(f), source(source), memory(*this), return_domain(false),
+ : f(f), source(source), memory(*this),
return_val(f.getType().getDummyValue(false)), return_memory(memory) {}
void State::resetGlobals() {
@@ -152,7 +152,7 @@ void State::addCondJump(const StateValue &cond, const BasicBlock &dst_true,
void State::addReturn(const StateValue &val) {
return_val.add(val, domain.first);
return_memory.add(memory, domain.first);
- return_domain |= domain.first;
+ return_domain.add(move(domain.first));
return_undef_vars.insert(undef_vars.begin(), undef_vars.end());
return_undef_vars.insert(domain.second.begin(), domain.second.end());
undef_vars.clear();

MODIFY
ir/state.h
ir/state.h
@@ -33,8 +33,8 @@ private:
bool source;
bool disable_undef_rewrite = false;
bool is_initialization_phase = true;
- smt::expr precondition = true;
- smt::expr axioms = true;
+ smt::AndExpr precondition;
+ smt::AndExpr axioms;
const BasicBlock *current_bb;
std::set<smt::expr> quantified_vars;
@@ -61,7 +61,7 @@ private:
unsigned i_tmp_values = 0; // next available position in tmp_values
// return_domain: a boolean expression describing return condition
- smt::expr return_domain;
+ smt::OrExpr return_domain;
smt::DisjointExpr<StateValue> return_val;
smt::DisjointExpr<Memory> return_memory;
std::set<smt::expr> return_undef_vars;
@@ -85,8 +85,8 @@ public:
const BasicBlock &dst_false);
void addReturn(const StateValue &val);
- void addAxiom(smt::expr &&axiom) { axioms &= std::move(axiom); }
- void addPre(smt::expr &&cond) { precondition &= std::move(cond); }
+ void addAxiom(smt::expr &&axiom) { axioms.add(std::move(axiom)); }
+ void addPre(smt::expr &&cond) { precondition.add(std::move(cond)); }
void addUB(smt::expr &&ub);
void addUB(const smt::expr &ub);

MODIFY
smt/exprs.cpp
smt/exprs.cpp
@@ -8,6 +8,36 @@ using namespace std;
namespace smt {
+void AndExpr::add(expr &&e) {
+ exprs.insert(move(e));
+}
+
+void AndExpr::add(const AndExpr &other) {
+ exprs.insert(other.exprs.begin(), other.exprs.end());
+}
+
+expr AndExpr::operator()() const {
+ return expr::mk_and(exprs);
+}
+
+ostream &operator<<(ostream &os, const AndExpr &e) {
+ return os << e();
+}
+
+
+void OrExpr::add(expr &&e) {
+ exprs.insert(move(e));
+}
+
+expr OrExpr::operator()() const {
+ return expr::mk_or(exprs);
+}
+
+ostream &operator<<(ostream &os, const OrExpr &e) {
+ return os << e();
+}
+
+
void FunctionExpr::add(const expr &key, expr &&val) {
ENSURE(fn.emplace(key, move(val)).second);
}

MODIFY
smt/exprs.h
smt/exprs.h
#include "smt/expr.h"
#include <map>
+#include <ostream>
+#include <set>
#include <utility>
namespace smt {
+class AndExpr {
+ std::set<expr> exprs;
+
+public:
+ void add(expr &&e);
+ void add(const AndExpr &other);
+ expr operator()() const;
+ friend std::ostream &operator<<(std::ostream &os, const AndExpr &e);
+};
+
+
+class OrExpr {
+ std::set<expr> exprs;
+
+public:
+ void add(expr &&e);
+ expr operator()() const;
+ friend std::ostream &operator<<(std::ostream &os, const OrExpr &e);
+};
+
+
template <typename T>
class DisjointExpr {
std::map<T, expr> vals; // val -> domain

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -248,7 +248,8 @@ static void check_refinement(Errors &errs, Transform &t,
check_each_var);
};
- expr axioms = src_state.getAxioms() && tgt_state.getAxioms();
+ AndExpr axioms = src_state.getAxioms();
+ axioms.add(tgt_state.getAxioms());
// restrict type variable from taking disabled values
if (config::disable_undef_input || config::disable_poison_input) {
@@ -257,11 +258,11 @@ static void check_refinement(Errors &errs, Transform &t,
auto var = in->getTyVar();
if (config::disable_undef_input) {
if (config::disable_poison_input)
- axioms &= var == 0;
+ axioms.add(var == 0);
else
- axioms &= var != 1;
+ axioms.add(var != 1);
} else if (config::disable_poison_input)
- axioms &= var.extract(1, 1) == 0;
+ axioms.add(var.extract(1, 1) == 0);
}
}
}
@@ -271,15 +272,16 @@ static void check_refinement(Errors &errs, Transform &t,
// FIXME: broken handling of transformation precondition
//src_state.startParsingPre();
//expr pre = t.precondition ? t.precondition->toSMT(src_state) : true;
- expr pre_src = src_state.getPre();
- expr pre_tgt = tgt_state.getPre();
+ expr pre_src = src_state.getPre()();
+ expr pre_tgt = tgt_state.getPre()();
auto [poison_cnstr, value_cnstr] = type.refines(src_state, tgt_state, a, b);
expr memory_cnstr
= src_state.returnMemory().refined(tgt_state.returnMemory());
+ expr axioms_expr = axioms();
expr dom = dom_a && dom_b;
- if (check_expr(axioms && (pre_src && pre_tgt)).isUnsat()) {
+ if (check_expr(axioms_expr && (pre_src && pre_tgt)).isUnsat()) {
errs.add("Precondition is always false", false);
return;
}
@@ -294,7 +296,7 @@ static void check_refinement(Errors &errs, Transform &t,
if (refines.isFalse())
return move(refines);
- return axioms &&
+ return axioms_expr &&
preprocess(t, qvars, uvars, pre_tgt && pre_src.implies(refines));
};
@@ -512,8 +514,8 @@ Errors TransformVerify::verify() const {
}
check_refinement(errs, t, src_state, tgt_state, nullptr, t.src.getType(),
- src_state.returnDomain(), src_state.returnVal(),
- tgt_state.returnDomain(), tgt_state.returnVal(),
+ src_state.returnDomain()(), src_state.returnVal(),
+ tgt_state.returnDomain()(), tgt_state.returnVal(),
check_each_var);
return errs;

State: change precondition, axioms, return domain to dedicated and/or exprs
TODO: switch BB constraint as well