88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use llvm:: BasicBlockRef ;
11+ use llvm:: { BasicBlockRef , ValueRef } ;
1212use rustc:: mir:: repr as mir;
1313use trans:: adt;
1414use trans:: base;
@@ -80,13 +80,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
8080 }
8181
8282 mir:: Terminator :: Resume => {
83- if let Some ( personalityslot) = self . llpersonalityslot {
84- let lp = build:: Load ( bcx, personalityslot) ;
85- base:: call_lifetime_end ( bcx, personalityslot) ;
86- build:: Resume ( bcx, lp) ;
87- } else {
88- panic ! ( "resume terminator without personality slot set" )
89- }
83+ let ps = self . get_personality_slot ( bcx) ;
84+ let lp = build:: Load ( bcx, ps) ;
85+ base:: call_lifetime_end ( bcx, ps) ;
86+ base:: trans_unwind_resume ( bcx, lp) ;
9087 }
9188
9289 mir:: Terminator :: Return => {
@@ -187,29 +184,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
187184 build:: Br ( target, postinvoketarget. llbb , debugloc) ;
188185 }
189186 } ,
190- // Everything else uses the regular `Call`, but we have to be careful to
191- // generate landing pads for later, even if we do not use it.
192- // FIXME: maybe just change Resume to not panic in that case?
193- ( _, k@& mir:: CallKind :: DivergingCleanup ( _) ) |
194- ( _, k@& mir:: CallKind :: Diverging ) => {
195- if let mir:: CallKind :: DivergingCleanup ( _) = * k {
196- // make a landing pad regardless, so it sets the personality slot.
197- let block = self . unreachable_block ( ) ;
198- self . make_landing_pad ( block) ;
199- }
187+ ( _, & mir:: CallKind :: DivergingCleanup ( _) ) |
188+ ( _, & mir:: CallKind :: Diverging ) => {
200189 build:: Call ( bcx, callee. immediate ( ) , & llargs[ ..] , Some ( attrs) , debugloc) ;
201190 build:: Unreachable ( bcx) ;
202191 }
203192 ( _, k@& mir:: CallKind :: ConvergingCleanup { .. } ) |
204193 ( _, k@& mir:: CallKind :: Converging { .. } ) => {
205- let ret = match * k {
194+ // Bug #20046
195+ let target = match * k {
196+ mir:: CallKind :: ConvergingCleanup { targets, .. } => targets. 0 ,
206197 mir:: CallKind :: Converging { target, .. } => target,
207- mir:: CallKind :: ConvergingCleanup { targets, .. } => {
208- // make a landing pad regardless (so it sets the personality slot.
209- let block = self . unreachable_block ( ) ;
210- self . make_landing_pad ( block) ;
211- targets. 0
212- } ,
213198 _ => unreachable ! ( )
214199 } ;
215200 let llret = build:: Call ( bcx,
@@ -222,29 +207,35 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
222207 . expect ( "return destination and type not set" ) ;
223208 base:: store_ty ( bcx, llret, ret_dest. llval , ret_ty) ;
224209 }
225- build:: Br ( bcx, self . llblock ( ret ) , debugloc)
210+ build:: Br ( bcx, self . llblock ( target ) , debugloc) ;
226211 }
227212 }
228213 }
229214 }
230215 }
231216
217+ fn get_personality_slot ( & mut self , bcx : Block < ' bcx , ' tcx > ) -> ValueRef {
218+ let ccx = bcx. ccx ( ) ;
219+ if let Some ( slot) = self . llpersonalityslot {
220+ slot
221+ } else {
222+ let llretty = Type :: struct_ ( ccx, & [ Type :: i8p ( ccx) , Type :: i32 ( ccx) ] , false ) ;
223+ let slot = base:: alloca ( bcx, llretty, "personalityslot" ) ;
224+ self . llpersonalityslot = Some ( slot) ;
225+ base:: call_lifetime_start ( bcx, slot) ;
226+ slot
227+ }
228+ }
229+
232230 fn make_landing_pad ( & mut self , cleanup : Block < ' bcx , ' tcx > ) -> Block < ' bcx , ' tcx > {
233231 let bcx = cleanup. fcx . new_block ( true , "cleanup" , None ) ;
234232 let ccx = bcx. ccx ( ) ;
235233 let llpersonality = bcx. fcx . eh_personality ( ) ;
236234 let llretty = Type :: struct_ ( ccx, & [ Type :: i8p ( ccx) , Type :: i32 ( ccx) ] , false ) ;
237235 let llretval = build:: LandingPad ( bcx, llretty, llpersonality, 1 ) ;
238236 build:: SetCleanup ( bcx, llretval) ;
239- match self . llpersonalityslot {
240- Some ( slot) => build:: Store ( bcx, llretval, slot) ,
241- None => {
242- let personalityslot = base:: alloca ( bcx, llretty, "personalityslot" ) ;
243- self . llpersonalityslot = Some ( personalityslot) ;
244- base:: call_lifetime_start ( bcx, personalityslot) ;
245- build:: Store ( bcx, llretval, personalityslot)
246- }
247- } ;
237+ let slot = self . get_personality_slot ( bcx) ;
238+ build:: Store ( bcx, llretval, slot) ;
248239 build:: Br ( bcx, cleanup. llbb , DebugLoc :: None ) ;
249240 bcx
250241 }
0 commit comments