[cfe-commits] r89632 - in /cfe/trunk: lib/CodeGen/TargetABIInfo.cpp test/CodeGenCXX/x86_64-arguments.cpp

Daniel Dunbar daniel at zuster.org
Sun Nov 22 15:01:23 PST 2009


Author: ddunbar
Date: Sun Nov 22 17:01:23 2009
New Revision: 89632

URL: http://llvm.org/viewvc/llvm-project?rev=89632&view=rev
Log:
x86_64, PR5582: Layout bases for C++ records.
 - Ideally we would have an single iteration interface for this, but this works
   for now.

Modified:
    cfe/trunk/lib/CodeGen/TargetABIInfo.cpp
    cfe/trunk/test/CodeGenCXX/x86_64-arguments.cpp

Modified: cfe/trunk/lib/CodeGen/TargetABIInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetABIInfo.cpp?rev=89632&r1=89631&r2=89632&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/TargetABIInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetABIInfo.cpp Sun Nov 22 17:01:23 2009
@@ -771,7 +771,7 @@
     // reference.
     if (hasNonTrivialDestructorOrCopyConstructor(RT))
       return;
-    
+
     const RecordDecl *RD = RT->getDecl();
 
     // Assume variable sized types are passed in memory.
@@ -782,6 +782,32 @@
 
     // Reset Lo class, this will be recomputed.
     Current = NoClass;
+
+    // If this is a C++ record, classify the bases first.
+    if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+      for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
+             e = CXXRD->bases_end(); i != e; ++i) {
+        assert(!i->isVirtual() && !i->getType()->isDependentType() &&
+               "Unexpected base class!");
+        const CXXRecordDecl *Base =
+          cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+
+        // Classify this field.
+        //
+        // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate exceeds a
+        // single eightbyte, each is classified separately. Each eightbyte gets
+        // initialized to class NO_CLASS.
+        Class FieldLo, FieldHi;
+        uint64_t Offset = OffsetBase + Layout.getBaseClassOffset(Base);
+        classify(i->getType(), Context, Offset, FieldLo, FieldHi);
+        Lo = merge(Lo, FieldLo);
+        Hi = merge(Hi, FieldHi);
+        if (Lo == Memory || Hi == Memory)
+          break;
+      }
+    }
+
+    // Classify the fields one at a time, merging the results.
     unsigned idx = 0;
     for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
            i != e; ++i, ++idx) {

Modified: cfe/trunk/test/CodeGenCXX/x86_64-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/x86_64-arguments.cpp?rev=89632&r1=89631&r2=89632&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/x86_64-arguments.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/x86_64-arguments.cpp Sun Nov 22 17:01:23 2009
@@ -1,9 +1,24 @@
-// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s
-struct A { ~A(); };
+// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
 
-// RUN: grep 'define void @_Z2f11A(.struct.A\* .a)' %t
-void f1(A a) { }
+// CHECK: [[i64_i64_ty:%.*]] = type { i64, i64 }
+// CHECK: [[i64_double_ty:%.*]] = type { i64, double }
+
+// Basic base class test.
+struct f0_s0 { unsigned a; };
+struct f0_s1 : public f0_s0 { void *b; };
+// CHECK: define void @_Z2f05f0_s1([[i64_i64_ty]])
+void f0(f0_s1 a0) { }
+
+// Check with two eight-bytes in base class.
+struct f1_s0 { unsigned a; unsigned b; float c; };
+struct f1_s1 : public f1_s0 { float d;};
+// CHECK: define void @_Z2f15f1_s1([[i64_double_ty]])
+void f1(f1_s1 a0) { }
+
+// Check with two eight-bytes in base class and merge.
+struct f2_s0 { unsigned a; unsigned b; float c; };
+struct f2_s1 : public f2_s0 { char d;};
+// CHECK: define void @_Z2f25f2_s1([[i64_i64_ty]])
+void f2(f2_s1 a0) { }
 
-// RUN: grep 'define void @_Z2f2v(.struct.A\* noalias sret .agg.result)' %t
-A f2() { return A(); }
 





More information about the cfe-commits mailing list