r219470 - Revert r218865 because it introduced PR21236, a crash in codegen emitting the try block.
Nick Lewycky
nicholas at mxc.ca
Thu Oct 9 21:05:00 PDT 2014
Author: nicholas
Date: Thu Oct 9 23:05:00 2014
New Revision: 219470
URL: http://llvm.org/viewvc/llvm-project?rev=219470&view=rev
Log:
Revert r218865 because it introduced PR21236, a crash in codegen emitting the try block.
Removed:
cfe/trunk/test/CodeGenCXX/unnamed-object-lifetime.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCleanup.cpp
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
Modified: cfe/trunk/lib/CodeGen/CGCleanup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCleanup.cpp?rev=219470&r1=219469&r2=219470&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCleanup.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCleanup.cpp Thu Oct 9 23:05:00 2014
@@ -387,9 +387,14 @@ void CodeGenFunction::PopCleanupBlocks(E
}
}
-/// Move our deferred cleanups onto the EH stack.
+/// Pops cleanup blocks until the given savepoint is reached, then add the
+/// cleanups from the given savepoint in the lifetime-extended cleanups stack.
void
-CodeGenFunction::MoveDeferedCleanups(size_t OldLifetimeExtendedSize) {
+CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old,
+ size_t OldLifetimeExtendedSize) {
+ PopCleanupBlocks(Old);
+
+ // Move our deferred cleanups onto the EH stack.
for (size_t I = OldLifetimeExtendedSize,
E = LifetimeExtendedCleanupStack.size(); I != E; /**/) {
// Alignment should be guaranteed by the vptrs in the individual cleanups.
@@ -409,17 +414,6 @@ CodeGenFunction::MoveDeferedCleanups(siz
LifetimeExtendedCleanupStack.resize(OldLifetimeExtendedSize);
}
-/// Pops cleanup blocks until the given savepoint is reached, then add the
-/// cleanups from the given savepoint in the lifetime-extended cleanups stack.
-void
-CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old,
- size_t OldLifetimeExtendedSize) {
- PopCleanupBlocks(Old);
-
- // Move our deferred cleanups onto the EH stack.
- MoveDeferedCleanups(OldLifetimeExtendedSize);
-}
-
static llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF,
EHCleanupScope &Scope) {
assert(Scope.isNormalCleanup());
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=219470&r1=219469&r2=219470&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Oct 9 23:05:00 2014
@@ -504,10 +504,12 @@ namespace {
: Addr(addr), Size(size) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitLifetimeEnd(Size, Addr);
+ llvm::Value *castAddr = CGF.Builder.CreateBitCast(Addr, CGF.Int8PtrTy);
+ CGF.Builder.CreateCall2(CGF.CGM.getLLVMLifetimeEndFn(),
+ Size, castAddr)
+ ->setDoesNotThrow();
}
};
-
}
/// EmitAutoVarWithLifetime - Does the setup required for an automatic
@@ -826,7 +828,8 @@ static bool shouldUseMemSetPlusStoresToI
}
/// Should we use the LLVM lifetime intrinsics for the given local variable?
-static bool shouldUseLifetimeMarkers(CodeGenFunction &CGF, uint64_t Size) {
+static bool shouldUseLifetimeMarkers(CodeGenFunction &CGF, const VarDecl &D,
+ unsigned Size) {
// For now, only in optimized builds.
if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0)
return false;
@@ -838,6 +841,7 @@ static bool shouldUseLifetimeMarkers(Cod
return Size > SizeThreshold;
}
+
/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
@@ -847,27 +851,6 @@ void CodeGenFunction::EmitAutoVarDecl(co
EmitAutoVarCleanups(emission);
}
-/// Emit a lifetime.begin marker if some criteria are satisfied.
-/// \return a pointer to the temporary size Value if a marker was emitted, null
-/// otherwise
-llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
- llvm::Value *Addr) {
- if (!shouldUseLifetimeMarkers(*this, Size))
- return nullptr;
-
- llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
- llvm::Value *CastAddr = Builder.CreateBitCast(Addr, Int8PtrTy);
- Builder.CreateCall2(CGM.getLLVMLifetimeStartFn(), SizeV, CastAddr)
- ->setDoesNotThrow();
- return SizeV;
-}
-
-void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
- llvm::Value *CastAddr = Builder.CreateBitCast(Addr, Int8PtrTy);
- Builder.CreateCall2(CGM.getLLVMLifetimeEndFn(), Size, CastAddr)
- ->setDoesNotThrow();
-}
-
/// EmitAutoVarAlloca - Emit the alloca and debug information for a
/// local variable. Does not emit initialization or destruction.
CodeGenFunction::AutoVarEmission
@@ -963,8 +946,13 @@ CodeGenFunction::EmitAutoVarAlloca(const
// Emit a lifetime intrinsic if meaningful. There's no point
// in doing this if we don't have a valid insertion point (?).
uint64_t size = CGM.getDataLayout().getTypeAllocSize(LTy);
- if (HaveInsertPoint() && EmitLifetimeStart(size, Alloc)) {
- emission.SizeForLifetimeMarkers = llvm::ConstantInt::get(Int64Ty, size);
+ if (HaveInsertPoint() && shouldUseLifetimeMarkers(*this, D, size)) {
+ llvm::Value *sizeV = llvm::ConstantInt::get(Int64Ty, size);
+
+ emission.SizeForLifetimeMarkers = sizeV;
+ llvm::Value *castAddr = Builder.CreateBitCast(Alloc, Int8PtrTy);
+ Builder.CreateCall2(CGM.getLLVMLifetimeStartFn(), sizeV, castAddr)
+ ->setDoesNotThrow();
} else {
assert(!emission.useLifetimeMarkers());
}
@@ -1406,32 +1394,6 @@ void CodeGenFunction::pushLifetimeExtend
cleanupKind, addr, type, destroyer, useEHCleanupForArray);
}
-void
-CodeGenFunction::pushLifetimeEndMarker(StorageDuration SD,
- llvm::Value *ReferenceTemporary,
- llvm::Value *SizeForLifeTimeMarkers) {
- // SizeForLifeTimeMarkers is null in case no corresponding
- // @llvm.lifetime.start was emitted: there is nothing to do then.
- if (!SizeForLifeTimeMarkers)
- return;
-
- switch (SD) {
- case SD_FullExpression:
- pushFullExprCleanup<CallLifetimeEnd>(NormalAndEHCleanup, ReferenceTemporary,
- SizeForLifeTimeMarkers);
- return;
- case SD_Automatic:
- EHStack.pushCleanup<CallLifetimeEnd>(static_cast<CleanupKind>(EHCleanup),
- ReferenceTemporary,
- SizeForLifeTimeMarkers);
- pushCleanupAfterFullExpr<CallLifetimeEnd>(
- NormalAndEHCleanup, ReferenceTemporary, SizeForLifeTimeMarkers);
- return;
- default:
- llvm_unreachable("unexpected storage duration for Lifetime markers");
- }
-}
-
/// emitDestroy - Immediately perform the destruction of the given
/// object.
///
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=219470&r1=219469&r2=219470&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Oct 9 23:05:00 2014
@@ -174,10 +174,9 @@ void CodeGenFunction::EmitAnyExprToMem(c
llvm_unreachable("bad evaluation kind");
}
-static void pushTemporaryCleanup(CodeGenFunction &CGF,
- const MaterializeTemporaryExpr *M,
- const Expr *E, llvm::Value *ReferenceTemporary,
- llvm::Value *SizeForLifeTimeMarkers) {
+static void
+pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
+ const Expr *E, llvm::Value *ReferenceTemporary) {
// Objective-C++ ARC:
// If we are binding a reference to a temporary that has ownership, we
// need to perform retain/release operations on the temporary.
@@ -244,10 +243,6 @@ static void pushTemporaryCleanup(CodeGen
}
}
- // Call @llvm.lifetime.end marker for the temporary.
- CGF.pushLifetimeEndMarker(M->getStorageDuration(), ReferenceTemporary,
- SizeForLifeTimeMarkers);
-
CXXDestructorDecl *ReferenceTemporaryDtor = nullptr;
if (const RecordType *RT =
E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
@@ -302,18 +297,11 @@ static void pushTemporaryCleanup(CodeGen
static llvm::Value *
createReferenceTemporary(CodeGenFunction &CGF,
- const MaterializeTemporaryExpr *M, const Expr *Inner,
- llvm::Value *&SizeForLifeTimeMarkers) {
- SizeForLifeTimeMarkers = nullptr;
+ const MaterializeTemporaryExpr *M, const Expr *Inner) {
switch (M->getStorageDuration()) {
case SD_FullExpression:
- case SD_Automatic: {
- llvm::Value *RefTemp = CGF.CreateMemTemp(Inner->getType(), "ref.tmp");
- uint64_t TempSize = CGF.CGM.getDataLayout().getTypeStoreSize(
- CGF.ConvertTypeForMem(Inner->getType()));
- SizeForLifeTimeMarkers = CGF.EmitLifetimeStart(TempSize, RefTemp);
- return RefTemp;
- }
+ case SD_Automatic:
+ return CGF.CreateMemTemp(Inner->getType(), "ref.tmp");
case SD_Thread:
case SD_Static:
@@ -334,8 +322,7 @@ LValue CodeGenFunction::EmitMaterializeT
M->getType().getObjCLifetime() != Qualifiers::OCL_None &&
M->getType().getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
// FIXME: Fold this into the general case below.
- llvm::Value *ObjectSize;
- llvm::Value *Object = createReferenceTemporary(*this, M, E, ObjectSize);
+ llvm::Value *Object = createReferenceTemporary(*this, M, E);
LValue RefTempDst = MakeAddrLValue(Object, M->getType());
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
@@ -347,7 +334,7 @@ LValue CodeGenFunction::EmitMaterializeT
EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false);
- pushTemporaryCleanup(*this, M, E, Object, ObjectSize);
+ pushTemporaryCleanup(*this, M, E, Object);
return RefTempDst;
}
@@ -365,10 +352,8 @@ LValue CodeGenFunction::EmitMaterializeT
}
}
- // Create and initialize the reference temporary and get the temporary size
- llvm::Value *ObjectSize;
- llvm::Value *Object = createReferenceTemporary(*this, M, E, ObjectSize);
-
+ // Create and initialize the reference temporary.
+ llvm::Value *Object = createReferenceTemporary(*this, M, E);
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
// If the temporary is a global and has a constant initializer, we may
// have already initialized it.
@@ -379,8 +364,7 @@ LValue CodeGenFunction::EmitMaterializeT
} else {
EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
}
-
- pushTemporaryCleanup(*this, M, E, Object, ObjectSize);
+ pushTemporaryCleanup(*this, M, E, Object);
// Perform derived-to-base casts and/or field accesses, to get from the
// temporary object we created (and, potentially, for which we extended
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=219470&r1=219469&r2=219470&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Oct 9 23:05:00 2014
@@ -229,11 +229,6 @@ void CodeGenFunction::FinishFunction(Sou
DI->EmitLocation(Builder, EndLoc);
}
- // Some top level lifetime extended variables may still need
- // to have their cleanups called.
- if (!LifetimeExtendedCleanupStack.empty())
- MoveDeferedCleanups(0);
-
// Pop any cleanups that might have been associated with the
// parameters. Do this in whatever block we're currently in; it's
// important to do this before we enter the return block or return
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=219470&r1=219469&r2=219470&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Oct 9 23:05:00 2014
@@ -445,23 +445,6 @@ public:
new (Buffer + sizeof(Header)) T(a0, a1, a2, a3);
}
- /// \brief Queue a cleanup to be pushed after finishing the current
- /// full-expression.
- template <class T, class A0, class A1>
- void pushCleanupAfterFullExpr(CleanupKind Kind, A0 a0, A1 a1) {
- assert(!isInConditionalBranch() && "can't defer conditional cleanup");
-
- LifetimeExtendedCleanupHeader Header = { sizeof(T), Kind };
-
- size_t OldSize = LifetimeExtendedCleanupStack.size();
- LifetimeExtendedCleanupStack.resize(
- LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size);
-
- char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
- new (Buffer) LifetimeExtendedCleanupHeader(Header);
- new (Buffer + sizeof(Header)) T(a0, a1);
- }
-
/// Set up the last cleaup that was pushed as a conditional
/// full-expression cleanup.
void initFullExprCleanup();
@@ -614,10 +597,6 @@ public:
void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize,
size_t OldLifetimeExtendedStackSize);
- /// \brief Moves deferred cleanups from lifetime-extended variables from
- /// the given position on top of the stack
- void MoveDeferedCleanups(size_t OldLifetimeExtendedSize);
-
void ResolveBranchFixups(llvm::BasicBlock *Target);
/// The given basic block lies in the current EH scope, but may be a
@@ -1134,9 +1113,6 @@ public:
void pushLifetimeExtendedDestroy(CleanupKind kind, llvm::Value *addr,
QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
- void pushLifetimeEndMarker(StorageDuration SD,
- llvm::Value *ReferenceTemporary,
- llvm::Value *SizeForLifeTimeMarkers);
void pushStackRestore(CleanupKind kind, llvm::Value *SPMem);
void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
@@ -1740,9 +1716,6 @@ public:
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
llvm::Value *Ptr);
- llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);
- void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
-
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
Removed: cfe/trunk/test/CodeGenCXX/unnamed-object-lifetime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/unnamed-object-lifetime.cpp?rev=219469&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/unnamed-object-lifetime.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/unnamed-object-lifetime.cpp (removed)
@@ -1,290 +0,0 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
-
-// Test lifetime marker generation for unnamed temporary objects.
-
-struct X {
- X();
- ~X();
- char t[33]; // make the class big enough so that lifetime markers get inserted
-};
-
-extern void useX(const X &);
-
-// CHECK-LABEL: define void @_Z6simplev
-// CHECK-EH-LABEL: define void @_Z6simplev
-void simple() {
- // CHECK: [[ALLOCA:%.*]] = alloca %struct.X
- // CHECK: [[PTR:%.*]] = getelementptr inbounds %struct.X* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[PTR]])
- // CHECK-NEXT: call void @_ZN1XC1Ev
- // CHECK-NEXT: call void @_Z4useXRK1X
- // CHECK-NEXT: call void @_ZN1XD1Ev
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 33, i8* [[PTR]])
- //
- // CHECK-EH: [[ALLOCA:%.*]] = alloca %struct.X
- // CHECK-EH: [[PTR:%.*]] = getelementptr inbounds %struct.X* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[PTR]])
- // CHECK-EH-NEXT: call void @_ZN1XC1Ev
- // CHECK-EH: invoke void @_Z4useXRK1X
- // CHECK-EH: invoke void @_ZN1XD1Ev
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[PTR]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[PTR]])
- useX(X());
-}
-
-// Same as above, but with a sub-scope
-// CHECK-LABEL: define void @_Z6simpleb
-// CHECK-EH-LABEL: define void @_Z6simpleb
-void simple(bool b) {
- // CHECK: [[ALLOCA:%.*]] = alloca %struct.X
- // CHECK: br i1 %b
- // CHECK: [[PTR:%.*]] = getelementptr inbounds %struct.X* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[PTR]])
- // CHECK-NEXT: call void @_ZN1XC1Ev
- // CHECK-NEXT: call void @_Z4useXRK1X
- // CHECK-NEXT: call void @_ZN1XD1Ev
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 33, i8* [[PTR]])
- //
- // CHECK-EH: [[ALLOCA:%.*]] = alloca %struct.X
- // CHECK-EH: br i1 %b
- // CHECK-EH: [[PTR:%.*]] = getelementptr inbounds %struct.X* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[PTR]])
- // CHECK-EH-NEXT: call void @_ZN1XC1Ev
- // CHECK-EH: invoke void @_Z4useXRK1X
- // CHECK-EH: invoke void @_ZN1XD1Ev
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[PTR]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[PTR]])
- if (b) {
- useX(X());
- }
-}
-
-struct Y {
- Y(){}
- ~Y(){}
- char t[34]; // make the class big enough so that lifetime markers get inserted
-};
-
-extern void useY(const Y &);
-
-// Check lifetime markers are inserted, despite Y's trivial constructor & destructor
-// CHECK-LABEL: define void @_Z7trivialv
-// CHECK-EH-LABEL: define void @_Z7trivialv
-void trivial() {
- // CHECK: [[ALLOCA:%.*]] = alloca %struct.Y
- // CHECK: [[PTR:%.*]] = getelementptr inbounds %struct.Y* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 34, i8* [[PTR]])
- // CHECK-NEXT: call void @_Z4useYRK1Y
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 34, i8* [[PTR]])
- //
- // CHECK-EH: [[ALLOCA:%.*]] = alloca %struct.Y
- // CHECK-EH: [[PTR:%.*]] = getelementptr inbounds %struct.Y* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 34, i8* [[PTR]])
- // CHECK-EH-NEXT: invoke void @_Z4useYRK1Y
- // CHECK-EH: call void @llvm.lifetime.end(i64 34, i8* [[PTR]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 34, i8* [[PTR]])
- useY(Y());
-}
-
-// Same as above, but with a sub-scope
-// CHECK-LABEL: define void @_Z7trivialb
-// CHECK-EH-LABEL: define void @_Z7trivialb
-void trivial(bool b) {
- // CHECK: [[ALLOCA:%.*]] = alloca %struct.Y
- // CHECK: br i1 %b
- // CHECK: [[PTR:%.*]] = getelementptr inbounds %struct.Y* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 34, i8* [[PTR]])
- // CHECK-NEXT: call void @_Z4useYRK1Y
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 34, i8* [[PTR]])
- //
- // CHECK-EH: [[ALLOCA:%.*]] = alloca %struct.Y
- // CHECK-EH: br i1 %b
- // CHECK-EH: [[PTR:%.*]] = getelementptr inbounds %struct.Y* [[ALLOCA]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 34, i8* [[PTR]])
- // CHECK-EH-NEXT: invoke void @_Z4useYRK1Y
- // CHECK-EH: call void @llvm.lifetime.end(i64 34, i8* [[PTR]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 34, i8* [[PTR]])
- if (b) {
- useY(Y());
- }
-}
-
-struct Z {
- Z();
- ~Z();
- char t;
-};
-
-extern void useZ(const Z &);
-
-// Check lifetime markers are not inserted if the unnamed object is too small
-// CHECK-LABEL: define void @_Z8tooSmallv
-// CHECK-EH-LABEL: define void @_Z8tooSmallv
-void tooSmall() {
- // CHECK-NOT: call void @llvm.lifetime.start
- // CHECK: call void @_Z4useZRK1Z
- // CHECK-NOT: call void @llvm.lifetime.end
- // CHECK: ret
- //
- // CHECK-EH-NOT: call void @llvm.lifetime.start
- // CHECK-EH: invoke void @_Z4useZRK1Z
- // CHECK-EH-NOT: call void @llvm.lifetime.end
- // CHECK-EH: ret
- useZ(Z());
-}
-
-// Check the lifetime are inserted at the right place in their respective scope
-// CHECK-LABEL: define void @_Z6scopesv
-// CHECK-EH-LABEL: define void @_Z6scopesv
-void scopes() {
- // CHECK: alloca %struct
- // CHECK: alloca %struct
- // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[X:%.*]])
- // CHECK: call void @llvm.lifetime.end(i64 33, i8* [[X]])
- // CHECK: call void @llvm.lifetime.start(i64 34, i8* [[Y:%.*]])
- // CHECK: call void @llvm.lifetime.end(i64 34, i8* [[Y]])
- //
- // CHECK-EH: alloca %struct
- // CHECK-EH: alloca %struct
- // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[X:%.*]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[X]])
- // CHECK-EH: call void @llvm.lifetime.start(i64 34, i8* [[Y:%.*]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 34, i8* [[Y]])
- useX(X());
- useY(Y());
-}
-
-struct L {
- L(int);
- ~L();
- char t[33];
-};
-
-// Check the lifetime-extended case, with a non trivial destructor
-// and a top level scope
-// CHECK-LABEL: define void @_Z16extendedLifetimev
-// CHECK-EH-LABEL: define void @_Z16extendedLifetimev
-void extendedLifetime() {
- extern void useL(const L&);
-
- // CHECK: [[A:%.*]] = alloca %struct.L
- // CHECK: [[P:%.*]] = getelementptr inbounds %struct.L* [[A]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK: call void @_ZN1LC1Ei(%struct.L* [[A]], i32 2)
- // CHECK-NOT: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK: call void @_Z4useLRK1L(%struct.L* dereferenceable(33) [[A]])
- // CHECK: call void @_ZN1LD1Ev(%struct.L* [[A]])
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- //
- // CHECK-EH: [[A:%.*]] = alloca %struct.L
- // CHECK-EH: [[P:%.*]] = getelementptr inbounds %struct.L* [[A]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK-EH: call void @_ZN1LC1Ei(%struct.L* [[A]], i32 2)
- // CHECK-EH-NOT: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-EH: invoke void @_Z4useLRK1L(%struct.L* dereferenceable(33) [[A]])
- // CHECK-EH: invoke void @_ZN1LD1Ev(%struct.L* [[A]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-EH: invoke void @_ZN1LD1Ev(%struct.L* [[A]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- const L &l = 2;
- useL(l);
-}
-
-// Check the lifetime-extended case, with a non trivial destructor in a
-// sub-scope
-// CHECK-LABEL: define void @_Z16extendedLifetimeb
-// CHECK-EH-LABEL: define void @_Z16extendedLifetimeb
-void extendedLifetime(bool b) {
- extern void useL(const L&);
-
- // CHECK: [[A:%.*]] = alloca %struct.L
- // CHECK: br i1 %b
- // CHECK: [[P:%.*]] = getelementptr inbounds %struct.L* [[A]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK: call void @_ZN1LC1Ei(%struct.L* [[A]], i32 2)
- // CHECK-NOT: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK: call void @_Z4useLRK1L(%struct.L* dereferenceable(33) [[A]])
- // CHECK: call void @_ZN1LD1Ev(%struct.L* [[A]])
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- //
- // CHECK-EH: [[A:%.*]] = alloca %struct.L
- // CHECK-EH: br i1 %b
- // CHECK-EH: [[P:%.*]] = getelementptr inbounds %struct.L* [[A]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK-EH: call void @_ZN1LC1Ei(%struct.L* [[A]], i32 2)
- // CHECK-EH-NOT: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-EH: invoke void @_Z4useLRK1L(%struct.L* dereferenceable(33) [[A]])
- // CHECK-EH: invoke void @_ZN1LD1Ev(%struct.L* [[A]])
- // CHECK-EH: invoke void @_ZN1LD1Ev(%struct.L* [[A]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- if (b) {
- const L &l = 2;
- useL(l);
- }
-}
-
-struct T {
- T();
- T(int);
- char t[33];
-};
-
-// Check the lifetime-extended case, with a trivial destructor,
-// in a sub-scope
-// CHECK-LABEL: define void @_Z37extendedLifetimeWithTrivialDestructorb
-// CHECK-EH-LABEL: define void @_Z37extendedLifetimeWithTrivialDestructorb
-void extendedLifetimeWithTrivialDestructor(bool b) {
- extern void useT(const T &);
-
- // CHECK: [[A:%.*]] = alloca %struct.T
- // CHECK: br i1 %b
- // CHECK: [[P:%.*]] = getelementptr inbounds %struct.T* [[A]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK: call void @_ZN1TC1Ei(%struct.T* [[A]], i32 2)
- // CHECK: call void @_Z4useTRK1T(%struct.T* dereferenceable(33) [[A]])
- // CHECK: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK: br label
- //
- // CHECK-EH: [[A:%.*]] = alloca %struct.T
- // CHECK-EH: br i1 %b
- // CHECK-EH: [[P:%.*]] = getelementptr inbounds %struct.T* [[A]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK-EH: call void @_ZN1TC1Ei(%struct.T* [[A]], i32 2)
- // CHECK-EH: invoke void @_Z4useTRK1T(%struct.T* dereferenceable(33) [[A]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-EH-NEXT: resume
- if (b) {
- const T &t = 2;
- useT(t);
- }
-}
-
-// Check the lifetime-extended case, with a trivial destructor and a top level
-// scope
-// CHECK-LABEL: define void @_Z37extendedLifetimeWithTrivialDestructorv
-// CHECK-EH-LABEL: define void @_Z37extendedLifetimeWithTrivialDestructorv
-void extendedLifetimeWithTrivialDestructor() {
- extern void useT(const T &);
-
- // CHECK: [[A:%.*]] = alloca %struct.T
- // CHECK: [[P:%.*]] = getelementptr inbounds %struct.T* [[A]], i32 0, i32 0, i32 0
- // CHECK: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK: call void @_ZN1TC1Ei(%struct.T* [[A]], i32 3)
- // CHECK: call void @_Z4useTRK1T(%struct.T* dereferenceable(33) [[A]])
- // CHECK: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-NEXT: ret
- //
- // CHECK-EH: [[A:%.*]] = alloca %struct.T
- // CHECK-EH: [[P:%.*]] = getelementptr inbounds %struct.T* [[A]], i32 0, i32 0, i32 0
- // CHECK-EH: call void @llvm.lifetime.start(i64 33, i8* [[P]])
- // CHECK-EH: call void @_ZN1TC1Ei(%struct.T* [[A]], i32 3)
- // CHECK-EH: invoke void @_Z4useTRK1T(%struct.T* dereferenceable(33) [[A]])
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-EH-NEXT: ret
- // CHECK-EH: call void @llvm.lifetime.end(i64 33, i8* [[P]])
- // CHECK-EH-NEXT: resume
- const T &t = 3;
- useT(t);
-}
More information about the cfe-commits
mailing list