Skip to content

inline asm: Behaviour on type mismatch for inputs #8107

@notYuriy

Description

@notYuriy

Compiler explorer link: https://zig.godbolt.org/z/KvG5h3
Zig code involved:

const std = @import("std");

pub fn main() !void {
    testcall(true);
    return;
}

export fn testcall(t: bool) void { 
    asm volatile("" : : [_] "{rbx}" (@as(u64,0x1122334455667788)) : "memory" ); // clobber rbx with garbage to not give it a chance
    asm volatile(
        \\push %%rbx
        \\pop  %%rdi
        \\call stage2
        :
        : [_] "{rbx}" (@boolToInt(t))
        : "memory"
    );

}

export fn stage2(param: usize) void {
    std.debug.warn("param: {x}", .{param});
}

What's the problem? Well, let's look at the code zig compiler from trunk gave us:

testcall:
        push    rbx
        movabs  rbx, 1234605616436508552; clobber rbx with garbage to not give it a chance 

        ; That's how rbx is assigned to 1
        and     dil, 1
        mov     ebx, edi 
        ; End of assignment

        push    rbx ; That is where our asm volatile code starts
        pop     rdi
        call    stage2
        pop     rbx
        ret

Zig compiler generates code that only makes the lowest bit of rbx set. The problem is that the code explicitly demands that the compiler generates code assigning one to the rbx, meaning that the value of rbx should be one, while if you run this example in compiler explorer, it will give you a different result.

Cast to u64 indeed solve the problem, however, this case is either 1) an incorrect behavior that should be patched 2) correct behavior that needs to be clarified (so that there is a requirement that code inside volatile asm block will only use rdi as u1, and not as usize as here)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavior

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions