Finish off support for typeinfo generation for classes.

llvm-svn: 88828
This commit is contained in:
Mike Stump 2009-11-15 03:28:10 +00:00
parent ad6c15465c
commit 4c808dfc58
2 changed files with 145 additions and 9 deletions

View File

@ -20,6 +20,8 @@ class RttiBuilder {
CodeGenModule &CGM; // Per-module state. CodeGenModule &CGM; // Per-module state.
llvm::LLVMContext &VMContext; llvm::LLVMContext &VMContext;
const llvm::Type *Int8PtrTy; const llvm::Type *Int8PtrTy;
llvm::SmallSet<const CXXRecordDecl *, 16> SeenVBase;
llvm::SmallSet<const CXXRecordDecl *, 32> SeenBase;
public: public:
RttiBuilder(CodeGenModule &cgm) RttiBuilder(CodeGenModule &cgm)
: CGM(cgm), VMContext(cgm.getModule().getContext()), : CGM(cgm), VMContext(cgm.getModule().getContext()),
@ -98,6 +100,47 @@ public:
return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
} }
/// CalculateFlags - Calculate the flags for the __vmi_class_type_info
/// datastructure. 1 for non-diamond repeated inheritance, 2 for a dimond
/// shaped class.
int CalculateFlags(const CXXRecordDecl*RD) {
int flags = 0;
if (SeenBase.count(RD))
flags |= 1;
else
SeenBase.insert(RD);
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (i->isVirtual()) {
if (SeenVBase.count(Base))
flags |= 2;
else
SeenVBase.insert(Base);
}
flags |= CalculateFlags(Base);
}
return flags;
}
bool SimpleInheritance(const CXXRecordDecl *RD) {
if (RD->getNumBases() != 1)
return false;
CXXRecordDecl::base_class_const_iterator i = RD->bases_begin();
if (i->isVirtual())
return false;
if (i->getAccessSpecifier() != AS_public)
return false;
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (Layout.getBaseClassOffset(Base) != 0)
return false;
return true;
}
llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) { llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) {
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
llvm::Constant *C; llvm::Constant *C;
@ -119,31 +162,35 @@ public:
linktype = llvm::GlobalValue::LinkOnceODRLinkage; linktype = llvm::GlobalValue::LinkOnceODRLinkage;
std::vector<llvm::Constant *> info; std::vector<llvm::Constant *> info;
bool simple = false;
if (RD->getNumBases() == 0) if (RD->getNumBases() == 0)
C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE"); C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE");
// FIXME: Add si_class_type_info optimization else if (SimpleInheritance(RD)) {
else simple = true;
C = BuildVtableRef("_ZTVN10__cxxabiv120__si_class_type_infoE");
} else
C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE"); C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
info.push_back(C); info.push_back(C);
info.push_back(BuildName(RD)); info.push_back(BuildName(RD));
// If we have no bases, there are no more fields. // If we have no bases, there are no more fields.
if (RD->getNumBases()) { if (RD->getNumBases()) {
if (!simple) {
// FIXME: Calculate is_diamond and non-diamond repeated inheritance, 3 is info.push_back(BuildFlags(CalculateFlags(RD)));
// conservative.
info.push_back(BuildFlags(3));
info.push_back(BuildBaseCount(RD->getNumBases())); info.push_back(BuildBaseCount(RD->getNumBases()));
}
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) { e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base = const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
info.push_back(CGM.GenerateRtti(Base)); info.push_back(CGM.GenerateRttiRef(Base));
if (simple)
break;
int64_t offset; int64_t offset;
if (!i->isVirtual()) if (!i->isVirtual())
offset = Layout.getBaseClassOffset(Base); offset = Layout.getBaseClassOffset(Base)/8;
else else
offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base); offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base);
offset <<= 8; offset <<= 8;

View File

@ -0,0 +1,89 @@
// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t.s
// RUN: FileCheck --input-file=%t.s %s
class test1_B1 {
virtual void foo() { }
};
class test1_B2 : public test1_B1 {
virtual void foo() { }
};
class test1_B3 : public test1_B2, public test1_B1 {
virtual void foo() { }
};
class test1_B4 : virtual public test1_B3 {
virtual void foo() { }
};
class test1_B5 : virtual test1_B3, test1_B4 {
virtual void foo() { }
};
class test1_B6 {
virtual void foo() { }
};
class test1_B7 : public test1_B6, public test1_B5 {
virtual void foo() { }
};
class test1_D : public test1_B7 {
virtual void foo() { }
} d1;
// CHECK:__ZTI7test1_D:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv120__si_class_type_infoE) + 16
// CHECK-NEXT: .quad __ZTS7test1_D
// CHECK-NEXT: .quad __ZTI8test1_B7
// CHECK:__ZTI8test1_B7:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
// CHECK-NEXT: .quad __ZTS8test1_B7
// CHECK-NEXT: .long 3
// CHECK-NEXT: .long 2
// CHECK-NEXT: .quad __ZTI8test1_B6
// CHECK-NEXT: .quad 2
// CHECK-NEXT: .quad __ZTI8test1_B5
// CHECK-NEXT: .quad 2050
// CHECK:__ZTI8test1_B5:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
// CHECK-NEXT: .quad __ZTS8test1_B5
// CHECK-NEXT: .long 3
// CHECK-NEXT: .long 2
// CHECK-NEXT: .quad __ZTI8test1_B3
// CHECK-NEXT: .quad 18446744073709545473
// CHECK-NEXT: .quad __ZTI8test1_B4
// CHECK-NEXT: .space 8
// CHECK:__ZTI8test1_B4:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
// CHECK-NEXT: .quad __ZTS8test1_B4
// CHECK-NEXT: .long 1
// CHECK-NEXT: .long 1
// CHECK-NEXT: .quad __ZTI8test1_B3
// CHECK-NEXT: .quad 18446744073709545475
// CHECK:__ZTI8test1_B6:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv117__class_type_infoE) + 16
// CHECK-NEXT: .quad __ZTS8test1_B6
// CHECK:__ZTI8test1_B3:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv121__vmi_class_type_infoE) + 16
// CHECK-NEXT: .quad __ZTS8test1_B3
// CHECK-NEXT: .long 1
// CHECK-NEXT: .long 2
// CHECK-NEXT: .quad __ZTI8test1_B2
// CHECK-NEXT: .quad 2
// CHECK-NEXT: .quad __ZTI8test1_B1
// CHECK-NEXT: .quad 2050
// CHECK:__ZTS8test1_B1:
// CHECK-NEXT: .asciz "8test1_B1"
// CHECK:__ZTI8test1_B1:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv117__class_type_infoE) + 16
// CHECK-NEXT:. quad __ZTS8test1_B1
// CHECK:__ZTS8test1_B2:
// CHECK-NEXT: .asciz "8test1_B2"
// CHECK:__ZTI8test1_B2:
// CHECK-NEXT: .quad (__ZTVN10__cxxabiv120__si_class_type_infoE) + 16
// CHECK-NEXT: .quad __ZTS8test1_B2
// CHECK-NEXT: .quad __ZTI8test1_B1