Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into FlashSheridan-CPR-1…
Browse files Browse the repository at this point in the history
…455-Standalone-timeout
  • Loading branch information
FlashSheridan committed Dec 23, 2023
2 parents 0eaa23f + 13266e9 commit 694a9f2
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 27 deletions.
22 changes: 22 additions & 0 deletions ir/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,8 @@ void Memory::mkAxioms(const Memory &tgt) const {
if (has_null_block)
state->addAxiom(Pointer::mkNullPointer(*this).getAddress(false) == 0);

const unsigned max_quadratic_disjoint = 75;

// Non-local blocks are disjoint.
auto zero = expr::mkUInt(0, bits_ptr_address);
auto one = expr::mkUInt(1, bits_ptr_address);
Expand Down Expand Up @@ -1341,6 +1343,9 @@ void Memory::mkAxioms(const Memory &tgt) const {
: addr.add_no_uoverflow(sz));
}

if (num_nonlocals > max_quadratic_disjoint)
continue;

// disjointness constraint
for (unsigned bid2 = bid + 1; bid2 < num_nonlocals; ++bid2) {
if (skip_bid(bid2))
Expand All @@ -1351,6 +1356,23 @@ void Memory::mkAxioms(const Memory &tgt) const {
p2.blockAlignment()));
}
}

// tame down quadratic explosion in disjointness constraint with a quantifier.
if (num_nonlocals > max_quadratic_disjoint) {
auto bid_ty = expr::mkUInt(0, Pointer::bitsShortBid());
expr bid1 = expr::mkFreshVar("#bid1", bid_ty);
expr bid2 = expr::mkFreshVar("#bid2", bid_ty);
expr offset = expr::mkUInt(0, bits_for_offset);
Pointer p1(*this, Pointer::mkLongBid(bid1, false), offset);
Pointer p2(*this, Pointer::mkLongBid(bid2, false), offset);
state->addAxiom(
expr::mkForAll({bid1, bid2},
bid1 == bid2 ||
disjoint(p1.getAddress(), p1.blockSize().zextOrTrunc(bits_ptr_address),
p1.blockAlignment(),
p2.getAddress(), p2.blockSize().zextOrTrunc(bits_ptr_address),
p2.blockAlignment())));
}
}

