zig icon indicating copy to clipboard operation
zig copied to clipboard

`@max(i64, 0)` generates invalid wasm in debug with `reference_types` enabled

Open luehmann opened this issue 1 year ago • 0 comments

Zig Version

0.14.0-dev.184+bf588f67d

Steps to Reproduce and Observed Behavior

Create bug.zig

const std = @import("std");
export fn foo(
    position_x: i64,
) void {
    const start_x = @max(position_x, 0);
    std.mem.doNotOptimizeAway(start_x);
}

Compile with

  • wasm32-freestanding
  • Debug
  • reference_types feature enabled

zig build-exe bug.zig -target wasm32-freestanding -fno-entry --export=foo -mcpu baseline+reference_types -ODebug

Validate with wabt's wasm-validate

wasm-validate bug.wasm
bug.wasm:000006a: error: type mismatch in call, expected [i64] but got [i32]

bug.wat

created with wasm2wat bug.wasm -o bug.wat --no-check

(module $bug.wasm
  (type (;0;) (func (param i64)))
  (type (;1;) (func (param i32)))
  (func $foo (type 0) (param i64)
    (local i64 i32 i64 i32)
    i64.const 0
    local.set 1
    local.get 0
    local.get 1
    i64.gt_s
    local.set 2
    local.get 0
    local.get 1
    local.get 2
    select
    local.set 3
    local.get 3
    i32.wrap_i64
    local.set 4
    local.get 4
    call $mem.doNotOptimizeAway__anon_1111
    return)
  (func $mem.doNotOptimizeAway__anon_1111 (type 0) (param i64)
    (local i32 i32 i32 i64 i64 i32 i32 i32 i32 i32)
    global.get $__stack_pointer
    local.set 1
    i32.const 16
    local.set 2
    local.get 1
    local.get 2
    i32.sub
    local.set 3
    local.get 3
    global.set $__stack_pointer
    i64.const 9223372036854775807
    local.set 4
    local.get 0
    local.get 4
    i64.and
    local.set 5
    local.get 3
    local.get 5
    i64.store offset=8
    i32.const 8
    local.set 6
    local.get 3
    local.get 6
    i32.add
    local.set 7
    local.get 7
    local.set 8
    local.get 8
    call $mem.doNotOptimizeAway__anon_1112
    i32.const 16
    local.set 9
    local.get 3
    local.get 9
    i32.add
    local.set 10
    local.get 10
    global.set $__stack_pointer
    return)
  (func $mem.doNotOptimizeAway__anon_1112 (type 1) (param i32)
    (local i32 i32 i32 i32 i32 i32 i32 i32 i32)
    global.get $__stack_pointer
    local.set 1
    i32.const 16
    local.set 2
    local.get 1
    local.get 2
    i32.sub
    local.set 3
    local.get 3
    global.set $__stack_pointer
    local.get 3
    local.get 0
    i32.store offset=12
    i32.const 12
    local.set 4
    local.get 3
    local.get 4
    i32.add
    local.set 5
    local.get 3
    local.get 5
    i32.store offset=8
    i32.const 8
    local.set 6
    local.get 3
    local.get 6
    i32.add
    local.set 7
    i32.const 16
    local.set 8
    local.get 3
    local.get 8
    i32.add
    local.set 9
    local.get 9
    global.set $__stack_pointer
    return)
  (memory (;0;) 16)
  (global $__stack_pointer (mut i32) (i32.const 1048576))
  (export "memory" (memory 0))
  (export "foo" (func $foo)))

Godbolt

Workaround: @max with 0 creates u63. Changing the type back to i64 fixes the problem.

- const start_x = @max(position_x, 0);
+ const start_x: i64 = @max(position_x, 0);

Expected Behavior

Emitted wasm file is valid.

luehmann avatar Jul 06 '24 22:07 luehmann