mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-30 16:00:19 +02:00
+ wasm resource writer: start writing the data segments, also the import section
This commit is contained in:
parent
868d5f29c9
commit
b28d49ced7
@ -97,6 +97,8 @@ type
|
||||
SYMTAB_EVENT = 4,
|
||||
SYMTAB_TABLE = 5);
|
||||
|
||||
TWasmResourceDataSegment = (wrdsResources, wrdsResHandles);
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
@ -40,14 +40,19 @@ type
|
||||
fDescription : string;
|
||||
fRoot : TRootResTreeNode;
|
||||
fResStringTable : TResStringTable;
|
||||
fOppositeEndianess : boolean;
|
||||
fDataAlignment : longword;
|
||||
fDataCurOfs : longword;
|
||||
FWasmSections: array [TWasmSectionID] of TMemoryStream;
|
||||
FDataSegments: array [TWasmResourceDataSegment] of TMemoryStream;
|
||||
function NextAligned(aBound, aValue : longword) : longword;
|
||||
procedure PrescanResourceTree;
|
||||
function PrescanNode(aNode : TResourceTreeNode; aNodeSize : longword) : longword;
|
||||
procedure WriteResHeader(aResources : TResources);
|
||||
procedure WriteWasmSection(aStream: TStream; wsid: TWasmSectionID);
|
||||
procedure WriteWasmSectionIfNotEmpty(aStream: TStream; wsid: TWasmSectionID);
|
||||
procedure WriteImportSection;
|
||||
procedure WriteDataSegments;
|
||||
protected
|
||||
function GetExtensions : string; override;
|
||||
function GetDescription : string; override;
|
||||
@ -59,6 +64,22 @@ type
|
||||
|
||||
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);
|
||||
var
|
||||
b: byte;
|
||||
@ -72,6 +93,13 @@ begin
|
||||
until v=0;
|
||||
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 }
|
||||
|
||||
function TWasmResourceWriter.NextAligned(aBound, aValue: longword): longword;
|
||||
@ -125,6 +153,33 @@ begin
|
||||
Result:=curofs;
|
||||
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;
|
||||
wsid: TWasmSectionID);
|
||||
var
|
||||
@ -143,6 +198,44 @@ begin
|
||||
WriteWasmSection(aStream,wsid);
|
||||
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;
|
||||
begin
|
||||
Result:=fExtensions;
|
||||
@ -154,17 +247,17 @@ begin
|
||||
end;
|
||||
|
||||
procedure TWasmResourceWriter.Write(aResources: TResources; aStream: TStream);
|
||||
const
|
||||
DataSegmentCount = 0;
|
||||
begin
|
||||
fRoot:=TRootResTreeNode(GetTree(aResources));
|
||||
PrescanResourceTree;
|
||||
WriteResHeader(aResources);
|
||||
|
||||
WriteUleb(FWasmSections[wsiData],DataSegmentCount);
|
||||
WriteUleb(FWasmSections[wsiDataCount],DataSegmentCount);
|
||||
WriteImportSection;
|
||||
WriteDataSegments;
|
||||
|
||||
aStream.WriteBuffer(WasmModuleMagic,SizeOf(WasmModuleMagic));
|
||||
aStream.WriteBuffer(WasmVersion,SizeOf(WasmVersion));
|
||||
WriteWasmSection(aStream,wsiImport);
|
||||
WriteWasmSection(aStream,wsiDataCount);
|
||||
WriteWasmSection(aStream,wsiData);
|
||||
end;
|
||||
@ -172,20 +265,31 @@ end;
|
||||
constructor TWasmResourceWriter.Create;
|
||||
var
|
||||
i: TWasmSectionID;
|
||||
j: TWasmResourceDataSegment;
|
||||
begin
|
||||
fExtensions:='.o .or';
|
||||
fDescription:='WebAssembly resource writer';
|
||||
fResStringTable:=TResStringTable.Create;
|
||||
fDataCurOfs:=0;
|
||||
fDataAlignment:=4;
|
||||
{$IFDEF FPC_BIG_ENDIAN}
|
||||
fOppositeEndianess := True;
|
||||
{$ELSE FPC_BIG_ENDIAN}
|
||||
fOppositeEndianess := False;
|
||||
{$ENDIF FPC_BIG_ENDIAN}
|
||||
for i in TWasmSectionID do
|
||||
FWasmSections[i] := TMemoryStream.Create;
|
||||
for j in TWasmResourceDataSegment do
|
||||
FDataSegments[j] := TMemoryStream.Create;
|
||||
end;
|
||||
|
||||
destructor TWasmResourceWriter.Destroy;
|
||||
var
|
||||
i: TWasmSectionID;
|
||||
j: TWasmResourceDataSegment;
|
||||
begin
|
||||
for j in TWasmResourceDataSegment do
|
||||
FreeAndNil(FDataSegments[j]);
|
||||
for i in TWasmSectionID do
|
||||
FreeAndNil(FWasmSections[i]);
|
||||
FreeAndNil(fResStringTable);
|
||||
|
Loading…
Reference in New Issue
Block a user