[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