Compare commits

..

6 Commits

60
asm.js
View File

@@ -106,6 +106,7 @@ const State = Object.freeze({
ELEM_TABLE: 33, ELEM_TABLE: 33,
ELEM_ELEM: 34, ELEM_ELEM: 34,
ELEM_LABEL: 35, ELEM_LABEL: 35,
ZERO: 36,
}); });
const Action = Object.freeze({ const Action = Object.freeze({
@@ -161,6 +162,7 @@ const opcodes = {
"i32.store": 0x36, "i32.store": 0x36,
"i32.store8": 0x3a, "i32.store8": 0x3a,
"i32.const": 0x41, "i32.const": 0x41,
"i64.const": 0x42,
"i32.eqz": 0x45, "i32.eqz": 0x45,
"i32.eq": 0x46, "i32.eq": 0x46,
"i32.ne": 0x47, "i32.ne": 0x47,
@@ -175,6 +177,8 @@ const opcodes = {
"i32.add": 0x6a, "i32.add": 0x6a,
"i32.sub": 0x6b, "i32.sub": 0x6b,
"i32.mul": 0x6c, "i32.mul": 0x6c,
"i32.div_s": 0x6d,
"i32.rem_s": 0x6f,
"i32.and": 0x71, "i32.and": 0x71,
"i32.or": 0x72, "i32.or": 0x72,
"i32.xor": 0x73, "i32.xor": 0x73,
@@ -183,12 +187,12 @@ const opcodes = {
"i32.shr_u": 0x76, "i32.shr_u": 0x76,
// Threads instructions // Threads instructions
"memory.atomic.notify": [ 0xfe, 0x00 ], "memory.atomic.notify": [ 0xfe, 0x00 ],
"memory.atomic.wait32": [ 0xfe, 0x01 ], "memory.atomic.wait32": [ 0xfe, 0x01 ],
"memory.atomic.load": [ 0xfe, 0x10 ], "i32.atomic.load": [ 0xfe, 0x10 ],
"memory.atomic.load8_u": [ 0xfe, 0x12 ], "i32.atomic.load8_u": [ 0xfe, 0x12 ],
"memory.atomic.store": [ 0xfe, 0x17 ], "i32.atomic.store": [ 0xfe, 0x17 ],
"memory.atomic.store8": [ 0xfe, 0x19 ], "i32.atomic.store8": [ 0xfe, 0x19 ],
}; };
const mem_flags = { const mem_flags = {
@@ -225,6 +229,7 @@ class Parser {
".type": State.TYPE_NAME, ".type": State.TYPE_NAME,
".table": State.TABLE_NAME, ".table": State.TABLE_NAME,
".elem": State.ELEM_TABLE, ".elem": State.ELEM_TABLE,
".zero": State.ZERO,
}; };
this.blocks = new Set(["block", "loop", "if"]); this.blocks = new Set(["block", "loop", "if"]);
this.handlers = { this.handlers = {
@@ -264,6 +269,7 @@ class Parser {
[State.ELEM_TABLE]: (token) => this.token_elem_table(token), [State.ELEM_TABLE]: (token) => this.token_elem_table(token),
[State.ELEM_ELEM]: (token) => this.token_elem_elem(token), [State.ELEM_ELEM]: (token) => this.token_elem_elem(token),
[State.ELEM_LABEL]: (token) => this.token_elem_label(token), [State.ELEM_LABEL]: (token) => this.token_elem_label(token),
[State.ZERO]: (token) => this.token_zero(token),
}; };
this.results = []; this.results = [];
@@ -547,15 +553,10 @@ class Parser {
token_at_addr(token) { token_at_addr(token) {
const value = this.integer(token); const value = this.integer(token);
if (value == null) { if (value != null)
console.error( this.at.addr = value;
`ERROR: Unexpected token ${token} in .mem: ` else
+ "expected address"); this.at.addr_symbol = token;
this.at = undefined;
return;
}
this.at.addr = value;
const action = { type: Action.AT, at: this.at }; const action = { type: Action.AT, at: this.at };
this.at = undefined; this.at = undefined;
this.state = State.TOP; this.state = State.TOP;
@@ -823,6 +824,26 @@ class Parser {
return action; return action;
} }
token_zero(token) {
if (token == LINE_END) {
console.error(
"ERROR: Unexpected newline in .zero, expected count")
this.state = State.TOP;
return;
}
const count = this.integer(token);
if (count == null) {
console.error(
`ERROR: Unexpected token ${token} in .zero, expected count`);
this.state = State.TOP;
return;
}
this.state = State.TOP;
return { type: Action.DATA, size: count, value: 0 }
}
mem_action() { mem_action() {
const action = { const action = {
type: Action.MEM, type: Action.MEM,
@@ -963,7 +984,7 @@ export class Assembler {
} }
func.body.push(...this.leb128(def_value)); func.body.push(...this.leb128(def_value));
} else { } else {
func.body.push(...this.leb128(value)); func.body.push(...this.uleb128(value));
} }
} }
@@ -995,7 +1016,8 @@ export class Assembler {
return; return;
} }
this.pos.mem = mem; this.pos.mem = mem;
this.pos.addr = action.at.addr; this.pos.addr = action.at.addr
?? this.lookup_def(action.at.addr_symbol);
this.data.push({ loc: { ...this.pos }, data: [] }) this.data.push({ loc: { ...this.pos }, data: [] })
} }
@@ -1327,7 +1349,9 @@ export class Assembler {
]; ];
const sections = template.map(([ code, generator ]) => { const sections = template.map(([ code, generator ]) => {
const body = generator(); const body = generator();
return body == null ? [] : [ code, body.length, body ]; if (body == null)
return [];
return [ code, this.uleb128(body.length), body ];
}); });
return new Uint8Array([ HEADER, sections ].flat(Infinity)); return new Uint8Array([ HEADER, sections ].flat(Infinity));