fix(parser): do not fuse local.get/local.tee across a branch target - #56
Open
stevefan1999-personal wants to merge 1 commit into
Open
Conversation
`visit_local_tee` peeked at the last emitted instruction and, when it was a
`local.get`, replaced the pair with `LocalCopy(src, dst); LocalGet(dst)`.
It never checked whether the tee's position is a jump target. When the
`local.get` is a block's fallthrough result and the `local.tee` is the first
instruction after `end`, every branch to that label lands on `LocalGet(dst)`
instead of the tee: the branch's value is left dangling on the stack and a
stale local is pushed on top. Loop starts and if/else joins have the same
shape.
TinyCC compiled with clang -Os/-Oz hit this in musl's realloc: the
`if (!p) { r = malloc(n); br 1 }` path returned n instead of r, so the
caller wrote into address 1200 and later trapped with an out-of-bounds
load, while V8 and wabt ran the same module correctly.
The lowering step now always emits a plain `LocalTee`. The fusion moves
into the peephole rewriter, which only matches within a basic block and so
cannot cross a label. Regression test covers the block-end, if/else-join
and loop-start cases.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I was trying to compile TCC to WASI and run it using tinywasm thanks to the exception implementation (sigh, which is because of the use of setjmp/longjmp for compiler rewind, that's the whole reason, WASI syscall is really not that hard to say the least), but it went into a mysterious bug that keeps trapping on the same address.
And yes, that means I did have a WASIp1 implementaion and I actually implemented it with a VFS (nix the network socket just yet), so I can theoretically have a cross-platform JIT compiler where I can have safe reentrancy, and it is not until recently the TCC mob branches have their TLS implementations, but it is all too late and they still rely on CRT. It is also theoretically possible.
So my plan is to compile libtcc as small as possible to WASI using fat LTO, and I keep getting trapped on the same address. Under NodeJS with a shim WASI implementation, the whole libtcc fat LTO WASI actually works. So it has to be a problem in tinywasm
Claude said this (it is Fable 5.1 btw):
I will try to use https://www.npmjs.com/package/@yowasp/clang to see if there are more VM shenanigans, though a simple benchmark shows me that the interpreter is 17x slower than native, and I guess the clang in tinywasm wouldn't take less than 3 minutes to get a meaningful outcome -- except if it blows up midway during execution.