mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 13:10:34 +02:00
* WebAssembly code generation for 'case' nodes changed to use labels
This commit is contained in:
parent
6fe647ee3d
commit
3094f75690
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user