@@ -67,36 +67,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
67
67
} => {
68
68
let old_stack = self . frame_idx ( ) ;
69
69
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) ?;
100
73
101
74
let destination = self . eval_place ( destination) ?;
102
75
self . eval_fn_call (
@@ -116,38 +89,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
116
89
}
117
90
118
91
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?
120
92
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) ?;
151
96
152
97
// This is the "canonical" implementation of tails calls,
153
98
// 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> {
401
346
self . copy_op ( & caller_arg, callee_arg, /*allow_transmute*/ true )
402
347
}
403
348
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
+
404
399
/// Call this function -- pushing the stack frame and initializing the arguments.
405
400
///
406
401
/// `caller_fn_abi` is used to determine if all the arguments are passed the proper way.
0 commit comments