Wasm type definitions

This commit is contained in:
nora 2023-07-24 21:23:12 +02:00
parent 02412c2a09
commit 1448edc164

363
src/wasm.ts Normal file
View file

@ -0,0 +1,363 @@
// Type definitions and encoding of Wasm.
// See https://webassembly.github.io/spec/core.
// Base types.
export type Vec<T> = T[];
export type u32 = number;
export type u64 = number;
export type f32 = number;
export type f64 = number;
export type VecByte = Uint8Array;
export type Name = string;
// types
export type Numtype = "i32" | "i64" | "f32" | "f64";
export type Vectype = "v128";
export type Reftype = "funcref" | "externref";
export type Valtype = Numtype | Vectype | Reftype;
export type ResultType = Vec<Valtype>;
export type Functype = {
params: ResultType;
returns: ResultType;
};
export type Limits = {
min: u32;
max: u32;
};
export type Memtype = Limits;
export type Tabletype = {
limits: Limits;
reftype: Reftype;
};
export type GlobalType = {
mut: Mut;
type: Valtype;
};
export type Mut = "const" | "var";
export type Externtype =
| {
kind: "func";
type: Functype;
}
| {
kind: "table";
type: Tabletype;
}
| {
kind: "mem";
type: Memtype;
}
| {
kind: "global";
type: GlobalType;
};
// instructions
// . numeric
export type BitWidth = "32" | "64";
export type Sign = "u" | "s";
export type NumericInstr =
| { kind: "i32.const"; imm: u32 }
| { kind: "i64.const"; imm: u64 }
| { kind: "f32.const"; imm: f32 }
| { kind: "f64.const"; imm: f64 }
| { kind: `i${BitWidth}.${IUnOp}` }
| { kind: `f${BitWidth}.${FUnOp}` }
| { kind: `i${BitWidth}.${IBinOp}` }
| { kind: `f${BitWidth}.${FBinOp}` }
| { kind: ITestOp }
| { kind: IRelOp }
| { kind: FRelOp }
| { kind: `i${BitWidth}.extend8_s` }
| { kind: `i${BitWidth}.extend16_s` }
| { kind: `i64.extend32_s` }
| { kind: "i32.wrap_i64" }
| { kind: `i64.extend_i32_${Sign}` }
| { kind: `i${BitWidth}.trunc_f${BitWidth}_${Sign}` }
| { kind: `i${BitWidth}.trunc_sat_f${BitWidth}_${Sign}` }
| { kind: "f32.demote_f64" }
| { kind: "f64.promote_f32" }
| { kind: `f${BitWidth}.convert_i${BitWidth}_${Sign}` }
| { kind: "i32.reinterpret_f32" | "i64.reinterpret_f64" }
| { kind: "f32.reinterpret_i32" | "f64.reinterpret_i64" };
export type IUnOp = "clz" | "ctz" | "popcnt";
export type IBinOp =
| "add"
| "sub"
| "mul"
| `div_${Sign}`
| `rem_${Sign}`
| "and"
| "or"
| "xor"
| "shl"
| `shr_${Sign}`
| "rotl"
| "rotr";
export type FUnOp =
| "abs"
| "neg"
| "sqrt"
| "ceil"
| "floor"
| "trunc"
| "nearest";
export type FBinOp = "add" | "sub" | "mul" | "div" | "min" | "max" | "copysign";
export type ITestOp = "eqz";
export type IRelOp =
| "eq"
| "ne"
| `lt_${Sign}`
| `gt_${Sign}`
| `le_${Sign}`
| `ge_${Sign}`;
export type FRelOp = "eq" | "ne" | "lt" | "gt" | "le" | "ge";
// . vectors
export type VectorInstr = never;
// . reference
export type ReferenceInstr =
| { kind: "ref.null"; imm: Reftype }
| { kind: "ref.is_null" }
| { kind: "ref.func"; imm: FuncIdx };
// . parametric
export type ParametricInstr =
| { kind: "drop" }
| { kind: "select"; type?: Valtype[] };
// . variable
export type VariableInstr =
| {
kind: `local.${"get" | "set" | "tee"}`;
imm: LocalIdx;
}
| {
kind: `global.${"get" | "set"}`;
imm: LocalIdx;
};
// . table
export type TableInstr =
| {
kind: `table.${"get" | "set" | "size" | "grow" | "fill"}`;
imm: TableIdx;
}
| {
kind: "table.copy";
imm1: TableIdx;
imm2: TableIdx;
}
| {
kind: "table.init";
imm1: TableIdx;
imm2: ElemIdx;
}
| {
kind: "elem.drop";
imm: ElemIdx;
};
// . memory
export type MemArg = {
offset: u32;
align: u32;
};
export type MemoryInstr =
| {
kind: `${`${"i" | "f"}${BitWidth}` | "v128"}.${"load" | "store"}`;
imm: MemArg;
}
| {
kind: `i${BitWidth}.load${"8" | "16"}_${Sign}`;
imm: MemArg;
}
| { kind: `i64.load32_${Sign}`; imm: MemArg }
| {
kind: `i${BitWidth}.store${"8" | "16"}`;
imm: MemArg;
}
| { kind: "i64.store32"; imm: MemArg }
| {
kind: `memory.${"size" | "grow" | "fill" | "copy"}`;
}
| {
kind: "memory.init";
imm: DataIdx;
}
| { kind: "data.drop"; imm: DataIdx };
// . control
export type Blocktype =
| { kind: "typeidx"; idx: TypeIdx }
| { kind: "valtype"; type?: Valtype };
export type ControlInstr =
| {
kind: "nop" | "unreachable";
}
| {
kind: "block" | "loop";
type: Blocktype;
instr: Instr[];
}
| {
kind: "if";
type: Blocktype;
then: Instr[];
else: Instr[];
}
| {
kind: "br" | "br_if";
label: LabelIdx;
}
| {
kind: "br_table";
labels: LabelIdx[];
label: LabelIdx;
}
| {
kind: "return";
}
| {
kind: "call";
func: FuncIdx;
}
| {
kind: "call_indirect";
table: TableIdx;
type: TypeIdx;
};
// . final
export type Instr =
| NumericInstr
| VectorInstr
| ReferenceInstr
| ParametricInstr
| VariableInstr
| TableInstr
| MemoryInstr
| ControlInstr;
export type Expr = Instr[];
// Modules
export type Module = {
types: Vec<Functype>;
funcs: Vec<Func>;
tables: Vec<Table>;
mems: Vec<Mem>;
globals: Vec<Global>;
elems: Vec<Elem>;
datas: Vec<Data>;
start?: Start;
imports: Vec<Import>;
exports: Vec<Export>;
};
export type TypeIdx = u32;
export type FuncIdx = u32;
export type TableIdx = u32;
export type MemIdx = u32;
export type GlobalIdx = u32;
export type ElemIdx = u32;
export type DataIdx = u32;
export type LocalIdx = u32;
export type LabelIdx = u32;
export type Func = {
type: TypeIdx;
locals: Vec<Valtype>;
body: Expr;
};
export type Table = {
type: Tabletype;
};
export type Mem = {
type: Memtype;
};
export type GLobal = {
type: GlobalType;
init: Expr;
};
export type Elem = unknown;
export type Data = {
init: VecByte;
mode: Datamode;
};
export type Datamode =
| { kind: "passive" }
| { kind: "active"; memory: MemIdx; offset: Expr };
export type Start = {
func: FuncIdx;
};
export type Export = {
name: Name;
desc: ExportDesc;
};
export type ExportDesc =
| {
kind: "func";
idx: FuncIdx;
}
| { kind: "table"; idx: TableIdx }
| { kind: "mem"; idx: MemIdx | { kind: "global"; idx: GlobalIdx } };
export type Import = {
module: Name;
name: Name;
desc: ImportDesc;
};
export type ImportDesc =
| {
kind: "func";
idx: FuncIdx;
}
| { kind: "table"; idx: TableIdx }
| { kind: "mem"; idx: MemIdx | { kind: "global"; idx: GlobalIdx } };