Some questions with D and webassembly

ryuukk_ ryuukk.dev at gmail.com
Fri Mar 3 13:42:55 UTC 2023


On Friday, 3 March 2023 at 03:32:37 UTC, TheZipCreator wrote:
> In webassembly, there's a type called `externref`, which 
> opaquely represents a javascript object. So, you could do this 
> for example, with this javascript:
> ```js
> class Foo {
> 	constructor(x) {
> 		this.x = x;
> 	}
> }
>
> const imports = {
> 	env: {
> 		fooNew: (x) => new Foo(x),
> 		fooX: (foo) => foo.x,
> 		fooSetX: (foo, x) => { foo.x = x; }
> 	}
> }
>
> WebAssembly.instantiateStreaming(fetch("./foo.wasm"), 
> imports).then(module => {
> 	let foo = module.instance.exports.f();
> 	console.log(foo.x); // 5
> 	module.instance.exports.g(foo);
> 	console.log(foo.x); // 8
> });
> ```
> and this webassembly:
> ```wat
> (module
> 	(import "env" "fooNew" (func $fooNew (param i32) (result 
> externref)))
> 	(import "env" "fooX" (func $fooX (result i32)))
> 	(import "env" "fooSetX" (func $fooSetX (param externref) 
> (param i32)))
> 	(func (export "f") (result externref)
> 		i32.const 5
> 		call $fooNew)
> 	(func (export "g") (param $foo externref)
> 		local.get $foo
> 		i32.const 8
> 		call $fooSetX))
> ```
> 5 and 8 get logged. Equivalent D to the webassembly part would 
> be:
> ```d
> extern(C):
>
> // how to get this externref type?
> externref fooNew(int);
> externref fooX(externref);
> void fooSetX(externref, int);
>
> externref f() {
> 	return fooNew();
> }
>
> void g(externref foo) {
> 	fooSetX(foo, 8);
> }
> ```
> problem being, there exists no `externref` type. So how would 
> you achieve it with ldc2?
>
> B) In the javascript WebAssembly API, you can pass in memory 
> like so:
> ```js
> const imports = {
> 	"mem": new WebAssembly.Memory({ initial: 1 })
> }
>
> WebAssembly.instantiateStreaming(fetch("bar.wasm"), imports, 
> module => { ... });
> ```
> then in WebAssembly
> ```wat
> (import "mem" (memory 1))
> ```
> so how could I do that in D? That is, I want the memory that D 
> uses to be accessible to javascript (this way I can pass 
> pointers between JS and D)

https://discourse.llvm.org/t/rfc-webassembly-reference-types-in-clang/66939

it says it is an opaque type, maybe just need to be ``void*``?

Also there are new intrinsics, maybe you can define them like 
this:

```D
     alias externref_t = void*;

     pragma(LDC_intrinsic, "llvm.wasm.table.set.externref.i32")
     extern(C) void llvm_wasm_table_set_externref(void*, int, 
externref_t);

     pragma(LDC_intrinsic, "llvm.wasm.table.get.externref.i32")
     extern(C) externref_t llvm_wasm_table_get_externref(void*, 
int);
```


More information about the Digitalmars-d-learn mailing list