mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Rollup merge of #104605 - RalfJung:clf_consts, r=bjorn3
deduplicate constant evaluation in cranelift backend The cranelift backend had two matches on `ConstantKind`, which can be avoided, and used this `eval_for_mir` that nothing else uses... this makes things more consistent with the (better-tested) LLVM backend. I noticed this because cranelift was the only user of `eval_for_mir`. However `try_eval_for_mir` still has one other user in `eval`... the odd thing is that the interpreter has its own `eval_mir_constant` which seems to duplicate the same functionality and does not use `try_eval_for_mir`. No idea what is happening here. r? ``@bjorn3`` Cc ``@lcnr``
This commit is contained in:
commit
ed22bdc18f
@ -38,22 +38,8 @@ impl ConstantCx {
|
|||||||
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
|
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
|
||||||
let mut all_constants_ok = true;
|
let mut all_constants_ok = true;
|
||||||
for constant in &fx.mir.required_consts {
|
for constant in &fx.mir.required_consts {
|
||||||
let unevaluated = match fx.monomorphize(constant.literal) {
|
if eval_mir_constant(fx, constant).is_none() {
|
||||||
ConstantKind::Ty(_) => unreachable!(),
|
|
||||||
ConstantKind::Unevaluated(uv, _) => uv,
|
|
||||||
ConstantKind::Val(..) => continue,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(err) = fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
|
|
||||||
all_constants_ok = false;
|
all_constants_ok = false;
|
||||||
match err {
|
|
||||||
ErrorHandled::Reported(_) => {
|
|
||||||
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
|
|
||||||
}
|
|
||||||
ErrorHandled::TooGeneric => {
|
|
||||||
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
all_constants_ok
|
all_constants_ok
|
||||||
@ -80,15 +66,15 @@ pub(crate) fn codegen_tls_ref<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn eval_mir_constant<'tcx>(
|
pub(crate) fn eval_mir_constant<'tcx>(
|
||||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
fx: &FunctionCx<'_, '_, 'tcx>,
|
||||||
constant: &Constant<'tcx>,
|
constant: &Constant<'tcx>,
|
||||||
) -> (ConstValue<'tcx>, Ty<'tcx>) {
|
) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
|
||||||
let constant_kind = fx.monomorphize(constant.literal);
|
let constant_kind = fx.monomorphize(constant.literal);
|
||||||
let uv = match constant_kind {
|
let uv = match constant_kind {
|
||||||
ConstantKind::Ty(const_) => match const_.kind() {
|
ConstantKind::Ty(const_) => match const_.kind() {
|
||||||
ty::ConstKind::Unevaluated(uv) => uv.expand(),
|
ty::ConstKind::Unevaluated(uv) => uv.expand(),
|
||||||
ty::ConstKind::Value(val) => {
|
ty::ConstKind::Value(val) => {
|
||||||
return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty());
|
return Some((fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty()));
|
||||||
}
|
}
|
||||||
err => span_bug!(
|
err => span_bug!(
|
||||||
constant.span,
|
constant.span,
|
||||||
@ -102,22 +88,31 @@ pub(crate) fn eval_mir_constant<'tcx>(
|
|||||||
span_bug!(constant.span, "MIR constant refers to static");
|
span_bug!(constant.span, "MIR constant refers to static");
|
||||||
}
|
}
|
||||||
ConstantKind::Unevaluated(uv, _) => uv,
|
ConstantKind::Unevaluated(uv, _) => uv,
|
||||||
ConstantKind::Val(val, _) => return (val, constant_kind.ty()),
|
ConstantKind::Val(val, _) => return Some((val, constant_kind.ty())),
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
let val = fx
|
||||||
fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| {
|
.tcx
|
||||||
span_bug!(constant.span, "erroneous constant not captured by required_consts");
|
.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None)
|
||||||
}),
|
.map_err(|err| match err {
|
||||||
constant_kind.ty(),
|
ErrorHandled::Reported(_) => {
|
||||||
)
|
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
|
||||||
|
}
|
||||||
|
ErrorHandled::TooGeneric => {
|
||||||
|
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
val.map(|val| (val, constant_kind.ty()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn codegen_constant_operand<'tcx>(
|
pub(crate) fn codegen_constant_operand<'tcx>(
|
||||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||||
constant: &Constant<'tcx>,
|
constant: &Constant<'tcx>,
|
||||||
) -> CValue<'tcx> {
|
) -> CValue<'tcx> {
|
||||||
let (const_val, ty) = eval_mir_constant(fx, constant);
|
let (const_val, ty) = eval_mir_constant(fx, constant).unwrap_or_else(|| {
|
||||||
|
span_bug!(constant.span, "erroneous constant not captured by required_consts")
|
||||||
|
});
|
||||||
|
|
||||||
codegen_const_value(fx, const_val, ty)
|
codegen_const_value(fx, const_val, ty)
|
||||||
}
|
}
|
||||||
@ -453,20 +448,13 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||||||
assert!(cx.todo.is_empty(), "{:?}", cx.todo);
|
assert!(cx.todo.is_empty(), "{:?}", cx.todo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used only for intrinsic implementations that need a compile-time constant
|
||||||
pub(crate) fn mir_operand_get_const_val<'tcx>(
|
pub(crate) fn mir_operand_get_const_val<'tcx>(
|
||||||
fx: &FunctionCx<'_, '_, 'tcx>,
|
fx: &FunctionCx<'_, '_, 'tcx>,
|
||||||
operand: &Operand<'tcx>,
|
operand: &Operand<'tcx>,
|
||||||
) -> Option<ConstValue<'tcx>> {
|
) -> Option<ConstValue<'tcx>> {
|
||||||
match operand {
|
match operand {
|
||||||
Operand::Constant(const_) => match fx.monomorphize(const_.literal) {
|
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0),
|
||||||
ConstantKind::Ty(const_) => Some(
|
|
||||||
const_.eval_for_mir(fx.tcx, ParamEnv::reveal_all()).try_to_value(fx.tcx).unwrap(),
|
|
||||||
),
|
|
||||||
ConstantKind::Val(val, _) => Some(val),
|
|
||||||
ConstantKind::Unevaluated(uv, _) => {
|
|
||||||
Some(fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).unwrap())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
|
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
|
||||||
// inside a temporary before being passed to the intrinsic requiring the const argument.
|
// inside a temporary before being passed to the intrinsic requiring the const argument.
|
||||||
// This code tries to find a single constant defining definition of the referenced local.
|
// This code tries to find a single constant defining definition of the referenced local.
|
||||||
|
@ -42,7 +42,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
|
self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
|
||||||
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
|
match err {
|
||||||
|
ErrorHandled::Reported(_) => {
|
||||||
|
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
|
||||||
|
}
|
||||||
|
ErrorHandled::TooGeneric => {
|
||||||
|
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
err
|
err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::mir::interpret::LitToConstInput;
|
use crate::mir::interpret::LitToConstInput;
|
||||||
use crate::mir::ConstantKind;
|
|
||||||
use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -230,20 +229,6 @@ impl<'tcx> Const<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated` and creates a ConstValue if the
|
|
||||||
/// evaluation succeeds. If it doesn't succeed, returns the unevaluated constant.
|
|
||||||
pub fn eval_for_mir(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> ConstantKind<'tcx> {
|
|
||||||
if let Some(val) = self.kind().try_eval_for_mir(tcx, param_env) {
|
|
||||||
match val {
|
|
||||||
Ok(const_val) => ConstantKind::from_value(const_val, self.ty()),
|
|
||||||
Err(guar) => ConstantKind::Ty(tcx.const_error_with_guaranteed(self.ty(), guar)),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ConstantKind::Ty(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
|
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
|
||||||
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
|
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
|
||||||
|
Loading…
Reference in New Issue
Block a user