Fix IRGen for passing transparent unions

We have had a test for this for a long time with a FIXME saying what we
should be doing. This just does it.

Fixes PR21573.

llvm-svn: 222074
This commit is contained in:
Reid Kleckner 2014-11-15 01:41:41 +00:00
parent 83171b32ed
commit b1be683074
2 changed files with 35 additions and 7 deletions

View File

@ -65,6 +65,19 @@ static CGCXXABI::RecordArgABI getRecordArgABI(QualType T,
return getRecordArgABI(RT, CXXABI);
}
/// Pass transparent unions as if they were the type of the first element. Sema
/// should ensure that all elements of the union have the same "machine type".
static QualType useFirstFieldIfTransparentUnion(QualType Ty) {
if (const RecordType *UT = Ty->getAsUnionType()) {
const RecordDecl *UD = UT->getDecl();
if (UD->hasAttr<TransparentUnionAttr>()) {
assert(!UD->field_empty() && "sema created an empty transparent union");
return UD->field_begin()->getType();
}
}
return Ty;
}
CGCXXABI &ABIInfo::getCXXABI() const {
return CGT.getCXXABI();
}
@ -1006,6 +1019,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
CCState &State) const {
// FIXME: Set alignment on indirect arguments.
Ty = useFirstFieldIfTransparentUnion(Ty);
// Check with the C++ ABI first.
const RecordType *RT = Ty->getAs<RecordType>();
if (RT) {
@ -2543,6 +2558,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(
bool isNamedArg)
const
{
Ty = useFirstFieldIfTransparentUnion(Ty);
X86_64ABIInfo::Class Lo, Hi;
classify(Ty, 0, Lo, Hi, isNamedArg);
@ -3520,6 +3537,8 @@ bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateSmallEnough(
ABIArgInfo
PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
Ty = useFirstFieldIfTransparentUnion(Ty);
if (Ty->isAnyComplexType())
return ABIArgInfo::getDirect();
@ -3911,6 +3930,8 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty,
unsigned &AllocatedGPR,
bool &IsSmallAggr,
bool IsNamedArg) const {
Ty = useFirstFieldIfTransparentUnion(Ty);
// Handle illegal vector types here.
if (isIllegalVectorType(Ty)) {
uint64_t Size = getContext().getTypeSize(Ty);
@ -4692,6 +4713,8 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
// to four Elements.
bool IsEffectivelyAAPCS_VFP = getABIKind() == AAPCS_VFP && !isVariadic;
Ty = useFirstFieldIfTransparentUnion(Ty);
// Handle illegal vector types here.
if (isIllegalVectorType(Ty)) {
uint64_t Size = getContext().getTypeSize(Ty);

View File

@ -1,8 +1,8 @@
// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -o %t %s
// RUN: FileCheck < %t %s
//
// FIXME: Note that we don't currently get the ABI right here. f0() should be
// f0(i8*).
// RUN: %clang_cc1 -Werror -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -Werror -triple i386-linux -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -Werror -triple armv7-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM
// RUN: %clang_cc1 -Werror -triple powerpc64le-linux -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -Werror -triple aarch64-linux -emit-llvm -o - %s | FileCheck %s
typedef union {
void *f0;
@ -10,10 +10,15 @@ typedef union {
void f0(transp_t0 obj);
// CHECK-LABEL: define void @f1_0(i32* %a0)
// CHECK: call void @f0(%union.transp_t0* byval align 4 %{{.*}})
// CHECK-LABEL: define void @f1_0(i32* %a0)
// CHECK: call void @f0(i8* %{{.*}})
// CHECK: call void %{{.*}}(i8* %{{[a-z0-9]*}})
// CHECK: }
// ARM-LABEL: define arm_aapcscc void @f1_0(i32* %a0)
// ARM: call arm_aapcscc void @f0(i8* %{{.*}})
// ARM: call arm_aapcscc void %{{.*}}(i8* %{{[a-z0-9]*}})
// ARM: }
void f1_0(int *a0) {
void (*f0p)(void *) = f0;
f0(a0);