void Memory::resetGlobals() {
Expand Down
2 changes: 1 addition & 1 deletion llvm_util/cmd_args_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ config::src_unroll_cnt = opt_unrolling_factor;
config::disable_undef_input = opt_disable_undef;
config::disable_poison_input = opt_disable_poison;
config::tgt_is_asm = opt_tgt_is_asm;
config::check_if_src_is_ub = opt_check_if_src_is_ub;
config::fail_if_src_is_ub = opt_fail_if_src_is_ub;
config::symexec_print_each_value = opt_se_verbose;
smt::set_query_timeout(to_string(opt_smt_to));
smt::set_memory_limit((uint64_t)opt_smt_max_mem * 1024 * 1024);
Expand Down
6 changes: 3 additions & 3 deletions llvm_util/cmd_args_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ llvm::cl::opt<bool> opt_disable_poison(LLVM_ARGS_PREFIX "disable-poison-input",
llvm::cl::desc("Assume inputs are not poison (default=false)"),
llvm::cl::init(false), llvm::cl::cat(alive_cmdargs));

llvm::cl::opt<bool> opt_check_if_src_is_ub(
LLVM_ARGS_PREFIX "check-src-ub",
llvm::cl::desc("Check if source function is always UB (default=false)"),
llvm::cl::opt<bool> opt_fail_if_src_is_ub(
LLVM_ARGS_PREFIX "fail-src-ub",
llvm::cl::desc("Fail if source function is always UB (default=false)"),
llvm::cl::init(false), llvm::cl::cat(alive_cmdargs));

llvm::cl::opt<bool> opt_tgt_is_asm(
Expand Down
3 changes: 3 additions & 0 deletions llvm_util/compare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ bool Verifier::compareFunctions(llvm::Function &F1, llvm::Function &F2) {
r.t.tgt.writeDot("tgt");
}

if (r.errs.hasWarnings())
r.errs.printWarnings(out);

switch (r.status) {
case Results::ERROR:
UNREACHABLE();
Expand Down
1 change: 1 addition & 0 deletions smt/ctx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void context::init() {
Z3_global_param_set("model.partial", "true");
Z3_global_param_set("smt.ematching", "false");
Z3_global_param_set("smt.mbqi.max_iterations", "1000000");
Z3_global_param_set("smtlib2_compliant", "true");
Z3_global_param_set("smt.random_seed", get_random_seed());
Z3_global_param_set("timeout", get_query_timeout());
Z3_global_param_set("memory_high_watermark", "2147483648"); // 2 GBs
Expand Down
2 changes: 1 addition & 1 deletion tools/alive-tv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ and "tgt5" will unused.
if (F1.isDeclaration())
continue;
auto SrcFName = F1.getName();
if (!SrcFName.startswith(opt_src_fn))
if (!SrcFName.starts_with(opt_src_fn))
continue;

// Check src{+d}/tgt{+d} variant
Expand Down
4 changes: 3 additions & 1 deletion tools/alive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ int main(int argc, char **argv) {
bool correct = true;
for (; types; ++types) {
tv.fixupTypes(types);
if (auto errs = tv.verify()) {
auto errs = tv.verify();
errs.printWarnings(cerr);
if (errs) {
cerr << errs;
correct = false;
break;
Expand Down
14 changes: 10 additions & 4 deletions tools/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,10 +502,16 @@ check_refinement(Errors &errs, const Transform &t, State &src_state,
axioms_expr = std::move(axioms)();
}

if (config::check_if_src_is_ub &&
check_expr(axioms_expr && fndom_a).isUnsat()) {
errs.add("Source function is always UB", false);
return;
if (check_expr(axioms_expr && fndom_a).isUnsat()) {
if (config::fail_if_src_is_ub) {
errs.add("Source function is always UB", false);
return;
} else {
errs.addWarning(
"Source function is always UB.\n"
"It can be refined by any target function.\n"
"Please make sure this is what you wanted.");
}
}

{
Expand Down
36 changes: 21 additions & 15 deletions tv/tv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,22 +324,28 @@ struct TVLegacyPass final : public llvm::ModulePass {
assert(types.hasSingleTyping());
}

if (Errors errs = verifier.verify()) {
*out << "Transformation doesn't verify!" <<
(errs.isUnsound() ? " (unsound)\n" : " (not unsound)\n")
<< errs;
if (errs.isUnsound()) {
has_failure = true;
*out << "\nPass: " << pass_name << '\n';
emitCommandLine(out);
if (!SavedBitcode.empty())
writeBitcode(report_filename);
*out << "\n";
{
Errors errs = verifier.verify();
if (errs.hasWarnings())
errs.printWarnings(*out);

if (errs) {
*out << "Transformation doesn't verify!" <<
(errs.isUnsound() ? " (unsound)\n" : " (not unsound)\n")
<< errs;
if (errs.isUnsound()) {
has_failure = true;
*out << "\nPass: " << pass_name << '\n';
emitCommandLine(out);
if (!SavedBitcode.empty())
writeBitcode(report_filename);
*out << "\n";
}
if (opt_error_fatal && has_failure)
finalize();
} else {
*out << "Transformation seems to be correct!\n\n";
}
if (opt_error_fatal && has_failure)
finalize();
} else {
*out << "Transformation seems to be correct!\n\n";
}

done:
Expand Down
2 changes: 1 addition & 1 deletion util/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ string smt_benchmark_dir;
bool disable_poison_input = false;
bool disable_undef_input = false;
bool tgt_is_asm = false;
bool check_if_src_is_ub = false;
bool fail_if_src_is_ub = false;
bool disallow_ub_exploitation = false;
bool debug = false;
unsigned src_unroll_cnt = 0;
Expand Down
2 changes: 1 addition & 1 deletion util/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extern bool disable_undef_input;

extern bool tgt_is_asm;

extern bool check_if_src_is_ub;
extern bool fail_if_src_is_ub;

/// This is a special mode to verify that LLVM's optimizations are not
/// exploiting UB. In particular, we disallow any UB related with arithmetic,
Expand Down
12 changes: 12 additions & 0 deletions util/errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ void Errors::add(AliveException &&e) {
add(std::move(e.msg), e.is_unsound);
}

void Errors::addWarning(const char *str) {
warnings.emplace(str);
}

bool Errors::isUnsound() const {
for (auto &[msg, unsound] : errs) {
if (unsound)
Expand All @@ -48,4 +52,12 @@ ostream& operator<<(ostream &os, const Errors &errs) {
return os;
}

void Errors::printWarnings(std::ostream &os) const {
for (auto &str : warnings) {
os << "\n****************************************\n"
"WARNING: " << str
<< "\n****************************************\n\n";
}
}

}
4 changes: 4 additions & 0 deletions util/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct AliveException {

class Errors {
std::set<std::pair<std::string, bool>> errs;
std::set<std::string> warnings;

public:
Errors() = default;
Expand All @@ -32,11 +33,14 @@ class Errors {
void add(const char *str, bool is_unsound);
void add(std::string &&str, bool is_unsound);
void add(AliveException &&e);
void addWarning(const char *str);

explicit operator bool() const { return !errs.empty(); }
bool isUnsound() const;
bool hasWarnings() const { return !warnings.empty(); }

friend std::ostream& operator<<(std::ostream &os, const Errors &e);
void printWarnings(std::ostream &os) const;
};

}

0 comments on commit 694a9f2

Please sign in to comment.