August 08, 2005
In article <dd655j$13ve$1@digitaldaemon.com>, Burton Radons says...
>
>Sean Kelly wrote:
>> In article <dd3mon$2eds$1@digitaldaemon.com>, Manfred Nowak says...
>> 
>>>1) Review this code:
>>>
>>>void f( inout int i, inout int j){
>>> i= 1;
>>> j= 2;
>>>}
>> 
>> 
>> # void f( inout int i, inout int j ) {
>> # in {
>> #     assert( &i != &j );
>> # }
>> # body {
>> #     i = 1; j = 2;
>> # }
>> 
>> Without this check, passing the same variable as both arguments will result in an undefined result, as whether the value is equal to 1 or 2 after the function call depends on the calling convention (C/D, Pascal, etc).
>
>No, it's well-defined and independent of calling convention: inout/out parameters are defined as pointers.  There is absolutely nothing wrong here and changing the language would limit the flexibility of the calling convention because you don't need to write to all inout parameters.

I'm not suggesting that the language be changed.  But the results are unpredictable specifically because of calling convention rules.


Sean


August 08, 2005
In article <dd6erg$1am3$1@digitaldaemon.com>, Sean Kelly says...
>
>In article <dd655j$13ve$1@digitaldaemon.com>, Burton Radons says...
>>
>>Sean Kelly wrote:
>>> In article <dd3mon$2eds$1@digitaldaemon.com>, Manfred Nowak says...
>>> 
>>>>1) Review this code:
>>>>
>>>>void f( inout int i, inout int j){
>>>> i= 1;
>>>> j= 2;
>>>>}
>>> 
>>> 
>>> # void f( inout int i, inout int j ) {
>>> # in {
>>> #     assert( &i != &j );
>>> # }
>>> # body {
>>> #     i = 1; j = 2;
>>> # }
>>> 
>>> Without this check, passing the same variable as both arguments will result in an undefined result, as whether the value is equal to 1 or 2 after the function call depends on the calling convention (C/D, Pascal, etc).
>>
>>No, it's well-defined and independent of calling convention: inout/out parameters are defined as pointers.  There is absolutely nothing wrong here and changing the language would limit the flexibility of the calling convention because you don't need to write to all inout parameters.
>
>I'm not suggesting that the language be changed.  But the results are unpredictable specifically because of calling convention rules.

Um... how exactly is the result unpredictable? I don't see how calling conventions have anything to do with this.

# int i = 0, j = 0;
# void f( inout int i, inout int j ) { i = 1; j = 2; }
# f(i, j);
# // Here i is 1, j is 2.

# int i = 0;
# void f( inout int i, inout int j ) { i = 1; j = 2; }
# f(i, i);
# // Here i is 2.

The results are quite predictable, IMHO. I don't think there is anything wrong with the language. How could this result be any different?

Cheers,
--AJG.



August 08, 2005
On Mon, 8 Aug 2005 02:07:36 +0000 (UTC), Sean Kelly wrote:

> In article <138h7vhtkvnm7$.1i39l7uetkpdf$.dlg@40tude.net>, Derek Parnell says...
>>
>>On Sun, 07 Aug 2005 19:01:18 +0200, Dejan Lekic wrote:
>>
>>> Yeah Mr. Kelly, that is how I would write the code...
>>> 
>>> Kind regards
>>> 
>>> Dejan
>>
>>But that doesn't check for overlapping arguments, just ones that start on the same RAM address, plus the checks disappear in '-release' editions. So this is not how I would be coding it.
> 
> But do overlapping arguments matter in this case?  The values passed are integers.  Frankly, if someone is passing oddly aligned primitives then he has more problems than the side effects of the posted function.
> 
> Sean

The short answer is "I don't know. What do the specifications say?".

I was just trying to be a pedantic bastard ;-)

And in any either case, the "-release" switch still blows away the contract checks and asserts. If you need runtime checking in production code, don't rely on using input validation in contract code. Contract code should only be for testing applications before they are shipped to customers, IMHO. But now we are off-topic ;-)

-- 
Derek
Melbourne, Australia
8/08/2005 12:15:20 PM
August 08, 2005
On Mon, 8 Aug 2005 02:08:48 +0000 (UTC), Sean Kelly wrote:

