Whole-known-network
@regehr@mastodon.social @whitequark@mastodon.social @lenary@types.pl @unlambda@hachyderm.io As an alternative, although we also use CVC5/Z3 directly in our compiler verification efforts, I've always wanted to move towards using a verification IL like Why3 instead of directly using a SMT solver. Boogie used to be very popular, and I think it's being developed again, and I've always felt you could save time with a verification language.
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@whitequark" class="u-url mention">@<span>whitequark</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> anyway, undef in LLVM was tricky enough that it took Nuno multiple iterations to get it right. it makes the quantifier alternation fundamentally harder and then Z3's quantifier elimination is not super great. it's a problem for us.</p>
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@whitequark" class="u-url mention">@<span>whitequark</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> ah, I don't know then. I've not used the C bindings much, but Nuno preferred them over the C++ bindings for Alive2, despite the fact that Alive2 is in C++. I forgot the reason.</p><p>you could emit SMT-LIB. I don't know. in Souper that's what we did and it's really slow, but a superoptimizer is making lot more solver calls than you're looking at.</p>
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@whitequark" class="u-url mention">@<span>whitequark</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> I don't think there's any reason to bother with incremental solving, but I'm not 100% on that.</p><p>loops are hard. we've not yet confronted them for real in Alive2, unfortunately. instead we just unroll.</p>
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@regehr" class="u-url mention">@<span>regehr</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> Rust. there is a Z3 crate that is a fairly thin binding for the C API. it's somewhat sparsely documented and I'm currently staring at it and also Z3 docs in confusion</p>
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@whitequark" class="u-url mention">@<span>whitequark</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> if your compiler is in Python, the Z3 python bindings are super nice. also there are CVC5 bindings that supposedly are mostly compatible, but I've never bothered to try that out. </p><p>emitting SMT-LIB adds an annoying level of indirection through strings, that's probably not the way I'd go if your language has good Z3 bindings</p>
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@regehr" class="u-url mention">@<span>regehr</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> any advice on how to tightly integrate Z3? do i need to think about incremental solving? do you know anything about transforming loops, in which case i think i might have to use induction?</p>
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@regehr" class="u-url mention">@<span>regehr</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> that's actually why I'm thinking of it now--the compiler is 4 days old (... and already runs on par with state-of-the-art on a subset of workloads, interestingly) and barely has unit tests, i feel like we can do better than that</p><p>there is undef, with similar but not identical semantics to LLVM's, and refinement under different versions of the semantics is something software in the field often gets very wrong</p>
<p><span class="h-card" translate="no"><a href="https://mastodon.social/@whitequark" class="u-url mention">@<span>whitequark</span></a></span> <span class="h-card" translate="no"><a href="https://types.pl/@lenary" class="u-url mention">@<span>lenary</span></a></span> <span class="h-card" translate="no"><a href="https://hachyderm.io/@unlambda" class="u-url mention">@<span>unlambda</span></a></span> my next piece of advice is to do formal verification from the start, don't put it off. it has a way of finding design flaws as well as implementation bugs, but once you've heavily committed to a design it's hard to make big changes. </p><p>another thing is that if there's undefined behavior then you're checking refinement instead of equivalence, might as well deal with that right at the start!</p>