about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-26 03:31:22 +0000
committerbors <bors@rust-lang.org>2014-07-26 03:31:22 +0000
commit34a6a8fc59343fca718a4d7d908012d1fdc83a80 (patch)
tree303b7c9087c10d21c79a1f2c8ce9093cc533fc33
parentcf1381c1d000a24f95be7d53c4318c18c2daddbb (diff)
parentb13cad3a9cef1d1fbc97434d9f3081788548e811 (diff)
auto merge of #15975 : dotdash/rust/unwind_lifetimes, r=pcwalton
Currently we don't emit lifetime end markers when translating the
unwinding code. I omitted that when I added the support for lifetime
intrinsics, because I initially made the mistake of just returning true
in clean_on_unwind(). That caused almost all calls to be translated as
invokes, leading to quite awful results.

To correctly emit the lifetime end markers, we must differentiate
between cleanup that requires unwinding and such cleanup that just wants
to emit code during unwinding.
-rw-r--r--src/librustc/middle/trans/cleanup.rs29
1 files changed, 21 insertions, 8 deletions
diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs
index c14429b2086..cf2410f6571 100644
--- a/src/librustc/middle/trans/cleanup.rs
+++ b/src/librustc/middle/trans/cleanup.rs
@@ -68,6 +68,7 @@ pub struct CachedEarlyExit {
 }
 
 pub trait Cleanup {
+    fn must_unwind(&self) -> bool;
     fn clean_on_unwind(&self) -> bool;
     fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a>;
 }
@@ -252,7 +253,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
         if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = box DropValue {
             is_immediate: false,
-            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
+            must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
             val: val,
             ty: ty,
             zero: false
@@ -278,7 +279,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
         if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = box DropValue {
             is_immediate: false,
-            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
+            must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
             val: val,
             ty: ty,
             zero: true
@@ -304,7 +305,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
         if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = box DropValue {
             is_immediate: true,
-            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
+            must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
             val: val,
             ty: ty,
             zero: false
@@ -793,10 +794,10 @@ impl<'a> CleanupScope<'a> {
     }
 
     fn needs_invoke(&self) -> bool {
-        /*! True if this scope has cleanups for use during unwinding */
+        /*! True if this scope has cleanups that need unwinding */
 
         self.cached_landing_pad.is_some() ||
-            self.cleanups.iter().any(|c| c.clean_on_unwind())
+            self.cleanups.iter().any(|c| c.must_unwind())
     }
 
     fn block_name(&self, prefix: &str) -> String {
@@ -864,15 +865,19 @@ impl EarlyExitLabel {
 
 pub struct DropValue {
     is_immediate: bool,
-    on_unwind: bool,
+    must_unwind: bool,
     val: ValueRef,
     ty: ty::t,
     zero: bool
 }
 
 impl Cleanup for DropValue {
+    fn must_unwind(&self) -> bool {
+        self.must_unwind
+    }
+
     fn clean_on_unwind(&self) -> bool {
-        self.on_unwind
+        self.must_unwind
     }
 
     fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
@@ -900,6 +905,10 @@ pub struct FreeValue {
 }
 
 impl Cleanup for FreeValue {
+    fn must_unwind(&self) -> bool {
+        true
+    }
+
     fn clean_on_unwind(&self) -> bool {
         true
     }
@@ -921,10 +930,14 @@ pub struct LifetimeEnd {
 }
 
 impl Cleanup for LifetimeEnd {
-    fn clean_on_unwind(&self) -> bool {
+    fn must_unwind(&self) -> bool {
         false
     }
 
+    fn clean_on_unwind(&self) -> bool {
+        true
+    }
+
     fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
         base::call_lifetime_end(bcx, self.ptr);
         bcx