ldc
ldc copied to clipboard
In optimized WASM build, recursive function mutates an immutable variable
a.d:
immutable struct S {
immutable int x;
}
void countTo2(immutable S a) {
if (a.x < 2)
countTo2(S(a.x + 1));
}
extern(C) void _start() {}
extern(C) int test() {
immutable S a = S(0);
immutable S b = a;
countTo2(a);
return a.x - b.x;
}
test.js:
const fs = require("fs")
const main = async () => {
const debug = await WebAssembly.instantiate(fs.readFileSync("./a-debug.wasm"))
console.log("DEBUG:", debug.instance.exports.test())
const opt = await WebAssembly.instantiate(fs.readFileSync("./a-O2.wasm"))
console.log("OPTIMIZED:", opt.instance.exports.test())
}
main().catch(e => { console.error("ERROR", e) })
Now run:
ldc2 -ofa-debug.wasm -w -betterC -mtriple=wasm32-unknown-unknown-wasm a.d
ldc2 -of a-O2.wasm -w -betterC -mtriple=wasm32-unknown-unknown-wasm -O2 a.d
node test.js
The output is:
DEBUG: 0
OPTIMIZED: 2
a and b are immutable and b = a, so the difference should be 0. But in an optimized WASM build, apparently a changes after countTo2(a). (And it was passed by value too.)
Tested with LDC 1.33.0-git-aa64fad.
I can't see any obvious bug in our unoptimized IR. I suspect a wasm-specific LLVM issue wrt. the byval IR attribute; the optimizer 'optimizes' the function to a return 2.