I've been testing this myself and here are my findings so far.
The following code behaves as expected on Win64 x86_64:
program test;
uses
Classes, SysUtils;
begin
writeln('begin');
try
writeln('try');
exit;
finally
WriteLn('finally');
end;
WriteLn('end');
end.
On Win64 AArch64, however, it only prints "begin" and "try". The "finally" block is skipped, which suggests that the exit statement isn’t working correctly. Since exit should trigger the finally block, this is clearly an issue.
The root cause seems related to the missing implementation of g_local_unwind in compiler/aarch64/cgcpu.pas, though there are other dependencies:
1) In compiler/options.pas, enabling FPC_USE_WIN64_SEH for system_aarch_win64 activates _FPC_local_unwind.
2) I added a Win64-specific g_local_unwind override to the AArch64 code generator so that Windows ARM64 builds can hook custom unwinding:
procedure tcgaarch64.g_local_unwind(list: TAsmList; l: TAsmLabel);
var
para1, para2: tcgpara;
href: treference;
pd: tprocdef;
begin
if target_info.system<>system_aarch64_win64 then
begin
inherited g_local_unwind(list,l);
exit;
end;
pd:=search_system_proc('_fpc_local_unwind');
para1.init;
para2.init;
paramanager.getcgtempparaloc(list,pd,1,para1);
paramanager.getcgtempparaloc(list,pd,2,para2);
reference_reset_symbol(href,l,0,1,[]);
a_load_reg_cgpara(list,OS_ADDR,NR_STACK_POINTER_REG,para1);
a_loadaddr_ref_cgpara(list,href,para2);
paramanager.freecgpara(list,para2);
paramanager.freecgpara(list,para1);
g_call(list,'_FPC_local_unwind');
para2.done;
para1.done;
end;
With this change, the program now correctly prints "finally" — but unfortunately crashes immediately afterwards.