mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 00:09:32 +02:00
[PATCH 002/188] the initial commit
From bce2a7ed20747f29b4c9d00834e9f4b9e3cef5a0 Mon Sep 17 00:00:00 2001 From: Dmitry Boyarintsev <skalogryz.lists@gmail.com> Date: Thu, 5 Sep 2019 17:03:31 -0400 git-svn-id: branches/wasm@45998 -
This commit is contained in:
parent
e173c688b0
commit
93d6993296
5
.gitattributes
vendored
5
.gitattributes
vendored
@ -18976,3 +18976,8 @@ utils/unicode/unihelper.lpr svneol=native#text/pascal
|
||||
utils/unicode/weight_derivation.inc svneol=native#text/pascal
|
||||
utils/usubst.pp svneol=native#text/plain
|
||||
utils/wasmbin/README.md svneol=native#text/plain
|
||||
utils/wasmbin/lebutils.pas svneol=native#text/plain
|
||||
utils/wasmbin/wasmbin.pas svneol=native#text/plain
|
||||
utils/wasmbin/wasmbindebug.pas svneol=native#text/plain
|
||||
utils/wasmbin/wasmld.lpi svneol=native#text/plain
|
||||
utils/wasmbin/wasmld.lpr svneol=native#text/plain
|
||||
|
111
utils/wasmbin/lebutils.pas
Normal file
111
utils/wasmbin/lebutils.pas
Normal file
@ -0,0 +1,111 @@
|
||||
unit lebutils;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes, wasmbin;
|
||||
|
||||
function ReadU(src: TStream): UInt64;
|
||||
function ReadS(src: TStream; bits: Integer): Int64;
|
||||
|
||||
procedure ReadFuncTypesArray(src: TStream; var arr: TFuncTypeArray);
|
||||
procedure ReadFuncType(src: TStream; var ft: TFuncType);
|
||||
|
||||
procedure ReadCodeEntry(src: TStream; var en: TCodeEntry);
|
||||
procedure ReadCodeSection(src: TStream; var sc: TCodeSection);
|
||||
|
||||
implementation
|
||||
|
||||
procedure ReadFuncType(src: TStream; var ft: TFuncType);
|
||||
var
|
||||
c: integer;
|
||||
begin
|
||||
// vector of t1
|
||||
c:=ReadU(src);
|
||||
SetLength(ft.param, c);
|
||||
src.Read(ft.param[0], c);
|
||||
|
||||
// vector of t2
|
||||
c:=ReadU(src);
|
||||
SetLength(ft.result, c);
|
||||
src.Read(ft.result[0], c);
|
||||
end;
|
||||
|
||||
procedure ReadFuncTypesArray(src: TStream; var arr: TFuncTypeArray);
|
||||
var
|
||||
cnt : integer;
|
||||
i : Integer;
|
||||
begin
|
||||
cnt := ReadU(src);
|
||||
SetLength(arr.funTypes, cnt);
|
||||
for i:=0 to cnt-1 do begin
|
||||
if src.ReadByte = func_type then
|
||||
ReadFuncType(src, arr.funTypes[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
function ReadU(src: TStream): UInt64;
|
||||
var
|
||||
b : byte;
|
||||
sh : integer;
|
||||
begin
|
||||
Result := 0;
|
||||
sh := 0;
|
||||
while true do begin
|
||||
b := src.ReadByte;
|
||||
Result := Result or ((b and $7f) shl sh);
|
||||
if (b and $80)>0 then inc(sh, 7)
|
||||
else break;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ReadS(src: TStream; bits: Integer): Int64;
|
||||
var
|
||||
b : byte;
|
||||
sh : Integer;
|
||||
begin
|
||||
result := 0;
|
||||
sh := 0;
|
||||
repeat
|
||||
b := src.ReadByte;
|
||||
result := Result or ((b and $77) shl sh);
|
||||
inc(sh, 7);
|
||||
until ((b and $80) = 0);
|
||||
|
||||
// sign bit of byte is second high order bit (0x40)
|
||||
if (sh < bits) and ((b and $40) > 0) then
|
||||
// sign extend
|
||||
result := result or ( (not 0) shl sh);
|
||||
end;
|
||||
|
||||
procedure ReadCodeEntry(src: TStream; var en: TCodeEntry);
|
||||
var
|
||||
sz : integer; // size in bytes
|
||||
//pos : int64;
|
||||
cnt : Integer;
|
||||
i : integer;
|
||||
begin
|
||||
sz := ReadU(src);
|
||||
|
||||
cnt := ReadU(src);
|
||||
SetLength(en.locals, cnt);
|
||||
for i:=0 to cnt-1 do begin
|
||||
en.locals[i].count := ReadU(src);
|
||||
en.locals[i].valtyp := src.ReadByte;
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure ReadCodeSection(src: TStream; var sc: TCodeSection);
|
||||
var
|
||||
cnt : integer;
|
||||
i : integer;
|
||||
begin
|
||||
cnt := ReadU(src);
|
||||
SetLength(sc.entries, cnt);
|
||||
for i:= 0 to cnt-1 do
|
||||
ReadCodeEntry(src, sc.entries[i]);
|
||||
end;
|
||||
|
||||
end.
|
131
utils/wasmbin/wasmbin.pas
Normal file
131
utils/wasmbin/wasmbin.pas
Normal file
@ -0,0 +1,131 @@
|
||||
unit wasmbin;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
const
|
||||
valtype_i32 = $7f;
|
||||
valtype_i64 = $7e;
|
||||
valtype_f32 = $7d;
|
||||
valtype_f64 = $7C;
|
||||
|
||||
block_type = $40;
|
||||
func_type = $60;
|
||||
elem_type = $70;
|
||||
|
||||
global_const = $00;
|
||||
global_mut = $01;
|
||||
|
||||
limit_min_inf = $00; // minimum - to infinity
|
||||
limit_min_max = $01; // minimum - maximum
|
||||
|
||||
const
|
||||
WasmId = #0'asm';
|
||||
WasmId_Int = $6D736100;
|
||||
|
||||
const
|
||||
sect_custom = 0; // custom section
|
||||
sect_type = 1; // type section
|
||||
sect_import = 2; // import section
|
||||
sect_function = 3; // function section
|
||||
sect_table = 4; // table section
|
||||
sect_memory = 5; // memory section
|
||||
sect_global = 6; // global section
|
||||
sect_export = 7; // export section
|
||||
sect_start = 8; // start section
|
||||
sect_element = 9; // element section
|
||||
sect_code = 10; // code section
|
||||
sect_data = 11; // data section
|
||||
|
||||
type
|
||||
TSection = packed record
|
||||
id : byte;
|
||||
size : LongWord; // it is Leb128 encoded in the file, thus cannot be read directly
|
||||
end;
|
||||
|
||||
TFuncType = record
|
||||
param : array of byte;
|
||||
result : array of byte;
|
||||
end;
|
||||
|
||||
TFuncTypeArray = record
|
||||
funTypes : array of TFuncType;
|
||||
end;
|
||||
|
||||
TCodeLocalEntry = record
|
||||
count : LongWord;
|
||||
valtyp : Byte;
|
||||
end;
|
||||
|
||||
TCodeInstr = record
|
||||
inst : byte;
|
||||
idxArr: array of LongWord;
|
||||
case byte of
|
||||
0: (align, offset : LongWord);
|
||||
1: (index: LongWord);
|
||||
2: (i32: LongWord);
|
||||
3: (i64: UInt64);
|
||||
4: (f32: single);
|
||||
5: (f64: double);
|
||||
// for labels
|
||||
6: (idxCount: integer;
|
||||
idxDef :LongWord);
|
||||
7: (returnType: byte);
|
||||
end;
|
||||
|
||||
TCodeEntry = record
|
||||
locals : array of TCodeLocalEntry;
|
||||
instCount : integer;
|
||||
instr : array of TCodeInstr;
|
||||
end;
|
||||
|
||||
TCodeSection = record
|
||||
entries : array of TCodeEntry;
|
||||
end;
|
||||
|
||||
function SectionIdToStr(id: integer): string;
|
||||
function ValTypeToStr(id: integer): string;
|
||||
|
||||
implementation
|
||||
|
||||
function ValTypeToStr(id: integer): string;
|
||||
begin
|
||||
case id of
|
||||
valtype_i32 : Result := 'i32';
|
||||
valtype_i64 : Result := 'i64';
|
||||
valtype_f32 : Result := 'f32';
|
||||
valtype_f64 : Result := 'f64';
|
||||
else
|
||||
Str(id, Result);
|
||||
Result := 'iUnk'+Result;
|
||||
end
|
||||
end;
|
||||
|
||||
function SectionIdToStr(id: integer): string;
|
||||
begin
|
||||
case id of
|
||||
sect_custom : Result := 'custom'; // custom section
|
||||
sect_type : Result := 'type'; // type section
|
||||
sect_import : Result := 'import'; // import section
|
||||
sect_function : Result := 'function'; // function section
|
||||
sect_table : Result := 'table'; // table section
|
||||
sect_memory : Result := 'memory'; // memory section
|
||||
sect_global : Result := 'global'; // global section
|
||||
sect_export : Result := 'export'; // export section
|
||||
sect_start : Result := 'start'; // start section
|
||||
sect_element : Result := 'element'; // element section
|
||||
sect_code : Result := 'code'; // code section
|
||||
sect_data : Result := 'data'; // data section
|
||||
else
|
||||
Str(id, Result);
|
||||
Result := 'sect_unknown'+Result;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
36
utils/wasmbin/wasmbindebug.pas
Normal file
36
utils/wasmbin/wasmbindebug.pas
Normal file
@ -0,0 +1,36 @@
|
||||
unit wasmbindebug;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, wasmbin, lebutils;
|
||||
|
||||
procedure DumpTypes(sr: TStream);
|
||||
|
||||
implementation
|
||||
|
||||
procedure DumpTypes(sr: TStream);
|
||||
var
|
||||
ar : TFuncTypeArray;
|
||||
i : integer;
|
||||
j : integer;
|
||||
begin
|
||||
ReadFuncTypesArray(sr, ar);
|
||||
for i:=0 to length(ar.funTypes)-1 do begin
|
||||
write('#',i);
|
||||
writeln;
|
||||
write(' params:');
|
||||
for j:=0 to length(ar.funTypes[i].param)-1 do
|
||||
write(' ', ValTypeToStr(ar.funTypes[i].param[j]));
|
||||
writeln;
|
||||
write(' result:');
|
||||
for j:=0 to length(ar.funTypes[i].result)-1 do
|
||||
write(' ', ValTypeToStr(ar.funTypes[i].result[j]));
|
||||
writeln;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
68
utils/wasmbin/wasmld.lpi
Normal file
68
utils/wasmbin/wasmld.lpi
Normal file
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<MainUnitHasCreateFormStatements Value="False"/>
|
||||
<MainUnitHasTitleStatement Value="False"/>
|
||||
<MainUnitHasScaledStatement Value="False"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<Title Value="wasmld"/>
|
||||
<UseAppBundle Value="False"/>
|
||||
<ResourceType Value="res"/>
|
||||
</General>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="Default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<UseFileFilters Value="True"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<FormatVersion Value="2"/>
|
||||
<Modes Count="0"/>
|
||||
</RunParams>
|
||||
<Units Count="3">
|
||||
<Unit0>
|
||||
<Filename Value="wasmld.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="wasmbin.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="wasmbindebug.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit2>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Target>
|
||||
<Filename Value="wasmld"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item3>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
59
utils/wasmbin/wasmld.lpr
Normal file
59
utils/wasmbin/wasmld.lpr
Normal file
@ -0,0 +1,59 @@
|
||||
program wasmld;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
{ you can add units after this }
|
||||
Classes, SysUtils, wasmbin, lebutils, wasmbindebug;
|
||||
|
||||
function ReadStream(st: TStream): Boolean;
|
||||
var
|
||||
dw : LongWord;
|
||||
ofs : int64;
|
||||
sc : TSection;
|
||||
ps : int64;
|
||||
begin
|
||||
dw := st.ReadDWord;
|
||||
Result := dw = WasmId_Int;
|
||||
if not Result then begin
|
||||
writeln('not a wasm file');
|
||||
Exit;
|
||||
end;
|
||||
dw := st.ReadDWord;
|
||||
writeln('version: ', dw);
|
||||
while st.Position<st.Size do begin
|
||||
ofs := st.Position;
|
||||
sc.id := st.ReadByte;
|
||||
sc.Size := ReadU(st);
|
||||
writeln(ofs,': id=', sc.id,'(', SectionIdToStr(sc.id),') sz=', sc.size);
|
||||
|
||||
ps := st.Position+sc.size;
|
||||
if sc.id= 1 then DumpTypes(st);
|
||||
|
||||
if st.Position <> ps then
|
||||
begin
|
||||
writeln('adjust stream targ=',ps,' actual: ', st.position);
|
||||
st.Position := ps;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
var
|
||||
fs :TFileStream;
|
||||
begin
|
||||
if ParamCount=0 then begin
|
||||
writeln('please sepcify .wasm file');
|
||||
exit;
|
||||
end;
|
||||
fs := TFileStream.Create(ParamStr(1), fmOpenRead or fmShareDenyNone);
|
||||
try
|
||||
ReadStream(fs);
|
||||
finally
|
||||
fs.Free;
|
||||
end;
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user