summaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-19 09:00:00 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-19 09:00:00 +0000
commitf5bd02d290ff15268853e0456c130a1afa15e907 (patch)
treec7f5a7b6fd212399d821b83b22c1e6a42e8c4a0d /lib/CodeGen
parentb3d5a323a5ca92ea73443499cee2f15db1ff0fb3 (diff)
Notes
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGCXX.cpp4
-rw-r--r--lib/CodeGen/CGDecl.cpp1
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp5
-rw-r--r--lib/CodeGen/CGRtti.cpp107
-rw-r--r--lib/CodeGen/CGVtable.cpp111
-rw-r--r--lib/CodeGen/CGVtable.h4
-rw-r--r--lib/CodeGen/CodeGenModule.cpp10
7 files changed, 182 insertions, 60 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 8f5cff4efafe3..b1d30a68bbb71 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -603,8 +603,8 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
EmitBlock(AfterFor, true);
}
-/// GenerateCXXAggrDestructorHelper - Generates a helper function which when invoked,
-/// calls the default destructor on array elements in reverse order of
+/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
+/// invoked, calls the default destructor on array elements in reverse order of
/// construction.
llvm::Constant *
CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1d2040bae203d..349ede51c63b0 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -611,4 +611,3 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder);
}
}
-
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 8e0864b8dd83d..a63c8325ffa72 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -345,6 +345,11 @@ static const CXXMethodDecl *GetKeyFunction(const RecordDecl *D) {
if (MD->isPure())
continue;
+ // FIXME: This doesn't work. If we have an out of line body, that body will
+ // set the MD to have a body, what we want to know is, was the body present
+ // inside the declaration of the class. For now, we just avoid the problem
+ // by pretending there is no key function.
+ return 0;
if (MD->getBody())
continue;
diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp
index e18843d5cf3f1..79d866427f0b8 100644
--- a/lib/CodeGen/CGRtti.cpp
+++ b/lib/CodeGen/CGRtti.cpp
@@ -47,21 +47,35 @@ public:
return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
}
- llvm::Constant *BuildName(QualType Ty, bool Hidden) {
+ llvm::Constant *BuildName(QualType Ty, bool Hidden, bool Extern) {
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
mangleCXXRttiName(CGM.getMangleContext(), Ty, Out);
+ llvm::StringRef Name = Out.str();
llvm::GlobalVariable::LinkageTypes linktype;
linktype = llvm::GlobalValue::LinkOnceODRLinkage;
+ if (!Extern)
+ linktype = llvm::GlobalValue::InternalLinkage;
+
+ llvm::GlobalVariable *GV;
+ GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV && !GV->isDeclaration())
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
llvm::Constant *C;
- C = llvm::ConstantArray::get(VMContext, Out.str().substr(4));
+ C = llvm::ConstantArray::get(VMContext, Name.substr(4));
- llvm::GlobalVariable * GV = new llvm::GlobalVariable(CGM.getModule(),
- C->getType(),
- true, linktype, C,
- Out.str());
+ llvm::GlobalVariable *OGV = GV;
+ GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
+ C, Name);
+ if (OGV) {
+ GV->takeName(OGV);
+ llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
+ OGV->getType());
+ OGV->replaceAllUsesWith(NewPtr);
+ OGV->eraseFromParent();
+ }
if (Hidden)
GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
@@ -87,8 +101,9 @@ public:
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
+ llvm::StringRef Name = Out.str();
- C = CGM.getModule().getGlobalVariable(Out.str());
+ C = CGM.getModule().getGlobalVariable(Name);
if (C)
return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
@@ -96,7 +111,7 @@ public:
linktype = llvm::GlobalValue::ExternalLinkage;;
C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype,
- 0, Out.str());
+ 0, Name);
return llvm::ConstantExpr::getBitCast(C, Int8PtrTy);
}
@@ -147,20 +162,19 @@ public:
llvm::Constant *finish(std::vector<llvm::Constant *> &info,
llvm::GlobalVariable *GV,
- llvm::StringRef Name, bool Hidden) {
+ llvm::StringRef Name, bool Hidden, bool Extern) {
llvm::GlobalVariable::LinkageTypes linktype;
linktype = llvm::GlobalValue::LinkOnceODRLinkage;
+ if (!Extern)
+ linktype = llvm::GlobalValue::InternalLinkage;
llvm::Constant *C;
C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false);
- if (GV == 0)
- GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
- linktype, C, Name);
- else {
- llvm::GlobalVariable *OGV = GV;
- GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
- linktype, C, Name);
+ llvm::GlobalVariable *OGV = GV;
+ GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype,
+ C, Name);
+ if (OGV) {
GV->takeName(OGV);
llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
OGV->getType());
@@ -183,15 +197,17 @@ public:
llvm::raw_svector_ostream Out(OutName);
mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD),
Out);
+ llvm::StringRef Name = Out.str();
llvm::GlobalVariable *GV;
- GV = CGM.getModule().getGlobalVariable(Out.str());
+ GV = CGM.getModule().getGlobalVariable(Name);
if (GV && !GV->isDeclaration())
return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
std::vector<llvm::Constant *> info;
bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
+ bool Extern = !RD->isInAnonymousNamespace();
bool simple = false;
if (RD->getNumBases() == 0)
@@ -202,7 +218,8 @@ public:
} else
C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE");
info.push_back(C);
- info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden));
+ info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden,
+ Extern));
// If we have no bases, there are no more fields.
if (RD->getNumBases()) {
@@ -235,7 +252,7 @@ public:
}
}
- return finish(info, GV, Out.str(), Hidden);
+ return finish(info, GV, Name, Hidden, Extern);
}
/// - BuildFlags - Build a __flags value for __pbase_type_info.
@@ -250,23 +267,49 @@ public:
return BuildType(Ty);
}
+ bool DecideExtern(QualType Ty) {
+ // For this type, see if all components are never in an anonymous namespace.
+ if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
+ return (DecideExtern(MPT->getPointeeType())
+ && DecideExtern(QualType(MPT->getClass(), 0)));
+ if (const PointerType *PT = Ty->getAs<PointerType>())
+ return DecideExtern(PT->getPointeeType());
+ if (const RecordType *RT = Ty->getAs<RecordType>())
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ return !RD->isInAnonymousNamespace();
+ return true;
+ }
+
+ bool DecideHidden(QualType Ty) {
+ // For this type, see if all components are never hidden.
+ if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
+ return (DecideHidden(MPT->getPointeeType())
+ && DecideHidden(QualType(MPT->getClass(), 0)));
+ if (const PointerType *PT = Ty->getAs<PointerType>())
+ return DecideHidden(PT->getPointeeType());
+ if (const RecordType *RT = Ty->getAs<RecordType>())
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
+ return false;
+ }
+
llvm::Constant *BuildPointerType(QualType Ty) {
llvm::Constant *C;
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
+ llvm::StringRef Name = Out.str();
llvm::GlobalVariable *GV;
- GV = CGM.getModule().getGlobalVariable(Out.str());
+ GV = CGM.getModule().getGlobalVariable(Name);
if (GV && !GV->isDeclaration())
return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
std::vector<llvm::Constant *> info;
- // FIXME: pointer to hidden should be hidden, we should be able to
- // grab a bit off the type for this.
- bool Hidden = false;
+ bool Extern = DecideExtern(Ty);
+ bool Hidden = DecideHidden(Ty);
QualType PTy = Ty->getPointeeType();
QualType BTy;
@@ -282,7 +325,7 @@ public:
else
C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE");
info.push_back(C);
- info.push_back(BuildName(Ty, Hidden));
+ info.push_back(BuildName(Ty, Hidden, Extern));
Qualifiers Q = PTy.getQualifiers();
PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType();
int flags = 0;
@@ -300,7 +343,8 @@ public:
if (PtrMem)
info.push_back(BuildType2(BTy));
- return finish(info, GV, Out.str(), true);
+ // We always generate these as hidden, only the name isn't hidden.
+ return finish(info, GV, Name, true, Extern);
}
llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) {
@@ -309,23 +353,24 @@ public:
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
mangleCXXRtti(CGM.getMangleContext(), Ty, Out);
+ llvm::StringRef Name = Out.str();
llvm::GlobalVariable *GV;
- GV = CGM.getModule().getGlobalVariable(Out.str());
+ GV = CGM.getModule().getGlobalVariable(Name);
if (GV && !GV->isDeclaration())
return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
std::vector<llvm::Constant *> info;
- // FIXME: pointer to hidden should be hidden, we should be able to
- // grab a bit off the type for this.
- bool Hidden = false;
+ bool Extern = DecideExtern(Ty);
+ bool Hidden = DecideHidden(Ty);
C = BuildVtableRef(vtbl);
info.push_back(C);
- info.push_back(BuildName(Ty, Hidden));
+ info.push_back(BuildName(Ty, Hidden, Extern));
- return finish(info, GV, Out.str(), true);
+ // We always generate these as hidden, only the name isn't hidden.
+ return finish(info, GV, Name, true, Extern);
}
llvm::Constant *BuildType(QualType Ty) {
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 4c97a9bdeebfb..9be1a3b22b337 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -69,7 +69,6 @@ private:
llvm::DenseMap<CtorVtable_t, int64_t> &AddressPoints;
typedef CXXRecordDecl::method_iterator method_iter;
- // FIXME: Linkage should follow vtable
const bool Extern;
const uint32_t LLVMPointerWidth;
Index_t extra;
@@ -82,7 +81,7 @@ public:
BLayout(cgm.getContext().getASTRecordLayout(l)),
rtti(cgm.GenerateRttiRef(c)), VMContext(cgm.getModule().getContext()),
CGM(cgm), AddressPoints(*new llvm::DenseMap<CtorVtable_t, int64_t>),
- Extern(true),
+ Extern(!l->isInAnonymousNamespace()),
LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
@@ -788,37 +787,73 @@ llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass,
mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset/8, RD, Out);
else
mangleCXXVtable(getMangleContext(), RD, Out);
+ llvm::StringRef Name = Out.str();
- llvm::GlobalVariable::LinkageTypes linktype;
- linktype = llvm::GlobalValue::LinkOnceODRLinkage;
std::vector<llvm::Constant *> methods;
llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
int64_t AddressPoint;
- VtableBuilder b(methods, RD, LayoutClass, Offset, *this);
+ llvm::GlobalVariable *GV = getModule().getGlobalVariable(Name);
+ if (GV && AddressPoints[LayoutClass] && !GV->isDeclaration())
+ AddressPoint=(*(*(AddressPoints[LayoutClass]))[RD])[std::make_pair(RD,
+ Offset)];
+ else {
+ VtableBuilder b(methods, RD, LayoutClass, Offset, *this);
- D1(printf("vtable %s\n", RD->getNameAsCString()));
- // First comes the vtables for all the non-virtual bases...
- AddressPoint = b.GenerateVtableForBase(RD, Offset);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
+ // First comes the vtables for all the non-virtual bases...
+ AddressPoint = b.GenerateVtableForBase(RD, Offset);
- // then the vtables for all the virtual bases.
- b.GenerateVtableForVBases(RD, Offset);
+ // then the vtables for all the virtual bases.
+ b.GenerateVtableForVBases(RD, Offset);
- CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass];
- if (ref == 0)
- ref = new CodeGenModule::AddrMap_t;
+ CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass];
+ if (ref == 0)
+ ref = new CodeGenModule::AddrMap_t;
- (*ref)[RD] = b.getAddressPoints();
+ (*ref)[RD] = b.getAddressPoints();
+
+ bool CreateDefinition = true;
+ if (LayoutClass != RD)
+ CreateDefinition = true;
+ else {
+ // We have to convert it to have a record layout.
+ Types.ConvertTagDeclType(LayoutClass);
+ const CGRecordLayout &CGLayout = Types.getCGRecordLayout(LayoutClass);
+ if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
+ if (!KeyFunction->getBody()) {
+ // If there is a KeyFunction, and it isn't defined, just build a
+ // reference to the vtable.
+ CreateDefinition = false;
+ }
+ }
+ }
- llvm::Constant *C;
- llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size());
- C = llvm::ConstantArray::get(type, methods);
- llvm::GlobalVariable *GV = new llvm::GlobalVariable(getModule(), type,
- true, linktype, C,
- Out.str());
- bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
- if (Hidden)
- GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
+ llvm::Constant *C = 0;
+ llvm::Type *type = Ptr8Ty;
+ llvm::GlobalVariable::LinkageTypes linktype
+ = llvm::GlobalValue::ExternalLinkage;
+ if (CreateDefinition) {
+ llvm::ArrayType *ntype = llvm::ArrayType::get(Ptr8Ty, methods.size());
+ C = llvm::ConstantArray::get(ntype, methods);
+ linktype = llvm::GlobalValue::LinkOnceODRLinkage;
+ if (LayoutClass->isInAnonymousNamespace())
+ linktype = llvm::GlobalValue::InternalLinkage;
+ type = ntype;
+ }
+ llvm::GlobalVariable *OGV = GV;
+ GV = new llvm::GlobalVariable(getModule(), type, true, linktype, C, Name);
+ if (OGV) {
+ GV->takeName(OGV);
+ llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV,
+ OGV->getType());
+ OGV->replaceAllUsesWith(NewPtr);
+ OGV->eraseFromParent();
+ }
+ bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
+ if (Hidden)
+ GV->setVisibility(llvm::GlobalVariable::HiddenVisibility);
+ }
llvm::Constant *vtable = llvm::ConstantExpr::getBitCast(GV, Ptr8Ty);
llvm::Constant *AddressPointC;
uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0);
@@ -1001,9 +1036,12 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) {
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
mangleCXXVTT(getMangleContext(), RD, Out);
+ llvm::StringRef Name = Out.str();
llvm::GlobalVariable::LinkageTypes linktype;
linktype = llvm::GlobalValue::LinkOnceODRLinkage;
+ if (RD->isInAnonymousNamespace())
+ linktype = llvm::GlobalValue::InternalLinkage;
std::vector<llvm::Constant *> inits;
llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
@@ -1015,20 +1053,41 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) {
llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, inits.size());
C = llvm::ConstantArray::get(type, inits);
llvm::GlobalVariable *vtt = new llvm::GlobalVariable(getModule(), type, true,
- linktype, C, Out.str());
+ linktype, C, Name);
bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden;
if (Hidden)
vtt->setVisibility(llvm::GlobalVariable::HiddenVisibility);
return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty);
}
+void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) {
+ Vtables[RD] = CGM.GenerateVtable(RD, RD);
+ CGM.GenerateRtti(RD);
+ CGM.GenerateVTT(RD);
+}
+
llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
llvm::Constant *&vtbl = Vtables[RD];
if (vtbl)
return vtbl;
vtbl = CGM.GenerateVtable(RD, RD);
- CGM.GenerateRtti(RD);
- CGM.GenerateVTT(RD);
+
+ bool CreateDefinition = true;
+ // We have to convert it to have a record layout.
+ CGM.getTypes().ConvertTagDeclType(RD);
+ const CGRecordLayout &CGLayout = CGM.getTypes().getCGRecordLayout(RD);
+ if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
+ if (!KeyFunction->getBody()) {
+ // If there is a KeyFunction, and it isn't defined, just build a
+ // reference to the vtable.
+ CreateDefinition = false;
+ }
+ }
+
+ if (CreateDefinition) {
+ CGM.GenerateRtti(RD);
+ CGM.GenerateVTT(RD);
+ }
return vtbl;
}
diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h
index f9ddf44284b1d..78ae670cf35af 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -61,6 +61,10 @@ public:
llvm::Constant *getVtable(const CXXRecordDecl *RD);
llvm::Constant *getCtorVtable(const CXXRecordDecl *RD,
const CXXRecordDecl *Class, uint64_t Offset);
+ /// GenerateClassData - Generate all the class data requires to be generated
+ /// upon definition of a KeyFunction. This includes the vtable, the
+ /// rtti data structure and the VTT.
+ void GenerateClassData(const CXXRecordDecl *RD);
};
}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 0e6f4a63a42ca..195acc5bc1579 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -616,6 +616,16 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
Context.getSourceManager(),
"Generating code for declaration");
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ const CXXRecordDecl *RD = MD->getParent();
+ // We have to convert it to have a record layout.
+ Types.ConvertTagDeclType(RD);
+ const CGRecordLayout &CGLayout = Types.getCGRecordLayout(RD);
+ // A definition of a KeyFunction, generates all the class data, such
+ // as vtable, rtti and the VTT.
+ if (CGLayout.getKeyFunction() == MD)
+ getVtableInfo().GenerateClassData(RD);
+ }
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
EmitCXXConstructor(CD, GD.getCtorType());
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D))