> In article <dd655j$13ve$1@digitaldaemon.com>, Burton Radons says...
>>
>>Sean Kelly wrote:
>>> In article <dd3mon$2eds$1@digitaldaemon.com>, Manfred Nowak says...
>>> 
>>>>1) Review this code:
>>>>
>>>>void f( inout int i, inout int j){
>>>> i= 1;
>>>> j= 2;
>>>>}
>>> 
>>> # void f( inout int i, inout int j ) {
>>> # in {
>>> #     assert( &i != &j );
>>> # }
>>> # body {
>>> #     i = 1; j = 2;
>>> # }
>>> 
>>> Without this check, passing the same variable as both arguments will result in an undefined result, as whether the value is equal to 1 or 2 after the function call depends on the calling convention (C/D, Pascal, etc).
>>
>>No, it's well-defined and independent of calling convention: inout/out parameters are defined as pointers.  There is absolutely nothing wrong here and changing the language would limit the flexibility of the calling convention because you don't need to write to all inout parameters.
> 
> I'm not suggesting that the language be changed.  But the results are unpredictable specifically because of calling convention rules.

I don't understand that. Why would the order of the addresses matter, its the order of the executions that matter. In this example, assuming that both pointed to the same RAM location, one of the address locations would get set to 1, then the other address location would get set to 2; in that order. It wouldn't matter which address location got used first.

-- 
Derek
Melbourne, Australia
8/08/2005 12:22:12 PM
August 08, 2005
On Mon, 8 Aug 2005 02:19:50 +0000 (UTC), AJG <AJG_member@pathlink.com> wrote:
> # int i = 0;
> # void f( inout int i, inout int j ) { i = 1; j = 2; }
> # f(i, i);
> # // Here i is 2.
>
> The results are quite predictable, IMHO. I don't think there is anything wrong with the language. How could this result be any different?

Is it not possible that an optimisiton compiler might re-order these statements?
Is it not possible that an optimising compiler might do these operations in parrallel on a multi cpu platform?

Is there any guarantee that the operations are carried out in the order they have been typed? (if so, what is the point of the volatile block statement?)
http://www.digitalmars.com/d/statement.html#volatile

In other words, is it possible for i to be 1 or 2 depending on what the optimising compiler decides to do and/or the enviroment the code is running in.

Regan
August 08, 2005
On Mon, 08 Aug 2005 14:37:16 +1200, Regan Heath wrote:

> On Mon, 8 Aug 2005 02:19:50 +0000 (UTC), AJG <AJG_member@pathlink.com> wrote:
>> # int i = 0;
>> # void f( inout int i, inout int j ) { i = 1; j = 2; }
>> # f(i, i);
>> # // Here i is 2.
>>
>> The results are quite predictable, IMHO. I don't think there is anything wrong with the language. How could this result be any different?
> 
> Is it not possible that an optimisiton compiler might re-order these
> statements?
> Is it not possible that an optimising compiler might do these operations
> in parrallel on a multi cpu platform?
> 
> Is there any guarantee that the operations are carried out in the order
> they have been typed? (if so, what is the point of the volatile block
> statement?)
> http://www.digitalmars.com/d/statement.html#volatile
> 
> In other words, is it possible for i to be 1 or 2 depending on what the optimising compiler decides to do and/or the enviroment the code is running in.

Very true, however Sean was talking about "calling conventions" and that *alone* would not effect this issue. True, the order that the operations is done in is more significant than the order that the parameters are passed.

-- 
Derek
Melbourne, Australia
8/08/2005 1:08:22 PM
August 08, 2005
Hi,

Playing the devil's advocate, huh? ;)

>On Mon, 8 Aug 2005 02:19:50 +0000 (UTC), AJG <AJG_member@pathlink.com> wrote:
>> # int i = 0;
>> # void f( inout int i, inout int j ) { i = 1; j = 2; }
>> # f(i, i);
>> # // Here i is 2.
>>
>> The results are quite predictable, IMHO. I don't think there is anything wrong with the language. How could this result be any different?
>
>Is it not possible that an optimisiton compiler might re-order these statements?

Why on earth would it do that? You specifically told it the order you wanted them in. Such an "optimization" is erroneous. That's more like a transmogrification.

