Skip to content

[AArch64] Wrong code for variadic argument with preserve_none calling convention #95093

Closed
@ostannard

Description

@ostannard

When using the preserve_none calling convention attribute, we generate incorrect code for variadic arguments:

#include <stdarg.h>

__attribute__((preserve_none))
int F1(int P5, ...) {
  va_list vl;
  va_start(vl, P5);
  int P6 = va_arg(vl, int);
  va_end(vl);
  return P6;
}
$ /work/llvm/install/bin/clang --target=aarch64--none-elf -c test.c -O1 -o - -S
        .text
        .file   "test.c"
        .globl  F1                              // -- Begin function F1
        .p2align        2
        .type   F1,@function
F1:                                     // @F1
// %bb.0:                               // %entry
        sub     sp, sp, #224
        mov     x8, #-64                        // =0xffffffffffffffc0
        mov     x9, sp
        add     x10, sp, #128
        movk    x8, #65408, lsl #32
        add     x9, x9, #128
        stp     x0, x1, [sp, #128]
        stp     x9, x8, [sp, #208]
        add     x9, x10, #64
        add     x10, sp, #224
        mov     x8, #-64                        // =0xffffffffffffffc0
        stp     x2, x3, [sp, #144]
        stp     x4, x5, [sp, #160]
        stp     x6, x7, [sp, #176]
        stp     q0, q1, [sp]
        stp     q2, q3, [sp, #32]
        stp     q4, q5, [sp, #64]
        stp     q6, q7, [sp, #96]
        stp     x10, x9, [sp, #192]
        tbz     w8, #31, .LBB0_3
// %bb.1:                               // %vaarg.maybe_reg
        add     w9, w8, #8
        cmn     w8, #8
        str     w9, [sp, #216]
        b.gt    .LBB0_3
// %bb.2:                               // %vaarg.in_reg
        ldr     x9, [sp, #200]
        add     x8, x9, x8
        b       .LBB0_4
.LBB0_3:                                // %vaarg.on_stack
        ldr     x8, [sp, #192]
        add     x9, x8, #8
        str     x9, [sp, #192]
.LBB0_4:                                // %vaarg.end
        ldr     w0, [x8]
        add     sp, sp, #224
        ret
.Lfunc_end0:
        .size   F1, .Lfunc_end0-F1
                                        // -- End function
        .ident  "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 79ce70b8033815b6abd3a9a5cc2335de70f1aaab)"
        .section        ".note.GNU-stack","",@progbits
        .addrsig

The two constants of -64 in the assembly correspond to the gr_offs field in the va_list, so this ends up loading the argument from the saved copy of x0, which the first (non-variadic) argument was passed in, instead of x1.

Without the preserve_none attribute, that constant is -56, so the argument is correctly loaded from x1:

$ /work/llvm/install/bin/clang --target=aarch64--none-elf -c test.c -O1 -o - -S
        .text
        .file   "test.c"
        .globl  F1                              // -- Begin function F1
        .p2align        2
        .type   F1,@function
F1:                                     // @F1
// %bb.0:                               // %entry
        sub     sp, sp, #224
        mov     x8, #-56                        // =0xffffffffffffffc8
        mov     x9, sp
        add     x10, sp, #136
        movk    x8, #65408, lsl #32
        add     x9, x9, #128
        stp     x1, x2, [sp, #136]
        stp     x9, x8, [sp, #208]
        add     x9, x10, #56
        add     x10, sp, #224
        mov     x8, #-56                        // =0xffffffffffffffc8
        stp     x3, x4, [sp, #152]
        stp     x5, x6, [sp, #168]
        stp     q0, q1, [sp]
        stp     q2, q3, [sp, #32]
        stp     q4, q5, [sp, #64]
        stp     q6, q7, [sp, #96]
        str     x9, [sp, #200]
        stp     x7, x10, [sp, #184]
        tbz     w8, #31, .LBB0_3
// %bb.1:                               // %vaarg.maybe_reg
        add     w9, w8, #8
        cmn     w8, #8
        str     w9, [sp, #216]
        b.gt    .LBB0_3
// %bb.2:                               // %vaarg.in_reg
        ldr     x9, [sp, #200]
        add     x8, x9, x8
        b       .LBB0_4
.LBB0_3:                                // %vaarg.on_stack
        ldr     x8, [sp, #192]
        add     x9, x8, #8
        str     x9, [sp, #192]
.LBB0_4:                                // %vaarg.end
        ldr     w0, [x8]
        add     sp, sp, #224
        ret
.Lfunc_end0:
        .size   F1, .Lfunc_end0-F1
                                        // -- End function
        .ident  "clang version 19.0.0git (git@github.com:llvm/llvm-project.git 79ce70b8033815b6abd3a9a5cc2335de70f1aaab)"
        .section        ".note.GNU-stack","",@progbits
        .addrsig

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions