Skip to content

Commit 45c7031

Browse files
committed
Refactor common part of evaluating Call&TailCall in the interpreter
1 parent 3b5a5ee commit 45c7031

File tree

1 file changed

+56
-63
lines changed

1 file changed

+56
-63
lines changed

compiler/rustc_const_eval/src/interpret/terminator.rs

Lines changed: 56 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
5059
impl<'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

Comments
 (0)