From bf191fe538a37d0469946ff360dee935cd32bcd2 Mon Sep 17 00:00:00 2001 From: TetzkatLipHoka Date: Sat, 11 Jul 2026 18:48:01 +0200 Subject: [PATCH] x64: pass by-value dynamic arrays as pointer value on FPC 3+ The classic x64 path passed by-value dynamic array parameters as the ADDRESS of the variable slot on FPC ({$IFDEF FPC} FVar.Dta instead of FVar.Dta^), a leftover from an FPC 2.4-era fix. On FPC 3.x x86_64-linux the callee then reads garbage instead of the array (Length() returns random values, element access crashes with an access violation). A dynamic array IS a pointer on every current target: pass its value, like the Delphi branch always did. The 2.4 behavior is kept behind {$IF FPC_VERSION < 3}. Repro (fails on master with the FPC-compilation fixes applied, passes with this change; fpc 3.2.2 x86_64-linux): host: function DynTake(const A: TArr): Integer; // TArr = array of string script: SetLength(a, 2); a[0] := 'x'; a[1] := 'y'; n := DynTake(a); Delphi Win64 classic path unchanged and re-verified. Co-Authored-By: Claude Fable 5 --- Source/x64.inc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/x64.inc b/Source/x64.inc index d06ba115..5eaf3732 100644 --- a/Source/x64.inc +++ b/Source/x64.inc @@ -760,11 +760,14 @@ _XMM0: Double; Result := True; exit; end else begin - {$IFDEF FPC} + {$IF DEFINED(FPC) AND (FPC_VERSION < 3)} + { kept for the old FPC 2.4 ABI this branch was written for } StoreReg(IPointer(FVar.Dta)); {$ELSE} + { a dynamic array is a pointer: pass its value, not the slot + address (FPC 3.x x86_64 crashed / read garbage here) } StoreReg(IPointer(FVar.Dta^)); - {$ENDIF} + {$IFEND} end; end; btSet,