Thread overview
Does the D teams would like to increase the WASM support
Nov 17, 2022
bioinfornatics
Nov 17, 2022
H. S. Teoh
Nov 18, 2022
Adam D Ruppe
Nov 18, 2022
Paulo Pinto
Nov 18, 2022
Adam D Ruppe
November 17, 2022

Dear D community,

After the discussion Can we ease WASM in D ?

We all know that D can do wasm code through ldc compiler since years. But as the dev experience int so good it is still a toy/an experimental thing.

So I would like to know if Dlang aims to provides a better experience to code wasm ?

Indeed, currently we have to

  1. use D mostly without object.d so it is close to use a D compiler to write C code.
  2. wrap de code into some llvm statements
// import a function "add" from module name "math" and rename it to "add_numbers"
@llvmAttr("wasm-import-module", "math") @llvmAttr("wasm-import-name", "add") {
	int add_numbers(int a, int b);
}
  1. Linux Distro user which use D though deb, rpm … have a shared phobos library how to put those symbol into the wasm in such case ?

  2. compiler triple parameters -mtriple=wasm32-unknown-unknown-wasm -betterC

So it would be really helpful that the compilers and Dlang get a better wasm support.

  1. As to provides a wasm flag to the compiler to do some stuff
  2. tags function @wasm or something else
    and any others thing that could turn the D wasm toy to something usable

As example I would lovo to see a D library/frameworks that do something like yew from rust lang
This code seems pretty clean (only rust), no use of workaround as llvm statement or use of C lang though -betterC

I would appreciate to get the point of views of D backend, phobos and druntime dev teams

As references:

Thanks

November 17, 2022
On Thu, Nov 17, 2022 at 10:49:32PM +0000, bioinfornatics via Digitalmars-d wrote: [...]
> We all know that D can do wasm code through ldc compiler since years. But as the dev experience int so good it is still a toy/an experimental thing.
> 
> So I would like to know if Dlang aims to provides a better experience to code wasm ?

It will happen when one of us who wants it to move forward take things into our own hands and write the code to make it happen.


> Indeed, currently we have to
> 1. use D mostly without object.d so it is close to use a D compiler to
> write C code.
> 2. wrap de code into some llvm statements
> 
> ```D
> // import a function "add" from module name "math" and rename it to
> "add_numbers"
> @llvmAttr("wasm-import-module", "math") @llvmAttr("wasm-import-name", "add")
> {
> 	int add_numbers(int a, int b);
> }
> ```

Here's my vision of how it should be: all of the above boilerplate should be factored into compile-time templates that automatically wrap around naturally-written D functions.  I.e., user code would write:

	import math;
	int my_code() {
		return add_numbers(1, 2);
	}

and the templates will automagically insert the rest of the boilerplate for you.


> 3. Linux Distro user which use D though deb, rpm … have a shared phobos library how to put those symbol into the wasm in such case ?

I don't think WASM even has the concept of shared libraries at the moment.  Each WASM module is essentially isolated in its own universe, and interaction with the outside world requires Javascript glue code.

For the most part, the codegen shouldn't be a problem; most of Phobos is templates anyway so the compiler will just instantiate and generate the WASM code along with the calling user code.

However, for the shared part you pretty much have to either compile Phobos into the user WASM module, or compile it as a separate module that will then require Javascript glue code to bind together.  For speed, I think the former would be preferable.


> 4. compiler triple parameters `-mtriple=wasm32-unknown-unknown-wasm -betterC`

One way to work around this is to write a WASM-specific object.d along with various druntime hooks stubbed.  Not sure how we'd do the GC part, though.


> So it would be really helpful that the compilers and Dlang get a better wasm support.

I think that goes without saying.


> 1. As to provides a wasm flag to the compiler to do some stuff
> 2. tags function `@wasm` or something else and any others thing that
> could turn the D wasm toy to something usable

