Kaynağa Gözat

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

Nikolay Nikolov 3 yıl önce
ebeveyn
işleme
3094f75690
3 değiştirilmiş dosya ile 45 ekleme ve 44 silme
  1. 0 3
      compiler/nset.pas
  2. 15 5
      compiler/wasm32/hlcgcpu.pas
  3. 30 36
      compiler/wasm32/nwasmset.pas

+ 0 - 3
compiler/nset.pas

@@ -61,9 +61,6 @@ interface
        tcaseblock = record
        tcaseblock = record
           { label (only used in pass_generate_code) }
           { label (only used in pass_generate_code) }
           blocklabel : tasmlabel;
           blocklabel : tasmlabel;
-{$ifdef WASM}
-          BlockBr : Integer;
-{$endif WASM}
 
 
           { shortcut - set to true if blocklabel isn't actually unique to the
           { shortcut - set to true if blocklabel isn't actually unique to the
             case block due to one of the following conditions:
             case block due to one of the following conditions:

+ 15 - 5
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);
   procedure thlcgwasm.a_cmp_const_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; const ref: treference; l: tasmlabel);
     begin
     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;
     end;
 
 
   procedure thlcgwasm.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
   procedure thlcgwasm.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
     begin
     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;
     end;
 
 
   procedure thlcgwasm.a_cmp_ref_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel);
   procedure thlcgwasm.a_cmp_ref_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel);
     begin
     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;
     end;
 
 
   procedure thlcgwasm.a_cmp_reg_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel);
   procedure thlcgwasm.a_cmp_reg_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel);
     begin
     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;
     end;
 
 
   procedure thlcgwasm.a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
   procedure thlcgwasm.a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
     begin
     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;
     end;
 
 
   procedure thlcgwasm.a_jmp_always(list: TAsmList; l: tasmlabel);
   procedure thlcgwasm.a_jmp_always(list: TAsmList; l: tasmlabel);

+ 30 - 36
compiler/wasm32/nwasmset.pas

@@ -26,7 +26,8 @@ unit nwasmset;
 interface
 interface
 
 
     uses
     uses
-      node,nset,ncgset;
+      node,nset,ncgset,
+      aasmbase;
 
 
     type
     type
 
 
@@ -41,12 +42,8 @@ interface
 
 
       twasmcasenode = class(tcgcasenode)
       twasmcasenode = class(tcgcasenode)
       private
       private
-        ElseBr: Integer;
-        EndBr: Integer;
-
-        function GetBranchBr(Block: TNode; out _Br: Integer): Boolean;
+        function GetBranchLabel(Block: TNode; out _Label: TAsmLabel): Boolean;
       protected
       protected
-        function BlockBr(id:longint):Integer;
         procedure genlinearlist(hp : pcaselabel);override;
         procedure genlinearlist(hp : pcaselabel);override;
         procedure genlinearcmplist(hp : pcaselabel);override;
         procedure genlinearcmplist(hp : pcaselabel);override;
       public
       public
@@ -80,14 +77,14 @@ implementation
                                 TWASMCASENODE
                                 TWASMCASENODE
 *****************************************************************************}
 *****************************************************************************}
 
 
