summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2016-04-01 22:58:55 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2016-04-01 22:58:55 +0000
commit8af7bb28aa225fe30e0a682325b5b9f4df74d6fe (patch)
tree2c57e78d83e44e464a746ae2151cde903978202d /clang
parent58a15d5a235c57aafdc881250c25d8ce37a0f47e (diff)
downloadbcm5719-llvm-8af7bb28aa225fe30e0a682325b5b9f4df74d6fe.tar.gz
bcm5719-llvm-8af7bb28aa225fe30e0a682325b5b9f4df74d6fe.zip
[CodeGen] Emit lifetime.end intrinsic after objects are destructed in
landing pads. Previously, lifetime.end intrinsics were inserted only on normal control flows. This prevented StackColoring from merging stack slots for objects that were destroyed on the exception handling control flow since it couldn't tell their lifetime ranges were disjoint. This patch fixes code-gen to emit the intrinsic on both control flows. rdar://problem/22181976 Differential Revision: http://reviews.llvm.org/D18196 llvm-svn: 265197
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/CGCleanup.cpp14
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp2
-rw-r--r--clang/lib/CodeGen/EHScopeStack.h4
-rw-r--r--clang/test/CodeGenCXX/destructors.cpp64
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp34
5 files changed, 114 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 2678b33f392..95333d0ddac 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -157,6 +157,20 @@ bool EHScopeStack::containsOnlyLifetimeMarkers(
return true;
}
+bool EHScopeStack::requiresLandingPad() const {
+ for (stable_iterator si = getInnermostEHScope(); si != stable_end(); ) {
+ // Skip lifetime markers.
+ if (auto *cleanup = dyn_cast<EHCleanupScope>(&*find(si)))
+ if (cleanup->isLifetimeMarker()) {
+ si = cleanup->getEnclosingEHScope();
+ continue;
+ }
+ return true;
+ }
+
+ return false;
+}
+
EHScopeStack::stable_iterator
EHScopeStack::getInnermostActiveNormalCleanup() const {
for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end();
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index e0c297508fa..c39b980ef2c 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1388,7 +1388,7 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
// Make sure we call @llvm.lifetime.end. This needs to happen
// *last*, so the cleanup needs to be pushed *first*.
if (emission.useLifetimeMarkers()) {
- EHStack.pushCleanup<CallLifetimeEnd>(NormalCleanup,
+ EHStack.pushCleanup<CallLifetimeEnd>(NormalAndEHCleanup,
emission.getAllocatedAddress(),
emission.getSizeForLifetimeMarkers());
EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index 85cd1543e5b..8352c75d64f 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -341,9 +341,7 @@ public:
/// Determines whether the exception-scopes stack is empty.
bool empty() const { return StartOfData == EndOfBuffer; }
- bool requiresLandingPad() const {
- return InnermostEHScope != stable_end();
- }
+ bool requiresLandingPad() const;
/// Determines whether there are any normal cleanups on the stack.
bool hasNormalCleanups() const {
diff --git a/clang/test/CodeGenCXX/destructors.cpp b/clang/test/CodeGenCXX/destructors.cpp
index 529603142d3..d6aabee58b9 100644
--- a/clang/test/CodeGenCXX/destructors.cpp
+++ b/clang/test/CodeGenCXX/destructors.cpp
@@ -4,6 +4,9 @@
// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s
// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s
// RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns -std=c++11 > %t2
+// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s
+// REQUIRES: asserts
struct A {
int a;
@@ -428,3 +431,64 @@ namespace test10 {
return true;
}
}
+
+#if __cplusplus >= 201103L
+namespace test11 {
+
+// Check that lifetime.end is emitted in the landing pad.
+
+// CHECK6-LABEL: define void @_ZN6test1115testLifetimeEndEi(
+// CHECK6: entry:
+// CHECK6: [[T1:%[a-z0-9]+]] = alloca %"struct.test11::S1"
+// CHECK6: [[T2:%[a-z0-9]+]] = alloca %"struct.test11::S1"
+// CHECK6: [[T3:%[a-z0-9]+]] = alloca %"struct.test11::S1"
+
+// CHECK6: {{^}}invoke.cont
+// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]])
+// CHECK6: [[BC1:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8*
+// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC1]])
+// CHECK6: {{^}}lpad
+// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]])
+// CHECK6: [[BC2:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8*
+// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC2]])
+
+// CHECK6: {{^}}invoke.cont
+// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]])
+// CHECK6: [[BC3:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8*
+// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC3]])
+// CHECK6: {{^}}lpad
+// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]])
+// CHECK6: [[BC4:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8*
+// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC4]])
+
+// CHECK6: {{^}}invoke.cont
+// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]])
+// CHECK6: [[BC5:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8*
+// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC5]])
+// CHECK6: {{^}}lpad
+// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]])
+// CHECK6: [[BC6:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8*
+// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC6]])
+
+ struct S1 {
+ ~S1();
+ int a[8];
+ };
+
+ void func1(S1 &) noexcept(false);
+
+ void testLifetimeEnd(int n) {
+ if (n < 10) {
+ S1 t1;
+ func1(t1);
+ } else if (n < 100) {
+ S1 t2;
+ func1(t2);
+ } else if (n < 1000) {
+ S1 t3;
+ func1(t3);
+ }
+ }
+
+}
+#endif
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
index bf05c693ec0..3afee1c1f12 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-LIFETIME %s
struct A {
A();
@@ -206,3 +207,36 @@ void f() {
// WIN32: cleanuppad
// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
// WIN32: cleanupret
+
+namespace lifetime_marker {
+struct C {
+ ~C();
+};
+void g();
+void f() {
+ C c;
+ g();
+}
+
+// WIN32-LIFETIME-LABEL: define void @"\01?f@lifetime_marker@@YAXXZ"()
+// WIN32-LIFETIME: %[[c:.*]] = alloca %"struct.lifetime_marker::C"
+// WIN32-LIFETIME: %[[bc0:.*]] = bitcast %"struct.lifetime_marker::C"* %c to i8*
+// WIN32-LIFETIME: call void @llvm.lifetime.start(i64 1, i8* %[[bc0]])
+// WIN32-LIFETIME: invoke void @"\01?g@lifetime_marker@@YAXXZ"()
+// WIN32-LIFETIME-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad0:[^ ]*]]
+//
+// WIN32-LIFETIME: [[cont]]:
+// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
+// WIN32-LIFETIME: %[[bc1:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8*
+// WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc1]])
+//
+// WIN32-LIFETIME: [[lpad0]]:
+// WIN32-LIFETIME-NEXT: cleanuppad
+// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}})
+// WIN32-LIFETIME: cleanupret {{.*}} unwind label %[[lpad1:[^ ]*]]
+//
+// WIN32-LIFETIME: [[lpad1]]:
+// WIN32-LIFETIME-NEXT: cleanuppad
+// WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8*
+// WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc2]])
+}
OpenPOWER on IntegriCloud