From 3094f756903a6c06ff7786a1fa972ff6a61de457 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Fri, 22 Oct 2021 17:31:04 +0300 Subject: [PATCH] * WebAssembly code generation for 'case' nodes changed to use labels --- compiler/nset.pas | 3 -- compiler/wasm32/hlcgcpu.pas | 20 ++++++++--- compiler/wasm32/nwasmset.pas | 66 ++++++++++++++++-------------------- 3 files changed, 45 insertions(+), 44 deletions(-) diff --git a/compiler/nset.pas b/compiler/nset.pas index afb3362b27..3ac18aecf3 100644 --- a/compiler/nset.pas +++ b/compiler/nset.pas @@ -61,9 +61,6 @@ interface tcaseblock = record { label (only used in pass_generate_code) } blocklabel : tasmlabel; -{$ifdef WASM} - BlockBr : Integer; -{$endif WASM} { shortcut - set to true if blocklabel isn't actually unique to the case block due to one of the following conditions: diff --git a/compiler/wasm32/hlcgcpu.pas b/compiler/wasm32/hlcgcpu.pas index 10e43447e7..2b5c0f9ba7 100644 --- a/compiler/wasm32/hlcgcpu.pas +++ b/compiler/wasm32/hlcgcpu.pas @@ -1770,27 +1770,37 @@ implementation procedure thlcgwasm.a_cmp_const_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; const ref: treference; l: tasmlabel); begin - internalerror(2021011802); + a_cmp_const_ref_stack(list,size,cmp_op,a,ref); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l)); + thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1); end; procedure thlcgwasm.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel); begin - internalerror(2021011802); + a_cmp_const_reg_stack(list,size,cmp_op,a,reg); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l)); + thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1); end; procedure thlcgwasm.a_cmp_ref_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel); begin - internalerror(2021011802); + a_cmp_ref_reg_stack(list,size,cmp_op,ref,reg); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l)); + thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1); end; procedure thlcgwasm.a_cmp_reg_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel); begin - internalerror(2021011802); + a_cmp_reg_ref_stack(list,size,cmp_op,reg,ref); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l)); + thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1); end; procedure thlcgwasm.a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); begin - internalerror(2021011802); + a_cmp_reg_reg_stack(list,size,cmp_op,reg1,reg2); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l)); + thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1); end; procedure thlcgwasm.a_jmp_always(list: TAsmList; l: tasmlabel); diff --git a/compiler/wasm32/nwasmset.pas b/compiler/wasm32/nwasmset.pas index f56ae26dd6..cff9b1fb8e 100644 --- a/compiler/wasm32/nwasmset.pas +++ b/compiler/wasm32/nwasmset.pas @@ -26,7 +26,8 @@ unit nwasmset; interface uses - node,nset,ncgset; + node,nset,ncgset, + aasmbase; type @@ -41,12 +42,8 @@ interface twasmcasenode = class(tcgcasenode) private - ElseBr: Integer; - EndBr: Integer; - - function GetBranchBr(Block: TNode; out _Br: Integer): Boolean; + function GetBranchLabel(Block: TNode; out _Label: TAsmLabel): Boolean; protected - function BlockBr(id:longint):Integer; procedure genlinearlist(hp : pcaselabel);override; procedure genlinearcmplist(hp : pcaselabel);override; public @@ -80,14 +77,14 @@ implementation TWASMCASENODE *****************************************************************************} - function twasmcasenode.GetBranchBr(Block: TNode; out _Br: Integer): Boolean; + function twasmcasenode.GetBranchLabel(Block: TNode; out _Label: TAsmLabel): Boolean; begin Result := True; if not Assigned(Block) then begin { Block doesn't exist / is empty } - _Br := EndBr; + _Label := endlabel; Exit; end; @@ -95,9 +92,9 @@ implementation if not (cs_opt_level2 in current_settings.optimizerswitches) then begin Result := False; + current_asmdata.getjumplabel(_Label); current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); thlcgwasm(hlcg).incblock; - _Br:=thlcgwasm(hlcg).br_blocks; Exit; end; @@ -106,7 +103,7 @@ implementation case Block.nodetype of nothingn: begin - _Br := EndBr; + _Label := endlabel; Exit; end; goton: @@ -139,15 +136,7 @@ implementation Result := False; current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); thlcgwasm(hlcg).incblock; - _Br:=thlcgwasm(hlcg).br_blocks; - end; - - - function twasmcasenode.BlockBr(id: longint): Integer; - begin - if not assigned(blocks[id]) then - internalerror(200411301); - result:=pcaseblock(blocks[id])^.BlockBr; + current_asmdata.getjumplabel(_Label); end; @@ -177,16 +166,16 @@ implementation genitem(t^.less); { do we need to test the first value? } if first and (t^._low>get_min_value(left.resultdef)) then - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList,opsize,jmp_lt,tcgint(t^._low.svalue),hregister,thlcgwasm(hlcg).br_blocks-ElseBr); + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,tcgint(t^._low.svalue),hregister,elselabel); if t^._low=t^._high then begin if t^._low-last=0 then - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList,opsize,OC_EQ,0,hregister,thlcgwasm(hlcg).br_blocks-BlockBr(t^.blockid)) + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_EQ,0,hregister,blocklabel(t^.blockid)) else begin gensub(tcgint(t^._low.svalue-last.svalue)); - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList,opsize, - OC_EQ,tcgint(t^._low.svalue-last.svalue),scratch_reg,thlcgwasm(hlcg).br_blocks-BlockBr(t^.blockid)); + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize, + OC_EQ,tcgint(t^._low.svalue-last.svalue),scratch_reg,blocklabel(t^.blockid)); end; last:=t^._low; end @@ -207,10 +196,10 @@ implementation { present label then the lower limit can be checked } { immediately. else check the range in between: } gensub(tcgint(t^._low.svalue-last.svalue)); - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList, opsize,jmp_lt,tcgint(t^._low.svalue-last.svalue),scratch_reg,thlcgwasm(hlcg).br_blocks-ElseBr); + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize,jmp_lt,tcgint(t^._low.svalue-last.svalue),scratch_reg,elselabel); end; gensub(tcgint(t^._high.svalue-t^._low.svalue)); - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList,opsize,jmp_le,tcgint(t^._high.svalue-t^._low.svalue),scratch_reg,thlcgwasm(hlcg).br_blocks-BlockBr(t^.blockid)); + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_le,tcgint(t^._high.svalue-t^._low.svalue),scratch_reg,blocklabel(t^.blockid)); last:=t^._high; end; first:=false; @@ -252,15 +241,15 @@ implementation begin { If only one label exists, we can greatly simplify the checks to a simple comparison } if hp^._low=hp^._high then - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList, opsize, OC_EQ, tcgint(hp^._low.svalue), hregister, thlcgwasm(hlcg).br_blocks-BlockBr(hp^.blockid)) + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ, tcgint(hp^._low.svalue), hregister,blocklabel(hp^.blockid)) else begin scratch_reg:=hlcg.getintregister(current_asmdata.CurrAsmList,opsize); gensub(tcgint(hp^._low.svalue)); - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList, opsize, OC_BE, tcgint(hp^._high.svalue-hp^._low.svalue), hregister, thlcgwasm(hlcg).br_blocks-BlockBr(hp^.blockid)) + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_BE, tcgint(hp^._high.svalue-hp^._low.svalue), hregister,blocklabel(hp^.blockid)) end; end; - current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,thlcgwasm(hlcg).br_blocks-ElseBr)); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,elselabel)); end; end; @@ -277,7 +266,7 @@ implementation genitem(t^.less); if t^._low=t^._high then begin - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList, opsize, OC_EQ, tcgint(t^._low.svalue),hregister, thlcgwasm(hlcg).br_blocks-BlockBr(t^.blockid)); + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ, tcgint(t^._low.svalue),hregister, blocklabel(t^.blockid)); { Reset last here, because we've only checked for one value and need to compare for the next range both the lower and upper bound } lastwasrange := false; @@ -288,8 +277,8 @@ implementation { is even smaller then jump immediately to the } { ELSE-label } if not lastwasrange or (t^._low-last>1) then - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList, opsize, jmp_lt, tcgint(t^._low.svalue), hregister, thlcgwasm(hlcg).br_blocks-ElseBr); - thlcgwasm(hlcg).a_cmp_const_reg_br(current_asmdata.CurrAsmList, opsize, jmp_le, tcgint(t^._high.svalue), hregister, thlcgwasm(hlcg).br_blocks-BlockBr(t^.blockid)); + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_lt, tcgint(t^._low.svalue), hregister, elselabel); + thlcgwasm(hlcg).a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_le, tcgint(t^._high.svalue), hregister, blocklabel(t^.blockid)); last:=t^._high; lastwasrange := true; @@ -302,7 +291,7 @@ implementation last:=0; lastwasrange:=false; genitem(hp); - current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,thlcgwasm(hlcg).br_blocks-ElseBr)); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,elselabel)); end; @@ -317,16 +306,17 @@ implementation oldflowcontrol := flowcontrol; include(flowcontrol,fc_inflowcontrol); + current_asmdata.getjumplabel(endlabel); + current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block)); thlcgwasm(hlcg).incblock; - EndBr:=thlcgwasm(hlcg).br_blocks; { Do some optimisation to deal with empty else blocks } - ShortcutElse := GetBranchBr(elseblock, ElseBr); + ShortcutElse := GetBranchLabel(elseblock, elselabel); for i:=blocks.count-1 downto 0 do with pcaseblock(blocks[i])^ do - shortcut := GetBranchBr(statement, BlockBr); + shortcut := GetBranchLabel(statement, blocklabel); with_sign:=is_signed(left.resultdef); if with_sign then @@ -466,13 +456,15 @@ implementation begin current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); thlcgwasm(hlcg).decblock; + hlcg.a_label(current_asmdata.CurrAsmList,blocklabel); + secondpass(statement); { don't come back to case line } current_filepos:=current_asmdata.CurrAsmList.getlasttaifilepos^; {$ifdef OLDREGVARS} load_all_regvars(current_asmdata.CurrAsmList); {$endif OLDREGVARS} - current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,thlcgwasm(hlcg).br_blocks-EndBr)); + current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,endlabel)); end; end; @@ -481,6 +473,7 @@ implementation begin current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); thlcgwasm(hlcg).decblock; + hlcg.a_label(current_asmdata.CurrAsmList,elselabel); end; if Assigned(elseblock) then @@ -494,6 +487,7 @@ implementation current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); thlcgwasm(hlcg).decblock; + hlcg.a_label(current_asmdata.CurrAsmList,endlabel); flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]); end;