-    function twasmcasenode.GetBranchBr(Block: TNode; out _Br: Integer): Boolean;
+    function twasmcasenode.GetBranchLabel(Block: TNode; out _Label: TAsmLabel): Boolean;
       begin
       begin
         Result := True;
         Result := True;
 
 
         if not Assigned(Block) then
         if not Assigned(Block) then
           begin
           begin
             { Block doesn't exist / is empty }
             { Block doesn't exist / is empty }
-            _Br := EndBr;
+            _Label := endlabel;
             Exit;
             Exit;
           end;
           end;
 
 
@@ -95,9 +92,9 @@ implementation
         if not (cs_opt_level2 in current_settings.optimizerswitches) then
         if not (cs_opt_level2 in current_settings.optimizerswitches) then
           begin
           begin
             Result := False;
             Result := False;
+            current_asmdata.getjumplabel(_Label);
             current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
             current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
             thlcgwasm(hlcg).incblock;
             thlcgwasm(hlcg).incblock;
-            _Br:=thlcgwasm(hlcg).br_blocks;
             Exit;
             Exit;
           end;
           end;
 
 
@@ -106,7 +103,7 @@ implementation
             case Block.nodetype of
             case Block.nodetype of
               nothingn:
               nothingn:
                 begin
                 begin
-                  _Br := EndBr;
+                  _Label := endlabel;
                   Exit;
                   Exit;
                 end;
                 end;
               goton:
               goton:
@@ -139,15 +136,7 @@ implementation
         Result := False;
         Result := False;
         current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
         current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
         thlcgwasm(hlcg).incblock;
         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;
       end;
 
 
 
 
@@ -177,16 +166,16 @@ implementation
             genitem(t^.less);
             genitem(t^.less);
           { do we need to test the first value? }
           { do we need to test the first value? }
           if first and (t^._low>get_min_value(left.resultdef)) then
           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
           if t^._low=t^._high then
             begin
             begin
               if t^._low-last=0 then
               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
               else
                 begin
                 begin
                   gensub(tcgint(t^._low.svalue-last.svalue));
                   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;
                 end;
               last:=t^._low;
               last:=t^._low;
             end
             end
@@ -207,10 +196,10 @@ implementation
                    { present label then the lower limit can be checked    }
                    { present label then the lower limit can be checked    }
                    { immediately. else check the range in between:       }
                    { immediately. else check the range in between:       }
                    gensub(tcgint(t^._low.svalue-last.svalue));
                    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;
                  end;
                gensub(tcgint(t^._high.svalue-t^._low.svalue));
                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;
                last:=t^._high;
             end;
             end;
           first:=false;
           first:=false;
@@ -252,15 +241,15 @@ implementation
               begin
               begin
                 { If only one label exists, we can greatly simplify the checks to a simple comparison }
                 { If only one label exists, we can greatly simplify the checks to a simple comparison }
                 if hp^._low=hp^._high then
                 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
                 else
                   begin
                   begin
                     scratch_reg:=hlcg.getintregister(current_asmdata.CurrAsmList,opsize);
                     scratch_reg:=hlcg.getintregister(current_asmdata.CurrAsmList,opsize);
                     gensub(tcgint(hp^._low.svalue));
                     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;
               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;
       end;
       end;
 
 
@@ -277,7 +266,7 @@ implementation
             genitem(t^.less);
             genitem(t^.less);
           if t^._low=t^._high then
           if t^._low=t^._high then
             begin
             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
               { 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 }
                 for the next range both the lower and upper bound }
               lastwasrange := false;
               lastwasrange := false;
@@ -288,8 +277,8 @@ implementation
               { is even smaller then jump immediately to the    }
               { is even smaller then jump immediately to the    }
               { ELSE-label                                }
               { ELSE-label                                }
               if not lastwasrange or (t^._low-last>1) then
               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;
               last:=t^._high;
               lastwasrange := true;
               lastwasrange := true;
@@ -302,7 +291,7 @@ implementation
         last:=0;
         last:=0;
         lastwasrange:=false;
         lastwasrange:=false;
         genitem(hp);
         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;
       end;
 
 
 
 
@@ -317,16 +306,17 @@ implementation
         oldflowcontrol := flowcontrol;
         oldflowcontrol := flowcontrol;
         include(flowcontrol,fc_inflowcontrol);
         include(flowcontrol,fc_inflowcontrol);
 
 
+        current_asmdata.getjumplabel(endlabel);
+
         current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
         current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
         thlcgwasm(hlcg).incblock;
         thlcgwasm(hlcg).incblock;
-        EndBr:=thlcgwasm(hlcg).br_blocks;
 
 
         { Do some optimisation to deal with empty else 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
         for i:=blocks.count-1 downto 0 do
           with pcaseblock(blocks[i])^ do
           with pcaseblock(blocks[i])^ do
-            shortcut := GetBranchBr(statement, BlockBr);
+            shortcut := GetBranchLabel(statement, blocklabel);
 
 
         with_sign:=is_signed(left.resultdef);
         with_sign:=is_signed(left.resultdef);
         if with_sign then
         if with_sign then
@@ -466,13 +456,15 @@ implementation
               begin
               begin
                 current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
                 current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
                 thlcgwasm(hlcg).decblock;
                 thlcgwasm(hlcg).decblock;
+                hlcg.a_label(current_asmdata.CurrAsmList,blocklabel);
+
                 secondpass(statement);
                 secondpass(statement);
                 { don't come back to case line }
                 { don't come back to case line }
                 current_filepos:=current_asmdata.CurrAsmList.getlasttaifilepos^;
                 current_filepos:=current_asmdata.CurrAsmList.getlasttaifilepos^;
 {$ifdef OLDREGVARS}
 {$ifdef OLDREGVARS}
                 load_all_regvars(current_asmdata.CurrAsmList);
                 load_all_regvars(current_asmdata.CurrAsmList);
 {$endif OLDREGVARS}
 {$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;
           end;
           end;
 
 
@@ -481,6 +473,7 @@ implementation
           begin
           begin
             current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
             current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
             thlcgwasm(hlcg).decblock;
             thlcgwasm(hlcg).decblock;
+            hlcg.a_label(current_asmdata.CurrAsmList,elselabel);
           end;
           end;
 
 
         if Assigned(elseblock) then
         if Assigned(elseblock) then
@@ -494,6 +487,7 @@ implementation
 
 
         current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
         current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
         thlcgwasm(hlcg).decblock;
         thlcgwasm(hlcg).decblock;
+        hlcg.a_label(current_asmdata.CurrAsmList,endlabel);
 
 
         flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
         flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
       end;
       end;