Skip to content

Commit 6d1e2d8

Browse files
committed
Refactor common part of evaluating Call&TailCall in the interpreter
1 parent 1f82033 commit 6d1e2d8

File tree

1 file changed

+56
-61
lines changed

1 file changed

+56
-61
lines changed

compiler/rustc_const_eval/src/interpret/terminator.rs

+56-61
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)