Skip to content

Incorrect AArch64 codegen for C variadic functions when compiling without float support.  #62966

@BlamKiwi

Description

@BlamKiwi

When compiling AArch64 targets without hard-float support e.g., -march=armv8-a+nofp+nosimd -mgeneral-regs-only, LLVM generates invalid assembly for C variadic functions when passed floating-point values.

When passing a floating-point value to a variadic function, it passes it as an integer register, and saves it to the integer register block. When fetching the value, it fetches it from the floating register block, which is uninitialized.

Keith Packard over at picolibc discovered the problem and provided a minimal example:
https://godbolt.org/z/5Y9qEq437

#include <stdarg.h>

double my_printf(const char* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    double d = va_arg(ap, double);
    return d;
}

void foo() {
    my_printf("Hello World!", 1.0);
}

It looks like the problem is in the method AArch64ABIInfo::EmitAAPCSVAArg, the check to see if a register is floating or integer only looks at the base type. The check also needs to take into account additional target information such as general-regs-only being enabled.

Additional information:
picolibc/picolibc#467

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions