From: James Molloy Date: Wed, 7 May 2014 14:45:55 +0000 (+0000) Subject: [ARM64-BE] Correctly deal with single element HFAs in varargs. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b00d1275d6bdb1e872599ed71774b713d7aa95a5;p=clang [ARM64-BE] Correctly deal with single element HFAs in varargs. 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 --- diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 300fb19f20..fefa864392 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -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 index 0000000000..16573934ad --- /dev/null +++ b/test/CodeGen/arm64-be-hfa-vararg.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple arm64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck %s + +#include + +// 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; +}