aarch64-win64: const method pointer parameters not passed by reference, breaking generics comparers
Description
On aarch64-win64, const record parameters are passed by reference (commit 0430e1bd), but const method pointer parameters (procvardef) are still passed by value. This causes a calling convention mismatch when the generics system uses TCompare.Method(const ALeft, ARight: TMethod) (recorddef, by reference) through a VMT where the actual type is a method pointer like TMyMethod = procedure(A: Integer) of object (procvardef, by value).
Reproducer
program test_method_list;
{$mode objfpc}{$H+}
uses Generics.Collections;
type
TMyMethod = procedure(A: Integer) of object;
TMyMethodList = TList<TMyMethod>;
TSomeClass = class
procedure Foo(A: Integer);
end;
procedure TSomeClass.Foo(A: Integer);
begin
end;
var
List: TMyMethodList;
C: TSomeClass;
begin
C := TSomeClass.Create;
List := TMyMethodList.Create;
try
List.Add(C.Foo);
WriteLn(List.IndexOf(C.Foo)); // Expected: 0, Got: -1 on aarch64-win64
finally
List.Free;
C.Free;
end;
end.
Root cause
In compiler/aarch64/cpupara.pas, push_addr_param has a special case for recorddef on aarch64-win64:
recorddef:
result:=
((varspez=vs_const) and
(target_info.system=system_aarch64_win64)
) or ...
But procvardef (method pointers, nested procvars) falls through to the default else branch, returning false (by value). Method pointers are 16-byte composites (Code + Data), structurally identical to TMethod records, and should follow the same convention.
The caller generates by-value code (two registers), the callee expects by-reference (pointer in register). CompareMemRange in the callee reads garbage, so IndexOf always returns -1.
Fix
Add a procvardef case to push_addr_param:
procvardef:
result:=
(varspez=vs_const) and
(target_info.system=system_aarch64_win64) and
not tprocvardef(def).is_addressonly;
This only affects method pointers and nested procvars (composites). Plain procedure variables (is_addressonly = true) and WinAPI callbacks are unaffected.
Affected test
TTestStdCollections.Test_MethodsList from rtl-generics test suite fails on aarch64-win64 (passes on x86_64-win64).