@@ -53,7 +53,23 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
53
53
_ => funclets[ bb] . as_ref ( ) ,
54
54
} ;
55
55
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
+
56
71
// Create the cleanup bundle, if needed.
72
+ let tcx = bcx. tcx ( ) ;
57
73
let cleanup_pad = funclet. map ( |lp| lp. cleanuppad ( ) ) ;
58
74
let cleanup_bundle = funclet. map ( |l| l. bundle ( ) ) ;
59
75
@@ -104,12 +120,53 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
104
120
}
105
121
} ;
106
122
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) ;
110
157
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
+ } ;
113
170
114
171
let span = terminator. source_info . span ;
115
172
self . set_debug_loc ( & bcx, terminator. source_info ) ;
@@ -218,24 +275,16 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
218
275
}
219
276
220
277
let lvalue = self . trans_lvalue ( & bcx, location) ;
278
+ let fn_ty = FnType :: of_instance ( bcx. ccx , & drop_fn) ;
221
279
let ( drop_fn, need_extra) = match ty. sty {
222
280
ty:: TyDynamic ( ..) => ( meth:: DESTRUCTOR . get_fn ( & bcx, lvalue. llextra ) ,
223
281
false ) ,
224
282
_ => ( callee:: get_fn ( bcx. ccx , drop_fn) , lvalue. has_extra ( ) )
225
283
} ;
226
284
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) ;
239
288
}
240
289
241
290
mir:: TerminatorKind :: Assert { ref cond, expected, ref msg, target, cleanup } => {
@@ -342,26 +391,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
342
391
// Obtain the panic entry point.
343
392
let def_id = common:: langcall ( bcx. tcx ( ) , Some ( span) , "" , lang_item) ;
344
393
let instance = ty:: Instance :: mono ( bcx. tcx ( ) , def_id) ;
394
+ let fn_ty = FnType :: of_instance ( bcx. ccx , & instance) ;
345
395
let llfn = callee:: get_fn ( bcx. ccx , instance) ;
346
396
347
397
// 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) ;
358
399
}
359
400
360
401
mir:: TerminatorKind :: DropAndReplace { .. } => {
361
- bug ! ( "undesugared DropAndReplace in trans: {:?}" , data ) ;
402
+ bug ! ( "undesugared DropAndReplace in trans: {:?}" , terminator ) ;
362
403
}
363
404
364
- mir:: TerminatorKind :: Call { ref func, ref args, ref destination, ref cleanup } => {
405
+ mir:: TerminatorKind :: Call { ref func, ref args, ref destination, cleanup } => {
365
406
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
366
407
let callee = self . trans_operand ( & bcx, func) ;
367
408
@@ -514,43 +555,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
514
555
_ => span_bug ! ( span, "no llfn for call" ) ,
515
556
} ;
516
557
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) ;
554
561
}
555
562
}
556
563
}
0 commit comments