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)]
}
}
-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> {
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
},
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();
- }
}