* WebAssembly code generation for 'case' nodes changed to use labels

This commit is contained in:
Nikolay Nikolov 2021-10-22 17:31:04 +03:00
parent 6fe647ee3d
commit 3094f75690
3 changed files with 45 additions and 44 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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;