Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2013-10

Argument evaluation order in Free Pascal and Delphi

11 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Michael Van Canneyt
to Dmitry Pribysh:
Dmitry Pribysh wrote
Hi,   As it is written in Free Pascal wiki, order of parameter evaluation is not defined in FPC, but it is defined in Delphi (Delphi guarantees left-to-right evaluation order).

Strange. Where is that documented ?

Michael.

Sven Barth
to Michael Van Canneyt
"Michael Van Canneyt" wrote 8 lines
On Mon, 28 Oct 2013, Dmitry Pribysh wrote: > Hi, > > As it is written in Free Pascal wiki, order of parameter evaluation is

not defined in FPC, but it is defined in Delphi (Delphi

> guarantees left-to-right evaluation order). Strange. Where is that documented ?

We document it ourselves here:
http://wiki.freepascal.org/Code_Conversion_Guide#Order_of_parameter_evaluation The Delphi documentation is however rather vague:
http://docwiki.embarcadero.com/RADStudio/XE5/en/Procedures_and_Functions#Calling_Conventions

Regards,
Sven

Jonas Maebe
to Michael Van Canneyt: Strange. Where is that documented ? Michael.
Michael Van Canneyt wrote 6 lines
On Mon, 28 Oct 2013, Dmitry Pribysh wrote: > As it is written in Free Pascal wiki, order of parameter evaluation is not defined in FPC, but it is defined in Delphi (Delphi > guarantees left-to-right evaluation order). Strange. Where is that documented ?

In the Delphi documentation in the past, but apparently this has changed (both the documentation and the implementation). Now it says that the order is undefined. See http://stackoverflow.com/questions/11010456/in-delphi-are-parameters-evaluated-in-order-when-passed-into-a-method, the linked Delphi documentation page at http://docwiki.embarcadero.com/RADStudio/XE5/en/Procedures_and_Functions#Calling_Conventions and Barry Kelly's blog post from 2008 at http://blog.barrkel.com/2008/04/c-evaluation-order-gotcha.html?m=1

Jonas

