aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGClass.cpp
diff options
context:
space:
mode:
authorPiotr Padlewski <prazek@google.com>2015-09-15 21:46:47 +0000
committerPiotr Padlewski <prazek@google.com>2015-09-15 21:46:47 +0000
commit338c9d0ade222e60bca1ad9f76fb837d071bd41f (patch)
tree3c3025c0946cc52e9c394794dd13d3814f98e680 /clang/lib/CodeGen/CGClass.cpp
parent68615ce60647672e2c23013abc9d17112b1eb8d3 (diff)
downloadllvm-338c9d0ade222e60bca1ad9f76fb837d071bd41f.zip
llvm-338c9d0ade222e60bca1ad9f76fb837d071bd41f.tar.gz
llvm-338c9d0ade222e60bca1ad9f76fb837d071bd41f.tar.bz2
Emiting llvm.invariant.group.barrier when dynamic type changes
For more goto: http://lists.llvm.org/pipermail/cfe-dev/2015-July/044227.html http://reviews.llvm.org/D12312 llvm-svn: 247723
Diffstat (limited to 'clang/lib/CodeGen/CGClass.cpp')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp33
1 files changed, 30 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 6c9f404..4c46d56 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1344,6 +1344,13 @@ namespace {
}
+static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
+ const Type *BaseType = BaseInit->getBaseClass();
+ const auto *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+ return BaseClassDecl->isDynamicClass();
+}
+
/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
@@ -1367,9 +1374,13 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(BaseCtorContinueBB);
}
+ bool BaseVPtrsInitialized = false;
// Virtual base initializers first.
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
+ CXXCtorInitializer *BaseInit = *B;
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
+ BaseVPtrsInitialized |= BaseInitializerUsesThis(getContext(),
+ BaseInit->getInit());
}
if (BaseCtorContinueBB) {
@@ -1382,8 +1393,15 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
for (; B != E && (*B)->isBaseInitializer(); B++) {
assert(!(*B)->isBaseVirtual());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
+ BaseVPtrsInitialized |= isInitializerOfDynamicClass(*B);
}
+ // Pointer to this requires to be passed through invariant.group.barrier
+ // only if we've initialized any base vptrs.
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 && BaseVPtrsInitialized)
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+
InitializeVTablePointers(ClassDecl);
// And finally, initialize class members.
@@ -1468,11 +1486,14 @@ FieldHasTrivialDestructorBody(ASTContext &Context,
/// any vtable pointers before calling this destructor.
static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor) {
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ if (!ClassDecl->isDynamicClass())
+ return true;
+
if (!Dtor->hasTrivialBody())
return false;
// Check the fields.
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
for (const auto *Field : ClassDecl->fields())
if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field))
return false;
@@ -1543,8 +1564,14 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
EnterDtorCleanups(Dtor, Dtor_Base);
// Initialize the vtable pointers before entering the body.
- if (!CanSkipVTablePointerInitialization(*this, Dtor))
- InitializeVTablePointers(Dtor->getParent());
+ if (!CanSkipVTablePointerInitialization(*this, Dtor)) {
+ // Insert the llvm.invariant.group.barrier intrinsic before initializing
+ // the vptrs to cancel any previous assumptions we might have made.
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0)
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+ InitializeVTablePointers(Dtor->getParent());
+ }
if (isTryBody)
EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());