>Is it not possible that an optimising compiler might do these operations in parrallel on a multi cpu platform?

No. Because such code is specifically not instrinsically parallelisable. If I want extra threads, I can ask for them myself, thank you, and I would make my code thread-safe.

The exception to that rule is when the compiler can guarantee identical behaviour. This is not such a case, as we can see. This is similar to the const optimization Walter was talking about; he couldn't optimize that one either.

There are languages that specialize in writing easily parallelisable code (via syntax). D, coming roughly from normal C/C++, is not one of them. An extended version of C, called Cilk, does just that:

http://supertech.lcs.mit.edu/cilk/

>Is there any guarantee that the operations are carried out in the order
>they have been typed? (if so, what is the point of the volatile block
>statement?)
>http://www.digitalmars.com/d/statement.html#volatile

The guarantee (real or simulated) of order of execution is the very foundation of logical programming. If you couldn't rely on your statements being executed in the order you intended, then there is utter chaos.

Btw, that's why the NON-guarantee of order of execution in parameter calls (in C) is such a hotly debated issue. It is one exception to the rule. It's a mistake, IMO, that should be fixed.

>In other words, is it possible for i to be 1 or 2 depending on what the optimising compiler decides to do and/or the enviroment the code is running in.

Optimization should not alter the behaviour (intrinsic order) of such code, otherwise it is erroneous. I do not recall seeing anywhere "variable references may not refer to the same thing" but please do correct me if I'm wrong.

--AJG.


August 08, 2005
In article <opsu538ejr23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Mon, 8 Aug 2005 02:19:50 +0000 (UTC), AJG <AJG_member@pathlink.com> wrote:
>> # int i = 0;
>> # void f( inout int i, inout int j ) { i = 1; j = 2; }
>> # f(i, i);
>> # // Here i is 2.
>>
>> The results are quite predictable, IMHO. I don't think there is anything wrong with the language. How could this result be any different?
>
>Is it not possible that an optimisiton compiler might re-order these statements?

No - C aliasing rules (which D uses) prohibit that. Google for documents describing Restricted Pointers for C99.

>Is it not possible that an optimising compiler might do these operations in parrallel on a multi cpu platform?
>

No - same reason as above.

>Is there any guarantee that the operations are carried out in the order
>they have been typed? (if so, what is the point of the volatile block
>statement?)
>http://www.digitalmars.com/d/statement.html#volatile
>

Basically, the parameters i and j in the OP are treated as 'volatile' by the compiler - in a manner of speaking - inside the function because of the aliasing rules followed by D (and C, C++, Pascal, etc.). Because they /can/ refer to the same memory, the memory that each refers to has to be updated before reads and after writes.

>In other words, is it possible for i to be 1 or 2 depending on what the optimising compiler decides to do and/or the enviroment the code is running in.
>

No - the D language follows the same aliasing rules that C, C++ and the Pascal derivitives do, along with just about any other language that can pass parameters byref. One notable exception is Fortran.

D won't (well, shouldn't) act any different than C/C++ given the equivalent C/C++ code in the OP - If the same variable is passed in for both parameters, it will be '2' after the function returns.

>Regan


August 08, 2005
In article <dd6fg6$1b70$1@digitaldaemon.com>, AJG says...
>
>>
>>I'm not suggesting that the language be changed.  But the results are unpredictable specifically because of calling convention rules.
>
>Um... how exactly is the result unpredictable? I don't see how calling conventions have anything to do with this.

I was being dumb.  The result depends on the order of assignments in the function.  And this is something that could easily change during maintenance.


Sean


August 08, 2005
On Mon, 8 Aug 2005 03:20:00 +0000 (UTC), AJG <AJG_member@pathlink.com> wrote:
> Playing the devil's advocate, huh? ;)

No. Just curious.

After a brief google:
http://www.nationmaster.com/encyclopedia/Compiler-optimization

Search for "reorder" within this page. Not sure if it applies in this case, to this code, but it is talking about compiler optimistations that reorder code.

Likewise:
http://www.absoluteastronomy.com/encyclopedia/c/co/compiler_optimization.htm

Notably:
"Compilers can schedule, or reorder, instructions so that pipeline stalls occur less frequently."

Regan