Browse Source

* On WebAssembly, when calling a function, first generate code for evaluating
all the parameters, and only after that, push them on the stack. This avoids
problems with our 'goto' support.

Nikolay Nikolov 10 months ago
parent
commit
4b757dd360
1 changed files with 45 additions and 0 deletions
  1. 45 0
      compiler/wasm32/nwasmcal.pas

+ 45 - 0
compiler/wasm32/nwasmcal.pas

@@ -34,6 +34,11 @@ interface
        { twasmcallparanode }
        { twasmcallparanode }
 
 
        twasmcallparanode = class(tcgcallparanode)
        twasmcallparanode = class(tcgcallparanode)
+       private
+         procedure secondpass_all;
+         procedure push_all;
+       public
+         procedure secondcallparan;override;
        end;
        end;
 
 
        { twasmcallnode }
        { twasmcallnode }
@@ -52,6 +57,46 @@ implementation
     uses
     uses
       globals, globtype, verbose, aasmdata, defutil, tgobj, hlcgcpu, symconst, symsym, symcpu;
       globals, globtype, verbose, aasmdata, defutil, tgobj, hlcgcpu, symconst, symsym, symcpu;
 
 
+      { twasmcallparanode }
+
+        procedure twasmcallparanode.secondpass_all;
+          begin
+            { Skip nothingn nodes which are used after disabling
+              a parameter }
+            if (left.nodetype<>nothingn) then
+              secondcallparan_do_secondpass;
+
+            { next parameter }
+            if assigned(right) then
+              twasmcallparanode(right).secondpass_all;
+          end;
+
+        procedure twasmcallparanode.push_all;
+          begin
+            { Skip nothingn nodes which are used after disabling
+              a parameter }
+            if (left.nodetype<>nothingn) then
+              secondcallparan_after_secondpass;
+
+            { next parameter }
+            if assigned(right) then
+              twasmcallparanode(right).push_all;
+          end;
+
+        procedure twasmcallparanode.secondcallparan;
+          begin
+            if not(assigned(parasym)) then
+              internalerror(200304242);
+
+            { On WebAssembly we generate code for evaluating all the parameters
+              first, and then we push them only after we've evaluated them all.
+              This is because the evaluation phase can generate labels, which
+              wreaks havoc in our 'goto' label resolution algorithm, when there
+              are labels at different stack heights. }
+            secondpass_all;
+            push_all;
+          end;
+
       { twasmcallnode }
       { twasmcallnode }
 
 
     function twasmcallnode.pass_typecheck:tnode;
     function twasmcallnode.pass_typecheck:tnode;