fitzgen edited issue #10171:
(module (type $appNode (struct (field $left anyref) (field $right anyref))) (type $comb (struct (field $asciiTag i32))) (func $prob1 (export "prob1") (param $p (ref null $appNode)) (result i32) (local.get $p) (struct.get $appNode $left) (ref.cast (ref null $appNode)) (struct.get $appNode $right) (ref.test (ref null $comb)) ) (func $prob2 (export "prob2") (param $p (ref null $appNode)) (result i32) (local.get $p) (struct.get $appNode $left) (ref.cast (ref null $appNode)) (struct.get $appNode $left) (ref.test (ref null $comb)) ) (func $main (export "main") (result i32) (struct.new $appNode (struct.new $appNode (struct.new $comb (i32.const 67)) (struct.new $comb (i32.const 73))) (ref.i31 (i32.const 2))) (call $prob2) ) )
Hey Wasmtime team!
call
ing$prob1
returns 1 but$prob2
returns 0. Why is that? Shouldn't it be reading the(struct.new $comb (i32.const 67))
which indeed is acomb
? I've tried reading the GC spec but haven't been able to figure out why the runtime behaves this way.
fitzgen commented on issue #10171:
Haven't managed to meaningfully reduce it past this:
(module (type $tree (struct (field $left anyref) (field $right anyref))) (type $s (struct)) (func (export "main") (result i32) (struct.new $tree (struct.new $tree (struct.new $s) (ref.i31 (i32.const 1))) (ref.i31 (i32.const 2))) struct.get $tree $left ref.cast (ref null $tree) struct.get $tree $left ref.test (ref null $s) ) )
Interestingly, changing
$right
to be ani31ref
also makes the test pass.
fitzgen commented on issue #10171:
And removing one layer of tree nesting also makes the test pass.
fitzgen commented on issue #10171:
Using the null collector instead of the DRC collector also makes the test pass. I'm starting to suspect that this involves a Wasm-to-CLIF translation bug where we are accidentally generating CLIF that is more optimizable than it should be.
fitzgen commented on issue #10171:
FWIW, here is the flattened version of the test case, which makes the order of instructions a little easier to read when staring at clif and comparing it to the original wasm:
(module (type $tree (struct (field $left anyref) (field $right anyref))) (type $s (struct)) (func (export "main") (result i32) struct.new $s ref.null i31 struct.new $tree i32.const 2 ref.i31 struct.new $tree struct.get $tree $left ref.cast (ref null $tree) struct.get $tree $left ref.test (ref null $s) ) )
apoorvaanand1998 commented on issue #10171:
Thank you for your quick response :bow:
Now that I know it's a bug with Wasmtime, I've been trying to run this on firefox. The first step I suppose is to use
wat2wasm
to compile this to a.wasm
file so I can run it as shown here. Butwat2wasm
fails to parse my programError: parseWat failed: test.wast:3:30: error: unexpected token "anyref", expected i32, i64, f32, f64, v128, externref or funcref. (struct (field $left anyref) ^^^^^^ test.wast:4:31: error: unexpected token anyref. (field $right anyref))) ^^^^^^ test.wast:8:50: error: unexpected token "null", expected a numeric index or a name (e.g. 12 or $foo). (func $prob1 (export "prob1") (param $p (ref null $appNode)) (result i32) ^^^^
How did you get it to run on firefox?
I am sorry if this isn't the right place to be asking this. Let me know if it isn't and we can switch communication channels. Thank you for your help!
alexcrichton commented on issue #10171:
You can try using wasm-tools as
wasm-tools parse foo.wat -o foo.wasm
fitzgen closed issue #10171:
(module (type $appNode (struct (field $left anyref) (field $right anyref))) (type $comb (struct (field $asciiTag i32))) (func $prob1 (export "prob1") (param $p (ref null $appNode)) (result i32) (local.get $p) (struct.get $appNode $left) (ref.cast (ref null $appNode)) (struct.get $appNode $right) (ref.test (ref null $comb)) ) (func $prob2 (export "prob2") (param $p (ref null $appNode)) (result i32) (local.get $p) (struct.get $appNode $left) (ref.cast (ref null $appNode)) (struct.get $appNode $left) (ref.test (ref null $comb)) ) (func $main (export "main") (result i32) (struct.new $appNode (struct.new $appNode (struct.new $comb (i32.const 67)) (struct.new $comb (i32.const 73))) (ref.i31 (i32.const 2))) (call $prob2) ) )
Hey Wasmtime team!
call
ing$prob1
returns 1 but$prob2
returns 0. Why is that? Shouldn't it be reading the(struct.new $comb (i32.const 67))
which indeed is acomb
? I've tried reading the GC spec but haven't been able to figure out why the runtime behaves this way.
Last updated: Feb 28 2025 at 03:10 UTC