mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 16:09:17 +02:00
[PATCH 049/188] updating binary writing
From 0a58746d18ee0f4c1405114adade9464b211132a Mon Sep 17 00:00:00 2001 From: Dmitry Boyarintsev <skalogryz.lists@gmail.com> Date: Thu, 21 Nov 2019 23:24:04 -0500 git-svn-id: branches/wasm@46045 -
This commit is contained in:
parent
56dff1f7cd
commit
ea3b38d6b5
@ -5,7 +5,7 @@ unit wasmbinwriter;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, wasmmodule, wasmbin, lebutils;
|
Classes, SysUtils, wasmmodule, wasmbin, lebutils, wasmbincode;
|
||||||
|
|
||||||
type
|
type
|
||||||
TSectionRec = record
|
TSectionRec = record
|
||||||
@ -26,6 +26,8 @@ type
|
|||||||
procedure SectionBegin(secId: byte; out secRec: TSectionRec; secsize: longWord=0);
|
procedure SectionBegin(secId: byte; out secRec: TSectionRec; secsize: longWord=0);
|
||||||
function SectionEnd(var secRec: TSectionRec): Boolean;
|
function SectionEnd(var secRec: TSectionRec): Boolean;
|
||||||
|
|
||||||
|
procedure WriteInstList(list: TWasmInstrList);
|
||||||
|
|
||||||
procedure WriteFuncTypeSect(m: TWasmModule);
|
procedure WriteFuncTypeSect(m: TWasmModule);
|
||||||
procedure WriteFuncSect(m: TWasmModule);
|
procedure WriteFuncSect(m: TWasmModule);
|
||||||
procedure WriteExportSect(m: TWasmModule);
|
procedure WriteExportSect(m: TWasmModule);
|
||||||
@ -42,8 +44,56 @@ type
|
|||||||
|
|
||||||
function WriteModule(m: TWasmModule; dst: TStream): Boolean;
|
function WriteModule(m: TWasmModule; dst: TStream): Boolean;
|
||||||
|
|
||||||
|
type
|
||||||
|
TLocalsInfo = record
|
||||||
|
count : Integer;
|
||||||
|
tp : byte;
|
||||||
|
end;
|
||||||
|
TLocalInfoArray = array of TLocalsInfo;
|
||||||
|
|
||||||
|
// returns the list of local arrays
|
||||||
|
procedure GetLocalInfo(func: TWasmFunc; out loc: TLocalInfoArray);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
procedure GetLocalInfo(func: TWasmFunc; out loc: TLocalInfoArray);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
cnt : integer;
|
||||||
|
tp : byte;
|
||||||
|
nt : byte;
|
||||||
|
j : integer;
|
||||||
|
|
||||||
|
procedure Push;
|
||||||
|
begin
|
||||||
|
if j=length(loc) then begin
|
||||||
|
if j=0 then SetLength(loc, 1)
|
||||||
|
else SetLength(loc, j*2);
|
||||||
|
end;
|
||||||
|
loc[j].tp:=tp;
|
||||||
|
loc[j].count:=cnt;
|
||||||
|
inc(j);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
SetLength(Loc, 0);
|
||||||
|
if func.LocalsCount = 0 then Exit;
|
||||||
|
cnt:=1;
|
||||||
|
tp:=func.GetLocal(0).tp;
|
||||||
|
j:=0;
|
||||||
|
for i:=1 to func.LocalsCount-1 do begin
|
||||||
|
nt := func.GetLocal(i).tp;
|
||||||
|
if nt<>tp then begin
|
||||||
|
Push;
|
||||||
|
tp:=nt;
|
||||||
|
cnt:=1;
|
||||||
|
end else
|
||||||
|
inc(cnt);
|
||||||
|
end;
|
||||||
|
Push;
|
||||||
|
SetLength(loc, j);
|
||||||
|
end;
|
||||||
|
|
||||||
function WriteModule(m: TWasmModule; dst: TStream): Boolean;
|
function WriteModule(m: TWasmModule; dst: TStream): Boolean;
|
||||||
var
|
var
|
||||||
bw : TBinWriter;
|
bw : TBinWriter;
|
||||||
@ -145,8 +195,6 @@ procedure TBinWriter.WriteFuncSect(m: TWasmModule);
|
|||||||
var
|
var
|
||||||
sc : TSectionRec;
|
sc : TSectionRec;
|
||||||
i : integer;
|
i : integer;
|
||||||
//j : integer;
|
|
||||||
//tp : TWasmFuncType;
|
|
||||||
begin
|
begin
|
||||||
SectionBegin(SECT_FUNCTION, sc);
|
SectionBegin(SECT_FUNCTION, sc);
|
||||||
|
|
||||||
@ -182,18 +230,31 @@ end;
|
|||||||
procedure TBinWriter.WriteCodeSect(m: TWasmModule);
|
procedure TBinWriter.WriteCodeSect(m: TWasmModule);
|
||||||
var
|
var
|
||||||
sc : TSectionRec;
|
sc : TSectionRec;
|
||||||
i : integer;
|
i, j : integer;
|
||||||
sz : int64;
|
sz : int64;
|
||||||
mem : TMemoryStream;
|
mem : TMemoryStream;
|
||||||
|
la : TLocalInfoArray;
|
||||||
|
f : TWasmFunc;
|
||||||
begin
|
begin
|
||||||
SectionBegin(SECT_CODE, sc);
|
SectionBegin(SECT_CODE, sc);
|
||||||
|
|
||||||
mem:=TMemoryStream.Create;
|
mem:=TMemoryStream.Create;
|
||||||
try
|
try
|
||||||
|
WriteU32(dst, m.FuncCount);
|
||||||
for i :=0 to m.FuncCount-1 do begin
|
for i :=0 to m.FuncCount-1 do begin
|
||||||
|
f:=m.GetFunc(i);
|
||||||
|
|
||||||
|
GetLocalInfo(f, la);
|
||||||
|
|
||||||
|
mem.Position:=0;
|
||||||
pushStream(mem);
|
pushStream(mem);
|
||||||
// todo: locals
|
|
||||||
// todo: instructions
|
WriteU32(dst, length(la));
|
||||||
|
for j:=0 to length(la)-1 do begin
|
||||||
|
WriteU32(dst, la[i].count);
|
||||||
|
dst.WriteByte(la[i].tp);
|
||||||
|
end;
|
||||||
|
WriteInstList(f.instr);
|
||||||
popStream;
|
popStream;
|
||||||
|
|
||||||
sz:=mem.Position;
|
sz:=mem.Position;
|
||||||
@ -208,6 +269,21 @@ begin
|
|||||||
SectionEnd(sc);
|
SectionEnd(sc);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TBinWriter.WriteInstList(list: TWasmInstrList);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
ci : TWasmInstr;
|
||||||
|
begin
|
||||||
|
for i:=0 to list.Count-1 do begin
|
||||||
|
ci :=list[i];
|
||||||
|
dst.WriteByte(ci.code);
|
||||||
|
case INST_FLAGS[ci.code].Param of
|
||||||
|
ipLeb:
|
||||||
|
WriteRelocU32(ci.operandNum);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TBinWriter.pushStream(st: TStream);
|
procedure TBinWriter.pushStream(st: TStream);
|
||||||
begin
|
begin
|
||||||
if st=nil then Exit;
|
if st=nil then Exit;
|
||||||
|
@ -3,7 +3,7 @@ unit wasmmodule;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, wasmbin;
|
Classes, SysUtils, wasmbin, wasmbincode;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -52,6 +52,7 @@ type
|
|||||||
operandText : string;
|
operandText : string;
|
||||||
insttype : TWasmFuncType; // used by call_indirect only
|
insttype : TWasmFuncType; // used by call_indirect only
|
||||||
function addInstType: TWasmFuncType;
|
function addInstType: TWasmFuncType;
|
||||||
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ type
|
|||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function AddLocal: TWasmParam;
|
function AddLocal: TWasmParam;
|
||||||
|
function GetLocal(i: integer): TWasmParam;
|
||||||
function LocalsCount: integer;
|
function LocalsCount: integer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -121,12 +123,16 @@ type
|
|||||||
// making binary friendly. finding proper "nums" for each symbol "index"
|
// making binary friendly. finding proper "nums" for each symbol "index"
|
||||||
// used or implicit type declartions
|
// used or implicit type declartions
|
||||||
procedure Normalize(m: TWasmModule);
|
procedure Normalize(m: TWasmModule);
|
||||||
//function RegisterFuncType(m: TWasmModule; funcType: TFuncType): integer;
|
|
||||||
function WasmBasTypeToChar(b: byte): Char;
|
function WasmBasTypeToChar(b: byte): Char;
|
||||||
function WasmFuncTypeDescr(t: TWasmFuncType): string;
|
function WasmFuncTypeDescr(t: TWasmFuncType): string;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
// returing a basic wasm basic type to a character
|
||||||
|
// i32 = i
|
||||||
|
// i64 = I
|
||||||
|
// f32 = f
|
||||||
|
// f64 = F
|
||||||
function WasmBasTypeToChar(b: byte): Char;
|
function WasmBasTypeToChar(b: byte): Char;
|
||||||
begin
|
begin
|
||||||
case b of
|
case b of
|
||||||
@ -139,6 +145,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// converting function type to the type string
|
||||||
|
// result and params are separated by ":"
|
||||||
|
// iI:i (param i32)(param i32) (result i32)
|
||||||
|
// :f (result f32)
|
||||||
|
// FF (param f64)(param(64)
|
||||||
function WasmFuncTypeDescr(t: TWasmFuncType): string;
|
function WasmFuncTypeDescr(t: TWasmFuncType): string;
|
||||||
var
|
var
|
||||||
cnt : integer;
|
cnt : integer;
|
||||||
@ -166,7 +177,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// deleting objects from the list and clearing the list
|
||||||
procedure ClearList(l: TList);
|
procedure ClearList(l: TList);
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
@ -199,6 +210,11 @@ begin
|
|||||||
result:=insttype;
|
result:=insttype;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor TWasmInstr.Create;
|
||||||
|
begin
|
||||||
|
operandNum:=-1;
|
||||||
|
end;
|
||||||
|
|
||||||
destructor TWasmInstr.Destroy;
|
destructor TWasmInstr.Destroy;
|
||||||
begin
|
begin
|
||||||
insttype.Free;
|
insttype.Free;
|
||||||
@ -432,12 +448,21 @@ begin
|
|||||||
locals.AdD(Result);
|
locals.AdD(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TWasmFunc.GetLocal(i: integer): TWasmParam;
|
||||||
|
begin
|
||||||
|
if (i>=0) and (i<locals.Count) then
|
||||||
|
Result:=TWasmParam(locals[i])
|
||||||
|
else
|
||||||
|
Result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
function TWasmFunc.LocalsCount: integer;
|
function TWasmFunc.LocalsCount: integer;
|
||||||
begin
|
begin
|
||||||
result:=locals.Count;
|
result:=locals.Count;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// registering new or finding the existing type for a function type
|
||||||
|
// it's assumed the function type is explicitly types
|
||||||
function RegisterFuncType(m: TWasmModule; funcType: TWasmFuncType): integer;
|
function RegisterFuncType(m: TWasmModule; funcType: TWasmFuncType): integer;
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
@ -456,6 +481,24 @@ begin
|
|||||||
funcType.CopyTo(m.AddType);
|
funcType.CopyTo(m.AddType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// searching through TWasmParam list for the specified index-by-name
|
||||||
|
function FindParam(l: TList; const idx: string): Integer;
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
begin
|
||||||
|
if not Assigned(l) then begin
|
||||||
|
Result:=-1;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
for i:=0 to l.Count-1 do
|
||||||
|
if TWasmParam(l[i]).id=idx then begin
|
||||||
|
Result:=i;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
Result:=i;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// finding functions by funcIdx
|
||||||
function FindFunc(m: TWasmModule; const funcIdx: string): integer;
|
function FindFunc(m: TWasmModule; const funcIdx: string): integer;
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
@ -468,6 +511,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// only looking up for the by the type index name
|
||||||
function FindFuncType(m: TWasmModule; const typeIdx: string): integer;
|
function FindFuncType(m: TWasmModule; const typeIdx: string): integer;
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
@ -480,6 +524,38 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Normalizing instruction list, popuplating index reference ($index)
|
||||||
|
// with the actual numbers. (params, locals, globals, memory, functions index)
|
||||||
|
procedure NormalizeInst(m: TWasmModule; f: TWasmFunc; l: TWasmInstrList; checkEnd: boolean = true);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
j : integer;
|
||||||
|
ci : TWasmInstr;
|
||||||
|
begin
|
||||||
|
for i:=0 to l.Count-1 do begin
|
||||||
|
ci:=l[i];
|
||||||
|
if ci.operandNum>=0 then Continue;
|
||||||
|
case ci.code of
|
||||||
|
INST_local_get, INST_local_set, INST_local_tee:
|
||||||
|
begin
|
||||||
|
if ci.operandIdx<>'' then begin
|
||||||
|
j:=FindParam(f.functype.params, ci.operandIdx);
|
||||||
|
if j<0 then begin
|
||||||
|
j:=FindParam(f.locals, ci.operandIdx);
|
||||||
|
if j>=0 then inc(j, f.functype.ParamCount);
|
||||||
|
end;
|
||||||
|
ci.operandNum:=j;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// adding end instruction
|
||||||
|
if checkEnd and (l.Count>0) and (l[l.Count-1].code<>INST_END) then
|
||||||
|
l.AddInstr(INST_END);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// normalizing reference
|
||||||
procedure Normalize(m: TWasmModule);
|
procedure Normalize(m: TWasmModule);
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
@ -492,7 +568,11 @@ begin
|
|||||||
if f.functype.typeIdx<>'' then
|
if f.functype.typeIdx<>'' then
|
||||||
f.functype.typeNum:=FindFuncType(m, f.functype.typeIdx);
|
f.functype.typeNum:=FindFuncType(m, f.functype.typeIdx);
|
||||||
end else
|
end else
|
||||||
f.functype.typeNum:=RegisterFuncType(m, f.functype)
|
f.functype.typeNum:=RegisterFuncType(m, f.functype);
|
||||||
|
|
||||||
|
// finding the reference in functions
|
||||||
|
// populating "nums" where string "index" is used
|
||||||
|
NormalizeInst(m, f, f.instr);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// normalizing exports
|
// normalizing exports
|
||||||
|
Loading…
Reference in New Issue
Block a user