ldc
ldc copied to clipboard
Memset is not typechecked, leads to "not enough arguments on the stack for drop" error
To reproduce, put this content in a.d:
struct A {
this(long[9] x_) { x = x_; }
long[9] x;
}
extern(C) void _start() {
A a = A([0, 0, 0, 0, 0, 0, 0, 0, 0]);
}
extern(C) @system pure void memset(scope ubyte* s, immutable int c, immutable size_t n) {
foreach (immutable size_t i; 0 .. n)
s[i] = cast(ubyte) c;
}
extern (C) @system pure void* memcpy(return scope ubyte* s1, scope const ubyte* s2, immutable size_t n) {
foreach (immutable size_t i; 0 .. n)
s1[i] = s2[i];
return s1;
}
Then run:
ldc2 -mtriple=wasm32-unknown-unknown-wasm a.d
node -p "WebAssembly.instantiate(require('fs').readFileSync('a.wasm'), {}).catch(console.error)"
The output is:
Promise { <pending> }
[CompileError: WebAssembly.instantiate(): Compiling function #2:"_start" failed: not enough arguments on the stack for drop, expected 1 more @+480]
The error is that memset returned void instead of void*.
Tested with ldc 1.27.1, based on DMD v2.097.2 and LLVM 12.0.1; and node 16.6.2.
I believe your issue is not solvable by the D compiler. memset is not a reserved or special function from a D language point of view. So if you want to write a memset function that returns void or a float you are free to do so.
A similar issue: In optimized builds only, the compiler may insert a call to memset into the implementation of memset, leading to an infinite recursion.
extern(C) void _start() {}
ubyte[65] someBytes;
extern(C) void callMemset() {
memset(someBytes.ptr, 42, 65);
}
extern(C) ubyte* memset(ubyte* dest, immutable int c, immutable size_t n) {
return helper(dest, c, n);
}
ubyte* helper(ubyte* dest, immutable int c, immutable size_t n) {
foreach (immutable size_t i; 0 .. n)
dest[i] = cast(ubyte) c;
return dest;
}
$ ldc2 -ofa.wasm -mtriple=wasm32-unknown-unknown-wasm -betterC -O1 a.d && node -p "WebAssembly.instantiate(require('fs').readFileSync('a.wasm'), {}).then(x => x.instance.exports.callMemset()).catch(console.error)"
Promise { <pending> }
RangeError: Maximum call stack size exceeded
at memset (wasm://wasm/cd74f04a:wasm-function[2]:0xaa)
at _D1a6helperFNaMNkPhyiykZQh (wasm://wasm/cd74f04a:wasm-function[3]:0xc7)
at memset (wasm://wasm/cd74f04a:wasm-function[2]:0xb1)
at _D1a6helperFNaMNkPhyiykZQh (wasm://wasm/cd74f04a:wasm-function[3]:0xc7)
at memset (wasm://wasm/cd74f04a:wasm-function[2]:0xb1)
at _D1a6helperFNaMNkPhyiykZQh (wasm://wasm/cd74f04a:wasm-function[3]:0xc7)
at memset (wasm://wasm/cd74f04a:wasm-function[2]:0xb1)
at _D1a6helperFNaMNkPhyiykZQh (wasm://wasm/cd74f04a:wasm-function[3]:0xc7)
at memset (wasm://wasm/cd74f04a:wasm-function[2]:0xb1)
at _D1a6helperFNaMNkPhyiykZQh (wasm://wasm/cd74f04a:wasm-function[3]:0xc7)