forked from OSchip/llvm-project
ARM ABI: fix ABI alignment issues in varargs.
We generalize r166040 to handle ABI alignment issues for all types. rdar://12439123 llvm-svn: 166052
This commit is contained in:
parent
d6f3168a08
commit
67effb97df
|
@ -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<VectorType>()) {
|
||||
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<VectorType>() &&
|
||||
(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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue