<div dir="ltr">On Mon, Nov 18, 2013 at 5:17 AM, Lukas Hellebrandt <span dir="ltr"><<a href="mailto:kamikazecz@gmail.com" target="_blank">kamikazecz@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">-----BEGIN PGP SIGNED MESSAGE-----<br>
Hash: SHA256<br>
<br>
</div>Hi, Richard,<br>
<br>
Thanks for confirming my thoughts! That's what I meant, make a set of<br>
rules using Clang and then check them by LLVM.<br>
<br>
As I said, I am relatively new to Clang and have never used LLVM<br>
before. So, what's the best way to do this? Do I make a Clang plugin?<br>
I can do that (I already did a part of the analyzer, however, without<br>
any alias analysis; and I never did any change to the AST). And if<br>
yes, how do I send some (meta)data to LLVM? The only way I can think<br>
of is to save them to a file. And then, do I run a LLVM pass? Just<br>
asking if I understood correctly. My problem is now more about using<br>
Clang together with LLVM (as you confirmed my approach was a good<br>
idea, thanks for that again!).</blockquote><div><br></div><div>To clarify, I'm suggesting that you teach Clang's IR generation to emit code to catch these bugs when the compiled program is run. That shouldn't require any alias analysis or similar at the point where you insert the checks (if you wanted to be a bit cleverer, you could emit metadata from Clang and use an LLVM pass to emit the checks, and avoid emitting checks for cases where alias analysis could prove they're unnecessary, but the optimizer should remove the redundant checks anyway, so such cleverness should hopefully be unnecessary).</div>
<div><br></div><div>We have deliberately avoided having any checks in Clang that operate by inspecting the IR post-optimization, since such checks tend to be very unstable across changes to the compiler, and that generates pain for users of the checks (a seemingly-unrelated change to the code could cause the optimizer to make a different decision and expose a problem, leading to an unexpected build break for a -Werror build).</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">
*****************************<br>
Lukas Hellebrandt<br>
<a href="mailto:kamikazecz@gmail.com">kamikazecz@gmail.com</a><br>
*****************************<br>
<br>
</div><div class="im">On 11/15/2013 09:46 PM, Richard Smith wrote:<br>
> On Fri, Nov 15, 2013 at 9:21 AM, Lukas Hellebrandt<br>
</div><div><div class="h5">> <<a href="mailto:kamikazecz@gmail.com">kamikazecz@gmail.com</a> <mailto:<a href="mailto:kamikazecz@gmail.com">kamikazecz@gmail.com</a>>> wrote:<br>
><br>
> Hi all,<br>
><br>
> I'm trying to write a tool for detecting undefined behavior in C<br>
> regarding sequence points and side effects.<br>
><br>
> I'm not sure whether it should be a Clang plugin or LLVM run or<br>
> something completely different (I'm really new to both Clang and<br>
> LLVM) and that's what I need advice with.<br>
><br>
> For my work, I need to use both AST and alias analysis<br>
><br>
> Clang plugin: +relatively easy to use +access to AST with all the<br>
> needed info EXCEPT alias analysis (right?) -no alias analysis, I'd<br>
> need to write one myself<br>
><br>
> LLVM run: +built-in alias analysis (I'd like to use it, writing my<br>
> own alias analysis is not really what my work is all about) -I do<br>
> NOT have access to AST -I don't know it at all (but I'm ready to<br>
> learn it if it shows up to be the best option)<br>
><br>
> The big PROBLEM is: a behavior that is undefined in C (and which<br>
> Clang has access to) might be (and in my case WILL be) well defined<br>
> in LLVM (for example, i=i++; is undefined in C but in LLVM code it<br>
> will be already well defined and the result will depend on Clang<br>
> behavior).<br>
><br>
> So I thought I could use both, in Clang create a list of rules,<br>
> for example "On line L, there is an undefined behavior if X aliases<br>
> with Y" and then SOMEHOW dig this info from LLVM run.<br>
><br>
> Is this a good idea? Is there a way (other than output to file<br>
> from Clang and then read it in LLVM) to give this set of rules to<br>
> LLVM? I'd also be glad for any other idea, not necessarily<br>
> including LLVM and Clang, to solve this problem.<br>
><br>
><br>
> I've thought about this a bit from the point of view of adding a<br>
> check to -fsanitize=undefined. We already detect cases where it's<br>
> "locally" obvious that the expression will have undefined behavior,<br>
> for instance, we'll warn on your example of "i = i++;".<br>
><br>
> From the ubsan perspective, I think the thing to do here is to form<br>
> a list of pairs of subexpressions within the full-expression where,<br>
> if the two subexpressions refer to the same object, we will have<br>
> unsequenced accesses (in the presence of ?:, &&, and ||, we'll need<br>
> to be careful to only check these if the relevant subexpression was<br>
> actually evaluated). Then, perhaps at the end of the<br>
> full-expression, we emit a check that no such pair evaluated to the<br>
> same address.<br>
><br>
> Building the set of pairs is a little tricky, but the code<br>
> implementing -Wunsequenced can probably be reused to form this<br>
> set.<br>
><br>
> That said, we have a representational weakness in LLVM here: we<br>
> have no way to express that the language semantics allow us to<br>
> freely reorder two memory operations. If we could emit somehow<br>
> (perhaps as metadata) the information that we have about<br>
> full-expressions, we could use that as input to an LLVM alias<br>
> analysis -- then we could use the same representation both to drive<br>
> a check and to drive optimizations. In the long term, that's<br>
> probably the superior approach.<br>
><br>
><br>
> (Not-fully-baked ideas follow...) We could imagine this working<br>
> something like the following. Given:<br>
><br>
> (a++, b) = c ? d++ : e<br>
><br>
> We divide it into separately-sequenced portions:<br>
><br>
> full expression: seq 0 a++: seq 1 for load, seq 2 for store b: seq<br>
> 3 c: seq 4 d++: seq 5 for load, seq 6 for store e: seq 7<br>
> assignment: seq 8<br>
><br>
> We know that:<br>
><br>
> seq 2 and seq 3 are sequenced after seq 1 seq 4 and seq 5 are<br>
> sequenced after seq 3 seq 6 is sequenced after seq 5 seq 8 is<br>
> sequenced after seq 3, 5, and 7 seq 1-8 are nested within seq 0 (so<br>
> are by default not sequenced with other things inside seq 0)<br>
><br>
> We could then express this as metadata as:<br>
><br>
> %a = load @a, !seq !seq1 %a.1 = add %a, 1 store @a, %a.1, !seq<br>
> !seq2 ; ...<br>
><br>
> !seq0 = !{} !seq1 = !{seq0} ; parent is 0 !seq2 = !{seq0, !{seq1}}<br>
> ; parent is 0, sequenced after 1 !seq3 = !{seq0, !{seq1}} ; parent<br>
> is 0, sequenced after 1 ; ...<br>
><br>
> ... with the semantics that memory operations A and B are known not<br>
> to alias if at least one is a load, and they have the same parent,<br>
> and neither is (transitively) sequenced before the other.<br>
</div></div><div class="im">-----BEGIN PGP SIGNATURE-----<br>
Version: GnuPG v1.4.13 (GNU/Linux)<br>
Comment: Using GnuPG with Thunderbird - <a href="http://www.enigmail.net/" target="_blank">http://www.enigmail.net/</a><br>
<br>
</div>iF4EAREIAAYFAlKKE28ACgkQHFHs/Czs0u61uAD+M+vsA0kFpGS9YztJkuN9Jkqb<br>
8a8q4RfFdCJiyku75QwBAKrshaFAfM98UMpymLrEbJn6q60UK9hw9wkny6u0M17S<br>
=GLxY<br>
-----END PGP SIGNATURE-----<br>
</blockquote></div><br></div></div>