]> granicus.if.org Git - clang/commitdiff
[ARM64-BE] Correctly deal with single element HFAs in varargs.
authorJames Molloy <james.molloy@arm.com>
Wed, 7 May 2014 14:45:55 +0000 (14:45 +0000)
committerJames Molloy <james.molloy@arm.com>
Wed, 7 May 2014 14:45:55 +0000 (14:45 +0000)
Just because the first "if" didn't fire, doesn't mean we can not have
an HFA in the "else" clause.

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

lib/CodeGen/TargetInfo.cpp
test/CodeGen/arm64-be-hfa-vararg.c [new file with mode: 0644]

index 300fb19f2096cb868bc5a6977114f9c20f6f0fc4..fefa8643921dcc83c87ef83d72047fabc2f5c36c 100644 (file)
@@ -3550,7 +3550,8 @@ static llvm::Value *EmitAArch64VAArg(llvm::Value *VAListAddr, QualType Ty,
 
   const Type *Base = 0;
   uint64_t NumMembers;
-  if (isHomogeneousAggregate(Ty, Base, Ctx, &NumMembers) && NumMembers > 1) {
+  bool IsHFA = isHomogeneousAggregate(Ty, Base, Ctx, &NumMembers);
+  if (IsHFA && NumMembers > 1) {
     // Homogeneous aggregates passed in registers will have their elements split
     // and stored 16-bytes apart regardless of size (they're notionally in qN,
     // qN+1, ...). We reload and store into a temporary local variable
@@ -3579,7 +3580,8 @@ static llvm::Value *EmitAArch64VAArg(llvm::Value *VAListAddr, QualType Ty,
   } else {
     // Otherwise the object is contiguous in memory
     unsigned BeAlign = reg_top_index == 2 ? 16 : 8;
-    if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) &&
+    if (CGF.CGM.getDataLayout().isBigEndian() &&
+        (IsHFA || !isAggregateTypeForABI(Ty)) &&
         Ctx.getTypeSize(Ty) < (BeAlign * 8)) {
       int Offset = BeAlign - Ctx.getTypeSize(Ty) / 8;
       BaseAddr = CGF.Builder.CreatePtrToInt(BaseAddr, CGF.Int64Ty);
diff --git a/test/CodeGen/arm64-be-hfa-vararg.c b/test/CodeGen/arm64-be-hfa-vararg.c
new file mode 100644 (file)
index 0000000..1657393
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN:  %clang_cc1 -triple arm64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck %s
+
+#include <stdarg.h>
+
+// A single member HFA must be aligned just like a non-HFA register argument.
+double callee(int a, ...) {
+// CHECK: %align_be = add i64 %{{.*}}, 8
+  va_list vl;
+  va_start(vl, a);
+  double result = va_arg(vl, struct { double a; }).a;
+  va_end(vl);
+  return result;
+}