Implement (limited) forward reference handling

This commit is contained in:
2026-03-18 10:32:49 +00:00
parent 37d56988ef
commit 896a1ca563

43
asm.js
View File

@@ -931,6 +931,7 @@ export class Assembler {
this.types = []; this.types = [];
this.type_bindings = {}; this.type_bindings = {};
this.tables = {}; this.tables = {};
this.unresolved = [];
} }
action_append(action) { action_append(action) {
@@ -1036,9 +1037,14 @@ export class Assembler {
} }
value = this.lookup_def(action.symbol); value = this.lookup_def(action.symbol);
if (value == undefined) { if (value == undefined) {
console.error( this.unresolved.push({
`ERROR: Unable to resolve symbol ${action.symbol}`); type: "data",
return; size: action.size,
symbol: action.symbol,
target: data,
offset: data.length,
});
value = 0;
} }
} }
bytes = this.le(value, action.size); bytes = this.le(value, action.size);
@@ -1326,7 +1332,7 @@ export class Assembler {
opcodes["i32.const"], opcodes["i32.const"],
...this.leb128(loc.addr), ...this.leb128(loc.addr),
opcodes["end"], opcodes["end"],
data.length, ...this.uleb128(data.length),
...data, ...data,
] ]
}); });
@@ -1334,6 +1340,7 @@ export class Assembler {
} }
wasm() { wasm() {
this.resolve_refs();
this.resolve_func_types(); this.resolve_func_types();
const template = [ const template = [
@@ -1402,4 +1409,32 @@ export class Assembler {
return acc; 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}`);
}
}
} }