X86: Align the stack on word boundaries in LowerFormalArguments()
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Wed, 20 Aug 2014 19:40:59 +0000 (19:40 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Wed, 20 Aug 2014 19:40:59 +0000 (19:40 +0000)
The goal of the patch is to implement section 3.2.3 of the AMD64 ABI
correctly.  The controlling sentence is, "The size of each argument gets
rounded up to eightbytes.  Therefore the stack will always be eightbyte
aligned." The equivalent sentence in the i386 ABI page 37 says, "At all
times, the stack pointer should point to a word-aligned area."  For both
architectures, the stack pointer is not being rounded up to the nearest
eightbyte or word between the last normal argument and the first
variadic argument.

Patch by Thomas Jablin!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216119 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/CallingConvLower.h
lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/aligned-variadic.ll [new file with mode: 0644]

index 866b3c8c6bc3bf973a877157df7f389d2d02ba8e..ffedd2e14103df454a7e599609ddd3cdc4cd5dcf 100644 (file)
@@ -371,11 +371,16 @@ public:
     return Reg;
   }
 
+  /// AlignStack - Align the top of the stakc to the specified alignment.
+  void AlignStack(unsigned Align) {
+    assert(Align && ((Align - 1) & Align) == 0); // Align is power of 2.
+    StackOffset = ((StackOffset + Align - 1) & ~(Align - 1));
+  }
+
   /// AllocateStack - Allocate a chunk of stack space with the specified size
   /// and alignment.
   unsigned AllocateStack(unsigned Size, unsigned Align) {
-    assert(Align && ((Align-1) & Align) == 0); // Align is power of 2.
-    StackOffset = ((StackOffset + Align-1) & ~(Align-1));
+    AlignStack(Align);
     unsigned Result = StackOffset;
     StackOffset += Size;
     MF.getFrameInfo()->ensureMaxAlignment(Align);
index 9cb9e6abbefa4147825279d79a4c918e027e1cf2..a10023df8a0be296d7198bf5d160438c8f29d24b 100644 (file)
@@ -2300,6 +2300,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
     CCInfo.AllocateStack(32, 8);
 
   CCInfo.AnalyzeFormalArguments(Ins, CC_X86);
+  CCInfo.AlignStack(Is64Bit ? 8 : 4);
 
   unsigned LastVal = ~0U;
   SDValue ArgValue;
diff --git a/test/CodeGen/X86/aligned-variadic.ll b/test/CodeGen/X86/aligned-variadic.ll
new file mode 100644 (file)
index 0000000..68000e3
--- /dev/null
@@ -0,0 +1,30 @@
+; RUN: llc < %s -march=x86-64 | FileCheck %s -check-prefix=X64
+; RUN: llc < %s -march=x86    | FileCheck %s -check-prefix=X32
+
+%struct.Baz = type { [17 x i8] }
+%struct.__va_list_tag = type { i32, i32, i8*, i8* }
+
+; Function Attrs: nounwind uwtable
+define void @bar(%struct.Baz* byval nocapture readnone align 8 %x, ...) {
+entry:
+  %va = alloca [1 x %struct.__va_list_tag], align 16
+  %arraydecay = getelementptr inbounds [1 x %struct.__va_list_tag]* %va, i64 0, i64 0
+  %arraydecay1 = bitcast [1 x %struct.__va_list_tag]* %va to i8*
+  call void @llvm.va_start(i8* %arraydecay1)
+  %overflow_arg_area_p = getelementptr inbounds [1 x %struct.__va_list_tag]* %va, i64 0, i64 0, i32 2
+  %overflow_arg_area = load i8** %overflow_arg_area_p, align 8
+  %overflow_arg_area.next = getelementptr i8* %overflow_arg_area, i64 24
+  store i8* %overflow_arg_area.next, i8** %overflow_arg_area_p, align 8
+; X32: leal    68(%esp), [[REG:%.*]]
+; X32: movl    [[REG]], 16(%esp)
+; X64: leaq    232(%rsp), [[REG:%.*]]
+; X64: movq    [[REG]], 184(%rsp)
+; X64: leaq    176(%rsp), %rdi
+  call void @qux(%struct.__va_list_tag* %arraydecay)
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.va_start(i8*)
+
+declare void @qux(%struct.__va_list_tag*)