PascalScript and XE2 X64

I can compile PascalScript with XE2 as x64 and it works fine with one exception:

Functions with a string return type crash with access violation.
But this belongs only to functions which defined with “AddDelphiFunction”/“RegisterDelphiFunction” (for example: DateToStr()).
Internal functions (for example: IntToStr() / defined with “RegisterFunctionName”) works fine.

Point of crash: function x64call() in x64.inc

Hello,
Thanks, the issue was logged as #55498

Any news about this issue?

Hello,
Sorry for delay, but it is slill in progress.

What news by this bug?

Hello,
Unfortunately, PascalScript is obsolete and has low priority. This bug is still in progress.

I think there is a define missing for Delphi:
{$DEFINE x64_string_result_as_varparameter}

this is only set for freepascal, but delphi will also pass the result as a var parameter.

You made my day.

A second define is needed.
If i add the following lines in PascalScript.inc after {$DEFINE PS_DYNARRAY}:
{$IFDEF CPUX64}
{$DEFINE PS_RESBEFOREPARAMETERS}
{$DEFINE x64_string_result_as_varparameter}
{$ENDIF}

all functions with string result type returns correct values.

But this makes the next problem visible.
All functions with Double (or TDateTime) result (“Now” or “EncodeDate” for example) returns always 0.
On functions with Double/TDateTime var parameter (as in “TryEncodeDate”) the result value is correct.

I have now a workaround for the Double/TDateTime result problem which works for me.

In X64.inc:

procedure x64call(
Address: Pointer;
out _RAX: IPointer;
_RCX, _RDX, _R8, _R9: IPointer;
var _XMM0: Double;
_XMM1, _XMM2, _XMM3: Double;
aStack: Pointer; aItems: IntPtr); assembler; {$IFDEF FPC}nostackframe;{$ENDIF}

_XMM0 is defined as var parameter and in the following statement
movsd xmm0,[_XMM0]
the register xmm0 is not correctly set with the value of _XMM0

I don’t know why this assignment goes wrong.

I changed the definition to

function x64call(
Address: Pointer;
out _RAX: IPointer;
_RCX, _RDX, _R8, _R9: IPointer;
_XMM0: Double;
_XMM1, _XMM2, _XMM3: Double;
aStack: Pointer; aItems: IntPtr): Double; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}

the statement from
movsd xmm0,[_XMM0]
to
movsd xmm0,_XMM0

and on the nearly end of the function
movsd [_XMM0],xmm0
to
// movsd [_XMM0],xmm0
(the result type Double uses the xmm0 register so no assignment is needed)

And the two calls to x64call() must be changed from
x64call(Address, _RAX, _RCX, _RDX, _R8, _R9, _XMM0, _XMM1, _XMM2, _XMM3, pp, Length(Stack) div 8);
to
_XMM0 := x64call(Address, _RAX, _RCX, _RDX, _R8, _R9, _XMM0, _XMM1, _XMM2, _XMM3, pp, Length(Stack) div 8);

_XMM0 is defined as var parameter and in the following statement movsd xmm0,[_XMM0] the register xmm0 is not correctly set with the value of _XMM0

I don’t know why this assignment goes wrong.

The var parameter is not dereference correctly, so xmm0 will not get the value but the address of the var parameter. The same problem is where the result should be copied back, here the return value is set as the new address for the var parameter.

Delphi XE2 will generate the same code for the following two lines:
movsd xmm0,[_XMM0]
movsd xmm0,_XMM0
The result for both will be:
movsd xmm0,qword ptr [rbp+$40]

So in both cases xmm0 will be set to the content of rbp+$40, which is the address and not the value of the var parameter.

I fixed this with this two changes to procedure x64call
movsd xmm0,[_XMM0]
replaced with:
mov RAX, _XMM0;
movsd xmm0,[RAX]

and for the result
movsd [_XMM0],xmm0
replaced with:
mov RDX, _XMM0
movsd [RDX], xmm0

So we found a new compiler bug :slight_smile: :frowning:
Your solution works and is a few more elegant. Thanks.