8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use llvm:: BasicBlockRef ;
11
+ use llvm:: { BasicBlockRef , ValueRef } ;
12
12
use rustc:: mir:: repr as mir;
13
13
use trans:: adt;
14
14
use trans:: base;
@@ -80,13 +80,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
80
80
}
81
81
82
82
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) ;
90
87
}
91
88
92
89
mir:: Terminator :: Return => {
@@ -187,29 +184,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
187
184
build:: Br ( target, postinvoketarget. llbb , debugloc) ;
188
185
}
189
186
} ,
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 ) => {
200
189
build:: Call ( bcx, callee. immediate ( ) , & llargs[ ..] , Some ( attrs) , debugloc) ;
201
190
build:: Unreachable ( bcx) ;
202
191
}
203
192
( _, k@& mir:: CallKind :: ConvergingCleanup { .. } ) |
204
193
( _, k@& mir:: CallKind :: Converging { .. } ) => {
205
- let ret = match * k {
194
+ // Bug #20046
195
+ let target = match * k {
196
+ mir:: CallKind :: ConvergingCleanup { targets, .. } => targets. 0 ,
206
197
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
- } ,
213
198
_ => unreachable ! ( )
214
199
} ;
215
200
let llret = build:: Call ( bcx,
@@ -222,29 +207,35 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
222
207
. expect ( "return destination and type not set" ) ;
223
208
base:: store_ty ( bcx, llret, ret_dest. llval , ret_ty) ;
224
209
}
225
- build:: Br ( bcx, self . llblock ( ret ) , debugloc)
210
+ build:: Br ( bcx, self . llblock ( target ) , debugloc) ;
226
211
}
227
212
}
228
213
}
229
214
}
230
215
}
231
216
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
+
232
230
fn make_landing_pad ( & mut self , cleanup : Block < ' bcx , ' tcx > ) -> Block < ' bcx , ' tcx > {
233
231
let bcx = cleanup. fcx . new_block ( true , "cleanup" , None ) ;
234
232
let ccx = bcx. ccx ( ) ;
235
233
let llpersonality = bcx. fcx . eh_personality ( ) ;
236
234
let llretty = Type :: struct_ ( ccx, & [ Type :: i8p ( ccx) , Type :: i32 ( ccx) ] , false ) ;
237
235
let llretval = build:: LandingPad ( bcx, llretty, llpersonality, 1 ) ;
238
236
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) ;
248
239
build:: Br ( bcx, cleanup. llbb , DebugLoc :: None ) ;
249
240
bcx
250
241
}
0 commit comments