@@ -122,36 +122,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
122
122
} => {
123
123
let old_stack = self . frame_idx ( ) ;
124
124
let old_loc = self . frame ( ) . loc ;
125
- let func = self . eval_operand ( func, None ) ?;
126
- let args = self . eval_fn_call_arguments ( args) ?;
127
-
128
- let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
129
- let fn_sig =
130
- self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
131
- let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
132
- let extra_args =
133
- self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout ( ) . ty ) ) ;
134
-
135
- let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
136
- ty:: FnPtr ( _sig) => {
137
- let fn_ptr = self . read_pointer ( & func) ?;
138
- let fn_val = self . get_ptr_fn ( fn_ptr) ?;
139
- ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
140
- }
141
- ty:: FnDef ( def_id, args) => {
142
- let instance = self . resolve ( def_id, args) ?;
143
- (
144
- FnVal :: Instance ( instance) ,
145
- self . fn_abi_of_instance ( instance, extra_args) ?,
146
- instance. def . requires_caller_location ( * self . tcx ) ,
147
- )
148
- }
149
- _ => span_bug ! (
150
- terminator. source_info. span,
151
- "invalid callee of type {}" ,
152
- func. layout. ty
153
- ) ,
154
- } ;
125
+
126
+ let ( fn_val, args, fn_sig, fn_abi, with_caller_location) =
127
+ self . prepare_fn_for_call ( terminator, func, args) ?;
155
128
156
129
let destination = self . eval_place ( destination) ?;
157
130
self . eval_fn_call (
@@ -171,38 +144,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
171
144
}
172
145
173
146
TailCall { ref func, ref args, fn_span : _ } => {
174
- // FIXME(explicit_tail_calls): a lot of code here is duplicated with normal calls, can we refactor this?
175
147
let old_frame_idx = self . frame_idx ( ) ;
176
- let func = self . eval_operand ( func, None ) ?;
177
- let args = self . eval_fn_call_arguments ( args) ?;
178
-
179
- let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
180
- let fn_sig =
181
- self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
182
- let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
183
- let extra_args =
184
- self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout ( ) . ty ) ) ;
185
-
186
- let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
187
- ty:: FnPtr ( _sig) => {
188
- let fn_ptr = self . read_pointer ( & func) ?;
189
- let fn_val = self . get_ptr_fn ( fn_ptr) ?;
190
- ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
191
- }
192
- ty:: FnDef ( def_id, substs) => {
193
- let instance = self . resolve ( def_id, substs) ?;
194
- (
195
- FnVal :: Instance ( instance) ,
196
- self . fn_abi_of_instance ( instance, extra_args) ?,
197
- instance. def . requires_caller_location ( * self . tcx ) ,
198
- )
199
- }
200
- _ => span_bug ! (
201
- terminator. source_info. span,
202
- "invalid callee of type {:?}" ,
203
- func. layout. ty
204
- ) ,
205
- } ;
148
+
149
+ let ( fn_val, args, fn_sig, fn_abi, with_caller_location) =
150
+ self . prepare_fn_for_call ( terminator, func, args) ?;
206
151
207
152
// This is the "canonical" implementation of tails calls,
208
153
// a pop of the current stack frame, followed by a normal call
@@ -561,6 +506,54 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
561
506
Ok ( ( ) )
562
507
}
563
508
509
+ /// Shared part of `Call` and `TailCall` implementation — finding and evaluating all the
510
+ /// necessary information about callee to make a call.
511
+ fn prepare_fn_for_call (
512
+ & self ,
513
+ terminator : & mir:: Terminator < ' tcx > ,
514
+ func : & mir:: Operand < ' tcx > ,
515
+ args : & [ Spanned < mir:: Operand < ' tcx > > ] ,
516
+ ) -> InterpResult <
517
+ ' tcx ,
518
+ (
519
+ FnVal < ' tcx , M :: ExtraFnVal > ,
520
+ Vec < FnArg < ' tcx , <M as Machine < ' mir , ' tcx > >:: Provenance > > ,
521
+ ty:: FnSig < ' tcx > ,
522
+ & ' tcx FnAbi < ' tcx , Ty < ' tcx > > ,
523
+ bool ,
524
+ ) ,
525
+ > {
526
+ let func = self . eval_operand ( func, None ) ?;
527
+ let args = self . eval_fn_call_arguments ( args) ?;
528
+
529
+ let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
530
+ let fn_sig = self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
531
+ let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
532
+ let extra_args =
533
+ self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout ( ) . ty ) ) ;
534
+
535
+ let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
536
+ ty:: FnPtr ( _sig) => {
537
+ let fn_ptr = self . read_pointer ( & func) ?;
538
+ let fn_val = self . get_ptr_fn ( fn_ptr) ?;
539
+ ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
540
+ }
541
+ ty:: FnDef ( def_id, args) => {
542
+ let instance = self . resolve ( def_id, args) ?;
543
+ (
544
+ FnVal :: Instance ( instance) ,
545
+ self . fn_abi_of_instance ( instance, extra_args) ?,
546
+ instance. def . requires_caller_location ( * self . tcx ) ,
547
+ )
548
+ }
549
+ _ => {
550
+ span_bug ! ( terminator. source_info. span, "invalid callee of type {}" , func. layout. ty)
551
+ }
552
+ } ;
553
+
554
+ Ok ( ( fn_val, args, fn_sig, fn_abi, with_caller_location) )
555
+ }
556
+
564
557
/// Call this function -- pushing the stack frame and initializing the arguments.
565
558
///
566
559
/// `caller_fn_abi` is used to determine if all the arguments are passed the proper way.
0 commit comments