Browse Source

* WebAssembly internal linker: refactored the writing of the memory section and
the memory import section: introduced a TWasmMemoryType record, and structures
for holding the memory entries in the import and memory sections, instead of
writing them in an ad hoc manner. The memory information in the linker map
file is now also a little more detailed.

Nikolay Nikolov 5 months ago
parent
commit
39fb7618e4
2 changed files with 106 additions and 38 deletions
  1. 93 38
      compiler/ogwasm.pas
  2. 13 0
      compiler/wasm32/cpubase.pas

+ 93 - 38
compiler/ogwasm.pas

@@ -284,6 +284,13 @@ interface
           FuncIdx: Integer;
           FuncIdx: Integer;
         end;
         end;
 
 
+        FImportedMemories: array of record
+          ModName: ansistring;
+          Name: ansistring;
+          MemType: TWasmMemoryType;
+        end;
+        FMemories: array of TWasmMemoryType;
+
         FRelocationPass: Integer;
         FRelocationPass: Integer;
         FWasmSections: array [TWasmSectionID] of tdynamicarray;
         FWasmSections: array [TWasmSectionID] of tdynamicarray;
         FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
         FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
@@ -320,6 +327,8 @@ interface
         procedure GenerateCode_InitSharedMemory;
         procedure GenerateCode_InitSharedMemory;
         procedure GenerateCode_InvokeHelper;
         procedure GenerateCode_InvokeHelper;
         procedure WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
         procedure WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
+        procedure WriteMemoryTo(dest: tdynamicarray;const MemType:TWasmMemoryType);
+        function Memory2String(const MemType:TWasmMemoryType):string;
         procedure WriteMap_TypeSection;
         procedure WriteMap_TypeSection;
         procedure WriteMap_IndirectFunctionTable;
         procedure WriteMap_IndirectFunctionTable;
       protected
       protected
@@ -4847,28 +4856,22 @@ implementation
       procedure WriteImportSection;
       procedure WriteImportSection;
         var
         var
           imports_count,
           imports_count,
-          memory_imports: SizeInt;
           i: Integer;
           i: Integer;
         begin
         begin
           if assigned(exemap) then
           if assigned(exemap) then
             exemap.AddHeader('Import section');
             exemap.AddHeader('Import section');
-          if ts_wasm_threads in current_settings.targetswitches then
-            memory_imports:=1
-          else
-            memory_imports:=0;
-          imports_count:=Length(FFunctionImports)+memory_imports;
+          imports_count:=Length(FImportedMemories)+Length(FFunctionImports);
           WriteUleb(FWasmSections[wsiImport],imports_count);
           WriteUleb(FWasmSections[wsiImport],imports_count);
-          if ts_wasm_threads in current_settings.targetswitches then
-            begin
-              WriteName(FWasmSections[wsiImport],'env');
-              WriteName(FWasmSections[wsiImport],'memory');
-              WriteByte(FWasmSections[wsiImport],$02);  { mem }
-              WriteByte(FWasmSections[wsiImport],$03);  { shared }
-              WriteUleb(FWasmSections[wsiImport],FMinMemoryPages);
-              WriteUleb(FWasmSections[wsiImport],Max(FMinMemoryPages,FMaxMemoryPages));  { max pages }
-              if assigned(exemap) then
-                exemap.Add('  Memory[0] pages: initial='+tostr(FMinMemoryPages)+' max='+tostr(Max(FMinMemoryPages,FMaxMemoryPages))+' shared <- env.memory');
-            end;
+          for i:=0 to Length(FImportedMemories)-1 do
+            with FImportedMemories[i] do
+              begin
+                WriteName(FWasmSections[wsiImport],ModName);
+                WriteName(FWasmSections[wsiImport],Name);
+                WriteByte(FWasmSections[wsiImport],$02);  { mem }
+                WriteMemoryTo(FWasmSections[wsiImport],MemType);
+                if assigned(exemap) then
+                  exemap.Add('  Memory['+tostr(i)+'] '+Memory2String(MemType)+' <- '+ModName+'.'+Name);
+              end;
           for i:=0 to Length(FFunctionImports)-1 do
           for i:=0 to Length(FFunctionImports)-1 do
             with FFunctionImports[i] do
             with FFunctionImports[i] do
               begin
               begin
@@ -5214,6 +5217,21 @@ implementation
             end;
             end;
         end;
         end;
 
 
+      procedure WriteMemorySection;
+        var
+          i: Integer;
+        begin
+          if assigned(exemap) then
+            exemap.AddHeader('Memory section');
+          WriteUleb(FWasmSections[wsiMemory],Length(FMemories));
+          for i:=low(FMemories) to high(FMemories) do
+            begin
+              WriteMemoryTo(FWasmSections[wsiMemory],FMemories[i]);
+              if assigned(exemap) then
+                exemap.Add('  Memory['+tostr(i+Length(FImportedMemories))+'] '+Memory2String(FMemories[i]));
+            end;
+        end;
+
       var
       var
         cust_sec: TWasmCustomSectionType;
         cust_sec: TWasmCustomSectionType;
       begin
       begin
