[M3devel] integer overflow and for loops

Tony Hosking hosking at cs.purdue.edu
Wed Jan 13 16:40:20 CET 2010


I really don't think an interface should support overflow checks for unsigned types.  We have Word.T and Long.T with their current semantics.  To be honest I don't think this is really a high priority right now.

I do have another suggestion for where to direct your energies.  :-)  What about going back to smartening up the integrated backend to generate LONGINT properly on Windows?  As a warmup to get you back in the groove you might first consider implementing the M3CG atomic primitives that I just added to m3middle and m3cg and will shortly push through the front-end.  Here is a link to the proposed implementations for these on x86/x86_64: http://www.decadentplace.org.uk/pipermail/cpp-threads/2008-December/001937.html

We only need the following:

Load Relaxed:  MOV (from memory)
Load Acquire:  MOV (from memory)
Load Seq_Cst:  LOCK XADD(0) // alternative: MFENCE,MOV (from memory)

Store Relaxed: MOV (into memory)
Store Release: MOV (into memory)
Store Seq Cst: LOCK XCHG    // alternative: MOV (into memory),MFENCE

Acquire Fence: <ignore>
Release Fence: <ignore>
Acq_Rel Fence: <ignore>
Seq_Cst Fence: MFENCE

Also, we need implementations for the fetch_and_op variants, which presumably require LOCK variants for all the operations to ensure that they are atomic (regardless of memory order).

One question I have for efficient code on x86 is whether the M3CG ops need to take an offset as well as the address of the atomic variable.  The ops as currently defined do not take an offset.  This would permit more efficient addressing modes for the instructions just like regular loads/stores.

On 12 Jan 2010, at 22:08, Jay K wrote:

> 
> If isn't needed for safety, then I agree.
> I really thought it was needed for safety.
> But I do not "argue" that that is true.
> I guess array bounds checking, and checks upon assignment to subranges, make it redundant.
> 
> 
> That said, even if it shouldn't be mandatory, making it a thread local still doesn't seem like the one true solution. It is one of a few solutions.
> This is a common problem. There are several solutions all with tradeoffs.
> It could be bound to a type, or an interface, or a process, or code compiled with a certain flag.
> I tend to think type/interface are the best options.
> 
> 
> INTERFACE IntegerOverflowOut;
> 
> 
> (* maybe UNTRACED REF := NIL for "compatibility" *)
> 
> PROCEDURE Add(a,b: INTEGER; VAR overflow: BOOLEAN): INTEGER;
> PROCEDURE Sub(a,b: INTEGER; VAR overflow: BOOLEAN): INTEGER;
> PROCEDURE Mult(a,b: INTEGER; VAR overflow: BOOLEAN): INTEGER;
> PROCEDURE AddUnsigned(a,b: Word.T; VAR overflow: BOOLEAN): Word.T;
> PROCEDURE SubUnsigned(a,b: Word.T; VAR overflow: BOOLEAN): Word.T;
> PROCEDURE MultUnsigned(a,b: Word.T; VAR overflow: BOOLEAN): Word.T;
> 
> PROCEDURE AddLong(a,b: LONGINT; VAR overflow: BOOLEAN): LONGINT;
> PROCEDURE SubLong(a,b: LONGINT; VAR overflow: BOOLEAN): LONGINT;
> PROCEDURE MultLong(a,b: LONGINT; VAR overflow: BOOLEAN): LONGINT;
> PROCEDURE AddUnsignedLong(a,b: Long.T; VAR overflow: BOOLEAN): Long.T;
> PROCEDURE SubUnsignedLong(a,b: Long.T; VAR overflow: BOOLEAN): Long.T;
> PROCEDURE MultUnsignedLong(a,b: Long.T; VAR overflow: BOOLEAN): Long.T;
> 
> 
> INTERFACE IntegerOverflowRaises;
> 
> EXCEPTION Error;
> 
> PROCEDURE Add(a,b: INTEGER): INTEGER RAISES Error;
> PROCEDURE Sub(a,b: INTEGER): INTEGER RAISES Error;
> PROCEDURE Mult(a,b: INTEGER): INTEGER RAISES Error;
> PROCEDURE AddUnsigned(a,b: Word.T): Word.T RAISES Error;
> PROCEDURE SubUnsigned(a,b: Word.T): Word.T RAISES Error;
> PROCEDURE MultUnsigned(a,b: Word.T): Word.T RAISES Error;
> 
> PROCEDURE AddLong(a,b: LONGINT): LONGINT RAISES Error;
> PROCEDURE SubLong(a,b: LONGINT): LONGINT RAISES Error;
> PROCEDURE MultLong(a,b: LONGINT): LONGINT RAISES Error;
> PROCEDURE AddUnsignedLong(a,b: Long.T): Long.T RAISES Error;
> PROCEDURE SubUnsignedLong(a,b: Long.T): Long.T RAISES Error;
> PROCEDURE MultUnsignedLong(a,b: Long.T): Long.T RAISES Error;
> 
> 
> INTERFACE IntegerOverflowSilent;
> 
> 
> PROCEDURE Add(a,b: INTEGER): INTEGER;
> PROCEDURE Sub(a,b: INTEGER): INTEGER;
> PROCEDURE Mult(a,b: INTEGER): INTEGER;
> PROCEDURE AddUnsigned(a,b: Word.T): Word.T;
> PROCEDURE SubUnsigned(a,b: Word.T): Word.T;
> PROCEDURE MultUnsigned(a,b: Word.T): Word.T;
> 
> PROCEDURE AddLong(a,b: LONGINT): LONGINT;
> PROCEDURE SubLong(a,b: LONGINT): LONGINT;
> PROCEDURE MultLong(a,b: LONGINT): LONGINT;
> PROCEDURE AddUnsignedLong(a,b: Long.T): Long.T;
> PROCEDURE SubUnsignedLong(a,b: Long.T): Long.T;
> PROCEDURE MultUnsignedLong(a,b: Long.T): Long.T;
> 
> 
> Notice how two of the interfaces are "source compatible" and allow
> easy switching between them for testing/investigation.
> That might be deemed a feature, and provided somehow across all three.
> 
> 
> Is anyone strongly opposed to providing something *like* these in m3core?
> Maybe inlined by the compiler?
> 
> 
> You know, some program might have a mix of code that absolutely requires integer overflow to raise, and other code that absolutely requires it to be silent. Having a thread local doesn't cut it for such code, unless you go to the trouble of fiddling back and forth the thread local.
> Sometimes the setting should be set by the author of the code and not be changable without recompiling it all.
> 
> And sometimes not.
> 
> 
> - Jay
> 
> 
> 
> ----------------------------------------
>> Subject: Re: [M3devel] integer overflow and for loops
>> From: hosking at cs.purdue.edu
>> Date: Tue, 12 Jan 2010 21:18:59 -0500
>> CC: m3devel at elegosoft.com
>> To: jay.krell at cornell.edu
>> 
>>> http://www.roland-illig.de/articles/modula-3-for-loop.pdf
>> 
>> This assumes that overflow checks should be defined on integers in the language. Rather than making things special for FOR loops it would mean general overflow checks on all integer arithmetic in the language. I think this is an unacceptable overhead for a systems programming language. C does not have it. The characteristics of restricted range integer arithmetic are well understood. If programmers want overflow checking it should be compiled/configured (using FloatMode) on the side (without tying the language spec down).
>> 		 	   		  




More information about the M3devel mailing list