From 67effb97df7fe4d951c7caba8aa6a840f5fde9c4 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Tue, 16 Oct 2012 19:51:48 +0000 Subject: [PATCH] ARM ABI: fix ABI alignment issues in varargs. We generalize r166040 to handle ABI alignment issues for all types. rdar://12439123 llvm-svn: 166052 --- clang/lib/CodeGen/TargetInfo.cpp | 15 ++++++--------- clang/test/CodeGen/arm-abi-vector.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 24be05f..4ee9b97 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -3213,13 +3213,11 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte. - if (Ty->getAs()) { - if (getABIKind() == ARMABIInfo::AAPCS_VFP || - getABIKind() == ARMABIInfo::AAPCS) - TyAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8); - else - TyAlign = 4; - } + if (getABIKind() == ARMABIInfo::AAPCS_VFP || + getABIKind() == ARMABIInfo::AAPCS) + TyAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8); + else + TyAlign = 4; // Use indirect if size of the illegal vector is bigger than 16 bytes. if (isIllegalVectorType(Ty) && Size > 16) { IsIndirect = true; @@ -3246,8 +3244,7 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, if (IsIndirect) Addr = Builder.CreateLoad(Builder.CreateBitCast(Addr, BPP)); - else if (Ty->getAs() && - (TyAlign < CGF.getContext().getTypeAlign(Ty) / 8)) { + else if (TyAlign < CGF.getContext().getTypeAlign(Ty) / 8) { // We can't directly cast ap.cur to pointer to a vector type, since ap.cur // may not be correctly aligned for the vector type. We create an aligned // temporary space and copy the content over from ap.cur to the temporary diff --git a/clang/test/CodeGen/arm-abi-vector.c b/clang/test/CodeGen/arm-abi-vector.c index 296359d..7fc771c 100644 --- a/clang/test/CodeGen/arm-abi-vector.c +++ b/clang/test/CodeGen/arm-abi-vector.c @@ -226,3 +226,38 @@ double test_5s(__short5 *in) { // APCS-GNU: call double (i32, ...)* @varargs_vec_5s(i32 5, <4 x i32> %3) return varargs_vec_5s(5, *in); } + +// Pass struct as varargs. +typedef struct +{ + __int2 i2; + float f; +} StructWithVec; + +double varargs_struct(int fixed, ...) { +// CHECK: varargs_struct +// CHECK: %3 = and i32 %2, -8 +// CHECK: %ap.align = inttoptr i32 %3 to i8* +// CHECK: %ap.next = getelementptr i8* %ap.align, i32 16 +// CHECK: bitcast i8* %ap.align to %struct.StructWithVec* +// APCS-GNU: varargs_struct +// APCS-GNU: %var.align = alloca %struct.StructWithVec +// APCS-GNU: %ap.next = getelementptr i8* %ap.cur, i32 16 +// APCS-GNU: %1 = bitcast %struct.StructWithVec* %var.align to i8* +// APCS-GNU: call void @llvm.memcpy + va_list ap; + double sum = fixed; + va_start(ap, fixed); + StructWithVec c3 = va_arg(ap, StructWithVec); + sum = sum + c3.i2.x + c3.i2.y + c3.f; + va_end(ap); + return sum; +} + +double test_struct(StructWithVec* d) { +// CHECK: test_struct +// CHECK: call arm_aapcscc double (i32, ...)* @varargs_struct(i32 3, [2 x i64] %3) +// APCS-GNU: test_struct +// APCS-GNU: call double (i32, ...)* @varargs_struct(i32 3, [2 x i64] %3) + return varargs_struct(3, *d); +} -- 2.7.4