about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-11-21 14:11:12 +0100
committerGitHub <noreply@github.com>2022-11-21 14:11:12 +0100
commitd3817e23397bac109440383d845d29152f8bfa4e (patch)
tree423596c822c940c5ea71da2b0de960614195370a
parent5fd3e4dabbc4786a5b7dfc4a0efe1c2e865c719e (diff)
parenta3c89a7ade837cb3d64c17e0b58a67d2c57f2887 (diff)
downloadrust-d3817e23397bac109440383d845d29152f8bfa4e.tar.gz
rust-d3817e23397bac109440383d845d29152f8bfa4e.zip
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``
-rw-r--r--src/constant.rs58
1 files changed, 23 insertions, 35 deletions
diff --git a/src/constant.rs b/src/constant.rs
index 5478caee57d..077f33bb99c 100644
--- a/src/constant.rs
+++ b/src/constant.rs
@@ -38,22 +38,8 @@ impl ConstantCx {
 pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
     let mut all_constants_ok = true;
     for constant in &fx.mir.required_consts {
-        let unevaluated = match fx.monomorphize(constant.literal) {
-            ConstantKind::Ty(_) => unreachable!(),
-            ConstantKind::Unevaluated(uv, _) => uv,
-            ConstantKind::Val(..) => continue,
-        };
-
-        if let Err(err) = fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
+        if eval_mir_constant(fx, constant).is_none() {
             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
@@ -80,15 +66,15 @@ pub(crate) fn codegen_tls_ref<'tcx>(
 }
 
 pub(crate) fn eval_mir_constant<'tcx>(
-    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    fx: &FunctionCx<'_, '_, 'tcx>,
     constant: &Constant<'tcx>,
-) -> (ConstValue<'tcx>, Ty<'tcx>) {
+) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
     let constant_kind = fx.monomorphize(constant.literal);
     let uv = match constant_kind {
         ConstantKind::Ty(const_) => match const_.kind() {
             ty::ConstKind::Unevaluated(uv) => uv.expand(),
             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!(
                 constant.span,
@@ -102,22 +88,31 @@ pub(crate) fn eval_mir_constant<'tcx>(
             span_bug!(constant.span, "MIR constant refers to static");
         }
         ConstantKind::Unevaluated(uv, _) => uv,
-        ConstantKind::Val(val, _) => return (val, constant_kind.ty()),
+        ConstantKind::Val(val, _) => return Some((val, constant_kind.ty())),
     };
 
-    (
-        fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| {
-            span_bug!(constant.span, "erroneous constant not captured by required_consts");
-        }),
-        constant_kind.ty(),
-    )
+    let val = fx
+        .tcx
+        .const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None)
+        .map_err(|err| 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);
+            }
+        })
+        .ok();
+    val.map(|val| (val, constant_kind.ty()))
 }
 
 pub(crate) fn codegen_constant_operand<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     constant: &Constant<'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)
 }
@@ -453,20 +448,13 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
     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>(
     fx: &FunctionCx<'_, '_, 'tcx>,
     operand: &Operand<'tcx>,
 ) -> Option<ConstValue<'tcx>> {
     match operand {
-        Operand::Constant(const_) => match fx.monomorphize(const_.literal) {
-            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())
-            }
-        },
+        Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0),
         // 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.
         // This code tries to find a single constant defining definition of the referenced local.