Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

LLVM miscompiles variadic functions with overaligned stack when targeting Thumb1 #35053

Closed Quuxplusone closed 5 years ago

Quuxplusone commented 6 years ago
Bugzilla Link PR36080
Status RESOLVED FIXED
Importance P normal
Reported by Momchil Velikov (momchil.velikov@arm.com)
Reported on 2018-01-24 09:58:10 -0800
Last modified on 2019-06-19 04:09:24 -0700
Version trunk
Hardware PC Linux
CC llvm-bugs@lists.llvm.org
Fixed by commit(s) rG505614bb4f695cb2d028726c8f37951f4ed831cf
Attachments variadic-stack-align.c (180 bytes, text/x-csrc)
Blocks
Blocked by
See also
Created attachment 19742
minimal testcase

When compiling for Arm architecture, which implements only the 16-bit Thumb
instruction set (like Armv4t or Armv6m) a variadic function, which has
increased stack alignment requirements (so it dynamically re-aligns the SP),
the Arm back end generates invalid code to store the incoming variadic
arguments, which are passed in registers.

When the attached test case is compiled via

    clang -target thumbv6m-eabi -O2 -S variadic-stack-align.c

the generated assembly looks like:

    test:
        .fnstart
        .pad    #12
        sub     sp, #12            ; allocate space for variadic register args
        .save   {r4, r6, r7, lr}
        push    {r4, r6, r7, lr}
        .setfp  r7, sp, #8
        add     r7, sp, #8
        .pad    #36
        sub     sp, #36         ;
        mov     r4, sp          ;
        lsrs    r4, r4, #5      ; Align stack pointer
        lsls    r4, r4, #5      ;
        mov     sp, r4          ;

        str     r3, [sp, #60]   ;
        str     r2, [sp, #56]   ; Store incoming arguments
        str     r1, [sp, #52]   ;

        ...

The offsets, used to store the register varargs are not correct after the SP is
aligned.  Instead, the function should store these arguments via the FP.
Quuxplusone commented 6 years ago

Attached variadic-stack-align.c (180 bytes, text/x-csrc): minimal testcase