@@ -47,6 +47,15 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
4747 }
4848}
4949
50+ struct EvaluatedCalleeAndArgs < ' tcx , M : Machine < ' tcx > > {
51+ callee : FnVal < ' tcx , M :: ExtraFnVal > ,
52+ args : Vec < FnArg < ' tcx , M :: Provenance > > ,
53+ fn_sig : ty:: FnSig < ' tcx > ,
54+ fn_abi : & ' tcx FnAbi < ' tcx , Ty < ' tcx > > ,
55+ /// True if the function is marked as `#[track_caller]` ([`ty::InstanceDef::requires_caller_location`])
56+ with_caller_location : bool ,
57+ }
58+
5059impl < ' tcx , M : Machine < ' tcx > > InterpCx < ' tcx , M > {
5160 /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
5261 /// original memory occurs.
@@ -124,40 +133,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
124133 } => {
125134 let old_stack = self . frame_idx ( ) ;
126135 let old_loc = self . frame ( ) . loc ;
127- let func = self . eval_operand ( func, None ) ?;
128- let args = self . eval_fn_call_arguments ( args) ?;
129-
130- let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
131- let fn_sig =
132- self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
133- let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
134- let extra_args =
135- self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout ( ) . ty ) ) ;
136-
137- let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
138- ty:: FnPtr ( _sig) => {
139- let fn_ptr = self . read_pointer ( & func) ?;
140- let fn_val = self . get_ptr_fn ( fn_ptr) ?;
141- ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
142- }
143- ty:: FnDef ( def_id, args) => {
144- let instance = self . resolve ( def_id, args) ?;
145- (
146- FnVal :: Instance ( instance) ,
147- self . fn_abi_of_instance ( instance, extra_args) ?,
148- instance. def . requires_caller_location ( * self . tcx ) ,
149- )
150- }
151- _ => span_bug ! (
152- terminator. source_info. span,
153- "invalid callee of type {}" ,
154- func. layout. ty
155- ) ,
156- } ;
136+
137+ let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
138+ self . eval_callee_and_args ( terminator, func, args) ?;
157139
158140 let destination = self . force_allocation ( & self . eval_place ( destination) ?) ?;
159141 self . eval_fn_call (
160- fn_val ,
142+ callee ,
161143 ( fn_sig. abi , fn_abi) ,
162144 & args,
163145 with_caller_location,
@@ -173,38 +155,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
173155 }
174156
175157 TailCall { ref func, ref args, fn_span : _ } => {
176- // FIXME(explicit_tail_calls): a lot of code here is duplicated with normal calls, can we refactor this?
177158 let old_frame_idx = self . frame_idx ( ) ;
178- let func = self . eval_operand ( func, None ) ?;
179- let args = self . eval_fn_call_arguments ( args) ?;
180-
181- let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
182- let fn_sig =
183- self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
184- let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
185- let extra_args =
186- self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout ( ) . ty ) ) ;
187-
188- let ( fn_val, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
189- ty:: FnPtr ( _sig) => {
190- let fn_ptr = self . read_pointer ( & func) ?;
191- let fn_val = self . get_ptr_fn ( fn_ptr) ?;
192- ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
193- }
194- ty:: FnDef ( def_id, substs) => {
195- let instance = self . resolve ( def_id, substs) ?;
196- (
197- FnVal :: Instance ( instance) ,
198- self . fn_abi_of_instance ( instance, extra_args) ?,
199- instance. def . requires_caller_location ( * self . tcx ) ,
200- )
201- }
202- _ => span_bug ! (
203- terminator. source_info. span,
204- "invalid callee of type {:?}" ,
205- func. layout. ty
206- ) ,
207- } ;
159+
160+ let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
161+ self . eval_callee_and_args ( terminator, func, args) ?;
208162
209163 // This is the "canonical" implementation of tails calls,
210164 // a pop of the current stack frame, followed by a normal call
@@ -227,7 +181,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
227181 } ;
228182
229183 self . eval_fn_call (
230- fn_val ,
184+ callee ,
231185 ( fn_sig. abi , fn_abi) ,
232186 & args,
233187 with_caller_location,
@@ -586,6 +540,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
586540 Ok ( ( ) )
587541 }
588542
543+ /// Shared part of `Call` and `TailCall` implementation — finding and evaluating all the
544+ /// necessary information about callee and arguments to make a call.
545+ fn eval_callee_and_args (
546+ & self ,
547+ terminator : & mir:: Terminator < ' tcx > ,
548+ func : & mir:: Operand < ' tcx > ,
549+ args : & [ Spanned < mir:: Operand < ' tcx > > ] ,
550+ ) -> InterpResult < ' tcx , EvaluatedCalleeAndArgs < ' tcx , M > > {
551+ let func = self . eval_operand ( func, None ) ?;
552+ let args = self . eval_fn_call_arguments ( args) ?;
553+
554+ let fn_sig_binder = func. layout . ty . fn_sig ( * self . tcx ) ;
555+ let fn_sig = self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig_binder) ;
556+ let extra_args = & args[ fn_sig. inputs ( ) . len ( ) ..] ;
557+ let extra_args =
558+ self . tcx . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |arg| arg. layout ( ) . ty ) ) ;
559+
560+ let ( callee, fn_abi, with_caller_location) = match * func. layout . ty . kind ( ) {
561+ ty:: FnPtr ( _sig) => {
562+ let fn_ptr = self . read_pointer ( & func) ?;
563+ let fn_val = self . get_ptr_fn ( fn_ptr) ?;
564+ ( fn_val, self . fn_abi_of_fn_ptr ( fn_sig_binder, extra_args) ?, false )
565+ }
566+ ty:: FnDef ( def_id, args) => {
567+ let instance = self . resolve ( def_id, args) ?;
568+ (
569+ FnVal :: Instance ( instance) ,
570+ self . fn_abi_of_instance ( instance, extra_args) ?,
571+ instance. def . requires_caller_location ( * self . tcx ) ,
572+ )
573+ }
574+ _ => {
575+ span_bug ! ( terminator. source_info. span, "invalid callee of type {}" , func. layout. ty)
576+ }
577+ } ;
578+
579+ Ok ( EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } )
580+ }
581+
589582 /// Call this function -- pushing the stack frame and initializing the arguments.
590583 ///
591584 /// `caller_fn_abi` is used to determine if all the arguments are passed the proper way.
0 commit comments