On Monday, 25 November 2019 at 18:44:01 UTC, thedeemon wrote:
On Saturday, 23 November 2019 at 09:51:13 UTC, Sebastiaan Koppe
wrote:
This is my proposal for porting D runtime to WebAssembly. I
would like to ask you to review it. You can find it here:
https://gist.github.com/skoppe/7617ceba6afd67b2e20c6be4f922725d
Please correct me where I'm wrong, but on the level of
WebAssembly there are no registers, there is an operand stack
outside the address space, there are local variables to the
current function, again outside the accessible address space of
program's linear memory, and there is the linear memory itself.
So scanning the stack becomes a really hard (should I say
impossible?) part. What some compilers do is they organize
another stack manually in the linear memory and store the
values that would otherwise be on the normal stack, there.
Yeah, that accurately describes the situation. I will update the
wording in the document to use 'stack', 'shadow stack' (also
sometimes called 'user stack') and the local variable. Thanks.
One solution that I employed in spasm's experimental gc is to
only run it directly from javascript. This way there can't be
anything hiding in the stack or in a local variable. Although
that approach doesn't work for all use cases.
Which means in case of D you'll have to seriously change the
codegen, to change how local variables are stored, and to use a
kind of shadow stack for temporaries in expressions that may be
pointers. Do you really have a plan about it?
Well, no, not fully. That is why I said 'unknown'. But there must
be a solution somewhere.
LLVM already puts pointers to stack or local variables in the
shadow stack. As well as for structs-by-val that don't fit the
stack. We could adjust LDC to nudge LLVM to maintain live roots
on the shadow stack as well.
Go's approach is to put everything on the shadow stack. (see:
https://docs.google.com/document/d/131vjr4DH6JFnb-blm_uRdaC0_Nv3OUwjEY5qVCxCup4/preview#heading=h.mjo1bish3xni)
There is also the possibility of a code transformation. Binaryen
has a spill-the-pointer pass that effectively gets you go's
solution (but only for i32's) (see:
https://github.com/WebAssembly/binaryen/blob/master/src/passes/pass.cpp#L310)
I am favoring the first option, but I don't know how hard that
would be. Will update the document with this info.
Thank you for questioning this.