diff --git a/asm.js b/asm.js index 8fad25c..242f9fd 100644 --- a/asm.js +++ b/asm.js @@ -89,6 +89,7 @@ const State = Object.freeze({ GLOBAL_INIT: 17, AT_MEM: 18, AT_ADDR: 19, + BYTE: 20, }); const Action = Object.freeze({ @@ -103,6 +104,7 @@ const Action = Object.freeze({ IMPORT: 8, GLOBAL: 9, AT: 10, + DATA: 11, }); const types = { @@ -146,6 +148,7 @@ class Parser { ".import": State.IMPORT_NAME, ".global": State.GLOBAL_NAME, ".at": State.AT_MEM, + ".byte": State.BYTE, }; this.handlers = { [State.TOP]: (token) => this.token_top(token), @@ -168,6 +171,7 @@ class Parser { [State.GLOBAL_INIT]: (token) => this.token_global_init(token), [State.AT_MEM]: (token) => this.token_at_mem(token), [State.AT_ADDR]: (token) => this.token_at_addr(token), + [State.BYTE]: (token) => this.token_byte(token), }; this.results = []; @@ -452,6 +456,25 @@ class Parser { 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() { const action = { type: Action.MEM, @@ -480,6 +503,7 @@ const Section = Object.freeze({ GLOBAL: 0x06, EXPORT: 0x07, CODE: 0x0a, + DATA: 0x0b, }); const Kind = Object.freeze({ @@ -504,6 +528,7 @@ export class Assembler { [Action.IMPORT]: (action) => this.action_import(action), [Action.GLOBAL]: (action) => this.action_global(action), [Action.AT]: (action) => this.action_at(action), + [Action.DATA]: (action) => this.action_data(action), }; this.exports = []; @@ -512,6 +537,7 @@ export class Assembler { this.imports = []; this.globals = {}; this.pos = { mem: 0, addr: 0 }; + this.data = []; } action_append(action) { @@ -586,6 +612,13 @@ export class Assembler { } this.pos.mem = mem; 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) { @@ -706,6 +739,21 @@ export class Assembler { 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() { const template = [ [ Section.TYPE, () => this.wasm_section_type() ], @@ -715,6 +763,7 @@ export class Assembler { [ Section.GLOBAL, () => this.wasm_section_global() ], [ Section.EXPORT, () => this.wasm_section_export() ], [ Section.CODE, () => this.wasm_section_code() ], + [ Section.DATA, () => this.wasm_section_data() ], ]; const sections = template.map(([ code, generator ]) => { const body = generator();