@@ -53,7 +53,23 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
5353 _ => funclets[ bb] . as_ref ( ) ,
5454 } ;
5555
56+ for statement in & data. statements {
57+ bcx = self . trans_statement ( bcx, statement) ;
58+ }
59+
60+ self . trans_terminator ( bcx, bb, data. terminator ( ) , funclet) ;
61+ }
62+
63+ fn trans_terminator ( & mut self ,
64+ mut bcx : Builder < ' a , ' tcx > ,
65+ bb : mir:: BasicBlock ,
66+ terminator : & mir:: Terminator < ' tcx > ,
67+ funclet : Option < & Funclet > )
68+ {
69+ debug ! ( "trans_terminator: {:?}" , terminator) ;
70+
5671 // Create the cleanup bundle, if needed.
72+ let tcx = bcx. tcx ( ) ;
5773 let cleanup_pad = funclet. map ( |lp| lp. cleanuppad ( ) ) ;
5874 let cleanup_bundle = funclet. map ( |l| l. bundle ( ) ) ;
5975
@@ -104,12 +120,53 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
104120 }
105121 } ;
106122
107- for statement in & data. statements {
108- bcx = self . trans_statement ( bcx, statement) ;
109- }
123+ let do_call = |
124+ this : & mut Self ,
125+ bcx : Builder < ' a , ' tcx > ,
126+ fn_ty : FnType < ' tcx > ,
127+ fn_ptr : ValueRef ,
128+ llargs : & [ ValueRef ] ,
129+ destination : Option < ( ReturnDest , ty:: Ty < ' tcx > , mir:: BasicBlock ) > ,
130+ cleanup : Option < mir:: BasicBlock >
131+ | {
132+ if let Some ( cleanup) = cleanup {
133+ let ret_bcx = if let Some ( ( _, _, target) ) = destination {
134+ this. blocks [ target]
135+ } else {
136+ this. unreachable_block ( )
137+ } ;
138+ let invokeret = bcx. invoke ( fn_ptr,
139+ & llargs,
140+ ret_bcx,
141+ llblock ( this, cleanup) ,
142+ cleanup_bundle) ;
143+ fn_ty. apply_attrs_callsite ( invokeret) ;
144+
145+ if let Some ( ( ret_dest, ret_ty, target) ) = destination {
146+ let ret_bcx = this. get_builder ( target) ;
147+ this. set_debug_loc ( & ret_bcx, terminator. source_info ) ;
148+ let op = OperandRef {
149+ val : Immediate ( invokeret) ,
150+ ty : ret_ty,
151+ } ;
152+ this. store_return ( & ret_bcx, ret_dest, & fn_ty. ret , op) ;
153+ }
154+ } else {
155+ let llret = bcx. call ( fn_ptr, & llargs, cleanup_bundle) ;
156+ fn_ty. apply_attrs_callsite ( llret) ;
110157
111- let terminator = data. terminator ( ) ;
112- debug ! ( "trans_block: terminator: {:?}" , terminator) ;
158+ if let Some ( ( ret_dest, ret_ty, target) ) = destination {
159+ let op = OperandRef {
160+ val : Immediate ( llret) ,
161+ ty : ret_ty,
162+ } ;
163+ this. store_return ( & bcx, ret_dest, & fn_ty. ret , op) ;
164+ funclet_br ( this, bcx, target) ;
165+ } else {
166+ bcx. unreachable ( ) ;
167+ }
168+ }
169+ } ;
113170
114171 let span = terminator. source_info . span ;
115172 self . set_debug_loc ( & bcx, terminator. source_info ) ;
@@ -218,24 +275,16 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
218275 }
219276
220277 let lvalue = self . trans_lvalue ( & bcx, location) ;
278+ let fn_ty = FnType :: of_instance ( bcx. ccx , & drop_fn) ;
221279 let ( drop_fn, need_extra) = match ty. sty {
222280 ty:: TyDynamic ( ..) => ( meth:: DESTRUCTOR . get_fn ( & bcx, lvalue. llextra ) ,
223281 false ) ,
224282 _ => ( callee:: get_fn ( bcx. ccx , drop_fn) , lvalue. has_extra ( ) )
225283 } ;
226284 let args = & [ lvalue. llval , lvalue. llextra ] [ ..1 + need_extra as usize ] ;
227- if let Some ( unwind) = unwind {
228- bcx. invoke (
229- drop_fn,
230- args,
231- self . blocks [ target] ,
232- llblock ( self , unwind) ,
233- cleanup_bundle
234- ) ;
235- } else {
236- bcx. call ( drop_fn, args, cleanup_bundle) ;
237- funclet_br ( self , bcx, target) ;
238- }
285+ do_call ( self , bcx, fn_ty, drop_fn, args,
286+ Some ( ( ReturnDest :: Nothing , tcx. mk_nil ( ) , target) ) ,
287+ unwind) ;
239288 }
240289
241290 mir:: TerminatorKind :: Assert { ref cond, expected, ref msg, target, cleanup } => {
@@ -342,26 +391,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
342391 // Obtain the panic entry point.
343392 let def_id = common:: langcall ( bcx. tcx ( ) , Some ( span) , "" , lang_item) ;
344393 let instance = ty:: Instance :: mono ( bcx. tcx ( ) , def_id) ;
394+ let fn_ty = FnType :: of_instance ( bcx. ccx , & instance) ;
345395 let llfn = callee:: get_fn ( bcx. ccx , instance) ;
346396
347397 // Translate the actual panic invoke/call.
348- if let Some ( unwind) = cleanup {
349- bcx. invoke ( llfn,
350- & args,
351- self . unreachable_block ( ) ,
352- llblock ( self , unwind) ,
353- cleanup_bundle) ;
354- } else {
355- bcx. call ( llfn, & args, cleanup_bundle) ;
356- bcx. unreachable ( ) ;
357- }
398+ do_call ( self , bcx, fn_ty, llfn, & args, None , cleanup) ;
358399 }
359400
360401 mir:: TerminatorKind :: DropAndReplace { .. } => {
361- bug ! ( "undesugared DropAndReplace in trans: {:?}" , data ) ;
402+ bug ! ( "undesugared DropAndReplace in trans: {:?}" , terminator ) ;
362403 }
363404
364- mir:: TerminatorKind :: Call { ref func, ref args, ref destination, ref cleanup } => {
405+ mir:: TerminatorKind :: Call { ref func, ref args, ref destination, cleanup } => {
365406 // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
366407 let callee = self . trans_operand ( & bcx, func) ;
367408
@@ -514,43 +555,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
514555 _ => span_bug ! ( span, "no llfn for call" ) ,
515556 } ;
516557
517- // Many different ways to call a function handled here
518- if let & Some ( cleanup) = cleanup {
519- let ret_bcx = if let Some ( ( _, target) ) = * destination {
520- self . blocks [ target]
521- } else {
522- self . unreachable_block ( )
523- } ;
524- let invokeret = bcx. invoke ( fn_ptr,
525- & llargs,
526- ret_bcx,
527- llblock ( self , cleanup) ,
528- cleanup_bundle) ;
529- fn_ty. apply_attrs_callsite ( invokeret) ;
530-
531- if let Some ( ( _, target) ) = * destination {
532- let ret_bcx = self . get_builder ( target) ;
533- self . set_debug_loc ( & ret_bcx, terminator. source_info ) ;
534- let op = OperandRef {
535- val : Immediate ( invokeret) ,
536- ty : sig. output ( ) ,
537- } ;
538- self . store_return ( & ret_bcx, ret_dest, & fn_ty. ret , op) ;
539- }
540- } else {
541- let llret = bcx. call ( fn_ptr, & llargs, cleanup_bundle) ;
542- fn_ty. apply_attrs_callsite ( llret) ;
543- if let Some ( ( _, target) ) = * destination {
544- let op = OperandRef {
545- val : Immediate ( llret) ,
546- ty : sig. output ( ) ,
547- } ;
548- self . store_return ( & bcx, ret_dest, & fn_ty. ret , op) ;
549- funclet_br ( self , bcx, target) ;
550- } else {
551- bcx. unreachable ( ) ;
552- }
553- }
558+ do_call ( self , bcx, fn_ty, fn_ptr, & llargs,
559+ destination. as_ref ( ) . map ( |& ( _, target) | ( ret_dest, sig. output ( ) , target) ) ,
560+ cleanup) ;
554561 }
555562 }
556563 }
0 commit comments