Browse Source

+ WebAssembly internal linker: rewrite the fpc_wasm_invoke_helper function in the linker, so that it becomes functional

Nikolay Nikolov 6 months ago
parent
commit
522612a632
1 changed files with 192 additions and 0 deletions
  1. 192 0
      compiler/ogwasm.pas

+ 192 - 0
compiler/ogwasm.pas

@@ -317,6 +317,7 @@ interface
         procedure SetThreadVarGlobalsInitValues;
         procedure SetThreadVarGlobalsInitValues;
         procedure GenerateCode_InitTls;
         procedure GenerateCode_InitTls;
         procedure GenerateCode_InitSharedMemory;
         procedure GenerateCode_InitSharedMemory;
+        procedure GenerateCode_InvokeHelper;
         procedure WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
         procedure WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
       protected
       protected
         function writeData:boolean;override;
         function writeData:boolean;override;
@@ -5196,6 +5197,7 @@ implementation
         SetThreadVarGlobalsInitValues;
         SetThreadVarGlobalsInitValues;
         GenerateCode_InitTls;
         GenerateCode_InitTls;
         GenerateCode_InitSharedMemory;
         GenerateCode_InitSharedMemory;
+        GenerateCode_InvokeHelper;
 
 
         FFuncTypes.WriteTo(FWasmSections[wsiType]);
         FFuncTypes.WriteTo(FWasmSections[wsiType]);
         WriteImportSection;
         WriteImportSection;
@@ -5994,6 +5996,196 @@ implementation
         Sec.writeUInt8($0B);
         Sec.writeUInt8($0B);
       end;
       end;
 
 
+    procedure TWasmExeOutput.GenerateCode_InvokeHelper;
+      var
+        Sec: TObjSection;
+
+      procedure InvokeFuncType(typidx: Integer);
+        var
+          ft: TWasmFuncType;
+          i, nextofs: Integer;
+        begin
+          ft:=FFuncTypes[typidx];
+          for i:=0 to Length(ft.results)-1 do
+            { local.get 2 }
+            Sec.writeUInt16BE($2002);
+          nextofs:=0;
+          for i:=0 to Length(ft.params)-1 do
+            begin
+              { local.get 1 }
+              Sec.writeUInt16BE($2001);
+              case ft.params[i] of
+                wbt_i32:
+                  begin
+                    { i32.load nextofs }
+                    Sec.writeUInt16BE($2802);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,4);
+                  end;
+                wbt_i64:
+                  begin
+                    { i64.load nextofs }
+                    Sec.writeUInt16BE($2902);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,8);
+                  end;
+                wbt_f32:
+                  begin
+                    { f32.load nextofs }
+                    Sec.writeUInt16BE($2A02);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,4);
+                  end;
+                wbt_f64:
+                  begin
+                    { f64.load nextofs }
+                    Sec.writeUInt16BE($2B02);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,8);
+                  end;
+                wbt_v128:
+                  begin
+                    { v128.load nextofs }
+                    Sec.writeUInt16BE($FD00);
+                    Sec.writeUInt8($02);  { align: 4 bytes }
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,16);
+                  end;
+                wbt_externref,
+                wbt_funcref:
+                  begin
+                    { unreachable }
+                    Sec.writeUInt8($00);
+                  end;
+                else
+                  internalerror(2025012501);
+              end;
+            end;
+          { local.get 0 }
+          Sec.writeUInt16BE($2000);
+          { call_indirect }
+          Sec.writeUInt8($11);
+          WriteUleb(Sec,typidx);
+          Sec.writeUInt8($0);  { table index 0 }
+          nextofs:=0;
+          for i:=0 to Length(ft.results)-1 do
+            begin
+              case ft.results[i] of
+                wbt_i32:
+                  begin
+                    { i32.store nextofs }
+                    Sec.writeUInt16BE($3602);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,4);
+                  end;
+                wbt_i64:
+                  begin
+                    { i64.store nextofs }
+                    Sec.writeUInt16BE($3702);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,8);
+                  end;
+                wbt_f32:
+                  begin
+                    { f32.store nextofs }
+                    Sec.writeUInt16BE($3802);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,4);
+                  end;
+                wbt_f64:
+                  begin
+                    { f64.store nextofs }
+                    Sec.writeUInt16BE($3902);
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,8);
+                  end;
+                wbt_v128:
+                  begin
+                    { v128.store nextofs }
+                    Sec.writeUInt16BE($FD0B);
+                    Sec.writeUInt8($02);  { align: 4 bytes }
+                    WriteUleb(Sec, nextofs);
+                    Inc(nextofs,16);
+                  end;
+                wbt_externref,
+                wbt_funcref:
+                  begin
+                    { unreachable }
+                    Sec.writeUInt8($00);
+                  end;
+                else
+                  internalerror(2025012501);
+              end;
+            end;
+          { return }
+          Sec.writeUInt8($0F);
+        end;
+
+      function FuncIdx2TypeIdx(fi: Integer): Integer;
+        var
+          exesec: TExeSection;
+          objsec: TWasmObjSection;
+          fsym: TWasmObjSymbol;
+        begin
+          if fi<Length(FFunctionImports) then
+            Result:=FFunctionImports[fi].TypeIdx
+          else
+            begin
+              exesec:=FindExeSection('.text');
+              if not assigned(exesec) then
+                internalerror(2023123106);
+              objsec:=TWasmObjSection(exesec.ObjSectionList[fi-Length(FFunctionImports)]);
+              fsym:=objsec.MainFuncSymbol;
+              Result:=fsym.LinkingData.ExeTypeIndex;
+            end;
+        end;
+
+      var
+        exesym: TExeSymbol;
+        objsym: TObjSymbol;
+        i: Integer;
+      begin
+        exesym:=TExeSymbol(ExeSymbolList.Find('fpc_wasm_invoke_helper'));
+        if not Assigned(exesym) then
+          exit;
+        objsym:=exesym.ObjSymbol;
+        Sec:=objsym.objsection;
+        Sec.Size:=0;
+        Sec.Data.reset;
+
+        { locals }
+        Sec.writeUInt8($00);
+
+        for i:=1 to Length(FIndirectFunctionTable)-1 do
+          { block }
+          Sec.writeUInt16BE($0240);
+
+        { block }
+        Sec.writeUInt16BE($0240);
+        { local.get 0 }
+        Sec.writeUInt16BE($2000);
+        { br_table <0, 1, 2, 3, 4, 5, 6, ..., High>, 0 }
+        Sec.writeUInt8($0E);
+        WriteUleb(Sec,Length(FIndirectFunctionTable));
+        for i:=0 to Length(FIndirectFunctionTable)-1 do
+          WriteUleb(Sec,i);
+        Sec.writeUInt8($00);
+        { end }
+        Sec.writeUInt8($0B);
+        { unreachable }
+        Sec.writeUInt8($00);
+
+        for i:=1 to Length(FIndirectFunctionTable)-1 do
+          begin
+            { end }
+            Sec.writeUInt8($0B);
+            InvokeFuncType(FuncIdx2TypeIdx(FIndirectFunctionTable[i].FuncIdx));
+          end;
+
+        { end }
+        Sec.writeUInt8($0B);
+      end;
+
     procedure TWasmExeOutput.WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
     procedure TWasmExeOutput.WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
       var
       var
         exesecdatapos: LongWord;
         exesecdatapos: LongWord;