Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asm blocks only allow identifiers to specify input/output #2334

Open
tyler569 opened this issue Apr 22, 2019 · 0 comments
Open

Asm blocks only allow identifiers to specify input/output #2334

tyler569 opened this issue Apr 22, 2019 · 0 comments
Labels
use case Describes a real use case that is difficult or impossible, but does not propose a solution.
Milestone

Comments

@tyler569
Copy link
Contributor

tyler569 commented Apr 22, 2019

Currently, Zig only accepts identifiers as output/output parameters to asm blocks, which is very limiting compared to the range of options available in gcc/clang, and makes a range of x86 asm instructions unusable.

I see this is currently expected, per the syntax description: LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN

I understand that the asm block syntax is in flux, but I believe widening the range of acceptable inputs/outputs is orthogonal to that effort.

As motivating examples:
in C I can have an asm block output directly to a struct field:

struct foo {
    long x;
};
struct foo x = {};
struct foo* y = &x;

int save_rsp() {
    asm volatile (
        "movq %%rsp, %[foo]"
        : [foo] "=r" (y->x)
    );
}

More subtly, in my operating system project, I have a need to save and restore floating point context, which is done with fxsave/fxrstor on x86. Due to the way these are encoded and the way gcc/clang choose to implement them, you have to pass the value at the location where the context should be stored as opposed to a pointer. Take the following C code:

typedef long fp_ctx[64];

int square(fp_ctx *ctx) {
    asm volatile (
        "fxsaveq %0"
        :
        : [ctx] "m" (*ctx)
    );
}

Notice how I have to dereference the context inside the asm block, and the generated instruction then somehow gets a pointer to that value:

square:                                 # @square
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 16], rdi
        mov     rax, qword ptr [rbp - 16]
        fxsave64        [rax]
        mov     eax, dword ptr [rbp - 4]
        pop     rbp
        ret

Compare that to the equivalent zig code, where I can't dereference that ctx:

const fp_ctx = [64]u64;

export fn square(ctx: *fp_ctx) void {
    asm volatile (
        \\ fxsaveq %[fpctx]
        :
        : [fpctx] "m" (ctx)
    );
}

In Zig, no matter what I try, the generated asm always tries to dump the floating point context onto the stack:

square:
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     rdi, qword ptr [rbp - 8]
        mov     qword ptr [rbp - 16], rdi
        fxsave64        [rbp - 16]   ; <<<--
        pop     rbp
        ret

I hope this is at least somewhat clear, I don't fully understand why the fp* instructions behave this way, but I hope the struct example at least serves as a more approachable motivating example for why more expressiveness in asm input/outputs would be great to have.

@andrewrk andrewrk added this to the 0.5.0 milestone Apr 24, 2019
@andrewrk andrewrk modified the milestones: 0.5.0, 0.6.0 Sep 20, 2019
@andrewrk andrewrk modified the milestones: 0.6.0, 0.7.0 Jan 5, 2020
@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Oct 30, 2020
@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 Nov 6, 2020
@SpexGuy SpexGuy added the use case Describes a real use case that is difficult or impossible, but does not propose a solution. label Mar 20, 2021
@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 May 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
use case Describes a real use case that is difficult or impossible, but does not propose a solution.
Projects
None yet
Development

No branches or pull requests

3 participants