brintos

brintos / hwjs-cc public Read only

0
0

HwjsCoroutinize/wasmld: link-time TRAP-CENSUS — attribute reachable bare `unreachable`s (source-level traps masquerade as pass-seam .resume traps) #7

Open jdbrinton opened this issue · 0 comments
jdbrinton jdbrinton commented

Filed from tonight's linux-in-the-browser#92 fix (agent for joel, 2026-07-14).

#92 cost a night of attribution because a SOURCE-COMPILED __builtin_trap() (the glibc overlay's loaderless dl-libc.c stub), inlined through a noreturn callee into a coroutinized caller, produced the runtime signature

RuntimeError: unreachable
    at <prog>.__nss_module_load.resume
    at <prog>.hwjs_resume / hwjs_drive_loop / _start

— byte-identical in shape to the closed pass-seam cluster (#40/#44/#46/#52/#61/#70/#71), and NOTHING at the link or in the trap distinguishes the two classes. The pass's own refuse/abort arms are already attributed (census lines at link time: REFUSE/FPCAST-ABORT/TRAPARM; hwjs_trap() at run time). A bare llvm.trap/unreachable that rides in from source is the one anonymous killer left, and noreturn folding makes it swallow the whole post-call continuation of its (coroutinized) caller, so the backtrace frame it fires in is ~unrelated to the trap's origin.

Proposal (link-time, zero runtime cost)

At the one merged-module pass run, census every function whose post-inline body contains a reachable bare unreachable / llvm.trap NOT emitted by the pass itself, with the !dbg inlinedAt chain:

[hwjs-coro] TRAP-CENSUS fn=__nss_module_load src=sysdeps/wasm32/dl-libc.c:47 via=__wasm32_no_dynamic_loader<-__libc_dlopen_mode

One grep of the link log would then have attributed #92 in minutes. The pass already walks every instruction of every function (classification), so the census is nearly free; condense per the ticket-#12 presentation rules.