* use WebAssembly asm labels for the raise branch instruction in branchful

exceptions mode
This commit is contained in:
Nikolay Nikolov 2021-10-20 16:20:08 +03:00
parent 1b6219823b
commit 5a0956d805
3 changed files with 48 additions and 27 deletions

View File

@ -36,6 +36,10 @@ interface
tcpuprocinfo=class(tcgprocinfo) tcpuprocinfo=class(tcgprocinfo)
public public
{ label to the nearest local exception handler }
CurrRaiseLabel : tasmlabel;
constructor create(aparent: tprocinfo); override;
function calc_stackframe_size : longint;override; function calc_stackframe_size : longint;override;
procedure setup_eh; override; procedure setup_eh; override;
procedure generate_exit_label(list: tasmlist); override; procedure generate_exit_label(list: tasmlist); override;
@ -317,6 +321,13 @@ implementation
tcpuprocinfo tcpuprocinfo
*****************************************************************************} *****************************************************************************}
constructor tcpuprocinfo.create(aparent: tprocinfo);
begin
inherited create(aparent);
if ts_wasm_bf_exceptions in current_settings.targetswitches then
current_asmdata.getjumplabel(CurrRaiseLabel);
end;
function tcpuprocinfo.calc_stackframe_size: longint; function tcpuprocinfo.calc_stackframe_size: longint;
begin begin
{ the stack frame in WebAssembly should always have a 16-byte alignment } { the stack frame in WebAssembly should always have a 16-byte alignment }
@ -342,6 +353,8 @@ implementation
list.concat(taicpu.op_none(a_end_block)); list.concat(taicpu.op_none(a_end_block));
thlcgwasm(hlcg).decblock; thlcgwasm(hlcg).decblock;
inherited generate_exit_label(list); inherited generate_exit_label(list);
if ts_wasm_bf_exceptions in current_settings.targetswitches then
hlcg.a_label(list,CurrRaiseLabel);
end; end;
procedure tcpuprocinfo.postprocess_code; procedure tcpuprocinfo.postprocess_code;

View File

@ -56,7 +56,6 @@ uses
function is_methodptr_like_type(d:tdef): boolean; function is_methodptr_like_type(d:tdef): boolean;
public public
br_blocks: integer; br_blocks: integer;
raiseBr: integer; // raiseBr is only used in branchful exceptions mode (ts_wasm_bf_exceptions)
fntypelookup : TWasmProcTypeLookup; fntypelookup : TWasmProcTypeLookup;
constructor create; constructor create;
@ -257,7 +256,7 @@ implementation
uses uses
verbose,cutils,globals,fmodule,constexp, verbose,cutils,globals,fmodule,constexp,
defutil, defutil,cpupi,
aasmtai,aasmcpu, aasmtai,aasmcpu,
symtable,symcpu, symtable,symcpu,
procinfo,cpuinfo,cgcpu,tgobj,tgcpu,paramgr; procinfo,cpuinfo,cgcpu,tgobj,tgcpu,paramgr;
@ -2192,7 +2191,6 @@ implementation
inherited; inherited;
list.concat(taicpu.op_none(a_block)); list.concat(taicpu.op_none(a_block));
incblock; incblock;
raiseBr:=br_blocks;
end; end;
procedure thlcgwasm.gen_exit_code(list: TAsmList); procedure thlcgwasm.gen_exit_code(list: TAsmList);
@ -2282,7 +2280,7 @@ implementation
decstack(current_asmdata.CurrAsmList,1); decstack(current_asmdata.CurrAsmList,1);
list.concat(taicpu.op_const(a_br_if,br_blocks-raiseBr)); list.concat(taicpu.op_sym(a_br_if,tcpuprocinfo(current_procinfo).CurrRaiseLabel));
end; end;
end; end;

View File

