<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 13, 2016 at 3:45 PM, Quentin Colombet via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Sanjay,<br>
<div><div class="h5"><br>
<br>
> On May 13, 2016, at 3:32 PM, Sanjoy Das <<a href="mailto:sanjoy@playingwithpointers.com">sanjoy@playingwithpointers.com</a>> wrote:<br>
><br>
> Hi,<br>
><br>
> This is a proposal to introduce a mechanism to LLVM that uses runtime<br>
> instrumentation to verify that a call target preserves all of the<br>
> registers it says it does. Internally, we have a diverse set of<br>
> calling conventions for runtime functions that get called from LLVM<br>
> compiled code, and having some sort of validation mechanism will give<br>
> us more confidence in selecting aggressive calling conventions for<br>
> these.<br>
><br>
> The general idea is this: before every call store a cookie in all the<br>
> registers that the call is supposed to preserve, and after the call<br>
> returns, assert that the supposedly callee saved registers weren't<br>
> clobbered. So for a call target that respects the C calling<br>
> convention, we'll generate something like:<br>
><br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rbp<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rbx # can also be movq %rbp, %rbx etc.<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %r12<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %r13<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %r14<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %r15<br>
> callq foo<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rax<br>
> cmpq %rax, %rbp<br>
> jne .LBB1_5<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rax<br>
> cmpq %rax, %rbx<br>
> jne .LBB1_5<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rax<br>
> cmpq %rax, %r12<br>
> jne .LBB1_5<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rax<br>
> cmpq %rax, %r13<br>
> jne .LBB1_5<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rax<br>
> cmpq %rax, %r14<br>
> jne .LBB1_5<br>
> movabsq $0xCA5FCA5FCA5FCA5F, %rax<br>
> cmpq %rax, %r15<br>
> jne .LBB1_5<br>
><br>
><br>
> The 0xCA5FCA5FCA5FCA5F cookie was selected arbitrarily, but in general<br>
> it can be anything that the call target is unlikely to clobber a CSR<br>
> with (so it shouldn't be 0, 1, -1 etc.).<br>
><br>
> This isn't intended to be fast, but is something you turn on in a slow<br>
> "validate corner cases" mode. I think for this to be practical we'll<br>
> need to be able to switch this on and off per calling convention,<br>
> since I suspect doing this for every call will be impractically slow,<br>
> even for a validation run.<br>
><br>
> Does the general idea sound reasonable?<br>
<br>
</div></div>The solution definitely solves your problems, I just wonder in what “corner case” mode this even makes sense.<br></blockquote><div><br></div><div>Yeah, that's sort of what I'd be wondering too.<br><br>It seems like if the compiler does the right thing for existing calling conventions - I hope our architecture is such that changing the set of callee save registers reflects on both sides (both the caller - relying on them to be saved, and the caller implementing that guarantee). So I wouldn't expect making weird/random calling conventions to be likely to have any new/interesting bugs here.<br><br>But perhaps the architecture doesn't & can't work that way?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
><br>
> Note: the focus here is **not** verifying the register allocator or<br>
> any other part of _LLVM_, but to verify that e.g. a custom calling<br>
> convention that says that a call target preserves %r10 actually does<br>
> preserve %r10. This is the compiler enforcing a contract, just at a<br>
> very low level.<br>
<br>
</span>You mean with code generated by another compiler/handwritten, because otherwise, this is pretty easy to verify in the machine verifier :).<br>
(We probably do not verify that though, but we should.)<br>
Thus, could you elaborate on the use cases.<br>
<span class=""><br>
><br>
><br>
> Implementation wise, I have a rough prototype that works by running a<br>
> MachineFunctionPass before register allocation that emits the<br>
> necessary MachineInstrs / control flow to make this happen. Is that a<br>
> right way to solve the problem?<br>
<br>
</span>I’d say yes, assuming the use cases do not involve llvm, otherwise the verifier approach seems preferable to me.<br>
<span class=""><br>
> If so, I'll clean up what I have and<br>
> put it up for review on llvm-commits. If there are better ways to do<br>
> this, then I'm happy to hear them.<br>
><br>
> -- Sanjoy<br>
<br>
</span>Cheers,<br>
-Quentin<br>
<div class="HOEnZb"><div class="h5">_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</div></div></blockquote></div><br></div></div>