[PATCH 020/188] adding utility for parsing bincode

From fa3b578e5e878d16eaacc42ec37503fc6a8fb9db Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <skalogryz.lists@gmail.com>
Date: Fri, 27 Sep 2019 00:46:16 -0400

git-svn-id: branches/wasm@46016 -
This commit is contained in:
nickysn 2020-08-03 12:59:05 +00:00
parent bb7fa2e3e4
commit 7e1968675c
2 changed files with 296 additions and 0 deletions

1
.gitattributes vendored
View File

@ -18978,6 +18978,7 @@ 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/wasmbincode.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

View File

@ -0,0 +1,295 @@
unit wasmbincode;
interface
uses
Classes, SysUtils, lebutils;
const
VALTYPE_NONE = $40;
VALTYPE_I32 = $7F;
VALTYPE_I64 = $7E;
VALTYPE_F32 = $7D;
VALTYPE_F64 = $7C;
INST_TRAP = $00;
// ..
INST_IF = $04;
INST_ELSE = $05;
// ...
INST_END = $0b;
// ...
INST_REINTERPRET_I64 = $BF;
MIN_INST = INST_TRAP;
MAX_INST = INST_REINTERPRET_I64;
type
TInstParamType = (ipNone,
ipLeb, // label index or function index
ip2Leb, // memory arguments, ask for offset + align
ipi32, // signed Leb of maximum 4 bytes
ipi64, // signed Leb of maximum 8 bytes
ipf32, // float point single
ipf64, // float point double
ipTable, // a complex structure... used for br_table only
ipResType // result type used for blocks, such as If, block or loop
);
TInstFlag = record
valid : Boolean;
Param : TInstParamType;
end;
const
INST_FLAGS : array [MIN_INST..MAX_INST] of TInstFlag = (
(valid: true; Param: ipNone) // 00 trap (unreachable)
,(valid: true; Param: ipNone) // 01 nop
,(valid: true; Param: ipResType) // 02
,(valid: true; Param: ipResType) // 03
,(valid: true; Param: ipResType) // 04
,(valid: true; Param: ipResType) // 05
,(valid: false; Param: ipNone) // 06
,(valid: false; Param: ipNone) // 07
,(valid: false; Param: ipNone) // 08
,(valid: false; Param: ipNone) // 09
,(valid: false; Param: ipNone) // 0A
,(valid: true; Param: ipNone) // 0B end
,(valid: true; Param: ipLeb) // 0C br
,(valid: true; Param: ipLeb) // 0D br_if
,(valid: true; Param: ipTable) // 0E br_table
,(valid: true; Param: ipNone) // 0F
,(valid: true; Param: ipLeb) // 10 call
,(valid: true; Param: ipLeb) // 11 call_indirect
,(valid: false; Param: ipNone) // 12
,(valid: false; Param: ipNone) // 13
,(valid: false; Param: ipNone) // 14
,(valid: false; Param: ipNone) // 15
,(valid: false; Param: ipNone) // 16
,(valid: false; Param: ipNone) // 17
,(valid: false; Param: ipNone) // 18
,(valid: false; Param: ipNone) // 19
,(valid: true; Param: ipNone) // 1A
,(valid: true; Param: ipNone) // 1B
,(valid: false; Param: ipNone) // 1C
,(valid: false; Param: ipNone) // 1D
,(valid: false; Param: ipNone) // 1E
,(valid: false; Param: ipNone) // 1F
,(valid: true; Param: ipLeb) // 20 local.get
,(valid: true; Param: ipLeb) // 21 local.set
,(valid: true; Param: ipLeb) // 22 local.tee
,(valid: true; Param: ipLeb) // 23 global.get
,(valid: true; Param: ipLeb) // 24 global.set
,(valid: false; Param: ipNone) // 25
,(valid: false; Param: ipNone) // 26
,(valid: false; Param: ipNone) // 27
,(valid: true; Param: ip2Leb) // 28 i32.load
,(valid: true; Param: ip2Leb) // 29
,(valid: true; Param: ip2Leb) // 2A
,(valid: true; Param: ip2Leb) // 2B
,(valid: true; Param: ip2Leb) // 2C
,(valid: true; Param: ip2Leb) // 2D
,(valid: true; Param: ip2Leb) // 2E
,(valid: true; Param: ip2Leb) // 2F
,(valid: true; Param: ip2Leb) // 30
,(valid: true; Param: ip2Leb) // 31
,(valid: true; Param: ip2Leb) // 32
,(valid: true; Param: ip2Leb) // 33
,(valid: true; Param: ip2Leb) // 34 i64.load32_s
,(valid: true; Param: ip2Leb) // 35 i64.load32_u
,(valid: true; Param: ip2Leb) // 36
,(valid: true; Param: ip2Leb) // 37
,(valid: true; Param: ip2Leb) // 38
,(valid: true; Param: ip2Leb) // 39
,(valid: true; Param: ip2Leb) // 3A
,(valid: true; Param: ip2Leb) // 3B
,(valid: true; Param: ip2Leb) // 3C
,(valid: true; Param: ip2Leb) // 3D
,(valid: true; Param: ip2Leb) // 3E i64.store32
,(valid: true; Param: ipNone) // 3F
,(valid: true; Param: ipNone) // 40
,(valid: true; Param: ipi32) // 41
,(valid: true; Param: ipi64) // 42
,(valid: true; Param: ipf32) // 43
,(valid: true; Param: ipf64) // 44
,(valid: true; Param: ipNone) // 45
,(valid: true; Param: ipNone) // 46
,(valid: true; Param: ipNone) // 47
,(valid: true; Param: ipNone) // 48
,(valid: true; Param: ipNone) // 49
,(valid: true; Param: ipNone) // 4A
,(valid: true; Param: ipNone) // 4B
,(valid: true; Param: ipNone) // 4C
,(valid: true; Param: ipNone) // 4D
,(valid: true; Param: ipNone) // 4E
,(valid: true; Param: ipNone) // 4F
,(valid: true; Param: ipNone) // 50
,(valid: true; Param: ipNone) // 51
,(valid: true; Param: ipNone) // 52
,(valid: true; Param: ipNone) // 53
,(valid: true; Param: ipNone) // 54
,(valid: true; Param: ipNone) // 55
,(valid: true; Param: ipNone) // 56
,(valid: true; Param: ipNone) // 57
,(valid: true; Param: ipNone) // 58
,(valid: true; Param: ipNone) // 59
,(valid: true; Param: ipNone) // 5A
,(valid: true; Param: ipNone) // 5B
,(valid: true; Param: ipNone) // 5C
,(valid: true; Param: ipNone) // 5D
,(valid: true; Param: ipNone) // 5E
,(valid: true; Param: ipNone) // 5F
,(valid: true; Param: ipNone) // 60
,(valid: true; Param: ipNone) // 61
,(valid: true; Param: ipNone) // 62
,(valid: true; Param: ipNone) // 63
,(valid: true; Param: ipNone) // 64
,(valid: true; Param: ipNone) // 65
,(valid: true; Param: ipNone) // 66
,(valid: true; Param: ipNone) // 67
,(valid: true; Param: ipNone) // 68
,(valid: true; Param: ipNone) // 69
,(valid: true; Param: ipNone) // 6A
,(valid: true; Param: ipNone) // 6B
,(valid: true; Param: ipNone) // 6C
,(valid: true; Param: ipNone) // 6D
,(valid: true; Param: ipNone) // 6E
,(valid: true; Param: ipNone) // 6F
,(valid: true; Param: ipNone) // 70
,(valid: true; Param: ipNone) // 71
,(valid: true; Param: ipNone) // 72
,(valid: true; Param: ipNone) // 73
,(valid: true; Param: ipNone) // 74
,(valid: true; Param: ipNone) // 75
,(valid: true; Param: ipNone) // 76
,(valid: true; Param: ipNone) // 77
,(valid: true; Param: ipNone) // 78
,(valid: true; Param: ipNone) // 79
,(valid: true; Param: ipNone) // 7A
,(valid: true; Param: ipNone) // 7B
,(valid: true; Param: ipNone) // 7C
,(valid: true; Param: ipNone) // 7D
,(valid: true; Param: ipNone) // 7E
,(valid: true; Param: ipNone) // 7F
,(valid: true; Param: ipNone) // 80
,(valid: true; Param: ipNone) // 81
,(valid: true; Param: ipNone) // 82
,(valid: true; Param: ipNone) // 83
,(valid: true; Param: ipNone) // 84
,(valid: true; Param: ipNone) // 85
,(valid: true; Param: ipNone) // 86
,(valid: true; Param: ipNone) // 87
,(valid: true; Param: ipNone) // 88
,(valid: true; Param: ipNone) // 89
,(valid: true; Param: ipNone) // 8A
,(valid: true; Param: ipNone) // 8B
,(valid: true; Param: ipNone) // 8C
,(valid: true; Param: ipNone) // 8D
,(valid: true; Param: ipNone) // 8E
,(valid: true; Param: ipNone) // 8F
,(valid: true; Param: ipNone) // 90
,(valid: true; Param: ipNone) // 91
,(valid: true; Param: ipNone) // 92
,(valid: true; Param: ipNone) // 93
,(valid: true; Param: ipNone) // 94
,(valid: true; Param: ipNone) // 95
,(valid: true; Param: ipNone) // 96
,(valid: true; Param: ipNone) // 97
,(valid: true; Param: ipNone) // 98
,(valid: true; Param: ipNone) // 99
,(valid: true; Param: ipNone) // 9A
,(valid: true; Param: ipNone) // 9B
,(valid: true; Param: ipNone) // 9C
,(valid: true; Param: ipNone) // 9D
,(valid: true; Param: ipNone) // 9E
,(valid: true; Param: ipNone) // 9F
,(valid: true; Param: ipNone) // A0
,(valid: true; Param: ipNone) // A1
,(valid: true; Param: ipNone) // A2
,(valid: true; Param: ipNone) // A3
,(valid: true; Param: ipNone) // A4
,(valid: true; Param: ipNone) // A5
,(valid: true; Param: ipNone) // A6
,(valid: true; Param: ipNone) // A7
,(valid: true; Param: ipNone) // A8
,(valid: true; Param: ipNone) // A9
,(valid: true; Param: ipNone) // AA
,(valid: true; Param: ipNone) // AB
,(valid: true; Param: ipNone) // AC
,(valid: true; Param: ipNone) // AD
,(valid: true; Param: ipNone) // AE
,(valid: true; Param: ipNone) // AF
,(valid: true; Param: ipNone) // B0
,(valid: true; Param: ipNone) // B1
,(valid: true; Param: ipNone) // B2
,(valid: true; Param: ipNone) // B3
,(valid: true; Param: ipNone) // B4
,(valid: true; Param: ipNone) // B5
,(valid: true; Param: ipNone) // B6
,(valid: true; Param: ipNone) // B7
,(valid: true; Param: ipNone) // B8
,(valid: true; Param: ipNone) // B9
,(valid: true; Param: ipNone) // BA
,(valid: true; Param: ipNone) // BB
,(valid: true; Param: ipNone) // BC
,(valid: true; Param: ipNone) // BD
,(valid: true; Param: ipNone) // BE
,(valid: true; Param: ipNone) // BF
);
function InstLen(st: TStream; endOfInst: Byte = INST_END): Integer;
implementation
function InstLen(st: TStream; endOfInst: Byte = INST_END): Integer;
var
cd : byte;
ofs : int64;
b : byte;
sz : int64;
begin
ofs := st.Position;
try
sz:=st.Size;
while ofs < sz do begin
cd := st.ReadByte;
if (cd > MAX_INST) then begin
Result:=-1; // invalid code
Exit;
end;
if cd = endOfInst then break;
case INST_FLAGS[cd].Param of
ipLeb:
ReadU(st);
ip2Leb: begin
ReadU(st);
ReadU(st);
end;
ipTable: begin // not implemented :(
Result:=-2;
Exit;
end;
ipi32: ReadS(st, 32);
ipi64: ReadS(st, 64);
ipf32: st.Position:=st.Position+4;
ipf64: st.Position:=st.Position+8;
ipResType: begin
// it's a block. must go into recursion
b := st.ReadByte; // reading type
if (cd=INST_IF) and (b <> VALTYPE_NONE) then begin
InstLen(st, INST_ELSE);
InstLen(st, INST_END);
end else
InstLen(st, INST_END)
end;
end;
end;
finally
Result := st.Position - ofs;
st.Position:=ofs;
end;
end;
end.