diff --git a/asm.js b/asm.js index b58bca9..604b750 100644 --- a/asm.js +++ b/asm.js @@ -931,6 +931,7 @@ export class Assembler { this.types = []; this.type_bindings = {}; this.tables = {}; + this.unresolved = []; } action_append(action) { @@ -1036,9 +1037,14 @@ export class Assembler { } value = this.lookup_def(action.symbol); if (value == undefined) { - console.error( - `ERROR: Unable to resolve symbol ${action.symbol}`); - return; + this.unresolved.push({ + type: "data", + size: action.size, + symbol: action.symbol, + target: data, + offset: data.length, + }); + value = 0; } } bytes = this.le(value, action.size); @@ -1326,7 +1332,7 @@ export class Assembler { opcodes["i32.const"], ...this.leb128(loc.addr), opcodes["end"], - data.length, + ...this.uleb128(data.length), ...data, ] }); @@ -1334,6 +1340,7 @@ export class Assembler { } wasm() { + this.resolve_refs(); this.resolve_func_types(); const template = [ @@ -1402,4 +1409,32 @@ export class Assembler { return acc; }, []); } + + resolve_refs() { + const failed = []; + for (const ref of this.unresolved) { + if (ref.type != "data") { + console.error( + `ERROR: Unsupported ref type ${ref.type} for ` + + `symbol ${ref.symbol}` + ); + failed.push(ref.symbol); + continue; + } + + const value = this.defs[ref.symbol]; + if (value == undefined) { + failed.push(ref.symbol); + continue; + } + + const bytes = this.le(value, ref.size); + ref.target.splice(ref.offset, ref.size, ...bytes); + } + + if (failed.length != 0) { + const failed_str = failed.join(" "); + console.error(`ERROR: Unable to resolve refs: ${failed_str}`); + } + } }