[llvm-bugs] [Bug 47155] New: [AArch64] 16-byte aligned parameter of empty struct type does not follow round NGNR to next even number

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Aug 13 01:49:31 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=47155

            Bug ID: 47155
           Summary: [AArch64] 16-byte aligned parameter of empty struct
                    type does not follow round NGNR to next even number
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Backend: AArch64
          Assignee: unassignedbugs at nondot.org
          Reporter: tbaeder at redhat.com
                CC: arnaud.degrandmaison at arm.com,
                    llvm-bugs at lists.llvm.org, smithp352 at googlemail.com,
                    Ties.Stuij at arm.com

Take the following C++ code:

struct __attribute__((aligned(16))) A {};

static void foo(struct A a, int f) {}

int main(int argc, char **argv) {
  struct A a;

  foo(a, 10);

  return 0;
}

If compiled into AArch64 code, the generated LLVM IR looks like this:

%struct.A = type { [16 x i8] }

; Function Attrs: noinline norecurse optnone
define dso_local i32 @main(i32 %argc, i8** %argv) #0 {
entry:
  %retval = alloca i32, align 4
  %argc.addr = alloca i32, align 4
  %argv.addr = alloca i8**, align 8
  %a = alloca %struct.A, align 16
  %agg.tmp = alloca %struct.A, align 16
  store i32 0, i32* %retval, align 4
  store i32 %argc, i32* %argc.addr, align 4
  store i8** %argv, i8*** %argv.addr, align 8
  %coerce.dive = getelementptr inbounds %struct.A, %struct.A* %agg.tmp, i32 0,
i32 0
  %0 = bitcast [16 x i8]* %coerce.dive to i8*
  %1 = load i8, i8* %0, align 16
  call void @_ZL3foo1Ai(i8 %1, i32 10)
  ret i32 0
}

; Function Attrs: noinline nounwind optnone
define internal void @_ZL3foo1Ai(i8 %a.coerce, i32 %f) #1 {
entry:
  %a = alloca %struct.A, align 16
  %f.addr = alloca i32, align 4
  %coerce.dive = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 0
  %0 = bitcast [16 x i8]* %coerce.dive to i8*
  store i8 %a.coerce, i8* %0, align 16
  store i32 %f, i32* %f.addr, align 4
  ret void
}



and the disassembly of the compiled executable looks like this:

0000000000000000 <main>:
   0:   d10143ff        sub     sp, sp, #0x50
   4:   a9047bfd        stp     x29, x30, [sp, #64]
   8:   910103fd        add     x29, sp, #0x40
   c:   2a1f03e8        mov     w8, wzr
  10:   b81fc3bf        stur    wzr, [x29, #-4]
  14:   b81f83a0        stur    w0, [x29, #-8]
  18:   f81f03a1        stur    x1, [x29, #-16]
  1c:   394043e0        ldrb    w0, [sp, #16]
  20:   52800141        mov     w1, #0xa                        // #10
  24:   b9000fe8        str     w8, [sp, #12]
  28:   94000005        bl      3c <_ZL3foo1Ai>
  2c:   b9400fe0        ldr     w0, [sp, #12]
  30:   a9447bfd        ldp     x29, x30, [sp, #64]
  34:   910143ff        add     sp, sp, #0x50
  38:   d65f03c0        ret

000000000000003c <_ZL3foo1Ai>:
  3c:   d10083ff        sub     sp, sp, #0x20
  40:   390043e0        strb    w0, [sp, #16]
  44:   b9000fe1        str     w1, [sp, #12]
  48:   910083ff        add     sp, sp, #0x20
  4c:   d65f03c0        ret


Note that the literal 10 (the second parameter to function call foo()) is being
passed in the w1 register.

The first parameter is a 16-byte aligned empty struct, which according to the
AAPCS clause C.8 ("If the argument has an alignment of 16 then the NGRN is
rounded up to the next even number.") means that the next parameter should be
passed in register 2.

g++ passes the second parameter in w2, was I would expect.

This problem does *not* happen if...
  1) The struct has an alignment other than 16
  2) The struct has a member
  3) The code is compiled as C and not as C++

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200813/990b1e05/attachment.html>


More information about the llvm-bugs mailing list