@ -102,7 +102,7 @@ implementation
verbose,globals,systems,globtype,constexp, verbose,globals,systems,globtype,constexp,
symconst,symdef,symsym,symtype,aasmtai,aasmdata,aasmcpu,defutil,defcmp, symconst,symdef,symsym,symtype,aasmtai,aasmdata,aasmcpu,defutil,defcmp,
procinfo,cgbase,cgexcept,pass_1,pass_2,parabase,compinnr, procinfo,cgbase,cgexcept,pass_1,pass_2,parabase,compinnr,
cpubase,cpuinfo, cpubase,cpuinfo,cpupi,
nbas,nld,ncon,ncnv,ncal,ninl,nmem,nadd,nutils, nbas,nld,ncon,ncnv,ncal,ninl,nmem,nadd,nutils,
tgobj,paramgr, tgobj,paramgr,
cgutils,hlcgobj,hlcgcpu; cgutils,hlcgobj,hlcgcpu;
@ -634,21 +634,22 @@ implementation
destroytemps, destroytemps,
excepttemps: tcgexceptionstatehandler.texceptiontemps; excepttemps: tcgexceptionstatehandler.texceptiontemps;
afteronflowcontrol: tflowcontrol; afteronflowcontrol: tflowcontrol;
oldCurrRaiseLabel,
oldCurrExitLabel, oldCurrExitLabel,
oldContinueLabel, oldContinueLabel,
oldBreakLabel, NewContinueLabel, NewBreakLabel, oldBreakLabel, NewContinueLabel, NewBreakLabel,
NewCurrExitLabel: tasmlabel; NewCurrExitLabel, NewCurrRaiseLabel: tasmlabel;
oldRaiseBr: Integer;
in_loop: Boolean; in_loop: Boolean;
label label
errorexit; errorexit;
begin begin
oldCurrRaiseLabel:=nil;
oldCurrExitLabel:=nil; oldCurrExitLabel:=nil;
oldContinueLabel:=nil; oldContinueLabel:=nil;
oldBreakLabel:=nil; oldBreakLabel:=nil;
oldRaiseBr:=0;
NewContinueLabel:=nil; NewContinueLabel:=nil;
NewBreakLabel:=nil; NewBreakLabel:=nil;
NewCurrRaiseLabel:=nil;
location_reset(location,LOC_VOID,OS_NO); location_reset(location,LOC_VOID,OS_NO);
doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate); doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate);
@ -667,8 +668,9 @@ implementation
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
thlcgwasm(hlcg).incblock; thlcgwasm(hlcg).incblock;
oldRaiseBr:=thlcgwasm(hlcg).raiseBr; oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
thlcgwasm(hlcg).raiseBr:=thlcgwasm(hlcg).br_blocks; current_asmdata.getjumplabel(NewCurrRaiseLabel);
tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
{ try block } { try block }
secondpass(left); secondpass(left);
@ -680,9 +682,10 @@ implementation
current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1));
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
thlcgwasm(hlcg).decblock; thlcgwasm(hlcg).decblock;
hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp; hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
thlcgwasm(hlcg).raiseBr:=oldRaiseBr; tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions]; flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
{ on statements } { on statements }
@ -726,8 +729,9 @@ implementation
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
thlcgwasm(hlcg).incblock; thlcgwasm(hlcg).incblock;
oldRaiseBr:=thlcgwasm(hlcg).raiseBr; oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
thlcgwasm(hlcg).raiseBr:=thlcgwasm(hlcg).br_blocks; current_asmdata.getjumplabel(NewCurrRaiseLabel);
tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
{ the 'exit' block } { the 'exit' block }
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
@ -800,6 +804,7 @@ implementation
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
thlcgwasm(hlcg).decblock; thlcgwasm(hlcg).decblock;
hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
current_procinfo.CurrExitLabel:=oldCurrExitLabel; current_procinfo.CurrExitLabel:=oldCurrExitLabel;
if in_loop then if in_loop then
@ -807,7 +812,7 @@ implementation
current_procinfo.CurrContinueLabel:=oldContinueLabel; current_procinfo.CurrContinueLabel:=oldContinueLabel;
current_procinfo.CurrBreakLabel:=oldBreakLabel; current_procinfo.CurrBreakLabel:=oldBreakLabel;
end; end;
thlcgwasm(hlcg).raiseBr:=oldRaiseBr; tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp; hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp; hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
@ -836,7 +841,7 @@ implementation
{ return all used control flow statements } { return all used control flow statements }
flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol + flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]); trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
thlcgwasm(hlcg).raiseBr:=oldRaiseBr; tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
end; end;
procedure twasmtryexceptnode.pass_generate_code; procedure twasmtryexceptnode.pass_generate_code;
@ -1253,13 +1258,14 @@ implementation
procedure twasmtryfinallynode.pass_generate_code_bf_exceptions; procedure twasmtryfinallynode.pass_generate_code_bf_exceptions;
var var
raisefinallylabel,
exitfinallylabel, exitfinallylabel,
continuefinallylabel, continuefinallylabel,
breakfinallylabel, breakfinallylabel,
oldCurrRaiseLabel,
oldCurrExitLabel, oldCurrExitLabel,
oldContinueLabel, oldContinueLabel,
oldBreakLabel: tasmlabel; oldBreakLabel: tasmlabel;
oldRaiseBr: integer;
finallyexceptionstate: tcgexceptionstatehandler.texceptionstate; finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
excepttemps : tcgexceptionstatehandler.texceptiontemps; excepttemps : tcgexceptionstatehandler.texceptiontemps;
exceptframekind: tcgexceptionstatehandler.texceptframekind; exceptframekind: tcgexceptionstatehandler.texceptframekind;
@ -1305,11 +1311,11 @@ implementation
begin begin
location_reset(location,LOC_VOID,OS_NO); location_reset(location,LOC_VOID,OS_NO);
oldCurrRaiseLabel:=nil;
oldBreakLabel:=nil; oldBreakLabel:=nil;
oldContinueLabel:=nil; oldContinueLabel:=nil;
continuefinallylabel:=nil; continuefinallylabel:=nil;
breakfinallylabel:=nil; breakfinallylabel:=nil;
oldRaiseBr:=0;
in_loop:=assigned(current_procinfo.CurrBreakLabel); in_loop:=assigned(current_procinfo.CurrBreakLabel);
@ -1365,8 +1371,9 @@ implementation
{ the inner 'try..end_try' block } { the inner 'try..end_try' block }
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
thlcgwasm(hlcg).incblock; thlcgwasm(hlcg).incblock;
oldRaiseBr:=thlcgwasm(hlcg).raiseBr; oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
thlcgwasm(hlcg).raiseBr:=thlcgwasm(hlcg).br_blocks; current_asmdata.getjumplabel(raisefinallylabel);
tcpuprocinfo(current_procinfo).CurrRaiseLabel:=raisefinallylabel;
{ try code } { try code }
if assigned(left) then if assigned(left) then
@ -1388,6 +1395,7 @@ implementation
{ exit the inner 'try..end_try' block } { exit the inner 'try..end_try' block }
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
thlcgwasm(hlcg).decblock; thlcgwasm(hlcg).decblock;
hlcg.a_label(current_asmdata.CurrAsmList,raisefinallylabel);
{ exceptionreason:=1 (exception) } { exceptionreason:=1 (exception) }
hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp; hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
@ -1427,8 +1435,7 @@ implementation
{ end cleanup } { end cleanup }
current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd)); current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
{ restore previous raiseBr } tcpuprocinfo(current_procinfo).CurrRaiseLabel:=oldCurrRaiseLabel;
thlcgwasm(hlcg).raiseBr:=oldRaiseBr;
{ finally code (don't unconditionally set fc_inflowcontrol, since the { finally code (don't unconditionally set fc_inflowcontrol, since the
finally code is unconditionally executed; we do have to filter out finally code is unconditionally executed; we do have to filter out
@ -1654,19 +1661,20 @@ implementation
exceptvarsym : tlocalvarsym; exceptvarsym : tlocalvarsym;
exceptlocdef: tdef; exceptlocdef: tdef;
exceptlocreg: tregister; exceptlocreg: tregister;
oldCurrRaiseLabel,
oldCurrExitLabel, oldCurrExitLabel,
oldContinueLabel, oldContinueLabel,
oldBreakLabel, NewContinueLabel, NewBreakLabel, oldBreakLabel, NewContinueLabel, NewBreakLabel,
NewCurrExitLabel: tasmlabel; NewCurrRaiseLabel, NewCurrExitLabel: tasmlabel;
oldRaiseBr: Integer;
in_loop: Boolean; in_loop: Boolean;
doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate; doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
excepttemps: tcgexceptionstatehandler.texceptiontemps; excepttemps: tcgexceptionstatehandler.texceptiontemps;
begin begin
oldCurrRaiseLabel:=nil;
oldCurrExitLabel:=nil; oldCurrExitLabel:=nil;
oldContinueLabel:=nil; oldContinueLabel:=nil;
oldBreakLabel:=nil; oldBreakLabel:=nil;
oldRaiseBr:=0; NewCurrRaiseLabel:=nil;
NewBreakLabel:=nil; NewBreakLabel:=nil;
NewContinueLabel:=nil; NewContinueLabel:=nil;
location_reset(location,LOC_VOID,OS_NO); location_reset(location,LOC_VOID,OS_NO);
@ -1704,8 +1712,9 @@ implementation
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
thlcgwasm(hlcg).incblock; thlcgwasm(hlcg).incblock;
oldRaiseBr:=thlcgwasm(hlcg).raiseBr; oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
thlcgwasm(hlcg).raiseBr:=thlcgwasm(hlcg).br_blocks; current_asmdata.getjumplabel(NewCurrRaiseLabel);
tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
{ the 'exit' block } { the 'exit' block }
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
@ -1779,6 +1788,7 @@ implementation
current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
thlcgwasm(hlcg).decblock; thlcgwasm(hlcg).decblock;
hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
current_procinfo.CurrExitLabel:=oldCurrExitLabel; current_procinfo.CurrExitLabel:=oldCurrExitLabel;
if in_loop then if in_loop then
@ -1786,7 +1796,7 @@ implementation
current_procinfo.CurrContinueLabel:=oldContinueLabel; current_procinfo.CurrContinueLabel:=oldContinueLabel;
current_procinfo.CurrBreakLabel:=oldBreakLabel; current_procinfo.CurrBreakLabel:=oldBreakLabel;
end; end;
thlcgwasm(hlcg).raiseBr:=oldRaiseBr; tcpuprocinfo(current_procinfo).CurrRaiseLabel:=oldCurrRaiseLabel;
hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp; hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp; hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;