diff options
| author | bors <bors@rust-lang.org> | 2014-07-26 03:31:22 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-07-26 03:31:22 +0000 |
| commit | 34a6a8fc59343fca718a4d7d908012d1fdc83a80 (patch) | |
| tree | 303b7c9087c10d21c79a1f2c8ce9093cc533fc33 | |
| parent | cf1381c1d000a24f95be7d53c4318c18c2daddbb (diff) | |
| parent | b13cad3a9cef1d1fbc97434d9f3081788548e811 (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.rs | 29 |
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 |
