r222074 - Fix IRGen for passing transparent unions
Reid Kleckner
reid at kleckner.net
Fri Nov 14 17:41:41 PST 2014
Author: rnk
Date: Fri Nov 14 19:41:41 2014
New Revision: 222074
URL: http://llvm.org/viewvc/llvm-project?rev=222074&view=rev
Log:
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.
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/test/CodeGen/transparent-union.c
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=222074&r1=222073&r2=222074&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri Nov 14 19:41:41 2014
@@ -65,6 +65,19 @@ static CGCXXABI::RecordArgABI getRecordA
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::classifyArgume
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::classifyArgume
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::isHomogeneousAg
ABIArgInfo
PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
+ Ty = useFirstFieldIfTransparentUnion(Ty);
+
if (Ty->isAnyComplexType())
return ABIArgInfo::getDirect();
@@ -3911,6 +3930,8 @@ ABIArgInfo AArch64ABIInfo::classifyArgum
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::classifyArgumentT
// 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);
Modified: cfe/trunk/test/CodeGen/transparent-union.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/transparent-union.c?rev=222074&r1=222073&r2=222074&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/transparent-union.c (original)
+++ cfe/trunk/test/CodeGen/transparent-union.c Fri Nov 14 19:41:41 2014
@@ -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);
More information about the cfe-commits
mailing list