Assemble kernel on the client #1
60
asm.js
60
asm.js
@@ -53,6 +53,8 @@ const State = Object.freeze({
|
|||||||
RESULT: 3,
|
RESULT: 3,
|
||||||
PARAM_NAME: 4,
|
PARAM_NAME: 4,
|
||||||
PARAM_TYPE: 5,
|
PARAM_TYPE: 5,
|
||||||
|
LOCAL_NAME: 6,
|
||||||
|
LOCAL_TYPE: 7,
|
||||||
});
|
});
|
||||||
|
|
||||||
const Action = Object.freeze({
|
const Action = Object.freeze({
|
||||||
@@ -62,6 +64,7 @@ const Action = Object.freeze({
|
|||||||
RESULT: 3,
|
RESULT: 3,
|
||||||
PARAM: 4,
|
PARAM: 4,
|
||||||
SYMBOL: 5,
|
SYMBOL: 5,
|
||||||
|
LOCAL: 6,
|
||||||
});
|
});
|
||||||
|
|
||||||
const types = {
|
const types = {
|
||||||
@@ -72,6 +75,8 @@ const types = {
|
|||||||
const opcodes = {
|
const opcodes = {
|
||||||
"end": 0x0b,
|
"end": 0x0b,
|
||||||
"local.get": 0x20,
|
"local.get": 0x20,
|
||||||
|
"local.set": 0x21,
|
||||||
|
"local.tee": 0x22,
|
||||||
"i32.const": 0x41,
|
"i32.const": 0x41,
|
||||||
"i32.mul": 0x6c,
|
"i32.mul": 0x6c,
|
||||||
};
|
};
|
||||||
@@ -86,6 +91,7 @@ class Parser {
|
|||||||
".func": State.FUNC,
|
".func": State.FUNC,
|
||||||
".result": State.RESULT,
|
".result": State.RESULT,
|
||||||
".param": State.PARAM_NAME,
|
".param": State.PARAM_NAME,
|
||||||
|
".local": State.LOCAL_NAME,
|
||||||
};
|
};
|
||||||
this.handlers = {
|
this.handlers = {
|
||||||
[State.TOP]: (token) => this.token_top(token),
|
[State.TOP]: (token) => this.token_top(token),
|
||||||
@@ -94,10 +100,13 @@ class Parser {
|
|||||||
[State.RESULT]: (token) => this.token_result(token),
|
[State.RESULT]: (token) => this.token_result(token),
|
||||||
[State.PARAM_NAME]: (token) => this.token_param_name(token),
|
[State.PARAM_NAME]: (token) => this.token_param_name(token),
|
||||||
[State.PARAM_TYPE]: (token) => this.token_param_type(token),
|
[State.PARAM_TYPE]: (token) => this.token_param_type(token),
|
||||||
|
[State.LOCAL_NAME]: (token) => this.token_local_name(token),
|
||||||
|
[State.LOCAL_TYPE]: (token) => this.token_local_type(token),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.results = [];
|
this.results = [];
|
||||||
this.params = {};
|
this.params = {};
|
||||||
|
this.locals = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
integer(token) {
|
integer(token) {
|
||||||
@@ -181,6 +190,31 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token_local_name(token) {
|
||||||
|
if (token == LINE_END) {
|
||||||
|
const action = { type: Action.LOCAL, locals: this.locals };
|
||||||
|
this.state = State.TOP;
|
||||||
|
this.locals = {};
|
||||||
|
return action;
|
||||||
|
} else {
|
||||||
|
this.current_local = token;
|
||||||
|
this.state = State.LOCAL_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
token_local_type(token) {
|
||||||
|
if (token == LINE_END) {
|
||||||
|
console.error(
|
||||||
|
"ERROR: Unexpected newline in .local: expected type");
|
||||||
|
this.state = State.TOP;
|
||||||
|
this.locals = {};
|
||||||
|
} else {
|
||||||
|
this.locals[this.current_local] = types[token];
|
||||||
|
this.current_local = undefined;
|
||||||
|
this.state = State.LOCAL_NAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*handle(src) {
|
*handle(src) {
|
||||||
let action;
|
let action;
|
||||||
for (const token of this.tokenizer.handle(src)) {
|
for (const token of this.tokenizer.handle(src)) {
|
||||||
@@ -209,6 +243,7 @@ export class Assembler {
|
|||||||
[Action.RESULT]: (action) => this.action_result(action),
|
[Action.RESULT]: (action) => this.action_result(action),
|
||||||
[Action.PARAM]: (action) => this.action_param(action),
|
[Action.PARAM]: (action) => this.action_param(action),
|
||||||
[Action.SYMBOL]: (action) => this.action_symbol(action),
|
[Action.SYMBOL]: (action) => this.action_symbol(action),
|
||||||
|
[Action.LOCAL]: (action) => this.action_local(action),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.exports = [];
|
this.exports = [];
|
||||||
@@ -242,9 +277,14 @@ export class Assembler {
|
|||||||
Object.assign(this.funcs[this.current_func].params, action.params);
|
Object.assign(this.funcs[this.current_func].params, action.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_local(action) {
|
||||||
|
Object.assign(this.funcs[this.current_func].locals, action.locals);
|
||||||
|
}
|
||||||
|
|
||||||
action_symbol(action) {
|
action_symbol(action) {
|
||||||
const func = this.funcs[this.current_func];
|
const func = this.funcs[this.current_func];
|
||||||
const index = Object.keys(func.params).indexOf(action.symbol);
|
const index = this.lookup_param(func, action.symbol)
|
||||||
|
?? this.lookup_local(func, action.symbol);
|
||||||
func.body.push(index);
|
func.body.push(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,6 +294,17 @@ export class Assembler {
|
|||||||
this.handlers[action.type](action);
|
this.handlers[action.type](action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lookup_param(func, symbol) {
|
||||||
|
const index = Object.keys(func.params).indexOf(symbol);
|
||||||
|
return index == -1 ? null : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup_local(func, symbol) {
|
||||||
|
const param_count = Object.entries(func.params).length;
|
||||||
|
const index = param_count + Object.keys(func.locals).indexOf(symbol);
|
||||||
|
return index == -1 ? null : index;
|
||||||
|
}
|
||||||
|
|
||||||
wasm_section_type() {
|
wasm_section_type() {
|
||||||
const funcs = Object.values(this.funcs);
|
const funcs = Object.values(this.funcs);
|
||||||
const contents = funcs.map(({ params, results }) => {
|
const contents = funcs.map(({ params, results }) => {
|
||||||
@@ -291,10 +342,13 @@ export class Assembler {
|
|||||||
wasm_section_code() {
|
wasm_section_code() {
|
||||||
const funcs = Object.values(this.funcs);
|
const funcs = Object.values(this.funcs);
|
||||||
const contents = funcs.map(({ body, locals }) => {
|
const contents = funcs.map(({ body, locals }) => {
|
||||||
const local_count = Object.entries(locals).length;
|
const local_types = Object.values(locals);
|
||||||
|
const local_count = local_types.length;
|
||||||
return [
|
return [
|
||||||
body.length + 2,
|
body.length + local_count + 3,
|
||||||
local_count,
|
local_count,
|
||||||
|
local_count,
|
||||||
|
...local_types,
|
||||||
...body,
|
...body,
|
||||||
opcodes["end"]
|
opcodes["end"]
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user