Why wait for stuff to be added to the compiler?  We can move stuff along now.  I envision two components to this: (1) a D template module that you import and instantiate, which will auto-generate the @llvmAttr boilerplate by introspection.  (2) a helper build script to automate away the `-mtriple=...` stuff and auto-generate Javascript glue code for moving stuff across the JS/WASM boundary.


[...]
> I would appreciate to get the point of views of D backend, `phobos` and `druntime` dev teams

I'm not holding my breath for anybody else to do anything.  Why not take things into our own hands and write the code now?

(And BTW, I'm not part of any "dev team"; I'm just a random nobody who's willing to write some code in his spare time to get things done.  I write code to do things I want to do; if it happens to help the community, then so much the better.)


> As references:
> * 2 years ago, yet! Adam provides some feedback to the D community: [D
> Tetris running on
> Webassembly](http://dpldocs.info/this-week-in-d/Blog.Posted_2020_08_10.html).
> * 3 years ago, Sebastian create the [spasm](https://github.com/skoppe/spasm)
> library
[...]

It will take someone who's motivated enough to do the work to get things to move forward.  A lot of the foundational work is already there; now it's just a matter of packaging it into a more user-friendly package.


T

-- 
Answer: Because it breaks the logical sequence of discussion. / Question: Why is top posting bad?
November 18, 2022
On Thursday, 17 November 2022 at 23:31:27 UTC, H. S. Teoh wrote:
> Not sure how we'd do the GC part, though.

The stock druntime gc works so long as the wasm stack is empty. llvm offers a shadow stack for this purpose, or I'm pretty sure (and Sebastiaan agrees, we've both been swamped with day job work but we chat every now and then a little) it'd work if we deferred the mark/sweep for when the wasm stack is empty.

In other words, GC.collect would always ask for new memory from the system as if the collection failed, but then queue it - javascript `setTimeout(GC.collect, 0);` would do the job. Then it collects when back to the event loop thus knowing the wasm work is paused and the call stack empty, so all stored values are available from memory.

Just like I said, I'm pretty swamped with work.... and when not doing work I have a million other things to do. I have some use case for webasm - it is kinda cool to put my little demo games online - but it isn't a high priority.

November 18, 2022
On Friday, 18 November 2022 at 02:06:41 UTC, Adam D Ruppe wrote:
> On Thursday, 17 November 2022 at 23:31:27 UTC, H. S. Teoh wrote:
>> Not sure how we'd do the GC part, though.
>
> The stock druntime gc works so long as the wasm stack is empty. llvm offers a shadow stack for this purpose, or I'm pretty sure (and Sebastiaan agrees, we've both been swamped with day job work but we chat every now and then a little) it'd work if we deferred the mark/sweep for when the wasm stack is empty.
>
> In other words, GC.collect would always ask for new memory from the system as if the collection failed, but then queue it - javascript `setTimeout(GC.collect, 0);` would do the job. Then it collects when back to the event loop thus knowing the wasm work is paused and the call stack empty, so all stored values are available from memory.
>
> Just like I said, I'm pretty swamped with work.... and when not doing work I have a million other things to do. I have some use case for webasm - it is kinda cool to put my little demo games online - but it isn't a high priority.

Other approaches would be to look into Java, Flash (yep), Go and .NET, all of them already have mature WebAssembly implementations, with working GCs.
November 18, 2022
On Friday, 18 November 2022 at 09:44:19 UTC, Paulo Pinto wrote:
> Other approaches would be to look into Java, Flash (yep), Go and .NET, all of them already have mature WebAssembly implementations, with working GCs.

Yeah, it is fairly easy to do with compiler support (I believe they all use a shadow stack). Same with exceptions and "blocking" functions, you can have the compiler output resumeable code with jump tables and such. llvm keeps adding more things upstream that we can tap into if we wanted to.

What I wanted to do was the smallest change to the already-almost-working webasm port to druntime that'd solve its problems with a stock D compiler.

But yes, enabling those compiler options ought not be difficult either.