@@ -5230,6 +5248,36 @@ implementation
         GenerateCode_InitTls;
         GenerateCode_InitTls;
         GenerateCode_InitSharedMemory;
         GenerateCode_InitSharedMemory;
 
 
+        if ts_wasm_threads in current_settings.targetswitches then
+          begin
+            SetLength(FImportedMemories,1);
+            with FImportedMemories[0] do
+              begin
+                ModName:='env';
+                Name:='memory';
+                with MemType do
+                  begin
+                    Flags:=[wmfShared,wmfHasMaximumBound];
+                    MinPages:=FMinMemoryPages;
+                    MaxPages:=Max(FMinMemoryPages,FMaxMemoryPages);
+                  end;
+              end;
+          end
+        else
+          begin
+            SetLength(FMemories,1);
+            with FMemories[0] do
+              begin
+                Flags:=[];
+                MinPages:=FMinMemoryPages;
+                if FMaxMemoryPages>=FMinMemoryPages then
+                  begin
+                    Include(Flags,wmfHasMaximumBound);
+                    MaxPages:=FMaxMemoryPages;
+                  end;
+              end;
+          end;
+
         FFuncTypes.WriteTo(FWasmSections[wsiType]);
         FFuncTypes.WriteTo(FWasmSections[wsiType]);
         WriteImportSection;
         WriteImportSection;
         WriteCodeSegments;
         WriteCodeSegments;
@@ -5238,27 +5286,8 @@ implementation
         WriteGlobalSection;
         WriteGlobalSection;
         WriteTagSection;
         WriteTagSection;
 
 
-        if not (ts_wasm_threads in current_settings.targetswitches) then
-          begin
-            if assigned(exemap) then
-              exemap.AddHeader('Memory section');
-            WriteUleb(FWasmSections[wsiMemory],1);
-            if FMaxMemoryPages>=FMinMemoryPages then
-              begin
-                WriteByte(FWasmSections[wsiMemory],1);
-                WriteUleb(FWasmSections[wsiMemory],FMinMemoryPages);
-                WriteUleb(FWasmSections[wsiMemory],FMaxMemoryPages);
-                if assigned(exemap) then
-                  exemap.Add('  Memory[0] pages: initial='+tostr(FMinMemoryPages)+' max='+tostr(FMaxMemoryPages));
-              end
-            else
-              begin
-                WriteByte(FWasmSections[wsiMemory],0);
-                WriteUleb(FWasmSections[wsiMemory],FMinMemoryPages);
-                if assigned(exemap) then
-                  exemap.Add('  Memory[0] pages: initial='+tostr(FMinMemoryPages));
-              end;
-          end;
+        if Length(FMemories)>0 then
+          WriteMemorySection;
 
 
         WriteExportSection;
         WriteExportSection;
 
 
@@ -6402,6 +6431,32 @@ implementation
           internalerror(2024010107);
           internalerror(2024010107);
       end;
       end;
 
 
+    procedure TWasmExeOutput.WriteMemoryTo(dest: tdynamicarray; const MemType: TWasmMemoryType);
+      begin
+        WriteByte(dest,Byte(MemType.Flags));
+        WriteUleb(dest,MemType.MinPages);
+        if wmfHasMaximumBound in MemType.Flags then
+          WriteUleb(dest,MemType.MaxPages);
+        { todo: wmfCustomPageSize }
+      end;
+
+    function TWasmExeOutput.Memory2String(const MemType: TWasmMemoryType): string;
+      begin
+        Result:='index type: ';
+        if wmfMemory64 in MemType.Flags then
+          Result:=Result+'i64'
+        else
+          Result:=Result+'i32';
+        Result:=Result+', pages: initial='+tostr(MemType.MinPages);
+        if wmfHasMaximumBound in MemType.Flags then
+          Result:=Result+' max='+tostr(MemType.MaxPages);
+        if wmfShared in MemType.Flags then
+          Result:=Result+', shared'
+        else
+          Result:=Result+', unshared';
+        { todo: wmfCustomPageSize }
+      end;
+
     procedure TWasmExeOutput.WriteMap_TypeSection;
     procedure TWasmExeOutput.WriteMap_TypeSection;
       var
       var
         i: Integer;
         i: Integer;

+ 13 - 0
compiler/wasm32/cpubase.pas

@@ -142,6 +142,19 @@ uses
       TWasmResultType = array of TWasmBasicType;
       TWasmResultType = array of TWasmBasicType;
       TWasmLocalsDynArray = array of TWasmBasicType;
       TWasmLocalsDynArray = array of TWasmBasicType;
 
 
+      TWasmMemoryFlag = (
+        wmfHasMaximumBound,
+        wmfShared,
+        wmfMemory64,
+        wmfCustomPageSize
+      );
+      TWasmMemoryFlags = set of TWasmMemoryFlag;
+      TWasmMemoryType = record
+        Flags: TWasmMemoryFlags;
+        MinPages, MaxPages: UInt64;
+        PageSize: UInt32;
+      end;
+
       { TWasmFuncType }
       { TWasmFuncType }
 
 
       PWasmFuncType = ^TWasmFuncType;
       PWasmFuncType = ^TWasmFuncType;