Bug 1790 ("musttail call must precede a ret with an optional bitcast")
is caused by the GC stack slot pass inserting a store instruction
between a musttail call and a return instruction. This is not allowed in
LLVM IR.
One solution would be to remove the musttail. That would probably work,
but 1) the go-llvm API doesn't support this and 2) this might have
unforeseen consequences. What I've done in this commit is to move the
store instruction to a position earlier in the basic block, just after
the last access to the GC stack slot alloca.
Thanks to @fgsch for a very small repro, which I've used as a regression
test.
Not sure why you would ever do this, but it appears to be allowed by the
Go specification and previously TinyGo would crash with an unhelpful
error message when you would do this. I don't see any practical use of
it.
The implementation simply runs the builtin directly.
While LLVM coroutines are one implementation of goroutines, it is not
the only one. Therefore, rename the tests to 'goroutines' to better
describe what they're for.
There were a few cases left where a named type would cause a crash in
the compiler. While going through enough code would have found them
eventually, I specifically looked for the `Type().(` pattern: a Type()
call that is then used in a type assert. Most of those were indeed bugs,
although for some I couldn't come up with a reproducer so I left them
as-is.
This commit allows starting a new goroutine directly from a func value,
not just when the static callee is known.
This is necessary to support the whole time package, not just the
commonly used subset that was compiled with the SimpleDCE pass enabled.
This is implemented as follows:
* The parent coroutine allocates space for the return value in its
frame and stores a pointer to this frame in the parent coroutine
handle.
* The child coroutine obtains the alloca from its parent using the
parent coroutine handle. It then stores the result value there.
* The parent value reads the data from the alloca on resumption.
A bitcast was inserted when the receiver of the call wasn't a *i8. This
is a pretty common case, and did not play well with goroutines.
Avoid this bitcast by changing each call to a direct call, after
unpacking the receiver type from the *i8 parameter. This might also fix
some undefined behavior in the resulting program, as it is technically
not allowed to call a function with a different signature (even if the
signature is compatible).
Before this commit, goroutine support was spread through the compiler.
This commit changes this support, so that the compiler itself only
generates simple intrinsics and leaves the real support to a compiler
pass that runs as one of the TinyGo-specific optimization passes.
The biggest change, that was done together with the rewrite, was support
for goroutines in WebAssembly for JavaScript. The challenge in
JavaScript is that in general no blocking operations are allowed, which
means that programs that call time.Sleep() but do not start goroutines
also have to be scheduled by the scheduler.