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