summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-15 07:44:25 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-15 07:44:25 +0000
commit67e5495076feb6c1338273ace96b58da95cdaf61 (patch)
treebadd8f913c2a7db8d5fbe7d83c862e35e403fd41 /lib/CodeGen
parent9092c3e0fa01f3139b016d05d267a89e3b07747a (diff)
downloadFreeBSD-src-67e5495076feb6c1338273ace96b58da95cdaf61.zip
FreeBSD-src-67e5495076feb6c1338273ace96b58da95cdaf61.tar.gz
Update clang to 84175.
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGExpr.cpp48
-rw-r--r--lib/CodeGen/CGVtable.cpp96
-rw-r--r--lib/CodeGen/CodeGenModule.cpp47
3 files changed, 156 insertions, 35 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 2834dfe..01a057f 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -78,6 +78,26 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E,
RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
QualType DestType,
bool IsInitializer) {
+ if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
+ // If we shouldn't destroy the temporaries, just emit the
+ // child expression.
+ if (!TE->shouldDestroyTemporaries())
+ return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
+ IsInitializer);
+
+ // Keep track of the current cleanup stack depth.
+ unsigned OldNumLiveTemporaries = LiveTemporaries.size();
+
+ RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
+ IsInitializer);
+
+ // Pop temporaries.
+ while (LiveTemporaries.size() > OldNumLiveTemporaries)
+ PopCXXTemporary();
+
+ return RV;
+ }
+
RValue Val;
if (E->isLvalue(getContext()) == Expr::LV_Valid) {
// Emit the expr as an lvalue.
@@ -86,9 +106,21 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
return RValue::get(LV.getAddress());
Val = EmitLoadOfLValue(LV, E->getType());
} else {
- // FIXME: Initializers don't work with casts yet. For example
- // const A& a = B();
- // if B inherits from A.
+ const CXXRecordDecl *BaseClassDecl = 0;
+ const CXXRecordDecl *DerivedClassDecl = 0;
+
+ if (const CastExpr *CE =
+ dyn_cast<CastExpr>(E->IgnoreParenNoopCasts(getContext()))) {
+ if (CE->getCastKind() == CastExpr::CK_DerivedToBase) {
+ E = CE->getSubExpr();
+
+ BaseClassDecl =
+ cast<CXXRecordDecl>(CE->getType()->getAs<RecordType>()->getDecl());
+ DerivedClassDecl =
+ cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+ }
+ }
+
Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,
IsInitializer);
@@ -106,6 +138,16 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
}
}
}
+
+ // Check if need to perform the derived-to-base cast.
+ if (BaseClassDecl) {
+ llvm::Value *Derived = Val.getAggregateAddr();
+
+ llvm::Value *Base =
+ GetAddressCXXOfBaseClass(Derived, DerivedClassDecl, BaseClassDecl,
+ /*NullCheckValue=*/false);
+ return RValue::get(Base);
+ }
}
if (Val.isAggregate()) {
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 41f7eef..6e73db3 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -56,6 +56,8 @@ private:
const bool Extern;
const uint32_t LLVMPointerWidth;
Index_t extra;
+ int CurrentVBaseOffset;
+ typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
public:
VtableBuilder(std::vector<llvm::Constant *> &meth,
const CXXRecordDecl *c,
@@ -63,7 +65,8 @@ public:
: methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)),
rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()),
CGM(cgm), Extern(true),
- LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
+ LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)),
+ CurrentVBaseOffset(0) {
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
}
@@ -187,7 +190,10 @@ public:
VCall[MD] = idx;
CallOffset ThisOffset;
// FIXME: calculate non-virtual offset
- ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8));
+ ThisOffset = std::make_pair(0 /* -CurrentVBaseOffset/8 + Offset/8 */,
+ -((idx+extra+2)*LLVMPointerWidth/8));
+ // FIXME: Do we always have to build a covariant thunk to save oret,
+ // which is the containing virtual base class?
if (ReturnOffset.first || ReturnOffset.second)
CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
@@ -199,6 +205,7 @@ public:
// FIXME: finish off
int64_t O = VCallOffset[OMD] - Offset/8;
+ // int64_t O = CurrentVBaseOffset/8 - Offset/8;
if (O || ReturnOffset.first || ReturnOffset.second) {
CallOffset ThisOffset = std::make_pair(O, 0);
@@ -241,10 +248,8 @@ public:
CovariantThunks.clear();
}
- void OverrideMethods(std::vector<std::pair<const CXXRecordDecl *,
- int64_t> > *Path, bool MorallyVirtual) {
- for (std::vector<std::pair<const CXXRecordDecl *,
- int64_t> >::reverse_iterator i =Path->rbegin(),
+ void OverrideMethods(Path_t *Path, bool MorallyVirtual) {
+ for (Path_t::reverse_iterator i = Path->rbegin(),
e = Path->rend(); i != e; ++i) {
const CXXRecordDecl *RD = i->first;
int64_t Offset = i->second;
@@ -314,7 +319,8 @@ public:
void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
const CXXRecordDecl *PrimaryBase,
bool PrimaryBaseWasVirtual, bool MorallyVirtual,
- int64_t Offset) {
+ int64_t Offset, Path_t *Path) {
+ Path->push_back(std::make_pair(RD, Offset));
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
if (i->isVirtual())
@@ -324,41 +330,65 @@ public:
if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
StartNewTable();
- std::vector<std::pair<const CXXRecordDecl *,
- int64_t> > S;
- S.push_back(std::make_pair(RD, Offset));
- GenerateVtableForBase(Base, MorallyVirtual, o, false, &S);
+ CurrentVBaseOffset = Offset;
+ GenerateVtableForBase(Base, MorallyVirtual, o, false, Path);
}
}
+ Path->pop_back();
+ }
+
+// #define D(X) do { X; } while (0)
+#define D(X)
+
+ void insertVCalls(int InsertionPoint) {
+ llvm::Constant *e = 0;
+ D(VCalls.insert(VCalls.begin(), 673));
+ D(VCalls.push_back(672));
+ methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e);
+ // The vcalls come first...
+ for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
+ e = VCalls.rend();
+ i != e; ++i)
+ methods[InsertionPoint++] = wrap((0?600:0) + *i);
+ VCalls.clear();
}
Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets,
const ASTRecordLayout &Layout,
const CXXRecordDecl *PrimaryBase,
bool PrimaryBaseWasVirtual, bool MorallyVirtual,
- int64_t Offset, bool ForVirtualBase) {
+ int64_t Offset, bool ForVirtualBase, Path_t *Path) {
+ bool alloc = false;
+ if (Path == 0) {
+ alloc = true;
+ Path = new Path_t;
+ }
+
StartNewTable();
extra = 0;
// FIXME: Cleanup.
if (!ForVirtualBase) {
+ D(methods.push_back(wrap(666)));
// then virtual base offsets...
for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
e = offsets.rend(); i != e; ++i)
methods.push_back(*i);
+ D(methods.push_back(wrap(667)));
}
- // The vcalls come first...
- for (std::vector<Index_t>::reverse_iterator i=VCalls.rbegin(),
- e=VCalls.rend();
- i != e; ++i)
- methods.push_back(wrap((0?600:0) + *i));
- VCalls.clear();
+ bool DeferVCalls = MorallyVirtual || ForVirtualBase;
+ int VCallInsertionPoint = methods.size();
+ if (!DeferVCalls) {
+ insertVCalls(VCallInsertionPoint);
+ }
if (ForVirtualBase) {
+ D(methods.push_back(wrap(668)));
// then virtual base offsets...
for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
e = offsets.rend(); i != e; ++i)
methods.push_back(*i);
+ D(methods.push_back(wrap(669)));
}
methods.push_back(wrap(-(Offset/8)));
@@ -371,7 +401,18 @@ public:
// and then the non-virtual bases.
NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
- MorallyVirtual, Offset);
+ MorallyVirtual, Offset, Path);
+
+ if (ForVirtualBase) {
+ D(methods.push_back(wrap(670)));
+ insertVCalls(VCallInsertionPoint);
+ AddressPoint += VCalls.size();
+ D(methods.push_back(wrap(671)));
+ }
+
+ if (alloc) {
+ delete Path;
+ }
return AddressPoint;
}
@@ -397,8 +438,7 @@ public:
int64_t GenerateVtableForBase(const CXXRecordDecl *RD,
bool MorallyVirtual = false, int64_t Offset = 0,
bool ForVirtualBase = false,
- std::vector<std::pair<const CXXRecordDecl *,
- int64_t> > *Path = 0) {
+ Path_t *Path = 0) {
if (!RD->isDynamicClass())
return 0;
@@ -426,18 +466,16 @@ public:
OverrideMethods(Path, MorallyVirtual);
return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
- MorallyVirtual, Offset, ForVirtualBase);
+ MorallyVirtual, Offset, ForVirtualBase, Path);
}
void GenerateVtableForVBases(const CXXRecordDecl *RD,
int64_t Offset = 0,
- std::vector<std::pair<const CXXRecordDecl *,
- int64_t> > *Path = 0) {
+ Path_t *Path = 0) {
bool alloc = false;
if (Path == 0) {
alloc = true;
- Path = new std::vector<std::pair<const CXXRecordDecl *,
- int64_t> >;
+ Path = new Path_t;
}
// FIXME: We also need to override using all paths to a virtual base,
// right now, we just process the first path
@@ -450,14 +488,18 @@ public:
// Mark it so we don't output it twice.
IndirectPrimary.insert(Base);
StartNewTable();
+ VCall.clear();
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
+ CurrentVBaseOffset = BaseOffset;
GenerateVtableForBase(Base, true, BaseOffset, true, Path);
}
int64_t BaseOffset = Offset;
if (i->isVirtual())
BaseOffset = BLayout.getVBaseClassOffset(Base);
- if (Base->getNumVBases())
+ if (Base->getNumVBases()) {
+ CurrentVBaseOffset = BaseOffset;
GenerateVtableForVBases(Base, BaseOffset, Path);
+ }
}
Path->pop_back();
if (alloc)
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 36ad7f5..4763b7f 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -541,7 +541,12 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
}
}
- return VD->getStorageClass() == VarDecl::Static;
+ // Static data may be deferred, but out-of-line static data members
+ // cannot be.
+ // FIXME: What if the initializer has side effects?
+ return VD->isInAnonymousNamespace() ||
+ (VD->getStorageClass() == VarDecl::Static &&
+ !(VD->isStaticDataMember() && VD->isOutOfLine()));
}
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
@@ -928,6 +933,37 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
EmitGlobalVarDefinition(D);
}
+static CodeGenModule::GVALinkage
+GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
+ // Everything located semantically within an anonymous namespace is
+ // always internal.
+ if (VD->isInAnonymousNamespace())
+ return CodeGenModule::GVA_Internal;
+
+ // Handle linkage for static data members.
+ if (VD->isStaticDataMember()) {
+ switch (VD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDefinition:
+ return CodeGenModule::GVA_StrongExternal;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ assert(false && "Variable should not be instantiated");
+ // Fall through to treat this like any other instantiation.
+
+ case TSK_ImplicitInstantiation:
+ return CodeGenModule::GVA_TemplateInstantiation;
+ }
+ }
+
+ // Static variables get internal linkage.
+ if (VD->getStorageClass() == VarDecl::Static)
+ return CodeGenModule::GVA_Internal;
+
+ return CodeGenModule::GVA_StrongExternal;
+}
+
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
llvm::Constant *Init = 0;
QualType ASTTy = D->getType();
@@ -1021,9 +1057,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->setAlignment(getContext().getDeclAlignInBytes(D));
// Set the llvm linkage type as appropriate.
- if (D->isInAnonymousNamespace())
- GV->setLinkage(llvm::Function::InternalLinkage);
- else if (D->getStorageClass() == VarDecl::Static)
+ GVALinkage Linkage = GetLinkageForVariable(getContext(), D);
+ if (Linkage == GVA_Internal)
GV->setLinkage(llvm::Function::InternalLinkage);
else if (D->hasAttr<DLLImportAttr>())
GV->setLinkage(llvm::Function::DLLImportLinkage);
@@ -1034,7 +1069,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage);
else
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
- } else if (!CompileOpts.NoCommon &&
+ } else if (Linkage == GVA_TemplateInstantiation)
+ GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
+ else if (!CompileOpts.NoCommon &&
!D->hasExternalStorage() && !D->getInit() &&
!D->getAttr<SectionAttr>()) {
GV->setLinkage(llvm::GlobalVariable::CommonLinkage);
OpenPOWER on IntegriCloud