Compare commits
4 Commits
347dd8f534
...
a3cfd405a9
| Author | SHA1 | Date | |
|---|---|---|---|
|
a3cfd405a9
|
|||
|
671e7f60d2
|
|||
|
580d5d2a4a
|
|||
|
1105daaad0
|
113
asm.js
113
asm.js
@@ -134,14 +134,47 @@ const opcodes = {
|
|||||||
"end": 0x0b,
|
"end": 0x0b,
|
||||||
"br": 0x0c,
|
"br": 0x0c,
|
||||||
"br_if": 0x0d,
|
"br_if": 0x0d,
|
||||||
|
"call": 0x10,
|
||||||
|
"call_indirect": 0x11,
|
||||||
|
"drop": 0x0a,
|
||||||
"local.get": 0x20,
|
"local.get": 0x20,
|
||||||
"local.set": 0x21,
|
"local.set": 0x21,
|
||||||
"local.tee": 0x22,
|
"local.tee": 0x22,
|
||||||
"global.get": 0x23,
|
"global.get": 0x23,
|
||||||
"global.set": 0x24,
|
"global.set": 0x24,
|
||||||
|
"i32.load": 0x28,
|
||||||
|
"i32.load8_u": 0x2d,
|
||||||
|
"i32.store": 0x36,
|
||||||
|
"i32.store8": 0x3a,
|
||||||
"i32.const": 0x41,
|
"i32.const": 0x41,
|
||||||
|
"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.gt_u": 0x4b,
|
||||||
|
"i32.le_s": 0x4c,
|
||||||
|
"i32.le_u": 0x4d,
|
||||||
|
"i32.ge_s": 0x4e,
|
||||||
|
"i32.ge_u": 0x4f,
|
||||||
|
"i32.add": 0x6a,
|
||||||
|
"i32.sub": 0x6b,
|
||||||
"i32.mul": 0x6c,
|
"i32.mul": 0x6c,
|
||||||
|
"i32.and": 0x71,
|
||||||
|
"i32.or": 0x72,
|
||||||
|
"i32.xor": 0x73,
|
||||||
|
"i32.shl": 0x74,
|
||||||
|
"i32.shr_s": 0x75,
|
||||||
|
"i32.shr_u": 0x76,
|
||||||
|
|
||||||
|
// Threads instructions
|
||||||
|
"memory.atomic.notify": [ 0xfe, 0x00 ],
|
||||||
|
"memory.atomic.wait32": [ 0xfe, 0x01 ],
|
||||||
|
"memory.atomic.load": [ 0xfe, 0x10 ],
|
||||||
|
"memory.atomic.load8_u": [ 0xfe, 0x12 ],
|
||||||
|
"memory.atomic.store": [ 0xfe, 0x17 ],
|
||||||
|
"memory.atomic.store8": [ 0xfe, 0x19 ],
|
||||||
};
|
};
|
||||||
|
|
||||||
const mem_flags = {
|
const mem_flags = {
|
||||||
@@ -708,11 +741,12 @@ export class Assembler {
|
|||||||
this.data = [];
|
this.data = [];
|
||||||
this.defs = {};
|
this.defs = {};
|
||||||
this.blocks = [];
|
this.blocks = [];
|
||||||
|
this.types = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
action_append(action) {
|
action_append(action) {
|
||||||
const code = action.opcode != undefined
|
const code = action.opcode != undefined
|
||||||
? [ action.opcode ]
|
? [ action.opcode ].flat()
|
||||||
: this.leb128(action.literal);
|
: this.leb128(action.literal);
|
||||||
this.funcs[this.current_func].body.push(...code);
|
this.funcs[this.current_func].body.push(...code);
|
||||||
}
|
}
|
||||||
@@ -799,7 +833,7 @@ export class Assembler {
|
|||||||
const data = this.data.at(-1).data;
|
const data = this.data.at(-1).data;
|
||||||
const value = action.value != null
|
const value = action.value != null
|
||||||
? action.value
|
? action.value
|
||||||
: this.le_bytes(this.lookup_def(action.symbol), action.size);
|
: this.le(this.lookup_def(action.symbol), action.size);
|
||||||
data.push(...value);
|
data.push(...value);
|
||||||
this.pos.addr += action.size;
|
this.pos.addr += action.size;
|
||||||
}
|
}
|
||||||
@@ -871,31 +905,36 @@ export class Assembler {
|
|||||||
return this.defs[symbol];
|
return this.defs[symbol];
|
||||||
}
|
}
|
||||||
|
|
||||||
le_bytes(value, count) {
|
le(value, count) {
|
||||||
let bytes = []
|
let bytes = []
|
||||||
while (value != 0 && bytes.length < count) {
|
while (value != 0) {
|
||||||
bytes.push(value & 0xff);
|
bytes.push(value & 0xff);
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
}
|
}
|
||||||
|
if (count != undefined) {
|
||||||
while (bytes.length < count)
|
while (bytes.length < count)
|
||||||
bytes.push(0);
|
bytes.push(0);
|
||||||
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leb128(x) {
|
||||||
|
const orig = x;
|
||||||
|
const bytes = [];
|
||||||
|
while (true) {
|
||||||
|
const b = x & 0x7f;
|
||||||
|
x >>= 7;
|
||||||
|
if (x == 0 && (b & 0x40) == 0 || x == -1 && (b & 0x40) != 0) {
|
||||||
|
bytes.push(b);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
bytes.push(b | 0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wasm_section_type() {
|
wasm_section_type() {
|
||||||
const funcs = Object.values(this.funcs);
|
if (this.types.length == 0) return null;
|
||||||
if (funcs.length == 0) return null;
|
return [ this.types.length ].concat(...this.types);
|
||||||
const contents = funcs.map(({ params, results }) => {
|
|
||||||
const param_types = Object.values(params);
|
|
||||||
return [
|
|
||||||
types["func"],
|
|
||||||
param_types.length,
|
|
||||||
...param_types,
|
|
||||||
results.length,
|
|
||||||
...results,
|
|
||||||
];
|
|
||||||
});
|
|
||||||
return [ contents.length ].concat(...contents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_section_import() {
|
wasm_section_import() {
|
||||||
@@ -917,9 +956,10 @@ export class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wasm_section_func() {
|
wasm_section_func() {
|
||||||
const func_count = Object.entries(this.funcs).length;
|
const types = Object.values(this.funcs).map(({type}) => type);
|
||||||
if (func_count == 0) return null;
|
const count = types.length;
|
||||||
return [ func_count, ...Array(func_count).keys() ];
|
if (count == 0) return null;
|
||||||
|
return [ count, ...types ];
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_section_mem() {
|
wasm_section_mem() {
|
||||||
@@ -998,6 +1038,8 @@ export class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wasm() {
|
wasm() {
|
||||||
|
this.resolve_func_types();
|
||||||
|
|
||||||
const template = [
|
const template = [
|
||||||
[ Section.TYPE, () => this.wasm_section_type() ],
|
[ Section.TYPE, () => this.wasm_section_type() ],
|
||||||
[ Section.IMPORT, () => this.wasm_section_import() ],
|
[ Section.IMPORT, () => this.wasm_section_import() ],
|
||||||
@@ -1023,17 +1065,28 @@ export class Assembler {
|
|||||||
return [ flags, init ];
|
return [ flags, init ];
|
||||||
}
|
}
|
||||||
|
|
||||||
leb128(x) {
|
func_type({ params, results }) {
|
||||||
const orig = x;
|
const param_types = Object.values(params);
|
||||||
const bytes = [];
|
return [
|
||||||
while (true) {
|
types["func"],
|
||||||
const b = x & 0x7f;
|
param_types.length,
|
||||||
x >>= 7;
|
...param_types,
|
||||||
if (x == 0 && (b & 0x40) == 0 || x == -1 && (b & 0x40) != 0) {
|
results.length,
|
||||||
bytes.push(b);
|
...results,
|
||||||
return bytes;
|
];
|
||||||
}
|
}
|
||||||
bytes.push(b | 0x80);
|
|
||||||
|
array_eq(a, b) {
|
||||||
|
return a.length == b.length && a.every((x, i) => x == b[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_type(type) {
|
||||||
|
const index = this.types.findIndex((t) => this.array_eq(type, t));
|
||||||
|
return index != -1 ? index : this.types.push(type) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_func_types() {
|
||||||
|
for (const func of Object.values(this.funcs))
|
||||||
|
func.type = this.ensure_type(this.func_type(func));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user