Browse Source

+ wasm resource writer: create the WASM_SEGMENT_INFO subsection of the linking custom section

Nikolay Nikolov 1 year ago
parent
commit
c771d772c4
2 changed files with 39 additions and 7 deletions
  1. 5 0
      packages/fcl-res/src/wasmconsts.pp
  2. 34 7
      packages/fcl-res/src/wasmwriter.pp

+ 5 - 0
packages/fcl-res/src/wasmconsts.pp

@@ -70,6 +70,11 @@ const
   WASM_SYM_NO_STRIP          = $80;
   WASM_SYM_NO_STRIP          = $80;
   WASM_SYM_TLS               = $100;
   WASM_SYM_TLS               = $100;
 
 
+  WasmResourceDataSegmentNames: array [TWasmResourceDataSegment] of string = (
+    'fpc.resources',
+    'fpc.reshandles'
+  );
+
 implementation
 implementation
 
 
 end.
 end.

+ 34 - 7
packages/fcl-res/src/wasmwriter.pp

@@ -46,6 +46,7 @@ type
     FWasmSections: array [TWasmSectionID] of TMemoryStream;
     FWasmSections: array [TWasmSectionID] of TMemoryStream;
     FDataSegments: array [TWasmResourceDataSegment] of TMemoryStream;
     FDataSegments: array [TWasmResourceDataSegment] of TMemoryStream;
     FWasmCustomSections: array [TWasmCustomSectionType] of TMemoryStream;
     FWasmCustomSections: array [TWasmCustomSectionType] of TMemoryStream;
+    FWasmLinkingSubsections: array [low(TWasmLinkingSubsectionType)..high(TWasmLinkingSubsectionType)] of TMemoryStream;
     function NextAligned(aBound, aValue : longword) : longword;
     function NextAligned(aBound, aValue : longword) : longword;
     procedure PrescanResourceTree;
     procedure PrescanResourceTree;
     function PrescanNode(aNode : TResourceTreeNode; aNodeSize : longword) : longword;
     function PrescanNode(aNode : TResourceTreeNode; aNodeSize : longword) : longword;
@@ -53,6 +54,7 @@ type
     procedure WriteWasmSection(aStream: TStream; wsid: TWasmSectionID);
     procedure WriteWasmSection(aStream: TStream; wsid: TWasmSectionID);
     procedure WriteWasmSectionIfNotEmpty(aStream: TStream; wsid: TWasmSectionID);
     procedure WriteWasmSectionIfNotEmpty(aStream: TStream; wsid: TWasmSectionID);
     procedure WriteWasmCustomSection(aStream: TStream; wcst: TWasmCustomSectionType);
     procedure WriteWasmCustomSection(aStream: TStream; wcst: TWasmCustomSectionType);
+    procedure WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
     procedure WriteCustomSectionNames;
     procedure WriteCustomSectionNames;
     procedure WriteImportSection;
     procedure WriteImportSection;
     procedure WriteDataSegments;
     procedure WriteDataSegments;
@@ -209,6 +211,17 @@ begin
   aStream.CopyFrom(FWasmCustomSections[wcst],0);
   aStream.CopyFrom(FWasmCustomSections[wcst],0);
 end;
 end;
 
 
+procedure TWasmResourceWriter.WriteLinkingSubsection(
+  wlst: TWasmLinkingSubsectionType);
+begin
+  if FWasmLinkingSubsections[wlst].size>0 then
+    begin
+      FWasmCustomSections[wcstLinking].WriteByte(Ord(wlst));
+      WriteUleb(FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
+      FWasmCustomSections[wcstLinking].CopyFrom(FWasmLinkingSubsections[wlst],0);
+    end;
+end;
+
 procedure TWasmResourceWriter.WriteCustomSectionNames;
 procedure TWasmResourceWriter.WriteCustomSectionNames;
 var
 var
   cust_sec: TWasmCustomSectionType;
   cust_sec: TWasmCustomSectionType;
@@ -233,25 +246,31 @@ end;
 
 
 procedure TWasmResourceWriter.WriteDataSegments;
 procedure TWasmResourceWriter.WriteDataSegments;
 const
 const
-  DataSegmentCount = 2;
+  DataSegmentCount = Ord(High(FDataSegments)) - Ord(Low(FDataSegments)) + 1;
 var
 var
-  ds: TMemoryStream;
   ofs: int64;
   ofs: int64;
+  ds: TWasmResourceDataSegment;
 begin
 begin
   WriteUleb(FWasmSections[wsiData],DataSegmentCount);
   WriteUleb(FWasmSections[wsiData],DataSegmentCount);
   WriteUleb(FWasmSections[wsiDataCount],DataSegmentCount);
   WriteUleb(FWasmSections[wsiDataCount],DataSegmentCount);
+  WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],DataSegmentCount);
+
   ofs:=0;
   ofs:=0;
