2
@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&#39;s quantifier elimination is not super great. it&#39;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&#39;t know then. I&#39;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&#39;t know. in Souper that&#39;s what we did and it&#39;s really slow, but a superoptimizer is making lot more solver calls than you&#39;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&#39;t think there&#39;s any reason to bother with incremental solving, but I&#39;m not 100% on that.</p><p>loops are hard. we&#39;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&#39;s somewhat sparsely documented and I&#39;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&#39;ve never bothered to try that out. </p><p>emitting SMT-LIB adds an annoying level of indirection through strings, that&#39;s probably not the way I&#39;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&#39;s actually why I&#39;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&#39;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&#39;t put it off. it has a way of finding design flaws as well as implementation bugs, but once you&#39;ve heavily committed to a design it&#39;s hard to make big changes. </p><p>another thing is that if there&#39;s undefined behavior then you&#39;re checking refinement instead of equivalence, might as well deal with that right at the start!</p>