@@ -122,36 +122,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
122122 } => {
123123 let old_stack = self . frame_idx ( ) ;
124124 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) ?;
155128
156129 let destination = self . eval_place ( destination) ?;
157130 self . eval_fn_call (
@@ -171,38 +144,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
171144 }
172145
173146 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?
175147 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) ?;
206151
207152 // This is the "canonical" implementation of tails calls,
208153 // 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> {
561506 Ok ( ( ) )
562507 }
563508
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+
564557 /// Call this function -- pushing the stack frame and initializing the arguments.
565558 ///
566559 /// `caller_fn_abi` is used to determine if all the arguments are passed the proper way.
0 commit comments