-  for ds in FDataSegments do
+  for ds:=Low(FDataSegments) to High(FDataSegments) do
   begin
   begin
+    WriteName(FWasmLinkingSubsections[WASM_SEGMENT_INFO],WasmResourceDataSegmentNames[ds]);
+    WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],BsrQWord(4));  { align }
+    WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],0);  { flags }
+
     FWasmSections[wsiData].WriteByte(0);
     FWasmSections[wsiData].WriteByte(0);
     FWasmSections[wsiData].WriteByte($41);
     FWasmSections[wsiData].WriteByte($41);
     WriteSleb(FWasmSections[wsiData],ofs);
     WriteSleb(FWasmSections[wsiData],ofs);
     FWasmSections[wsiData].WriteByte($0b);
     FWasmSections[wsiData].WriteByte($0b);
-    WriteUleb(FWasmSections[wsiData],ds.Size);
-    if ds.Size>0 then
+    WriteUleb(FWasmSections[wsiData],FDataSegments[ds].Size);
+    if FDataSegments[ds].Size>0 then
     begin
     begin
-      FWasmSections[wsiData].CopyFrom(ds, 0);
-      Inc(ofs,ds.Size);
+      FWasmSections[wsiData].CopyFrom(FDataSegments[ds], 0);
+      Inc(ofs,FDataSegments[ds].Size);
     end;
     end;
   end;
   end;
 end;
 end;
@@ -279,6 +298,8 @@ begin
   WriteImportSection;
   WriteImportSection;
   WriteDataSegments;
   WriteDataSegments;
 
 
+  WriteLinkingSubsection(WASM_SEGMENT_INFO);
+
   aStream.WriteBuffer(WasmModuleMagic,SizeOf(WasmModuleMagic));
   aStream.WriteBuffer(WasmModuleMagic,SizeOf(WasmModuleMagic));
   aStream.WriteBuffer(WasmVersion,SizeOf(WasmVersion));
   aStream.WriteBuffer(WasmVersion,SizeOf(WasmVersion));
   WriteWasmSection(aStream,wsiImport);
   WriteWasmSection(aStream,wsiImport);
@@ -292,6 +313,7 @@ var
   i: TWasmSectionID;
   i: TWasmSectionID;
   j: TWasmResourceDataSegment;
   j: TWasmResourceDataSegment;
   k: TWasmCustomSectionType;
   k: TWasmCustomSectionType;
+  l: TWasmLinkingSubsectionType;
 begin
 begin
   fExtensions:='.o .or';
   fExtensions:='.o .or';
   fDescription:='WebAssembly resource writer';
   fDescription:='WebAssembly resource writer';
@@ -309,6 +331,8 @@ begin
     FDataSegments[j] := TMemoryStream.Create;
     FDataSegments[j] := TMemoryStream.Create;
   for k in TWasmCustomSectionType do
   for k in TWasmCustomSectionType do
     FWasmCustomSections[k] := TMemoryStream.Create;
     FWasmCustomSections[k] := TMemoryStream.Create;
+  for l:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
+    FWasmLinkingSubsections[l] := TMemoryStream.Create;
 end;
 end;
 
 
 destructor TWasmResourceWriter.Destroy;
 destructor TWasmResourceWriter.Destroy;
@@ -316,7 +340,10 @@ var
   i: TWasmSectionID;
   i: TWasmSectionID;
   j: TWasmResourceDataSegment;
   j: TWasmResourceDataSegment;
   k: TWasmCustomSectionType;
   k: TWasmCustomSectionType;
+  l: TWasmLinkingSubsectionType;
 begin
 begin
+  for l:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
+    FreeAndNil(FWasmLinkingSubsections[l]);
   for k in TWasmCustomSectionType do
   for k in TWasmCustomSectionType do
     FreeAndNil(FWasmCustomSections[k]);
     FreeAndNil(FWasmCustomSections[k]);
   for j in TWasmResourceDataSegment do
   for j in TWasmResourceDataSegment do