digitalmars.D.learn - Some questions with D and webassembly
- TheZipCreator (72/72) Mar 02 2023 In webassembly, there's a type called `externref`, which opaquely
- ryuukk_ (14/87) Mar 03 2023 https://discourse.llvm.org/t/rfc-webassembly-reference-types-in-clang/66...
- TheZipCreator (8/23) Mar 03 2023 Using `void*` doesn't appear to work (and looking at the
- Johan (6/12) Mar 03 2023 It looks like this needs some more compiler support. Please
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)
Mar 02 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); ```
Mar 03 2023
On Friday, 3 March 2023 at 13:42:55 UTC, ryuukk_ wrote:On Friday, 3 March 2023 at 03:32:37 UTC, TheZipCreator wrote:Using `void*` doesn't appear to work (and looking at the generated wasm it seems to reduce it to `i32`, which is not the right type unfortunately). I guess what I could do is have a global array in js which stores all objects I'll need to access, then just access them via the index into that array but that feels like a hack especially when `externref` is a thing that exists.[...]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); ```
Mar 03 2023
On Friday, 3 March 2023 at 18:34:24 UTC, TheZipCreator wrote:On Friday, 3 March 2023 at 13:42:55 UTC, ryuukk_ wrote:It looks like this needs some more compiler support. Please submit the feature request (including the link to this LLVM page) on LDC's github page. cheers, JohanOn Friday, 3 March 2023 at 03:32:37 UTC, TheZipCreator wrote:[...]https://discourse.llvm.org/t/rfc-webassembly-reference-types-in-clang/66939
Mar 03 2023