[PATCH] Use 16 byte stack alignment for NaCl on ARM, and fix a varargs bug

Mark Seaborn mseaborn at chromium.org
Mon Feb 3 12:50:35 PST 2014


Hi sdyatkovskiy,

Use 16 byte stack alignment for NaCl on ARM, and fix a varargs bug

NaCl's ARM ABI uses 16 byte stack alignment.

Using this alignment exposes a bug 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.  With the bug, 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 >= 8".


http://llvm-reviews.chandlerc.com/D2677

Files:
  lib/Target/ARM/ARMISelLowering.cpp
  lib/Target/ARM/ARMSubtarget.cpp
  test/CodeGen/ARM/varargs-spill-stack-align-nacl.ll

Index: lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- lib/Target/ARM/ARMISelLowering.cpp
+++ lib/Target/ARM/ARMISelLowering.cpp
@@ -2760,7 +2760,7 @@
   ArgRegsSize = NumGPRs * 4;
 
   // If parameter is split between stack and GPRs...
-  if (NumGPRs && Align == 8 &&
+  if (NumGPRs && Align >= 8 &&
       (ArgRegsSize < ArgSize ||
         InRegsParamRecordIdx >= CCInfo.getInRegsParamsCount())) {
     // Add padding for part of param recovered from GPRs, so
Index: lib/Target/ARM/ARMSubtarget.cpp
===================================================================
--- lib/Target/ARM/ARMSubtarget.cpp
+++ lib/Target/ARM/ARMSubtarget.cpp
@@ -210,6 +210,8 @@
 
   if (isAAPCS_ABI())
     stackAlignment = 8;
+  if (isTargetNaCl())
+    stackAlignment = 16;
 
   UseMovt = hasV6T2Ops() && ArmUseMOVT;
 
Index: test/CodeGen/ARM/varargs-spill-stack-align-nacl.ll
===================================================================
--- /dev/null
+++ test/CodeGen/ARM/varargs-spill-stack-align-nacl.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -mtriple=arm-nacl-gnueabi | FileCheck %s
+
+declare void @llvm.va_start(i8*)
+declare void @external_func(i8*)
+
+ at va_list = external global i8*
+
+; On ARM, varargs arguments are passed in r0-r3 with the rest on the
+; stack.  A varargs function must therefore spill rN-r3 just below the
+; function's initial stack pointer.
+;
+; This test checks for a bug in which a gap was left between the spill
+; area and varargs arguments on the stack when using 16 byte stack
+; alignment.
+
+define void @varargs_func(i32 %arg1, ...) {
+  call void @llvm.va_start(i8* bitcast (i8** @va_list to i8*))
+  call void @external_func(i8* bitcast (i8** @va_list to i8*))
+  ret void
+}
+; CHECK-LABEL: varargs_func:
+; Reserve space for the varargs save area.  This currently reserves
+; more than enough (16 bytes rather than the 12 bytes needed).
+; CHECK: sub sp, sp, #16
+; CHECK-NEXT: push {lr}
+; Align the stack pointer to a multiple of 16.
+; CHECK-NEXT: sub sp, sp, #12
+; Calculate the address of the varargs save area and save varargs
+; arguments into it.
+; CHECK-NEXT: add r0, sp, #20
+; CHECK-NEXT: stm r0, {r1, r2, r3}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2677.1.patch
Type: text/x-patch
Size: 2215 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140203/ed177d6e/attachment.bin>


More information about the llvm-commits mailing list