Michael Van Canneyt
to Sven Barth: not defined in FPC, but it is defined in Delphi (Delphi We document it ourselves here:…
Sven Barth wrote 18 lines
Am 29.10.2013 08:35 schrieb "Michael Van Canneyt" : > > > > On Mon, 28 Oct 2013, Dmitry Pribysh wrote: > >> Hi, >>   >> As it is written in Free Pascal wiki, order of parameter evaluation is not defined in FPC, but it is defined in Delphi (Delphi >> guarantees left-to-right evaluation order). > > > Strange. Where is that documented ? We document it ourselves here: http://wiki.freepascal.org/Code_Conversion_Guide#Order_of_parameter_evaluation

This I know, I meant where is the delphi documentation of left-to-right evaluation order ?

I know this, and it says explicitly

"For the register and pascal conventions, the evaluation order is not defined."

Which is why I thought the original poster's statement to be wrong.

But maybe Delphi changed since I last read that, but apparently not.

Michael.

Jonas Maebe
to Michael Van Canneyt
Michael Van Canneyt wrote 9 lines
On Tue, 29 Oct 2013, Sven Barth wrote: > The Delphi documentation is however rather vague: > http://docwiki.embarcadero.com/RADStudio/XE5/en/Procedures_and_Functions#Calling_Conventions I know this, and it says explicitly "For the register and pascal conventions, the evaluation order is not defined."

I think they use "evaluation order" as a synonym for "parameter passing order" on that page, given the table below: it says that the order in which the parameters are passed for register/pascal is undefined. That basically means that pure assembler routines using the register or pascal calling conventions are no longer supported in Delphi, since you can't know how the parameters are passed (or at least there are no guarantees about it).

Jonas

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 19 lines
On 29 Oct 2013, at 09:44, Michael Van Canneyt wrote: > On Tue, 29 Oct 2013, Sven Barth wrote: > >> The Delphi documentation is however rather vague: >> http://docwiki.embarcadero.com/RADStudio/XE5/en/Procedures_and_Functions#Calling_Conventions > > I know this, and it says explicitly > > "For the register and pascal conventions, the evaluation order is not > defined." I think they use "evaluation order" as a synonym for "parameter passing order" on that page, given the table below: it says that the order in which the parameters are passed for register/pascal is undefined. That basically means that pure assembler routines using the register or pascal calling conventions are no longer supported in Delphi, since you can't know how the parameters are passed (or at least there are no guarantees about it).

Probably a consequence of their adding a new llvm backend architecture.

Michael.

Jonas Maebe
to Michael Van Canneyt
Michael Van Canneyt wrote 14 lines
On Tue, 29 Oct 2013, Jonas Maebe wrote: > I think they use "evaluation order" as a synonym for "parameter > passing order" on that page, given the table below: it says that > the order in which the parameters are passed for register/pascal is > undefined. That basically means that pure assembler routines using > the register or pascal calling conventions are no longer supported > in Delphi, since you can't know how the parameters are passed (or > at least there are no guarantees about it). Probably a consequence of their adding a new llvm backend architecture.

I also thought that at first, but on the other hand LLVM doesn't have any built-in support for "a calling convention that passes parameters in registers whereby the callee is responsible for the stack cleanup", and yet Embarcardero still advertises the "register" calling convention as doing exactly that (I guess as an alternative for "pascal", they can use stdcall since that one also passes everything on the stack and has callee-side cleanup iirc). If they added it themselves in a private LLVM branch, I don't understand why they didn't implement it in a way that was compatible with existing code.

Jonas

Michael Schnell
to Dmitry Pribysh:
Dmitry Pribysh wrote 5 lines
As it is written in Free Pascal wiki <http://wiki.freepascal.org/Code_Conversion_Guide#Order_of_parameter_evaluation>, order of parameter evaluation is not defined in FPC, but it is defined in Delphi (Delphi guarantees left-to-right evaluation order).

IMHO =in fact evaluation of a parameter should not be compiler should be free to inline a function, detect that the parameter is not necessary for the evaluation of the function result and drop the evaluation of the parameter (maybe giving a warning or error message if that might trigger side-effects).

-Michael

Sven Barth
to Michael Schnell
Michael Schnell wrote 12 lines
On 10/28/2013 02:47 PM, Dmitry Pribysh wrote: > As it is written in Free Pascal wiki > <http://wiki.freepascal.org/Code_Conversion_Guide#Order_of_parameter_evaluation>, > order of parameter evaluation is not defined in FPC, but it is > defined in Delphi (Delphi guarantees left-to-right evaluation order). > IMHO =in fact evaluation of a parameter should not be guaranteed at all. The compiler should be free to inline a function, detect that the parameter is not necessary for the evaluation of the function result and drop the evaluation of the parameter (maybe giving a warning or error message if that might trigger side-effects).

1. FPC does not guarantee evaluation order exactly for this reason
2. The compiler already does this inlining already in that way (at least partially).
Take this code:

=== code begin ===

program tinlinetest;
{$mode objfpc}
function GetStr1: String; inline;
begin
   Result := 'Hello World';
end;
function GetStr2: String;
begin
   Result := 'Hello World';
end;
function Test(aArg1: Integer; aArg2: String): Integer; inline;
begin
   Result := aArg1 * 42;
end;
begin
   Writeln(Test(42, 'Hello World'));
   Writeln(Test(42, GetStr1));
   Writeln(Test(42, GetStr2));
end.

=== code end ===

this will produce this output in the main function (2.7.1 and compiled with -O2):

=== assembler begin ===

PASCALMAIN:
.globl _main
_main:
# Temps allocated between esp+0 and esp+512
# [20] begin
pushl %ebx
addl $-512,%esp
call FPC_INITIALIZEUNITS
# [21] Writeln(Test(42, 'Hello World'));

   // No usage of 'Hello World' constant here
     call    fpc_get_output
     movl    %eax,%ebx
     movl    %ebx,%edx
     movl    $1764,%ecx
     movl    $0,%eax
     call    fpc_write_text_sint
     call    FPC_IOCHECK
     movl    %ebx,%eax
     call    fpc_writeln_end
     call    FPC_IOCHECK

# [22] Writeln(Test(42, GetStr1));

   // here this might be a bug... the compiler inlines GetStr1, but does

not detect that its result is constant and not used... call fpc_get_output
movl %eax,%ebx
movl $_$TINLINETEST$_Ld1,%ecx
leal 256(%esp),%eax
movl $255,%edx
call fpc_shortstr_to_shortstr
leal 256(%esp),%ecx
movl %esp,%eax
movl $255,%edx
call fpc_shortstr_to_shortstr
movl $1764,%ecx
movl %ebx,%edx
movl $0,%eax
call fpc_write_text_sint
call FPC_IOCHECK
movl %ebx,%eax
call fpc_writeln_end
call FPC_IOCHECK
# [23] Writeln(Test(42, GetStr2));

   // here it can not inline GetStr2, because it can not detect whether

GetStr2 is sideeffect free
call fpc_get_output
movl %eax,%ebx
leal 256(%esp),%eax
call P$TINLINETEST_$$_GETSTR2$$SHORTSTRING
leal 256(%esp),%ecx
movl %esp,%eax
movl $255,%edx
call fpc_shortstr_to_shortstr
movl $1764,%ecx
movl %ebx,%edx
movl $0,%eax
call fpc_write_text_sint
call FPC_IOCHECK
movl %ebx,%eax
call fpc_writeln_end
call FPC_IOCHECK
# [24] end.
call FPC_DO_EXIT
addl $512,%esp
popl %ebx
ret

=== assembler end ===

So case 2 could be improved a bit.
And for case 3 it might be interesting to have the compiler mark functions with additional flags to check whether they are e.g. "constant" or access memory (aside from parameters) in a writing way, etc. This *might* improve some optimizations...

Regards,
Sven