|
19 | 19 | //! completing evaluation successfully without panic). |
20 | 20 |
|
21 | 21 | use llvm::{BasicBlockRef, ValueRef}; |
22 | | -use base::{self, Lifetime}; |
23 | | -use common; |
| 22 | +use base; |
24 | 23 | use common::{BlockAndBuilder, FunctionContext, Funclet}; |
25 | 24 | use glue; |
26 | 25 | use type_::Type; |
@@ -55,90 +54,41 @@ impl<'tcx> DropValue<'tcx> { |
55 | 54 | /// This should only be called once per function, as it creates an alloca for the landingpad. |
56 | 55 | fn get_landing_pad<'a>(&self, fcx: &FunctionContext<'a, 'tcx>) -> BasicBlockRef { |
57 | 56 | debug!("get_landing_pad"); |
| 57 | + let bcx = fcx.build_new_block("cleanup_unwind"); |
| 58 | + let llpersonality = bcx.ccx.eh_personality(); |
| 59 | + bcx.set_personality_fn(llpersonality); |
58 | 60 |
|
59 | | - let mut pad_bcx = fcx.build_new_block("unwind_custom_"); |
60 | | - |
61 | | - let llpersonality = pad_bcx.ccx.eh_personality(); |
62 | | - |
63 | | - let resume_bcx = fcx.build_new_block("resume"); |
64 | | - let val = if base::wants_msvc_seh(fcx.ccx.sess()) { |
65 | | - // A cleanup pad requires a personality function to be specified, so |
66 | | - // we do that here explicitly (happens implicitly below through |
67 | | - // creation of the landingpad instruction). We then create a |
68 | | - // cleanuppad instruction which has no filters to run cleanup on all |
69 | | - // exceptions. |
70 | | - pad_bcx.set_personality_fn(llpersonality); |
71 | | - let llretval = pad_bcx.cleanup_pad(None, &[]); |
72 | | - resume_bcx.cleanup_ret(resume_bcx.cleanup_pad(None, &[]), None); |
73 | | - UnwindKind::CleanupPad(llretval) |
| 61 | + if base::wants_msvc_seh(fcx.ccx.sess()) { |
| 62 | + // Insert cleanup instructions into the cleanup block |
| 63 | + let funclet = Some(Funclet::new(bcx.cleanup_pad(None, &[]))); |
| 64 | + self.trans(funclet.as_ref(), &bcx); |
| 65 | + |
| 66 | + bcx.cleanup_ret(bcx.cleanup_pad(None, &[]), None); |
74 | 67 | } else { |
75 | 68 | // The landing pad return type (the type being propagated). Not sure |
76 | 69 | // what this represents but it's determined by the personality |
77 | 70 | // function and this is what the EH proposal example uses. |
78 | 71 | let llretty = Type::struct_(fcx.ccx, &[Type::i8p(fcx.ccx), Type::i32(fcx.ccx)], false); |
79 | 72 |
|
80 | 73 | // The only landing pad clause will be 'cleanup' |
81 | | - let llretval = pad_bcx.landing_pad(llretty, llpersonality, 1, pad_bcx.fcx().llfn); |
| 74 | + let llretval = bcx.landing_pad(llretty, llpersonality, 1, bcx.fcx().llfn); |
82 | 75 |
|
83 | 76 | // The landing pad block is a cleanup |
84 | | - pad_bcx.set_cleanup(llretval); |
85 | | - |
86 | | - let addr = pad_bcx.fcx().alloca(common::val_ty(llretval), ""); |
87 | | - Lifetime::Start.call(&pad_bcx, addr); |
88 | | - pad_bcx.store(llretval, addr); |
89 | | - let lp = resume_bcx.load(addr); |
90 | | - Lifetime::End.call(&resume_bcx, addr); |
91 | | - if !resume_bcx.sess().target.target.options.custom_unwind_resume { |
92 | | - resume_bcx.resume(lp); |
93 | | - } else { |
94 | | - let exc_ptr = resume_bcx.extract_value(lp, 0); |
95 | | - resume_bcx.call(fcx.eh_unwind_resume().reify(fcx.ccx), &[exc_ptr], None); |
96 | | - resume_bcx.unreachable(); |
97 | | - } |
98 | | - UnwindKind::LandingPad |
99 | | - }; |
| 77 | + bcx.set_cleanup(llretval); |
100 | 78 |
|
101 | | - let mut cleanup = fcx.build_new_block("clean_custom_"); |
| 79 | + // Insert cleanup instructions into the cleanup block |
| 80 | + self.trans(None, &bcx); |
102 | 81 |
|
103 | | - // Insert cleanup instructions into the cleanup block |
104 | | - let funclet = match val { |
105 | | - UnwindKind::CleanupPad(_) => Some(Funclet::new(cleanup.cleanup_pad(None, &[]))), |
106 | | - UnwindKind::LandingPad => None, |
107 | | - }; |
108 | | - self.trans(funclet.as_ref(), &cleanup); |
109 | | - |
110 | | - // Insert instruction into cleanup block to branch to the exit |
111 | | - val.branch(&mut cleanup, resume_bcx.llbb()); |
112 | | - |
113 | | - // Branch into the cleanup block |
114 | | - val.branch(&mut pad_bcx, cleanup.llbb()); |
115 | | - |
116 | | - pad_bcx.llbb() |
117 | | - } |
118 | | -} |
119 | | - |
120 | | -#[derive(Copy, Clone, Debug)] |
121 | | -enum UnwindKind { |
122 | | - LandingPad, |
123 | | - CleanupPad(ValueRef), |
124 | | -} |
125 | | - |
126 | | -impl UnwindKind { |
127 | | - /// Generates a branch going from `bcx` to `to_llbb` where `self` is |
128 | | - /// the exit label attached to the start of `bcx`. |
129 | | - /// |
130 | | - /// Transitions from an exit label to other exit labels depend on the type |
131 | | - /// of label. For example with MSVC exceptions unwind exit labels will use |
132 | | - /// the `cleanupret` instruction instead of the `br` instruction. |
133 | | - fn branch(&self, bcx: &BlockAndBuilder, to_llbb: BasicBlockRef) { |
134 | | - match *self { |
135 | | - UnwindKind::CleanupPad(pad) => { |
136 | | - bcx.cleanup_ret(pad, Some(to_llbb)); |
137 | | - } |
138 | | - UnwindKind::LandingPad => { |
139 | | - bcx.br(to_llbb); |
| 82 | + if !bcx.sess().target.target.options.custom_unwind_resume { |
| 83 | + bcx.resume(llretval); |
| 84 | + } else { |
| 85 | + let exc_ptr = bcx.extract_value(llretval, 0); |
| 86 | + bcx.call(fcx.eh_unwind_resume().reify(fcx.ccx), &[exc_ptr], None); |
| 87 | + bcx.unreachable(); |
140 | 88 | } |
141 | 89 | } |
| 90 | + |
| 91 | + bcx.llbb() |
142 | 92 | } |
143 | 93 | } |
144 | 94 |
|
|
0 commit comments