|
@@ -40,14 +40,19 @@ type
|
|
fDescription : string;
|
|
fDescription : string;
|
|
fRoot : TRootResTreeNode;
|
|
fRoot : TRootResTreeNode;
|
|
fResStringTable : TResStringTable;
|
|
fResStringTable : TResStringTable;
|
|
|
|
+ fOppositeEndianess : boolean;
|
|
fDataAlignment : longword;
|
|
fDataAlignment : longword;
|
|
fDataCurOfs : longword;
|
|
fDataCurOfs : longword;
|
|
FWasmSections: array [TWasmSectionID] of TMemoryStream;
|
|
FWasmSections: array [TWasmSectionID] of TMemoryStream;
|
|
|
|
+ FDataSegments: array [TWasmResourceDataSegment] 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;
|
|
|
|
+ procedure WriteResHeader(aResources : TResources);
|
|
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 WriteImportSection;
|
|
|
|
+ procedure WriteDataSegments;
|
|
protected
|
|
protected
|
|
function GetExtensions : string; override;
|
|
function GetExtensions : string; override;
|
|
function GetDescription : string; override;
|
|
function GetDescription : string; override;
|
|
@@ -59,6 +64,22 @@ type
|
|
|
|
|
|
implementation
|
|
implementation
|
|
|
|
|
|
|
|
+procedure WriteSleb(aStream: TStream; v: int64);
|
|
|
|
+var
|
|
|
|
+ b: byte;
|
|
|
|
+ Done: Boolean=false;
|
|
|
|
+begin
|
|
|
|
+ repeat
|
|
|
|
+ b:=byte(v) and 127;
|
|
|
|
+ v:=SarInt64(v,7);
|
|
|
|
+ if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
|
|
|
|
+ Done:=true
|
|
|
|
+ else
|
|
|
|
+ b:=b or 128;
|
|
|
|
+ aStream.WriteByte(b);
|
|
|
|
+ until Done;
|
|
|
|
+end;
|
|
|
|
+
|
|
procedure WriteUleb(aStream: TStream; v: uint64);
|
|
procedure WriteUleb(aStream: TStream; v: uint64);
|
|
var
|
|
var
|
|
b: byte;
|
|
b: byte;
|
|
@@ -72,6 +93,13 @@ begin
|
|
until v=0;
|
|
until v=0;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure WriteName(aStream: TStream; const s: string);
|
|
|
|
+begin
|
|
|
|
+ WriteUleb(aStream,Length(s));
|
|
|
|
+ if Length(s)>0 then
|
|
|
|
+ aStream.WriteBuffer(s[1],Length(s));
|
|
|
|
+end;
|
|
|
|
+
|
|
{ TWasmResourceWriter }
|
|
{ TWasmResourceWriter }
|
|
|
|
|
|
function TWasmResourceWriter.NextAligned(aBound, aValue: longword): longword;
|
|
function TWasmResourceWriter.NextAligned(aBound, aValue: longword): longword;
|
|
@@ -125,6 +153,33 @@ begin
|
|
Result:=curofs;
|
|
Result:=curofs;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TWasmResourceWriter.WriteResHeader(aResources: TResources);
|
|
|
|
+var hdr : TResHdr32;
|
|
|
|
+begin
|
|
|
|
+ hdr.count:=aResources.Count;
|
|
|
|
+ hdr.usedhandles:=0;
|
|
|
|
+ hdr.handles:=0;
|
|
|
|
+
|
|
|
|
+ //fSymbolTable.AddSection(RSRCSECT_IDX);
|
|
|
|
+ //fSymbolTable.AddSection(HANDLESECT_IDX);
|
|
|
|
+ //case fRelocInfo.SectionType of
|
|
|
|
+ // SHT_REL : hdr.rootptr:=sizeof(hdr);
|
|
|
|
+ // SHT_RELA : hdr.rootptr:=0;
|
|
|
|
+ //end;
|
|
|
|
+
|
|
|
|
+ //fRelocTable.Add(0,sizeof(hdr),RSRCSECT_IDX);
|
|
|
|
+ //fRelocTable.Add(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),0,HANDLESECT_IDX);
|
|
|
|
+ if fOppositeEndianess then
|
|
|
|
+ begin
|
|
|
|
+ hdr.rootptr:=SwapEndian(hdr.rootptr);
|
|
|
|
+ hdr.count:=SwapEndian(hdr.count);
|
|
|
|
+ //handles must be fixed later
|
|
|
|
+// hdr.usedhandles:=SwapEndian(hdr.usedhandles);
|
|
|
|
+// hdr.handles:=SwapEndian(hdr.handles);
|
|
|
|
+ end;
|
|
|
|
+ FDataSegments[wrdsResources].WriteBuffer(hdr,sizeof(hdr));
|
|
|
|
+end;
|
|
|
|
+
|
|
procedure TWasmResourceWriter.WriteWasmSection(aStream: TStream;
|
|
procedure TWasmResourceWriter.WriteWasmSection(aStream: TStream;
|
|
wsid: TWasmSectionID);
|
|
wsid: TWasmSectionID);
|
|
var
|
|
var
|
|
@@ -143,6 +198,44 @@ begin
|
|
WriteWasmSection(aStream,wsid);
|
|
WriteWasmSection(aStream,wsid);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TWasmResourceWriter.WriteImportSection;
|
|
|
|
+const
|
|
|
|
+ ImportsCount = 1;
|
|
|
|
+begin
|
|
|
|
+ WriteUleb(FWasmSections[wsiImport],ImportsCount);
|
|
|
|
+ { import memories }
|
|
|
|
+ WriteName(FWasmSections[wsiImport],'env');
|
|
|
|
+ WriteName(FWasmSections[wsiImport],'__linear_memory');
|
|
|
|
+ FWasmSections[wsiImport].WriteByte($02); { mem }
|
|
|
|
+ FWasmSections[wsiImport].WriteByte($00); { min }
|
|
|
|
+ WriteUleb(FWasmSections[wsiImport],1); { 1 page }
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TWasmResourceWriter.WriteDataSegments;
|
|
|
|
+const
|
|
|
|
+ DataSegmentCount = 2;
|
|
|
|
+var
|
|
|
|
+ ds: TMemoryStream;
|
|
|
|
+ ofs: int64;
|
|
|
|
+begin
|
|
|
|
+ WriteUleb(FWasmSections[wsiData],DataSegmentCount);
|
|
|
|
+ WriteUleb(FWasmSections[wsiDataCount],DataSegmentCount);
|
|
|
|
+ ofs:=0;
|
|
|
|
+ for ds in FDataSegments do
|
|
|
|
+ begin
|
|
|
|
+ FWasmSections[wsiData].WriteByte(0);
|
|
|
|
+ FWasmSections[wsiData].WriteByte($41);
|
|
|
|
+ WriteSleb(FWasmSections[wsiData],ofs);
|
|
|
|
+ FWasmSections[wsiData].WriteByte($0b);
|
|
|
|
+ WriteUleb(FWasmSections[wsiData],ds.Size);
|
|
|
|
+ if ds.Size>0 then
|
|
|
|
+ begin
|
|
|
|
+ FWasmSections[wsiData].CopyFrom(ds, 0);
|
|
|
|
+ Inc(ofs,ds.Size);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
function TWasmResourceWriter.GetExtensions: string;
|
|
function TWasmResourceWriter.GetExtensions: string;
|
|
begin
|
|
begin
|
|
Result:=fExtensions;
|
|
Result:=fExtensions;
|
|
@@ -154,17 +247,17 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TWasmResourceWriter.Write(aResources: TResources; aStream: TStream);
|
|
procedure TWasmResourceWriter.Write(aResources: TResources; aStream: TStream);
|
|
-const
|
|
|
|
- DataSegmentCount = 0;
|
|
|
|
begin
|
|
begin
|
|
fRoot:=TRootResTreeNode(GetTree(aResources));
|
|
fRoot:=TRootResTreeNode(GetTree(aResources));
|
|
PrescanResourceTree;
|
|
PrescanResourceTree;
|
|
|
|
+ WriteResHeader(aResources);
|
|
|
|
|
|
- WriteUleb(FWasmSections[wsiData],DataSegmentCount);
|
|
|
|
- WriteUleb(FWasmSections[wsiDataCount],DataSegmentCount);
|
|
|
|
|
|
+ WriteImportSection;
|
|
|
|
+ WriteDataSegments;
|
|
|
|
|
|
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,wsiDataCount);
|
|
WriteWasmSection(aStream,wsiDataCount);
|
|
WriteWasmSection(aStream,wsiData);
|
|
WriteWasmSection(aStream,wsiData);
|
|
end;
|
|
end;
|
|
@@ -172,20 +265,31 @@ end;
|
|
constructor TWasmResourceWriter.Create;
|
|
constructor TWasmResourceWriter.Create;
|
|
var
|
|
var
|
|
i: TWasmSectionID;
|
|
i: TWasmSectionID;
|
|
|
|
+ j: TWasmResourceDataSegment;
|
|
begin
|
|
begin
|
|
fExtensions:='.o .or';
|
|
fExtensions:='.o .or';
|
|
fDescription:='WebAssembly resource writer';
|
|
fDescription:='WebAssembly resource writer';
|
|
fResStringTable:=TResStringTable.Create;
|
|
fResStringTable:=TResStringTable.Create;
|
|
fDataCurOfs:=0;
|
|
fDataCurOfs:=0;
|
|
fDataAlignment:=4;
|
|
fDataAlignment:=4;
|
|
|
|
+{$IFDEF FPC_BIG_ENDIAN}
|
|
|
|
+ fOppositeEndianess := True;
|
|
|
|
+{$ELSE FPC_BIG_ENDIAN}
|
|
|
|
+ fOppositeEndianess := False;
|
|
|
|
+{$ENDIF FPC_BIG_ENDIAN}
|
|
for i in TWasmSectionID do
|
|
for i in TWasmSectionID do
|
|
FWasmSections[i] := TMemoryStream.Create;
|
|
FWasmSections[i] := TMemoryStream.Create;
|
|
|
|
+ for j in TWasmResourceDataSegment do
|
|
|
|
+ FDataSegments[j] := TMemoryStream.Create;
|
|
end;
|
|
end;
|
|
|
|
|
|
destructor TWasmResourceWriter.Destroy;
|
|
destructor TWasmResourceWriter.Destroy;
|
|
var
|
|
var
|
|
i: TWasmSectionID;
|
|
i: TWasmSectionID;
|
|
|
|
+ j: TWasmResourceDataSegment;
|
|
begin
|
|
begin
|
|
|
|
+ for j in TWasmResourceDataSegment do
|
|
|
|
+ FreeAndNil(FDataSegments[j]);
|
|
for i in TWasmSectionID do
|
|
for i in TWasmSectionID do
|
|
FreeAndNil(FWasmSections[i]);
|
|
FreeAndNil(FWasmSections[i]);
|
|
FreeAndNil(fResStringTable);
|
|
FreeAndNil(fResStringTable);
|