@@ -67,36 +67,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6767 } => {
6868 let old_stack = self . frame_idx ( ) ;
6969 let old_loc = self . frame ( ) . loc ;
70- let func = self . eval_operand ( func, None ) ?;
71- let args = self . eval_operands ( args) ?;
72-
73- let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
74- let fn_sig =
75- self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
76- let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
77- let extra_args =
78- self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout . ty ) ) ;
79-
80- let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
81- ty:: FnPtr ( _sig) => {
82- let fn_ptr = self . read_pointer ( & func) ?;
83- let fn_val = self . get_ptr_fn ( fn_ptr) ?;
84- ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
85- }
86- ty:: FnDef ( def_id, substs) => {
87- let instance = self . resolve ( def_id, substs) ?;
88- (
89- FnVal :: Instance ( instance) ,
90- self . fn_abi_of_instance ( instance, extra_args) ?,
91- instance. def . requires_caller_location ( * self . tcx ) ,
92- )
93- }
94- _ => span_bug ! (
95- terminator. source_info. span,
96- "invalid callee of type {:?}" ,
97- func. layout. ty
98- ) ,
99- } ;
70+
71+ let ( fn_val, args, fn_sig, fn_abi, with_caller_location) =
72+ self . prepare_fn_for_call ( terminator, func, args) ?;
10073
10174 let destination = self . eval_place ( destination) ?;
10275 self . eval_fn_call (
@@ -116,38 +89,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
11689 }
11790
11891 TailCall { ref func, ref args, fn_span : _ } => {
119- // FIXME(explicit_tail_calls): a lot of code here is duplicated with normal calls, can we refactor this?
12092 let old_frame_idx = self . frame_idx ( ) ;
121- let func = self . eval_operand ( func, None ) ?;
122- let args = self . eval_operands ( args) ?;
123-
124- let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
125- let fn_sig =
126- self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
127- let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
128- let extra_args =
129- self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout . ty ) ) ;
130-
131- let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
132- ty:: FnPtr ( _sig) => {
133- let fn_ptr = self . read_pointer ( & func) ?;
134- let fn_val = self . get_ptr_fn ( fn_ptr) ?;
135- ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
136- }
137- ty:: FnDef ( def_id, substs) => {
138- let instance = self . resolve ( def_id, substs) ?;
139- (
140- FnVal :: Instance ( instance) ,
141- self . fn_abi_of_instance ( instance, extra_args) ?,
142- instance. def . requires_caller_location ( * self . tcx ) ,
143- )
144- }
145- _ => span_bug ! (
146- terminator. source_info. span,
147- "invalid callee of type {:?}" ,
148- func. layout. ty
149- ) ,
150- } ;
93+
94+ let ( fn_val, args, fn_sig, fn_abi, with_caller_location) =
95+ self . prepare_fn_for_call ( terminator, func, args) ?;
15196
15297 // This is the "canonical" implementation of tails calls,
15398 // a pop of the current stack frame, followed by a normal call
@@ -401,6 +346,56 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
401346 self . copy_op ( & caller_arg, callee_arg, /*allow_transmute*/ true )
402347 }
403348
349+ /// Shared part of `Call` and `TailCall` implementation — finding and evaluating all the
350+ /// necessary information about callee to make a call.
351+ fn prepare_fn_for_call (
352+ & self ,
353+ terminator : & mir:: Terminator < ' tcx > ,
354+ func : & mir:: Operand < ' tcx > ,
355+ args : & [ mir:: Operand < ' tcx > ] ,
356+ ) -> InterpResult <
357+ ' tcx ,
358+ (
359+ FnVal < ' tcx , M :: ExtraFnVal > ,
360+ Vec < OpTy < ' tcx , M :: Provenance > > ,
361+ ty:: FnSig < ' tcx > ,
362+ & ' tcx FnAbi < ' tcx , Ty < ' tcx > > ,
363+ bool ,
364+ ) ,
365+ > {
366+ let func = self . eval_operand ( func, None ) ?;
367+ let args = self . eval_operands ( args) ?;
368+
369+ let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
370+ let fn_sig = self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
371+ let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
372+ let extra_args =
373+ self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout . ty ) ) ;
374+
375+ let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
376+ ty:: FnPtr ( _sig) => {
377+ let fn_ptr = self . read_pointer ( & func) ?;
378+ let fn_val = self . get_ptr_fn ( fn_ptr) ?;
379+ ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
380+ }
381+ ty:: FnDef ( def_id, substs) => {
382+ let instance = self . resolve ( def_id, substs) ?;
383+ (
384+ FnVal :: Instance ( instance) ,
385+ self . fn_abi_of_instance ( instance, extra_args) ?,
386+ instance. def . requires_caller_location ( * self . tcx ) ,
387+ )
388+ }
389+ _ => span_bug ! (
390+ terminator. source_info. span,
391+ "invalid callee of type {:?}" ,
392+ func. layout. ty
393+ ) ,
394+ } ;
395+
396+ Ok ( ( fn_val, args, fn_sig, fn_abi, with_caller_location) )
397+ }
398+
404399 /// Call this function -- pushing the stack frame and initializing the arguments.
405400 ///
406401 /// `caller_fn_abi` is used to determine if all the arguments are passed the proper way.
0 commit comments