core.checkedint

Observer via Digitalmars-d digitalmars-d at puremagic.com
Sat Jun 25 15:06:48 PDT 2016


On Saturday, 25 June 2016 at 01:49:22 UTC, Andrei Alexandrescu 
wrote:
> On 06/24/2016 09:42 PM, Andrei Alexandrescu wrote:
>> long x = -1;
>> auto y = array.length + x;
>>
>> I would be hard pressed to acknowledge that as an overflow 
>> that needs to
>> be dynamically signaled. And the beauty of two's complement is 
>> that
>> indeed it just works.
>
> To clarify: if array.length is 0, then indeed that should be 
> signaled as an error. But otherwise it should just go through, 
> no overflow. -- Andrei

I'm curious how one attempts to handle overflow detection in a
user-level implementation.  It seems to me that such calculations 
are
much better handled at the hardware level -- and that means, in 
the
compiler.  To wit, I'm looking at some old processor manuals I 
happen
to have sitting around, since they tend to be quite descriptive
about such details.  My pdp-11 processor handbook says about the V
(overflow) and C (carry) status bits in an ADD instruction:

V:  set if there was arithmetic overflow as a result of the
     operation; that is both operands were of the same sign and the
     result was of the opposite sign; cleared otherwise

C:  set if there was a carry from the most significant bit of the
     result; cleared otherwise

I guess this is just assuming both operands are signed.  It 
doesn't
talk about a separate ADDU (add unsigned) instruction, so I guess
you'd have to just use ADD and interpret the flags appropriately
for that situation.

The point is, there are two separate flags involved, and they need
to be thought about separately and in detail in such contexts.

In the MC68020 32-Bit Microprocessor User's Manual, Appendix A
("Condition Codes Computation") is really nice because it is
precise and goes right down to the bottom-most detail, listing
the logical equations used to set such flags.  For instance, for
the ADD instruction, the V and C flags are set according to these
logical equations:

     V = (Sm and Dm and (not Rm)) or ((not Sm) and (not Dm) and Rm)
     C = (Sm and Dm) or ((not Rm) and Dm) or (Sm and (not Rm))

where:

     Sm = source (first operand) most significant bit
     Dm = destination (second operand) most significant bit
     Rm = result most significant bit

(I've added parentheses to what is presented in the book, assuming
that logical AND is of higher precedence than logical OR.)
I'm assuming that once again, these flags are being set on the
assumption that both operands are signed, as I see no separate
ADDU instruction.

My points are:

* correct overflow detection involves an awful lot of bit-fiddling

* the V (overflow) bit is *not* the same as the C (carry) bit that
   everyone first thinks about when considering whether or not a
   simple add calculation overflowed

I had to wonder, how is this handled at the user level in a
checkedint implementation?  Do you perform a lot of data masking
and testing in user-level code?  Or do you depend on accessing the
machine's hardware flags register and hoping it hasn't changed in
between when you executed the compiled ADD instruction and when
you attempt to access it from high-level code?

I just checked the implementations of adds() and addu() here:

https://github.com/dlang/druntime/blob/master/src/core/checkedint.d

They don't seem to have quite the complexity of the logical 
equations
I just showed.  Not that they're necessarily incorrect as they 
stand;
I'm just curious.


More information about the Digitalmars-d mailing list