Expose intrinsics to set/get the pointer to the simulated stack.
LLVM currently creates a mutable global that points to a location in memory that acts as a local stack from webassembly. This is akin to the stack pointer register on most cpus. Currently, there is no way to figure out where that points or to set it to a new location.
In nebulet, this is required to implement different simulated stacks for each user-level thread.
I propose implementing two intrinsics:
get_stackset_stack
On further explorations, it looks like llvm exports intrinsics for this: llvm.stacksave and llvm.stackrestore. I've confirmed these as working in wasm. Nevertheless, it would be good to have these exposed in std::arch.
hey hey @lachlansneff ! Why did you close the issue? Maybe it is a good idea to leave it for tracking/discussing about exposing this intrinsics in std::arch?
It turns out that the llvm.stackrestore intrinsic actually is not useful for this use-case. It has to be used with a matching llvm.stacksave, and thus is not the same as being able to set the stack pointer. I'm all for exposing intrinsics to set/get the stack pointer, but it'll be more complicated than just binding to those.
So let's then reopen this issue.
My use-case is to avoid stack-overflows and dynamically grow the stack in wasm runtime. Maybe something similar to @alexcrichton 's stacker!
@pepyakin Have you had any luck with this?
Unfortunately, no, haven't tried to do something about it. Thankfully, it doesn't press me, yet : )
I just came across this issue, but something to be aware of is that the shadow stack used by LLVM is separate from the host stack (i.e. the "real" stack), so it cannot be relied upon as a way to prevent stack overflows. Even if you only ever allocate on the shadow stack, the host may allocate on its own stack, e.g. activation records, function arguments, etc. So with deep enough recursion you can still overflow the host stack, and cause a crash - currently there seems to be no way to avoid this.
I brought this up to the WebAssembly CG recently, in the context of continuations, and requested primitives for being able to query the host stack size and position in the stack (in relative terms, not actual pointers, to avoid raising security concerns). This would allow one to check both the shadow stack and host stack, and if overflow is imminent, reclaim stack space by jumping or returning to a trampoline (ala Cheney on the MTA). In my use case, this would perform much better than trampolining for every call, and enable garbage collection schemes that leverage the Cheney on the MTA-style approach of using the stack as a young generation in a generational collector. More generally though, it would enable a variety of use cases where stack management is necessary. I have not yet created an issue with a formal proposal, but it is on my TODO list.
Based on the use case in the OP, some form of continuations or coroutines may be useful for you as well. There is also some discussion around extending the base exception handling proposal with "resumable" exceptions, which may be able to act as a foundation for delimited continuations/coroutines, but I don't believe that is part of the proposal today, so if that kind of functionality is important for things you are building, I would definitely suggestion dropping by the WebAssembly design repository and make sure your voice gets heard!