digitalmars.D - Order of evaluation - aka hidden undefined behaviours.
- Iain Buclaw (40/40) Sep 25 2012 Pop quiz!
- Andrei Alexandrescu (5/8) Sep 25 2012 The right answer is to have the front-end rewrite such expressions in a
- Timon Gehr (6/46) Sep 25 2012 As far as my understanding of the issue goes, the correct answer is
- H. S. Teoh (9/59) Sep 25 2012 [...]
- Timon Gehr (7/64) Sep 25 2012 There are 3 'corresponding' side-effecting expressions.
- Don Clugston (3/59) Sep 26 2012 I expected "BCA" too. Left associative expressions evaluated
- Timon Gehr (8/72) Sep 26 2012 I don't think that makes any sense. Why would that be the case?
- Walter Bright (6/12) Sep 25 2012 D needs to move towards a defined order of evaluation. I understand that...
- Iain Buclaw (16/36) Sep 26 2012 Indeed, but where does that leave code that gets compiled down to
- Walter Bright (6/37) Sep 26 2012 C functions all seem to evaluate their args right-to-left, even though t...
- Iain Buclaw (13/54) Sep 26 2012 Speaking as a generalisation, no that is not true. C functions
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (7/62) Sep 26 2012 There is a pull request that does this, but it has not yet been merged
- Iain Buclaw (5/74) Sep 26 2012 Got a link? :~)
- Timon Gehr (7/48) Sep 26 2012 On x86. It is unspecified, therefore different compilers on different
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (7/58) Sep 26 2012 Completely agree with this. Calling convention is irrelevant.
- Walter Bright (4/7) Sep 27 2012 The best order is the one that generates the fewest temporaries, and tha...
- Iain Buclaw (6/14) Sep 27 2012 Can't see how you can get any fewer temporaries when following the
- bearophile (5/7) Sep 27 2012 Java and Python and C# give a precedent, maybe many programmers
- Timon Gehr (4/9) Sep 27 2012 Well, those can use a calling convention that optimally fits the
- Timon Gehr (6/13) Sep 27 2012 The number of temporaries is not affected by the order of
- monarch_dodra (6/17) Sep 26 2012 I'd say abc's value is "unspecified", and any attempt at
- Iain Buclaw (8/28) Sep 26 2012 There is no physical code generation from the frontend that says
- David Nadlinger (13/26) Sep 26 2012 I'm not quite sure what you are trying to say here; I guess it
- Iain Buclaw (12/34) Sep 26 2012 Yes, this is what's done in GDC. All parameters with side effects
- Timon Gehr (2/15) Sep 26 2012 Why? This is not useful behaviour.
- monarch_dodra (13/33) Sep 26 2012 What do you mean "why"? Because order of evaluation is not
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (8/37) Sep 26 2012 No it isn't. There's a perfectly sensible, sane, and intuitive fix for
- monarch_dodra (21/27) Sep 26 2012 You know, I think you are right on second though. However, it is
- Jonathan M Davis (12/27) Sep 26 2012 I'd still consider it to be bad practice to do anything which relies on ...
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (6/33) Sep 27 2012 I do not know any other languages than C and C++ that leave it undefined...
Pop quiz! Analyse this code: ---- string abc; float[] A() { abc ~= "A"; return []; } float[] B() { abc ~= "B"; return []; } float[] C() { abc ~= "C"; return []; } void main() { A()[] = B()[] + C()[]; assert(abc == "???"); } ---- Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64. The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it? Regards, Iain.
Sep 25 2012
On 9/25/12 6:58 PM, Iain Buclaw wrote: [snip]Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?The right answer is to have the front-end rewrite such expressions in a form that enforces correct order of operations. Andrei
Sep 25 2012
On 09/26/2012 12:58 AM, Iain Buclaw wrote:Pop quiz! Analyse this code: ---- string abc; float[] A() { abc ~= "A"; return []; } float[] B() { abc ~= "B"; return []; } float[] C() { abc ~= "C"; return []; } void main() { A()[] = B()[] + C()[]; assert(abc == "???"); } ---- Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64. The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it? Regards, Iain.As far as my understanding of the issue goes, the correct answer is "ABC", and compilers that do not produce "ABC" are buggy. The solution is to transform the code to code that evaluates the arguments to the extern(C) call in the correct order and eg. stores them in temporaries before passing them on.
Sep 25 2012
On Wed, Sep 26, 2012 at 01:10:00AM +0200, Timon Gehr wrote:On 09/26/2012 12:58 AM, Iain Buclaw wrote:[...][...]string abc; float[] A() { abc ~= "A"; return []; } float[] B() { abc ~= "B"; return []; } float[] C() { abc ~= "C"; return []; } void main() { A()[] = B()[] + C()[]; assert(abc == "???"); } ---- Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64. The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?As far as my understanding of the issue goes, the correct answer is "ABC", and compilers that do not produce "ABC" are buggy. The solution is to transform the code to code that evaluates the arguments to the extern(C) call in the correct order and eg. stores them in temporaries before passing them on.[...] Shouldn't it be BCA? I'd expect the assignment operation to take place last, so the corresponding expression should be evaluated last. T -- Leather is waterproof. Ever see a cow with an umbrella?
Sep 25 2012
On 09/26/2012 01:31 AM, H. S. Teoh wrote:On Wed, Sep 26, 2012 at 01:10:00AM +0200, Timon Gehr wrote:There are 3 'corresponding' side-effecting expressions. I expect left-to right, top to bottom evaluation. If BCA is desired it is possible to do auto b = B(), c = C(); A()[] = b[] + c[]; I think having a simple consistent rule for evaluation order is desirable.On 09/26/2012 12:58 AM, Iain Buclaw wrote:[...][...]string abc; float[] A() { abc ~= "A"; return []; } float[] B() { abc ~= "B"; return []; } float[] C() { abc ~= "C"; return []; } void main() { A()[] = B()[] + C()[]; assert(abc == "???"); } ---- Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64. The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?As far as my understanding of the issue goes, the correct answer is "ABC", and compilers that do not produce "ABC" are buggy. The solution is to transform the code to code that evaluates the arguments to the extern(C) call in the correct order and eg. stores them in temporaries before passing them on.[...] Shouldn't it be BCA? I'd expect the assignment operation to take place last, so the corresponding expression should be evaluated last. T
Sep 25 2012
On 26/09/12 01:31, H. S. Teoh wrote:On Wed, Sep 26, 2012 at 01:10:00AM +0200, Timon Gehr wrote:I expected "BCA" too. Left associative expressions evaluated left-to-right, right associative expressions evaluated right-to-left.On 09/26/2012 12:58 AM, Iain Buclaw wrote:[...][...]string abc; float[] A() { abc ~= "A"; return []; } float[] B() { abc ~= "B"; return []; } float[] C() { abc ~= "C"; return []; } void main() { A()[] = B()[] + C()[]; assert(abc == "???"); } ---- Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64. The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?As far as my understanding of the issue goes, the correct answer is "ABC", and compilers that do not produce "ABC" are buggy. The solution is to transform the code to code that evaluates the arguments to the extern(C) call in the correct order and eg. stores them in temporaries before passing them on.[...] Shouldn't it be BCA? I'd expect the assignment operation to take place last, so the corresponding expression should be evaluated last.
Sep 26 2012
On 09/26/2012 12:13 PM, Don Clugston wrote:On 26/09/12 01:31, H. S. Teoh wrote:I don't think that makes any sense. Why would that be the case? a = b = c; => a.opAssign(b.opAssign(c)); foo() ^^ bar() ^^ qux() => pow(foo(), pow(bar(), qux()));On Wed, Sep 26, 2012 at 01:10:00AM +0200, Timon Gehr wrote:I expected "BCA" too. Left associative expressions evaluated left-to-right, right associative expressions evaluated right-to-left.On 09/26/2012 12:58 AM, Iain Buclaw wrote:[...][...]string abc; float[] A() { abc ~= "A"; return []; } float[] B() { abc ~= "B"; return []; } float[] C() { abc ~= "C"; return []; } void main() { A()[] = B()[] + C()[]; assert(abc == "???"); } ---- Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64. The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?As far as my understanding of the issue goes, the correct answer is "ABC", and compilers that do not produce "ABC" are buggy. The solution is to transform the code to code that evaluates the arguments to the extern(C) call in the correct order and eg. stores them in temporaries before passing them on.[...] Shouldn't it be BCA? I'd expect the assignment operation to take place last, so the corresponding expression should be evaluated last.
Sep 26 2012
On 9/25/2012 3:58 PM, Iain Buclaw wrote:The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C rules
Sep 25 2012
On Tuesday, 25 September 2012 at 23:39:39 UTC, Walter Bright wrote:On 9/25/2012 3:58 PM, Iain Buclaw wrote:Indeed, but where does that leave code that gets compiled down to a extern(C) call? eg, in the OP, the following is generated: _arraySliceSliceAddSliceAssign_f(A[], C[], B[]); To say that all extern(C) calls must follow D rules for D code (LTR evaluation), is to change the current behaviour of array operations on it's head, so we'll have to correct a whole lotta changes in code generation to alter the order of parameters, and ensure that both DRT supplied and internally generated functions are corrected for this. Well... someone's got to do the grizzly bits that no one else wants to do. :~) Regards, Iain.The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C rules
Sep 26 2012
On 9/26/2012 12:36 AM, Iain Buclaw wrote:On Tuesday, 25 September 2012 at 23:39:39 UTC, Walter Bright wrote:C functions all seem to evaluate their args right-to-left, even though the C Standard doesn't specify that. So we should be all right by simply defining that D do it that way for C functions. It doesn't actually matter what order D does things, we just have to pick one. And so we might as well pick one that C compilers naturally do anyway.On 9/25/2012 3:58 PM, Iain Buclaw wrote:Indeed, but where does that leave code that gets compiled down to a extern(C) call?The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C ruleseg, in the OP, the following is generated: _arraySliceSliceAddSliceAssign_f(A[], C[], B[]); To say that all extern(C) calls must follow D rules for D code (LTR evaluation), is to change the current behaviour of array operations on it's head, so we'll have to correct a whole lotta changes in code generation to alter the order of parameters, and ensure that both DRT supplied and internally generated functions are corrected for this. Well... someone's got to do the grizzly bits that no one else wants to do. :~) Regards, Iain.
Sep 26 2012
On Wednesday, 26 September 2012 at 08:12:16 UTC, Walter Bright wrote:On 9/26/2012 12:36 AM, Iain Buclaw wrote:Speaking as a generalisation, no that is not true. C functions for x86/x86_64 all seem to evaluate their args right-to-left. However - and this may be different from compiler to compiler - GCC at least does left-to-right evaluation for everything else (ARM, SPARC, etc) because that is the order that arguments are pushed onto the stack for those architecture backends. If right-to-left should be the strict standard to follow for extern(C), then document this behaviour as part of the specification, and I'll implement it. :~) Regards IainOn Tuesday, 25 September 2012 at 23:39:39 UTC, Walter Bright wrote:C functions all seem to evaluate their args right-to-left, even though the C Standard doesn't specify that. So we should be all right by simply defining that D do it that way for C functions. It doesn't actually matter what order D does things, we just have to pick one. And so we might as well pick one that C compilers naturally do anyway.On 9/25/2012 3:58 PM, Iain Buclaw wrote:Indeed, but where does that leave code that gets compiled down to a extern(C) call?The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C rules
Sep 26 2012
On 26-09-2012 13:45, Iain Buclaw wrote:On Wednesday, 26 September 2012 at 08:12:16 UTC, Walter Bright wrote:There is a pull request that does this, but it has not yet been merged because it's waiting on compilers to catch up... ;) -- Alex Rønne Petersen alex lycus.org http://lycus.orgOn 9/26/2012 12:36 AM, Iain Buclaw wrote:Speaking as a generalisation, no that is not true. C functions for x86/x86_64 all seem to evaluate their args right-to-left. However - and this may be different from compiler to compiler - GCC at least does left-to-right evaluation for everything else (ARM, SPARC, etc) because that is the order that arguments are pushed onto the stack for those architecture backends. If right-to-left should be the strict standard to follow for extern(C), then document this behaviour as part of the specification, and I'll implement it. :~) Regards IainOn Tuesday, 25 September 2012 at 23:39:39 UTC, Walter Bright wrote:C functions all seem to evaluate their args right-to-left, even though the C Standard doesn't specify that. So we should be all right by simply defining that D do it that way for C functions. It doesn't actually matter what order D does things, we just have to pick one. And so we might as well pick one that C compilers naturally do anyway.On 9/25/2012 3:58 PM, Iain Buclaw wrote:Indeed, but where does that leave code that gets compiled down to a extern(C) call?The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C rules
Sep 26 2012
On 26 September 2012 16:10, Alex R=F8nne Petersen <alex lycus.org> wrote:On 26-09-2012 13:45, Iain Buclaw wrote:Got a link? :~) --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';On Wednesday, 26 September 2012 at 08:12:16 UTC, Walter Bright wrote:There is a pull request that does this, but it has not yet been merged because it's waiting on compilers to catch up... ;)On 9/26/2012 12:36 AM, Iain Buclaw wrote:Speaking as a generalisation, no that is not true. C functions for x86/x86_64 all seem to evaluate their args right-to-left. However - and this may be different from compiler to compiler - GCC at least does left-to-right evaluation for everything else (ARM, SPARC, etc) because that is the order that arguments are pushed onto the stack for those architecture backends. If right-to-left should be the strict standard to follow for extern(C), then document this behaviour as part of the specification, and I'll implement it. :~) Regards IainOn Tuesday, 25 September 2012 at 23:39:39 UTC, Walter Bright wrote:C functions all seem to evaluate their args right-to-left, even though the C Standard doesn't specify that. So we should be all right by simply defining that D do it that way for C functions. It doesn't actually matter what order D does things, we just have to pick one. And so we might as well pick one that C compilers naturally do anyway.On 9/25/2012 3:58 PM, Iain Buclaw wrote:Indeed, but where does that leave code that gets compiled down to a extern(C) call?The problem here is that the array operation A[] =3D B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C rules
Sep 26 2012
On 09/26/2012 10:11 AM, Walter Bright wrote:On 9/26/2012 12:36 AM, Iain Buclaw wrote:On x86. It is unspecified, therefore different compilers on different architectures do it in different ways.On Tuesday, 25 September 2012 at 23:39:39 UTC, Walter Bright wrote:C functions all seem to evaluate their args right-to-left, even though the C Standard doesn't specify that.On 9/25/2012 3:58 PM, Iain Buclaw wrote:Indeed, but where does that leave code that gets compiled down to a extern(C) call?The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C rulesSo we should be all right by simply defining that D do it that way for C functions.I disagree. Why should the calling convention have an impact on code semantics? The code reads LTR, therefore evaluation should consistently be LTR.It doesn't actually matter what order D does things, we just have to pick one. And so we might as well pick one that C compilers naturally do anyway. ...There is no such thing. C and C++ get evaluation order thoroughly wrong.
Sep 26 2012
On 26-09-2012 14:04, Timon Gehr wrote:On 09/26/2012 10:11 AM, Walter Bright wrote:Completely agree with this. Calling convention is irrelevant. Let us not inherit the C/C++ mess.On 9/26/2012 12:36 AM, Iain Buclaw wrote:On x86. It is unspecified, therefore different compilers on different architectures do it in different ways.On Tuesday, 25 September 2012 at 23:39:39 UTC, Walter Bright wrote:C functions all seem to evaluate their args right-to-left, even though the C Standard doesn't specify that.On 9/25/2012 3:58 PM, Iain Buclaw wrote:Indeed, but where does that leave code that gets compiled down to a extern(C) call?The problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL). Serious note: This test is bogus as this and similar other failing tests on non-x86 platforms are not at all obvious to the users who get issues. So what are we to do about it?D needs to move towards a defined order of evaluation. I understand that there's a problem when using parts of a C compiler that feels free to reorder within the C rules. It's something we have to deal with sooner or later, by either: 1. adjusting the C optimizer so it follows D rules for D code 2. assigning terms to temporaries that are executed in a specific order by C rulesSo we should be all right by simply defining that D do it that way for C functions.I disagree. Why should the calling convention have an impact on code semantics? The code reads LTR, therefore evaluation should consistently be LTR.-- Alex Rønne Petersen alex lycus.org http://lycus.orgIt doesn't actually matter what order D does things, we just have to pick one. And so we might as well pick one that C compilers naturally do anyway. ...There is no such thing. C and C++ get evaluation order thoroughly wrong.
Sep 26 2012
On 9/26/2012 5:04 AM, Timon Gehr wrote:Why should the calling convention have an impact on code semantics?Maximizing performance.The code reads LTR, therefore evaluation should consistently be LTR.The best order is the one that generates the fewest temporaries, and that's the order that should be defined for D.
Sep 27 2012
On 27 September 2012 11:38, Walter Bright <newshound2 digitalmars.com> wrote:On 9/26/2012 5:04 AM, Timon Gehr wrote:Can't see how you can get any fewer temporaries when following the rule: If it has side-effects, cache it's return value. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';Why should the calling convention have an impact on code semantics?Maximizing performance.The code reads LTR, therefore evaluation should consistently be LTR.The best order is the one that generates the fewest temporaries, and that's the order that should be defined for D.
Sep 27 2012
Walter Bright:The best order is the one that generates the fewest temporaries, and that's the order that should be defined for D.expect a behavior like those ones. Bye, bearophile
Sep 27 2012
On 09/27/2012 01:43 PM, bearophile wrote:Walter Bright:Well, those can use a calling convention that optimally fits the evaluation order, as they do not provide zero-overhead interaction with C code.The best order is the one that generates the fewest temporaries, and that's the order that should be defined for D.behavior like those ones.
Sep 27 2012
On 09/27/2012 12:38 PM, Walter Bright wrote:On 9/26/2012 5:04 AM, Timon Gehr wrote:Optimisations by definition do not have an impact on code semantics.Why should the calling convention have an impact on code semantics?Maximizing performance.The number of temporaries is not affected by the order of evaluation. Just push the arguments on the stack out-of-order. Furthermore, the 'natural' order of C argument evaluation differs between architectures, making the entire point moot.The code reads LTR, therefore evaluation should consistently be LTR.The best order is the one that generates the fewest temporaries, and that's the order that should be defined for D.
Sep 27 2012
On Tuesday, 25 September 2012 at 22:58:11 UTC, Iain Buclaw wrote:Pop quiz! Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64.I'd say abc's value is "unspecified", and any attempt at predicting it would be bogus. That's my answer anywaysThe problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL).I don't see how the "extern(C)" is involved here, since it is the D compiler that first evaluates A(), B() and C() before passing the making the C function call. Or did I miss something?
Sep 26 2012
On 26 September 2012 13:07, monarch_dodra <monarchdodra gmail.com> wrote:On Tuesday, 25 September 2012 at 22:58:11 UTC, Iain Buclaw wrote:There is no physical code generation from the frontend that says "evaluate this". What it passes to be backend for this operation is a function call. So the backend determines the order of evaluation depending on the order of parameters. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';Pop quiz! Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64.I'd say abc's value is "unspecified", and any attempt at predicting it would be bogus. That's my answer anywaysThe problem here is that the array operation A[] = B[] + C[] gets transformed into an extern(C) call. And because there's no strict rules in place over the order of which it's parameters are evaluated, it could go either way (LTR, or RTL).I don't see how the "extern(C)" is involved here, since it is the D compiler that first evaluates A(), B() and C() before passing the making the C function call. Or did I miss something?
Sep 26 2012
On Wednesday, 26 September 2012 at 12:29:38 UTC, Iain Buclaw wrote:On 26 September 2012 13:07, monarch_dodra <monarchdodra gmail.com> wrote:I'm not quite sure what you are trying to say here; I guess it depends on the definition of "backend". monarch_dodra is right in so far as the effects of "extern(C)" are an implementation detail coming from the particular way your compiler "glue code" is written; there is no fundamental reason why it should be important for parameter evaluation at all. Speaking of it, what is the reason that the actual order of formal parameters (in terms of register allocation/stack layout) is reversed in the D calling convention, compared to extern (C) (e.g. on *nix x86_64)? DavidI don't see how the "extern(C)" is involved here, since it is the D compiler that first evaluates A(), B() and C() before passing the making the C function call. Or did I miss something?There is no physical code generation from the frontend that says "evaluate this". What it passes to be backend for this operation is a function call. So the backend determines the order of evaluation depending on the order of parameters.
Sep 26 2012
On 26 September 2012 16:25, David Nadlinger <see klickverbot.at> wrote:On Wednesday, 26 September 2012 at 12:29:38 UTC, Iain Buclaw wrote:Yes, this is what's done in GDC. All parameters with side effects have their result evaluated and saved before calling the extern(D) functions.On 26 September 2012 13:07, monarch_dodra <monarchdodra gmail.com> wrote:I'm not quite sure what you are trying to say here; I guess it depends on the definition of "backend". monarch_dodra is right in so far as the effects of "extern(C)" are an implementation detail coming from the particular way your compiler "glue code" is written; there is no fundamental reason why it should be important for parameter evaluation at all.I don't see how the "extern(C)" is involved here, since it is the D compiler that first evaluates A(), B() and C() before passing the making the C function call. Or did I miss something?There is no physical code generation from the frontend that says "evaluate this". What it passes to be backend for this operation is a function call. So the backend determines the order of evaluation depending on the order of parameters.Speaking of it, what is the reason that the actual order of formal parameters (in terms of register allocation/stack layout) is reversed in the D calling convention, compared to extern (C) (e.g. on *nix x86_64)?DMD pushes arguments on the stack in reverse order to that of x86/x86_64. So it gives the *impression* of LTR evaluation, however, the parameters themselves aren't actually explicitly evaluated / saved in temporaries prior to calling. Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Sep 26 2012
On 09/26/2012 02:07 PM, monarch_dodra wrote:On Tuesday, 25 September 2012 at 22:58:11 UTC, Iain Buclaw wrote:Why? This is not useful behaviour.Pop quiz! Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64.I'd say abc's value is "unspecified", and any attempt at predicting it would be bogus. That's my answer anyways ...
Sep 26 2012
On Wednesday, 26 September 2012 at 12:48:19 UTC, Timon Gehr wrote:On 09/26/2012 02:07 PM, monarch_dodra wrote:What do you mean "why"? Because order of evaluation is not specified, so the value of abc is not specified. That was my answer. The question wasn't really "what would useful behavior be". IMO: useful behavior would be if it was explicitly illegal to modify (or modify + read) the same value twice in the same expression. I'd rather expressions such as: A()[] = B()[] + C()[]; x[i] = ++i + 1; Be illegal rather than have (an arbitrarily defined) specified behavior. Trying to specify a specific behavior in such cases is opening a can of worms.On Tuesday, 25 September 2012 at 22:58:11 UTC, Iain Buclaw wrote:Why? This is not useful behaviour.Pop quiz! Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64.I'd say abc's value is "unspecified", and any attempt at predicting it would be bogus. That's my answer anyways ...
Sep 26 2012
On 26-09-2012 15:34, monarch_dodra wrote:On Wednesday, 26 September 2012 at 12:48:19 UTC, Timon Gehr wrote:No it isn't. There's a perfectly sensible, sane, and intuitive fix for this: always evaluate arguments left-to-right. No exceptions. It's not that complicated. -- Alex Rønne Petersen alex lycus.org http://lycus.orgOn 09/26/2012 02:07 PM, monarch_dodra wrote:What do you mean "why"? Because order of evaluation is not specified, so the value of abc is not specified. That was my answer. The question wasn't really "what would useful behavior be". IMO: useful behavior would be if it was explicitly illegal to modify (or modify + read) the same value twice in the same expression. I'd rather expressions such as: A()[] = B()[] + C()[]; x[i] = ++i + 1; Be illegal rather than have (an arbitrarily defined) specified behavior. Trying to specify a specific behavior in such cases is opening a can of worms.On Tuesday, 25 September 2012 at 22:58:11 UTC, Iain Buclaw wrote:Why? This is not useful behaviour.Pop quiz! Without cheating, I invite people to have a good guess what 'abc' is equal to, but just to narrow it down. 1) It isn't "ABC". 2) On x86/x86_64, it isn't "ACB". 3) On everything else, it's the reverse of what you'd expect on x86/x86_64.I'd say abc's value is "unspecified", and any attempt at predicting it would be bogus. That's my answer anyways ...
Sep 26 2012
On Wednesday, 26 September 2012 at 15:12:05 UTC, Alex Rønne Petersen wrote:On 26-09-2012 15:34, monarch_dodra wrote:You know, I think you are right on second though. However, it is a matter of not mistaking "left to right evaluation of arguments" with normal the associative behavior of operators. EG: (a = (b = c) = d): *a is evaluated *b is evaluated *c is evaluated *(b = c) is evaluad into a temp called bc *d is evaluated *bc = d is evaluated into bcd *a = bcd is evaluated. So back to my example: (where i starts at 1) x[i++] = ++i + 1; *i++ is evaluated to 1, and i is now 2. *x[i++] is now a reference to x[1] *++i is evaluated to 3 *++i + 1 is 4 *x[1] becomes 4 Yeah... it looks like it works.[SNIP]No it isn't. There's a perfectly sensible, sane, and intuitive fix for this: always evaluate arguments left-to-right. No exceptions. It's not that complicated.
Sep 26 2012
On Wednesday, September 26, 2012 17:12:49 Alex Rønne Petersen wrote:On 26-09-2012 15:34, monarch_dodra wrote:I'd still consider it to be bad practice to do anything which relies on the order of evaluation of function arguments, because the order is undefined in other languages, and if you get into the habit of doing stuff like func(++i, ++i, ++i) in D, you're going to be screwed when you have to program in other languages. It's just cleaner to avoid that kind of stuff, and I'd love it if it were illegal (a single ++i is fine - it's using i in multiple arguments _and_ modifying it in one of them which is the problem). That being said, defining the order will at least reduce bugs, even if it's considered bad practice to do anything in a function call which would rely on the arguments being evaluated in a particular order. - Jonathan M DavisIMO: useful behavior would be if it was explicitly illegal to modify (or modify + read) the same value twice in the same expression. I'd rather expressions such as: A()[] = B()[] + C()[]; x[i] = ++i + 1; Be illegal rather than have (an arbitrarily defined) specified behavior. Trying to specify a specific behavior in such cases is opening a can of worms.No it isn't. There's a perfectly sensible, sane, and intuitive fix for this: always evaluate arguments left-to-right. No exceptions. It's not that complicated.
Sep 26 2012
On 26-09-2012 19:23, Jonathan M Davis wrote:On Wednesday, September 26, 2012 17:12:49 Alex Rønne Petersen wrote:I do not know any other languages than C and C++ that leave it undefined. -- Alex Rønne Petersen alex lycus.org http://lycus.orgOn 26-09-2012 15:34, monarch_dodra wrote:I'd still consider it to be bad practice to do anything which relies on the order of evaluation of function arguments, because the order is undefined in other languages, and if you get into the habit of doing stuff like func(++i, ++i, ++i) in D, you're going to be screwed when you have to program in other languages. It's just cleaner to avoid that kind of stuff, and I'd love it if it were illegal (a single ++i is fine - it's using i in multiple arguments _and_ modifying it in one of them which is the problem). That being said, defining the order will at least reduce bugs, even if it's considered bad practice to do anything in a function call which would rely on the arguments being evaluated in a particular order. - Jonathan M DavisIMO: useful behavior would be if it was explicitly illegal to modify (or modify + read) the same value twice in the same expression. I'd rather expressions such as: A()[] = B()[] + C()[]; x[i] = ++i + 1; Be illegal rather than have (an arbitrarily defined) specified behavior. Trying to specify a specific behavior in such cases is opening a can of worms.No it isn't. There's a perfectly sensible, sane, and intuitive fix for this: always evaluate arguments left-to-right. No exceptions. It's not that complicated.
Sep 27 2012