Assemble kernel on the client #1
49
asm.js
49
asm.js
@@ -89,6 +89,7 @@ const State = Object.freeze({
|
|||||||
GLOBAL_INIT: 17,
|
GLOBAL_INIT: 17,
|
||||||
AT_MEM: 18,
|
AT_MEM: 18,
|
||||||
AT_ADDR: 19,
|
AT_ADDR: 19,
|
||||||
|
BYTE: 20,
|
||||||
});
|
});
|
||||||
|
|
||||||
const Action = Object.freeze({
|
const Action = Object.freeze({
|
||||||
@@ -103,6 +104,7 @@ const Action = Object.freeze({
|
|||||||
IMPORT: 8,
|
IMPORT: 8,
|
||||||
GLOBAL: 9,
|
GLOBAL: 9,
|
||||||
AT: 10,
|
AT: 10,
|
||||||
|
DATA: 11,
|
||||||
});
|
});
|
||||||
|
|
||||||
const types = {
|
const types = {
|
||||||
@@ -146,6 +148,7 @@ class Parser {
|
|||||||
".import": State.IMPORT_NAME,
|
".import": State.IMPORT_NAME,
|
||||||
".global": State.GLOBAL_NAME,
|
".global": State.GLOBAL_NAME,
|
||||||
".at": State.AT_MEM,
|
".at": State.AT_MEM,
|
||||||
|
".byte": State.BYTE,
|
||||||
};
|
};
|
||||||
this.handlers = {
|
this.handlers = {
|
||||||
[State.TOP]: (token) => this.token_top(token),
|
[State.TOP]: (token) => this.token_top(token),
|
||||||
@@ -168,6 +171,7 @@ class Parser {
|
|||||||
[State.GLOBAL_INIT]: (token) => this.token_global_init(token),
|
[State.GLOBAL_INIT]: (token) => this.token_global_init(token),
|
||||||
[State.AT_MEM]: (token) => this.token_at_mem(token),
|
[State.AT_MEM]: (token) => this.token_at_mem(token),
|
||||||
[State.AT_ADDR]: (token) => this.token_at_addr(token),
|
[State.AT_ADDR]: (token) => this.token_at_addr(token),
|
||||||
|
[State.BYTE]: (token) => this.token_byte(token),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.results = [];
|
this.results = [];
|
||||||
@@ -452,6 +456,25 @@ class Parser {
|
|||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token_byte(token) {
|
||||||
|
if (token == LINE_END) {
|
||||||
|
this.state = State.TOP;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const action = { type: Action.DATA, size: 1 };
|
||||||
|
const value = this.integer(token);
|
||||||
|
if (value == null) {
|
||||||
|
console.error(
|
||||||
|
`ERROR: Unexpected token ${token}, expected value`);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (value > 0xff)
|
||||||
|
console.error(`WARNING: Value ${token} is truncated`);
|
||||||
|
action.value = [ value & 0xff ];
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
mem_action() {
|
mem_action() {
|
||||||
const action = {
|
const action = {
|
||||||
type: Action.MEM,
|
type: Action.MEM,
|
||||||
@@ -480,6 +503,7 @@ const Section = Object.freeze({
|
|||||||
GLOBAL: 0x06,
|
GLOBAL: 0x06,
|
||||||
EXPORT: 0x07,
|
EXPORT: 0x07,
|
||||||
CODE: 0x0a,
|
CODE: 0x0a,
|
||||||
|
DATA: 0x0b,
|
||||||
});
|
});
|
||||||
|
|
||||||
const Kind = Object.freeze({
|
const Kind = Object.freeze({
|
||||||
@@ -504,6 +528,7 @@ export class Assembler {
|
|||||||
[Action.IMPORT]: (action) => this.action_import(action),
|
[Action.IMPORT]: (action) => this.action_import(action),
|
||||||
[Action.GLOBAL]: (action) => this.action_global(action),
|
[Action.GLOBAL]: (action) => this.action_global(action),
|
||||||
[Action.AT]: (action) => this.action_at(action),
|
[Action.AT]: (action) => this.action_at(action),
|
||||||
|
[Action.DATA]: (action) => this.action_data(action),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.exports = [];
|
this.exports = [];
|
||||||
@@ -512,6 +537,7 @@ export class Assembler {
|
|||||||
this.imports = [];
|
this.imports = [];
|
||||||
this.globals = {};
|
this.globals = {};
|
||||||
this.pos = { mem: 0, addr: 0 };
|
this.pos = { mem: 0, addr: 0 };
|
||||||
|
this.data = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
action_append(action) {
|
action_append(action) {
|
||||||
@@ -586,6 +612,13 @@ export class Assembler {
|
|||||||
}
|
}
|
||||||
this.pos.mem = mem;
|
this.pos.mem = mem;
|
||||||
this.pos.addr = action.at.addr;
|
this.pos.addr = action.at.addr;
|
||||||
|
this.data.push({ loc: { ...this.pos }, data: [] })
|
||||||
|
}
|
||||||
|
|
||||||
|
action_data(action) {
|
||||||
|
const data = this.data.at(-1).data;
|
||||||
|
data.push(...action.value);
|
||||||
|
this.pos.addr += action.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
push(chunk) {
|
push(chunk) {
|
||||||
@@ -706,6 +739,21 @@ export class Assembler {
|
|||||||
return [ contents.length ].concat(...contents);
|
return [ contents.length ].concat(...contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wasm_section_data() {
|
||||||
|
if (this.data.length == 0) return null;
|
||||||
|
const contents = this.data.map(({ loc, data }) => {
|
||||||
|
return [
|
||||||
|
...(loc.mem == 0 ? [ 0 ] : [ 2, loc.mem ]),
|
||||||
|
opcodes["i32.const"],
|
||||||
|
loc.addr,
|
||||||
|
opcodes["end"],
|
||||||
|
data.length,
|
||||||
|
...data,
|
||||||
|
]
|
||||||
|
});
|
||||||
|
return [ contents.length ].concat(...contents);
|
||||||
|
}
|
||||||
|
|
||||||
wasm() {
|
wasm() {
|
||||||
const template = [
|
const template = [
|
||||||
[ Section.TYPE, () => this.wasm_section_type() ],
|
[ Section.TYPE, () => this.wasm_section_type() ],
|
||||||
@@ -715,6 +763,7 @@ export class Assembler {
|
|||||||
[ Section.GLOBAL, () => this.wasm_section_global() ],
|
[ Section.GLOBAL, () => this.wasm_section_global() ],
|
||||||
[ Section.EXPORT, () => this.wasm_section_export() ],
|
[ Section.EXPORT, () => this.wasm_section_export() ],
|
||||||
[ Section.CODE, () => this.wasm_section_code() ],
|
[ Section.CODE, () => this.wasm_section_code() ],
|
||||||
|
[ Section.DATA, () => this.wasm_section_data() ],
|
||||||
];
|
];
|
||||||
const sections = template.map(([ code, generator ]) => {
|
const sections = template.map(([ code, generator ]) => {
|
||||||
const body = generator();
|
const body = generator();
|
||||||
|
|||||||
Reference in New Issue
Block a user