llvm.org GIT mirror llvm / 09d1d54
Use 16 byte stack alignment for NaCl on ARM NaCl's ARM ABI uses 16 byte stack alignment, so set that in ARMSubtarget.cpp. Using 16 byte alignment exposes an issue in code generation in which a varargs function leaves a 4 byte gap between the values of r1-r3 saved to the stack and the following arguments that were passed on the stack. (Previously, this code only needed to support 4 byte and 8 byte alignment.) With this issue, llc generated: varargs_func: sub sp, sp, #16 push {lr} sub sp, sp, #12 add r0, sp, #16 // Should be 20 stm r0, {r1, r2, r3} ldr r0, .LCPI0_0 // Address of va_list add r1, sp, #16 str r1, [r0] bl external_func Fix the bug by checking for "Align > 4". Also simplify the code by using OffsetToAlignment(), and update comments. Differential Revision: http://llvm-reviews.chandlerc.com/D2677 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201497 91177308-0d34-0410-b5e6-96231b3b80d8 Mark Seaborn 6 years ago
4 changed file(s) with 38 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
27552755 ArgRegsSize = NumGPRs * 4;
27562756
27572757 // If parameter is split between stack and GPRs...
2758 if (NumGPRs && Align == 8 &&
2758 if (NumGPRs && Align > 4 &&
27592759 (ArgRegsSize < ArgSize ||
27602760 InRegsParamRecordIdx >= CCInfo.getInRegsParamsCount())) {
2761 // Add padding for part of param recovered from GPRs, so
2762 // its last byte must be at address K*8 - 1.
2761 // Add padding for part of param recovered from GPRs. For example,
2762 // if Align == 8, its last byte must be at address K*8 - 1.
27632763 // We need to do it, since remained (stack) part of parameter has
27642764 // stack alignment, and we need to "attach" "GPRs head" without gaps
27652765 // to it:
27692769 //
27702770 ARMFunctionInfo *AFI = MF.getInfo();
27712771 unsigned Padding =
2772 ((ArgRegsSize + AFI->getArgRegsSaveSize() + Align - 1) & ~(Align-1)) -
2773 (ArgRegsSize + AFI->getArgRegsSaveSize());
2772 OffsetToAlignment(ArgRegsSize + AFI->getArgRegsSaveSize(), Align);
27742773 ArgRegsSaveSize = ArgRegsSize + Padding;
27752774 } else
27762775 // We don't need to extend regs save size for byval parameters if they
3737
3838 /// StByValParamsPadding - For parameter that is split between
3939 /// GPRs and memory; while recovering GPRs part, when
40 /// StackAlignment == 8, and GPRs-part-size mod 8 != 0,
40 /// StackAlignment > 4, and GPRs-part-size mod StackAlignment != 0,
4141 /// we need to insert gap before parameter start address. It allows to
4242 /// "attach" GPR-part to the part that was passed via stack.
4343 unsigned StByValParamsPadding;
209209
210210 if (isAAPCS_ABI())
211211 stackAlignment = 8;
212 if (isTargetNaCl())
213 stackAlignment = 16;
212214
213215 UseMovt = hasV6T2Ops() && ArmUseMOVT;
214216
0 ; RUN: llc < %s -mtriple=arm-nacl-gnueabi | FileCheck %s
1
2 declare void @llvm.va_start(i8*)
3 declare void @external_func(i8*)
4
5 @va_list = external global i8*
6
7 ; On ARM, varargs arguments are passed in r0-r3 with the rest on the
8 ; stack. A varargs function must therefore spill rN-r3 just below the
9 ; function's initial stack pointer.
10 ;
11 ; This test checks for a bug in which a gap was left between the spill
12 ; area and varargs arguments on the stack when using 16 byte stack
13 ; alignment.
14
15 define void @varargs_func(i32 %arg1, ...) {
16 call void @llvm.va_start(i8* bitcast (i8** @va_list to i8*))
17 call void @external_func(i8* bitcast (i8** @va_list to i8*))
18 ret void
19 }
20 ; CHECK-LABEL: varargs_func:
21 ; Reserve space for the varargs save area. This currently reserves
22 ; more than enough (16 bytes rather than the 12 bytes needed).
23 ; CHECK: sub sp, sp, #16
24 ; CHECK: push {lr}
25 ; Align the stack pointer to a multiple of 16.
26 ; CHECK: sub sp, sp, #12
27 ; Calculate the address of the varargs save area and save varargs
28 ; arguments into it.
29 ; CHECK-NEXT: add r0, sp, #20
30 ; CHECK-NEXT: stm r0, {r1, r2, r3}