Proposal for porting D runtime to WebAssembly

Sebastiaan Koppe mail at skoppe.eu
Tue Nov 26 09:16:51 UTC 2019


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.


More information about the Digitalmars-d-announce mailing list