From f2abce7ea58decf10255bdfea14740578068dd4a Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Tue, 28 Sep 2021 20:23:27 +0300 Subject: [PATCH] + initial implementation of try..except..end in wasm native exceptions mode. The 'on' statements are not implemented yet. --- compiler/wasm32/nwasmflw.pas | 102 ++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/compiler/wasm32/nwasmflw.pas b/compiler/wasm32/nwasmflw.pas index 4c016a1ef7..cea1902b58 100644 --- a/compiler/wasm32/nwasmflw.pas +++ b/compiler/wasm32/nwasmflw.pas @@ -88,7 +88,7 @@ implementation symconst,symdef,symsym,aasmtai,aasmdata,aasmcpu,defutil,defcmp, procinfo,cgbase,cgexcept,pass_1,pass_2,parabase,compinnr, cpubase,cpuinfo, - nbas,nld,ncon,ncnv,ncal,ninl,nmem,nadd, + nbas,nld,ncon,ncnv,ncal,ninl,nmem,nadd,nutils, tgobj,paramgr, cgutils,hlcgobj,hlcgcpu; @@ -365,9 +365,109 @@ implementation end; procedure twasmtryexceptnode.pass_generate_code_native_exceptions; + var + trystate,doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate; + destroytemps, + excepttemps: tcgexceptionstatehandler.texceptiontemps; + afteronflowcontrol: tflowcontrol; + label + errorexit; begin location_reset(location,LOC_VOID,OS_NO); + + { Exception temps? We don't need no stinking exception temps! :) } + fillchar(excepttemps,sizeof(excepttemps),0); + reference_reset(excepttemps.envbuf,0,[]); + reference_reset(excepttemps.jmpbuf,0,[]); + reference_reset(excepttemps.reasonbuf,0,[]); + + //exceptstate.oldflowcontrol:=flowcontrol; + //flowcontrol:=[fc_inflowcontrol,fc_catching_exceptions]; + cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,trystate); + + current_asmdata.CurrAsmList.concat(taicpu.op_none(a_try)); + thlcgwasm(hlcg).incblock; + + { try block } secondpass(left); + if codegenerror then + goto errorexit; + + //exceptionstate.newflowcontrol:=flowcontrol; + //flowcontrol:=exceptionstate.oldflowcontrol; + cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,nil); + + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG))); + + flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions]; + { on statements } + //if assigned(right) then + // secondpass(right); + + afteronflowcontrol:=flowcontrol; + + { default handling except handling } + if assigned(t1) then + begin + { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called, + it doesn't change any state and its return value is ignored (Sergei) + } + + { the destruction of the exception object must be also } + { guarded by an exception frame, but it can be omitted } + { if there's no user code in 'except' block } + + if not (has_no_code(t1)) then + begin + { if there is an outer frame that catches exceptions, remember this for the "except" + part of this try/except } + flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]; + { Exception temps? We don't need no stinking exception temps! :) } + fillchar(excepttemps,sizeof(destroytemps),0); + reference_reset(destroytemps.envbuf,0,[]); + reference_reset(destroytemps.jmpbuf,0,[]); + reference_reset(destroytemps.reasonbuf,0,[]); + cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate); + { the flowcontrol from the default except-block must be merged + with the flowcontrol flags potentially set by the + on-statements handled above (secondpass(right)), as they are + at the same program level } + flowcontrol:= + flowcontrol+ + afteronflowcontrol; + + current_asmdata.CurrAsmList.concat(taicpu.op_none(a_try)); + thlcgwasm(hlcg).incblock; + + secondpass(t1); + + hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp; + + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG))); + + hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp; + + current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_try)); + end + else + begin + doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol; + hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp; + end; + end + else + begin + current_asmdata.CurrAsmList.concat(taicpu.op_const(a_rethrow,0)); + doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol; + end; + + current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_try)); + thlcgwasm(hlcg).decblock; + + errorexit: + { return all used control flow statements } + flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol + + trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]); end; procedure twasmtryexceptnode.pass_generate_code;