https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110533

            Bug ID: 110533
           Summary: [x86-64] naked with -O0 and register-passed
                    struct/int128 clobbers parameters/callee-saved regs
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: engelke at in dot tum.de
  Target Milestone: ---

Compiling a naked function with a parameter that is split over multiple
registers generates several mov operations with -O0, clobbering other
parameters and callee-saved registers. This does not happen with -O1. This
happens since the introduction of naked in GCC 8, at least up to GCC 13.

Example:

    __attribute__((naked))
    void fn(__int128 a) {
        asm("ret");
    }

Compiles to; note that rbx (callee-saved) is clobbered:

    fn:
    .LFB0:
            .cfi_startproc
            movq    %rdi, %rdx
            movq    %rsi, %rax
            movq    %rcx, %rbx
            movq    %rdx, %rcx
            movq    %rax, %rbx
    #APP
    # 3 "<stdin>" 1
            ret
    # 0 "" 2
    #NO_APP
            nop
            ud2
            .cfi_endproc

With two parameters:

    __attribute__((naked))
    void fn(__int128 a, __int128 b) {
        asm("ret");
    }

Compiles to; note that rbx and the second parameter are clobbered:

    fn:
    .LFB0:
            .cfi_startproc
            movq    %rdi, %rdx
            movq    %rsi, %rax
            movq    %rcx, %rbx
            movq    %rdx, %rcx
            movq    %rax, %rbx
    #APP
    # 3 "<stdin>" 1
            ret
    # 0 "" 2
    #NO_APP
            nop
            ud2
            .cfi_endproc

With a slight modification everything works as expected:

    __attribute__((naked))
    void fn(int x, int y, __int128 a) {
        asm("ret");
    }

Compiles to:

    fn:
    .LFB0:
            .cfi_startproc
    #APP
    # 3 "<stdin>" 1
            ret
    # 0 "" 2
    #NO_APP
            nop
            ud2
            .cfi_endproc

(Above examples generated with gcc 12.2.1, but many other versions are affected
as well.)

Reply via email to