diff options
author | Piotr Padlewski <prazek@google.com> | 2015-09-15 21:46:47 +0000 |
---|---|---|
committer | Piotr Padlewski <prazek@google.com> | 2015-09-15 21:46:47 +0000 |
commit | 338c9d0ade222e60bca1ad9f76fb837d071bd41f (patch) | |
tree | 3c3025c0946cc52e9c394794dd13d3814f98e680 /clang/lib/CodeGen/CGClass.cpp | |
parent | 68615ce60647672e2c23013abc9d17112b1eb8d3 (diff) | |
download | llvm-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.cpp | 33 |
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()); |