[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