diff options
| author | Mark Simulacrum <mark.simulacrum@gmail.com> | 2016-12-19 18:19:19 -0700 |
|---|---|---|
| committer | Mark Simulacrum <mark.simulacrum@gmail.com> | 2016-12-20 20:04:43 -0700 |
| commit | 0d5a8ad11029d484e48821326bb8b193c519aa49 (patch) | |
| tree | 1d8fba2304f1a19d00adf83b00b1a27f7ce67b55 | |
| parent | 6f368e6da045b0ac179ac3fb02423c4d7db3c62c (diff) | |
| download | rust-0d5a8ad11029d484e48821326bb8b193c519aa49.tar.gz rust-0d5a8ad11029d484e48821326bb8b193c519aa49.zip | |
Move get_landing_pad onto DropVal.
| -rw-r--r-- | src/librustc_trans/cleanup.rs | 149 |
1 files changed, 69 insertions, 80 deletions
diff --git a/src/librustc_trans/cleanup.rs b/src/librustc_trans/cleanup.rs index 67dc347f21f..6dd8d8b2247 100644 --- a/src/librustc_trans/cleanup.rs +++ b/src/librustc_trans/cleanup.rs @@ -46,6 +46,74 @@ impl<'tcx> DropValue<'tcx> { fn trans<'a>(&self, funclet: Option<&'a Funclet>, bcx: &BlockAndBuilder<'a, 'tcx>) { glue::call_drop_glue(bcx, self.val, self.ty, self.skip_dtor, funclet) } + + /// Creates a landing pad for the top scope. The landing pad will perform all cleanups necessary + /// for an unwind and then `resume` to continue error propagation: + /// + /// landing_pad -> ... cleanups ... -> [resume] + /// + /// This should only be called once per function, as it creates an alloca for the landingpad. + fn get_landing_pad<'a>(&self, fcx: &FunctionContext<'a, 'tcx>) -> BasicBlockRef { + debug!("get_landing_pad"); + + let mut pad_bcx = fcx.build_new_block("unwind_custom_"); + + let llpersonality = pad_bcx.fcx().eh_personality(); + + let resume_bcx = fcx.build_new_block("resume"); + let val = if base::wants_msvc_seh(fcx.ccx.sess()) { + // A cleanup pad requires a personality function to be specified, so + // we do that here explicitly (happens implicitly below through + // creation of the landingpad instruction). We then create a + // cleanuppad instruction which has no filters to run cleanup on all + // exceptions. + pad_bcx.set_personality_fn(llpersonality); + let llretval = pad_bcx.cleanup_pad(None, &[]); + resume_bcx.cleanup_ret(resume_bcx.cleanup_pad(None, &[]), None); + UnwindKind::CleanupPad(llretval) + } else { + // The landing pad return type (the type being propagated). Not sure + // what this represents but it's determined by the personality + // function and this is what the EH proposal example uses. + let llretty = Type::struct_(fcx.ccx, &[Type::i8p(fcx.ccx), Type::i32(fcx.ccx)], false); + + // The only landing pad clause will be 'cleanup' + let llretval = pad_bcx.landing_pad(llretty, llpersonality, 1, pad_bcx.fcx().llfn); + + // The landing pad block is a cleanup + pad_bcx.set_cleanup(llretval); + + let addr = pad_bcx.fcx().alloca(common::val_ty(llretval), ""); + Lifetime::Start.call(&pad_bcx, addr); + pad_bcx.store(llretval, addr); + let lp = resume_bcx.load(addr); + Lifetime::End.call(&resume_bcx, addr); + if !resume_bcx.sess().target.target.options.custom_unwind_resume { + resume_bcx.resume(lp); + } else { + let exc_ptr = resume_bcx.extract_value(lp, 0); + resume_bcx.call(fcx.eh_unwind_resume().reify(fcx.ccx), &[exc_ptr], None); + } + UnwindKind::LandingPad + }; + + let mut cleanup = fcx.build_new_block("clean_custom_"); + + // Insert cleanup instructions into the cleanup block + let funclet = match val { + UnwindKind::CleanupPad(_) => Some(Funclet::new(cleanup.cleanup_pad(None, &[]))), + UnwindKind::LandingPad => None, + }; + self.trans(funclet.as_ref(), &cleanup); + + // Insert instruction into cleanup block to branch to the exit + val.branch(&mut cleanup, resume_bcx.llbb()); + + // Branch into the cleanup block + val.branch(&mut pad_bcx, cleanup.llbb()); + + pad_bcx.llbb() + } } #[derive(Copy, Clone, Debug)] @@ -73,16 +141,6 @@ impl UnwindKind { } } -impl PartialEq for UnwindKind { - fn eq(&self, label: &UnwindKind) -> bool { - match (*self, *label) { - (UnwindKind::LandingPad, UnwindKind::LandingPad) | - (UnwindKind::CleanupPad(..), UnwindKind::CleanupPad(..)) => true, - _ => false, - } - } -} - impl<'a, 'tcx> FunctionContext<'a, 'tcx> { /// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty` pub fn schedule_drop_mem(&self, val: ValueRef, ty: Ty<'tcx>) -> CleanupScope<'tcx> { @@ -126,7 +184,7 @@ impl<'tcx> CleanupScope<'tcx> { CleanupScope { cleanup: Some(drop_val), landing_pad: if !fcx.ccx.sess().no_landing_pads() { - Some(CleanupScope::get_landing_pad(fcx, &drop_val)) + Some(drop_val.get_landing_pad(fcx)) } else { None }, @@ -145,73 +203,4 @@ impl<'tcx> CleanupScope<'tcx> { cleanup.trans(None, &bcx); } } - - /// Creates a landing pad for the top scope. The landing pad will perform all cleanups necessary - /// for an unwind and then `resume` to continue error propagation: - /// - /// landing_pad -> ... cleanups ... -> [resume] - /// - /// This should only be called once per function, as it creates an alloca for the landingpad. - fn get_landing_pad<'a>(fcx: &FunctionContext<'a, 'tcx>, drop_val: &DropValue<'tcx>) - -> BasicBlockRef { - debug!("get_landing_pad"); - - let mut pad_bcx = fcx.build_new_block("unwind_custom_"); - - let llpersonality = pad_bcx.fcx().eh_personality(); - - let resume_bcx = fcx.build_new_block("resume"); - let val = if base::wants_msvc_seh(fcx.ccx.sess()) { - // A cleanup pad requires a personality function to be specified, so - // we do that here explicitly (happens implicitly below through - // creation of the landingpad instruction). We then create a - // cleanuppad instruction which has no filters to run cleanup on all - // exceptions. - pad_bcx.set_personality_fn(llpersonality); - let llretval = pad_bcx.cleanup_pad(None, &[]); - resume_bcx.cleanup_ret(resume_bcx.cleanup_pad(None, &[]), None); - UnwindKind::CleanupPad(llretval) - } else { - // The landing pad return type (the type being propagated). Not sure - // what this represents but it's determined by the personality - // function and this is what the EH proposal example uses. - let llretty = Type::struct_(fcx.ccx, &[Type::i8p(fcx.ccx), Type::i32(fcx.ccx)], false); - - // The only landing pad clause will be 'cleanup' - let llretval = pad_bcx.landing_pad(llretty, llpersonality, 1, pad_bcx.fcx().llfn); - - // The landing pad block is a cleanup - pad_bcx.set_cleanup(llretval); - - let addr = pad_bcx.fcx().alloca(common::val_ty(llretval), ""); - Lifetime::Start.call(&pad_bcx, addr); - pad_bcx.store(llretval, addr); - let lp = resume_bcx.load(addr); - Lifetime::End.call(&resume_bcx, addr); - if !resume_bcx.sess().target.target.options.custom_unwind_resume { - resume_bcx.resume(lp); - } else { - let exc_ptr = resume_bcx.extract_value(lp, 0); - resume_bcx.call(fcx.eh_unwind_resume().reify(fcx.ccx), &[exc_ptr], None); - } - UnwindKind::LandingPad - }; - - let mut cleanup = fcx.build_new_block("clean_custom_"); - - // Insert cleanup instructions into the cleanup block - let funclet = match val { - UnwindKind::CleanupPad(_) => Some(Funclet::new(cleanup.cleanup_pad(None, &[]))), - UnwindKind::LandingPad => None, - }; - drop_val.trans(funclet.as_ref(), &cleanup); - - // Insert instruction into cleanup block to branch to the exit - val.branch(&mut cleanup, resume_bcx.llbb()); - - // Branch into the cleanup block - val.branch(&mut pad_bcx, cleanup.llbb()); - - return pad_bcx.llbb(); - } } |
