|
@@ -511,8 +511,183 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure twasmtryfinallynode.pass_generate_code_native_exceptions;
|
|
procedure twasmtryfinallynode.pass_generate_code_native_exceptions;
|
|
|
|
+ var
|
|
|
|
+ exitfinallylabel,
|
|
|
|
+ continuefinallylabel,
|
|
|
|
+ breakfinallylabel,
|
|
|
|
+ oldCurrExitLabel,
|
|
|
|
+ oldContinueLabel,
|
|
|
|
+ oldBreakLabel: tasmlabel;
|
|
|
|
+ oldLoopContBr: integer;
|
|
|
|
+ oldLoopBreakBr: integer;
|
|
|
|
+ oldExitBr: integer;
|
|
|
|
+ finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
|
|
|
|
+ excepttemps : tcgexceptionstatehandler.texceptiontemps;
|
|
|
|
+ exceptframekind: tcgexceptionstatehandler.texceptframekind;
|
|
|
|
+ in_loop: Boolean;
|
|
|
|
+
|
|
|
|
+ procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
|
|
|
|
+ var
|
|
|
|
+ reasonreg : tregister;
|
|
|
|
+ begin
|
|
|
|
+ reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
|
|
|
|
+ hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
|
|
|
|
+ thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
|
|
|
|
+ thlcgwasm(hlcg).incblock;
|
|
|
|
+ thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,br+1));
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
|
|
|
|
+ thlcgwasm(hlcg).decblock;
|
|
|
|
+ end;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
- internalerror(2021091703);
|
|
|
|
|
|
+ location_reset(location,LOC_VOID,OS_NO);
|
|
|
|
+ oldBreakLabel:=nil;
|
|
|
|
+ oldContinueLabel:=nil;
|
|
|
|
+ continuefinallylabel:=nil;
|
|
|
|
+ breakfinallylabel:=nil;
|
|
|
|
+
|
|
|
|
+ in_loop:=assigned(current_procinfo.CurrBreakLabel);
|
|
|
|
+
|
|
|
|
+ if not implicitframe then
|
|
|
|
+ exceptframekind:=tek_normalfinally
|
|
|
|
+ else
|
|
|
|
+ exceptframekind:=tek_implicitfinally;
|
|
|
|
+
|
|
|
|
+ { in 'no exceptions' mode, we still want to handle properly exit,
|
|
|
|
+ continue and break (they still need to execute the 'finally'
|
|
|
|
+ statements), so for this we need excepttemps.reasonbuf, and for this
|
|
|
|
+ reason, we need to allocate excepttemps }
|
|
|
|
+ cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
|
|
|
|
+ cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
|
|
|
|
+
|
|
|
|
+ { the finally block must catch break, continue and exit }
|
|
|
|
+ { statements }
|
|
|
|
+
|
|
|
|
+ { the outer 'try..finally' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
|
|
|
|
+ thlcgwasm(hlcg).incblock;
|
|
|
|
+
|
|
|
|
+ { the 'exit' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
|
|
|
|
+ thlcgwasm(hlcg).incblock;
|
|
|
|
+
|
|
|
|
+ oldCurrExitLabel:=current_procinfo.CurrExitLabel;
|
|
|
|
+ oldExitBr:=thlcgwasm(hlcg).exitBr;
|
|
|
|
+ exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
|
|
|
|
+ current_procinfo.CurrExitLabel:=exitfinallylabel;
|
|
|
|
+ thlcgwasm(hlcg).exitBr:=thlcgwasm(hlcg).br_blocks;
|
|
|
|
+
|
|
|
|
+ { the 'break' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
|
|
|
|
+ thlcgwasm(hlcg).incblock;
|
|
|
|
+
|
|
|
|
+ if in_loop then
|
|
|
|
+ begin
|
|
|
|
+ oldBreakLabel:=current_procinfo.CurrBreakLabel;
|
|
|
|
+ oldLoopBreakBr:=thlcgwasm(hlcg).loopBreakBr;
|
|
|
|
+ breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
|
|
|
|
+ current_procinfo.CurrBreakLabel:=breakfinallylabel;
|
|
|
|
+ thlcgwasm(hlcg).loopBreakBr:=thlcgwasm(hlcg).br_blocks;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ { the 'continue' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
|
|
|
|
+ thlcgwasm(hlcg).incblock;
|
|
|
|
+
|
|
|
|
+ if in_loop then
|
|
|
|
+ begin
|
|
|
|
+ oldContinueLabel:=current_procinfo.CurrContinueLabel;
|
|
|
|
+ oldLoopContBr:=thlcgwasm(hlcg).loopContBr;
|
|
|
|
+ continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
|
|
|
|
+ current_procinfo.CurrContinueLabel:=continuefinallylabel;
|
|
|
|
+ thlcgwasm(hlcg).loopContBr:=thlcgwasm(hlcg).br_blocks;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ { try code }
|
|
|
|
+ if assigned(left) then
|
|
|
|
+ begin
|
|
|
|
+ secondpass(left);
|
|
|
|
+ if codegenerror then
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ { don't generate line info for internal cleanup }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
|
|
|
|
+
|
|
|
|
+ cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
|
|
|
|
+
|
|
|
|
+ { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
|
|
|
|
+ hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,3)); // jump to the 'finally' section
|
|
|
|
+
|
|
|
|
+ { exit the 'continue' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
|
|
|
|
+ thlcgwasm(hlcg).decblock;
|
|
|
|
+ { exceptionreason:=4 (continue) }
|
|
|
|
+ hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
|
|
|
|
+
|
|
|
|
+ { exit the 'break' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
|
|
|
|
+ thlcgwasm(hlcg).decblock;
|
|
|
|
+ { exceptionreason:=3 (break) }
|
|
|
|
+ hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
|
|
|
|
+
|
|
|
|
+ { exit the 'exit' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
|
|
|
|
+ thlcgwasm(hlcg).decblock;
|
|
|
|
+ { exceptionreason:=2 (exit) }
|
|
|
|
+ hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
|
|
|
|
+ { proceed to the 'finally' section, which follow immediately, no need for jumps }
|
|
|
|
+
|
|
|
|
+ { exit the outer 'try..finally' block }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
|
|
|
|
+ thlcgwasm(hlcg).decblock;
|
|
|
|
+
|
|
|
|
+ { end cleanup }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
|
|
|
|
+
|
|
|
|
+ { finally code (don't unconditionally set fc_inflowcontrol, since the
|
|
|
|
+ finally code is unconditionally executed; we do have to filter out
|
|
|
|
+ flags regarding break/contrinue/etc. because we have to give an
|
|
|
|
+ error in case one of those is used in the finally-code }
|
|
|
|
+ flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
|
|
|
|
+ secondpass(right);
|
|
|
|
+ { goto is allowed if it stays inside the finally block,
|
|
|
|
+ this is checked using the exception block number }
|
|
|
|
+ if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
|
|
|
|
+ CGMessage(cg_e_control_flow_outside_finally);
|
|
|
|
+ if codegenerror then
|
|
|
|
+ exit;
|
|
|
|
+
|
|
|
|
+ { don't generate line info for internal cleanup }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
|
|
|
|
+
|
|
|
|
+ if fc_exit in finallyexceptionstate.newflowcontrol then
|
|
|
|
+ generate_exceptreason_check_br(2,thlcgwasm(hlcg).br_blocks-oldExitBr);
|
|
|
|
+ if fc_break in finallyexceptionstate.newflowcontrol then
|
|
|
|
+ generate_exceptreason_check_br(3,thlcgwasm(hlcg).br_blocks-oldLoopBreakBr);
|
|
|
|
+ if fc_continue in finallyexceptionstate.newflowcontrol then
|
|
|
|
+ generate_exceptreason_check_br(4,thlcgwasm(hlcg).br_blocks-oldLoopContBr);
|
|
|
|
+
|
|
|
|
+ cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
|
|
|
|
+
|
|
|
|
+ { end cleanup }
|
|
|
|
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
|
|
|
|
+
|
|
|
|
+ current_procinfo.CurrExitLabel:=oldCurrExitLabel;
|
|
|
|
+ thlcgwasm(hlcg).exitBr:=oldExitBr;
|
|
|
|
+ if assigned(current_procinfo.CurrBreakLabel) then
|
|
|
|
+ begin
|
|
|
|
+ current_procinfo.CurrContinueLabel:=oldContinueLabel;
|
|
|
|
+ thlcgwasm(hlcg).loopContBr:=oldLoopContBr;
|
|
|
|
+ current_procinfo.CurrBreakLabel:=oldBreakLabel;
|
|
|
|
+ thlcgwasm(hlcg).loopBreakBr:=oldLoopBreakBr;
|
|
|
|
+ end;
|
|
|
|
+ flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure twasmtryfinallynode.pass_generate_code;
|
|
procedure twasmtryfinallynode.pass_generate_code;
|