[fpc-pascal] const records passed incorrectly
Anthony Walter
sysrpl at gmail.com
Mon Nov 16 14:50:40 CET 2009
Actually the help does. The first thing I did when I got to work with
morning was top open my Delphi 7 help file and typed "const" then
choose the topic "constant (const) parameters".
Quote:
"Using const allows the compiler to optimize code for structured- and
string-type parameters."
Using const with string type and structured types causes a known
optimization to pass references rather than copies on the stack. The
key is Delphi checks code in the callee making sure you don't try to
write to the const parameter.
This is useful not only for speed purposes, but for operability with C
code like below (take from the Windows Platform SDK help file):
BOOL RectVisible(
HDC hdc, // handle of the device context
CONST RECT *lprc // address of rectangle structure
);
Delphi declares this import as follows:
function RectVisible(DC: HDC; const Rect: TRect): BOOL; stdcall;
Note the "const Rect: TRect"
Now I wrote an example to test the differences between FPC (version
2.2.4) and Delphi (version 7). I found something interesting, please
read the results at the bottom.
Code:
program test;
{$APPTYPE CONSOLE}
type
TRect = record
Left, Top, Right, Bottom: Integer;
end;
procedure A(const R: TRect; P: Pointer);
begin
if @R = P then
WriteLn('R refers to a reference on the stack')
else
WriteLn('R is a structure on the stack');
end;
procedure B;
var
R: TRect;
begin
A(R, @R);
end;
begin
B;
end.
Output:
FPC: "R refers to a reference on the stack"
Delphi: "R refers to a reference on the stack"
Which is exactly correct with both compilers. So there is no problem,
my original problem doesn't apply.
***** BUT *****
There is a problem with the above code on FPC when you change calling
conventions of A.
If you change the calling convention to stdcall it still works, no
problem. Both FPC and Delphi output "R refers to a reference on the
stack."
On the other hand, changing to cdecl breaks things on the FPC side.
procedure A(const R: TRect; P: Pointer); cdecl;
Output:
FPC: "R is a structure on the stack"
Delphi: "R refers to a reference on the stack"
See, FPC is now working differently. This is causing me headaches when
I am writing code to import libc (which uses cdecl).
I believe FPC is in error when it is generating code to pass const
structures (which I've tested). It handles parameters one way with
fastcall, stdcall, pascal (which I believe is the correct way), and a
different way with cdecl.
I've tested Delphi and it always uses a reference on the stack with
all calling conventions using the code above.
I've provided the information from the Delphi help file which
documents this feature.
On Mon, Nov 16, 2009 at 2:59 AM, Michael Van Canneyt
<michael at freepascal.org> wrote:
>
>
> On Sun, 15 Nov 2009, Anthony Walter wrote:
>
>> Hi all. I am new to fpc and linux in general, though I do have a long
>> time experience with Delphi.
>>
>> I was writing some code basic system (using the libc library) when I
>> ran across the following problem .. some code:
>>
>> const
>> libc = 'libc.so.6';
>>
>> type
>> TTimeSpec = record
>> Sec: Cardinal; { Seconds }
>> NSec: Cardinal; { Nanoseconds }
>> end;
>> PTimeSpec = ^TTimeSpec;
>>
>> function nanosleep(const RequestedTime: TTimeSpec; Remaining:
>> PTimeSpec): Integer; cdecl; external libc;
>>
>> The problem with fpc and the above import is with the RequestedTime
>> parameter, declared as a const record. In Delphi declaring a const
>> record parameter cause the compiler to generate code to pass the
>> record by reference (that is to say passing the address). In fpc,
>> however this is not happening.
>
> No.
>
> It is nowhere written in the Delphi specs that const parameters
> are passed by reference. It is often so, but is by no means guaranteed.
>
> If you want to pass it as a reference, you should use var. Not const.
>
> Const means that the called procedure does not change the contents.
> The compiler may then decide to pass it by reference if it is more
> advantageous to do so, but it is not a rule that this is done.
>
> Michael.
> _______________________________________________
> fpc-pascal maillist - fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
More information about the fpc-pascal
mailing list