File size: 3,718 Bytes
3ce1a40 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | /**
* WebAssembly binary encoding primitives: LEB128 integers, IEEE floats, vectors
* and sections, plus the opcodes the kernel backend emits. Nothing here knows
* about kernels.
*/
export const ValType = { I32: 0x7f, I64: 0x7e, F32: 0x7d, F64: 0x7c };
export const BLOCK_EMPTY = 0x40;
export const Section = { TYPE: 1, IMPORT: 2, FUNCTION: 3, EXPORT: 7, CODE: 10 };
export const ExternalKind = { FUNC: 0x00, MEMORY: 0x02 };
export const OpCode = {
unreachable: 0x00, block: 0x02, loop: 0x03, if: 0x04, else: 0x05, end: 0x0b,
br: 0x0c, br_if: 0x0d, return: 0x0f, call: 0x10,
local_get: 0x20, local_set: 0x21,
i32_load: 0x28, f32_load: 0x2a, f64_load: 0x2b,
i32_store: 0x36, f32_store: 0x38, f64_store: 0x39,
i32_const: 0x41, f32_const: 0x43, f64_const: 0x44,
i32_eqz: 0x45, i32_eq: 0x46, i32_ne: 0x47,
i32_lt_s: 0x48, i32_lt_u: 0x49, i32_gt_s: 0x4a, i32_gt_u: 0x4b,
i32_le_s: 0x4c, i32_le_u: 0x4d, i32_ge_s: 0x4e, i32_ge_u: 0x4f,
f32_eq: 0x5b, f32_ne: 0x5c, f32_lt: 0x5d, f32_gt: 0x5e, f32_le: 0x5f, f32_ge: 0x60,
f64_eq: 0x61, f64_ne: 0x62, f64_lt: 0x63, f64_gt: 0x64, f64_le: 0x65, f64_ge: 0x66,
i32_add: 0x6a, i32_sub: 0x6b, i32_mul: 0x6c, i32_div_s: 0x6d, i32_div_u: 0x6e,
i32_rem_s: 0x6f, i32_rem_u: 0x70, i32_and: 0x71, i32_or: 0x72, i32_xor: 0x73,
i32_shl: 0x74, i32_shr_s: 0x75, i32_shr_u: 0x76,
f32_neg: 0x8c, f32_add: 0x92, f32_sub: 0x93, f32_mul: 0x94, f32_div: 0x95,
f64_neg: 0x9a, f64_add: 0xa0, f64_sub: 0xa1, f64_mul: 0xa2, f64_div: 0xa3,
f32_convert_i32_s: 0xb2, f32_convert_i32_u: 0xb3, f32_demote_f64: 0xb6,
f64_convert_i32_s: 0xb7, f64_convert_i32_u: 0xb8, f64_promote_f32: 0xbb,
};
/** Saturating float-to-int truncations, 0xFC-prefixed. They never trap on NaN or overflow. */
export const SatOpCode = {
i32_trunc_sat_f32_s: 0x00, i32_trunc_sat_f32_u: 0x01,
i32_trunc_sat_f64_s: 0x02, i32_trunc_sat_f64_u: 0x03,
};
export function uleb(n) {
const bytes = [];
let v = n >>> 0;
do {
let byte = v & 0x7f;
v >>>= 7;
if (v !== 0) byte |= 0x80;
bytes.push(byte);
} while (v !== 0);
return bytes;
}
/** Signed LEB128 of a 32-bit integer. */
export function sleb(n) {
const bytes = [];
let v = n | 0;
for (;;) {
const byte = v & 0x7f;
v >>= 7;
const done = (v === 0 && (byte & 0x40) === 0) || (v === -1 && (byte & 0x40) !== 0);
bytes.push(done ? byte : byte | 0x80);
if (done) return bytes;
}
}
export function f32(n) {
const view = new DataView(new ArrayBuffer(4));
view.setFloat32(0, n, true);
return [...new Uint8Array(view.buffer)];
}
export function f64(n) {
const view = new DataView(new ArrayBuffer(8));
view.setFloat64(0, n, true);
return [...new Uint8Array(view.buffer)];
}
export function name(text) {
const bytes = [...new TextEncoder().encode(text)];
return [...uleb(bytes.length), ...bytes];
}
/** A length-prefixed vector of already-encoded items. */
export function vec(items) {
return [...uleb(items.length), ...items.flat()];
}
export function section(id, bytes) {
return [id, ...uleb(bytes.length), ...bytes];
}
export function funcType(params, results) {
return [0x60, ...vec(params.map((p) => [p])), ...vec(results.map((r) => [r]))];
}
/** A function body: local declarations run-length encoded by type, then code. */
export function funcBody(localTypes, code) {
const runs = [];
for (const type of localTypes) {
if (runs.length && runs.at(-1).type === type) runs.at(-1).count += 1;
else runs.push({ type, count: 1 });
}
const body = [...vec(runs.map((r) => [...uleb(r.count), r.type])), ...code, OpCode.end];
return [...uleb(body.length), ...body];
}
export const MAGIC_AND_VERSION = [0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00];
|