[rust-dev] Integer overflow, round -2147483648

Daniel Micay danielmicay at gmail.com
Sun Jun 22 21:35:20 PDT 2014

On 23/06/14 12:17 AM, comex wrote:
> On Sun, Jun 22, 2014 at 5:05 PM, Daniel Micay <danielmicay at gmail.com> wrote:
>> Anyway, no one has offered an explanation of how they're
>> planning on integrating this into LLVM and how they propose turning a
>> trapping operation into unwinding across various platforms.
> Isn't that what asynchronous unwind tables are for?  The actual
> platform glue isn't that difficult on the platforms I know of - at the
> cost of making interoperability with C programs that use signal
> handlers tend to break, but that's not fatal.

Asynchronous unwind tables are the low-level implementation detail for
providing this support. However, that doesn't mean it has well-defined
behaviour in LLVM IR. LLVM has modelling of effects like unwinding, and
it does assume that unwinding cannot simply occur anywhere. If it had to
make that assumption, it would be far less capable of performing

In the case of MPX, you could add new LLVM intrinsics and provide a hard
guarantee that whatever signal handler glue you use to turn MPX into
unwinding *never* occurs outside of those LLVM intrinsics.

> On Reddit you mentioned that unwinding impedes optimization.  But I'd
> still like to hear more specifics... what sort of optimizations?  I
> believe you if you say that simply allowing unwinding (without
> considering the cost of actually trapping*) significantly impedes
> performance today, but can some of that can be fixed?  In terms of
> true limitations, I can think of:

An operation that can unwind isn't pure. It impedes code motion such as
hoisting operations out of a loop, which is very important for easing
the performance issues caused by indexing bounds checks. LLVM doesn't
model the `nounwind` effect on functions simply for fun.

> - No more speculative execution - 'foo ? x + 2 : y + 4' now must be a
> branch instead of a cmov.  But how common is this in practice?  'foo ?
> x + 2 : x + 4' can of course be done with a cmov.  Bigger statements
> turn into branches anyway in practice.
> - Can't reorder arithmetic with respect to stores that could be
> visible to destructors.  Does it matter?  It's still fine to eliminate
> common subexpressions as long as they're only computed when one of
> their instances should be.
> My intuition could be wildly off, but I don't see why this should be
> such a big deal.  And the value many people seem to assign to the
> issue (albeit which I'm not presupposing is merited) suggests that
> making any useful improvements to LLVM in this case should be doable.
> (Easy to say without volunteering to do it myself, I know...)

Unwinding is a stateful effect, and any code that would be otherwise
pure is no longer pure if it has the potential to unwind. It's not
simply a matter of unwinding or not unwinding, the compiler needs to
ensure that the source of the unwinding is the same.

An abort (`llvm.trap`) or undefined behaviour is similar in that it adds
an effect and prevents the compiler from doing as much with the code.
However, the unwinding invariants are harder to maintain and LLVM
doesn't even take on this problem.

> Even if this turns out to be a bad idea in the end, I'm not sure this
> thread has enough of a real, measured idea of the costs involved yet,
> and again, people seem to think it's important enough that I don't
> think it's worth giving up without that.  Yes, even though 1.0 is
> soon.  Just my two cents.

I provided an example demonstrating the cost with `clang`.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140623/5089c9b5/attachment.sig>

More information about the Rust-dev mailing list