mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Move eval_const_fn_call
to the const_eval
module
This commit is contained in:
parent
2d67edd32c
commit
9a82458e70
@ -149,18 +149,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
// sensitive check here. But we can at least rule out functions that are not const
|
||||
// at all.
|
||||
if ecx.tcx.is_const_fn_raw(def_id) {
|
||||
// If this function is a `const fn` then as an optimization we can query this
|
||||
// evaluation immediately.
|
||||
//
|
||||
// For the moment we only do this for functions which take no arguments
|
||||
// (or all arguments are ZSTs) so that we don't memoize too much.
|
||||
//
|
||||
// Because `#[track_caller]` adds an implicit non-ZST argument, we also cannot
|
||||
// perform this optimization on items tagged with it.
|
||||
let no_implicit_args = !instance.def.requires_caller_location(ecx.tcx());
|
||||
if args.iter().all(|a| a.layout.is_zst()) && no_implicit_args {
|
||||
let gid = GlobalId { instance, promoted: None };
|
||||
ecx.eval_const_fn_call(gid, ret)?;
|
||||
// If this function is a `const fn` then under certain circumstances we
|
||||
// can evaluate call via the query system, thus memoizing all future calls.
|
||||
if ecx.try_eval_const_fn_call(instance, ret, args)? {
|
||||
return Ok(None);
|
||||
}
|
||||
} else {
|
||||
@ -326,3 +317,43 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
|
||||
/// Evaluate a const function where all arguments (if any) are zero-sized types.
|
||||
/// The evaluation is memoized thanks to the query system.
|
||||
///
|
||||
/// Returns `true` if the call has been evaluated.
|
||||
fn try_eval_const_fn_call(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
|
||||
args: &[OpTy<'tcx>],
|
||||
) -> InterpResult<'tcx, bool> {
|
||||
trace!("try_eval_const_fn_call: {:?}", instance);
|
||||
// Because `#[track_caller]` adds an implicit non-ZST argument, we also cannot
|
||||
// perform this optimization on items tagged with it.
|
||||
if instance.def.requires_caller_location(self.tcx()) {
|
||||
return Ok(false);
|
||||
}
|
||||
// For the moment we only do this for functions which take no arguments
|
||||
// (or all arguments are ZSTs) so that we don't memoize too much.
|
||||
if args.iter().any(|a| !a.layout.is_zst()) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let gid = GlobalId { instance, promoted: None };
|
||||
|
||||
let place = self.const_eval_raw(gid)?;
|
||||
let dest = match ret {
|
||||
Some((dest, _)) => dest,
|
||||
// Don't memoize diverging function calls.
|
||||
None => return Ok(false),
|
||||
};
|
||||
|
||||
self.copy_op(place.into(), dest)?;
|
||||
|
||||
self.return_to_block(ret.map(|r| r.1))?;
|
||||
self.dump_place(*dest);
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ use rustc_target::spec::abi::Abi;
|
||||
use syntax::source_map::Span;
|
||||
|
||||
use super::{
|
||||
FnVal, GlobalId, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy,
|
||||
StackPopCleanup,
|
||||
FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, StackPopCleanup,
|
||||
};
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
@ -402,26 +401,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate a const function where all arguments (if any) are zero-sized types.
|
||||
/// The evaluation is memoized thanks to the query system.
|
||||
// FIXME: Consider moving this to `const_eval.rs`.
|
||||
pub(crate) fn eval_const_fn_call(
|
||||
&mut self,
|
||||
gid: GlobalId<'tcx>,
|
||||
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("eval_const_fn_call: {:?}", gid);
|
||||
|
||||
let place = self.const_eval_raw(gid)?;
|
||||
let dest = ret.ok_or_else(|| err_ub!(Unreachable))?.0;
|
||||
|
||||
self.copy_op(place.into(), dest)?;
|
||||
|
||||
self.return_to_block(ret.map(|r| r.1))?;
|
||||
self.dump_place(*dest);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn drop_in_place(
|
||||
&mut self,
|
||||
place: PlaceTy<'tcx, M::PointerTag>,
|
||||
|
Loading…
Reference in New Issue
Block a user