Skip to content

Commit d3817e2

Browse files
authored
Rollup merge of rust-lang#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``
2 parents 5fd3e4d + a3c89a7 commit d3817e2

File tree

1 file changed

+23
-35
lines changed

1 file changed

+23
-35
lines changed

src/constant.rs

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,8 @@ impl ConstantCx {
3838
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
3939
let mut all_constants_ok = true;
4040
for constant in &fx.mir.required_consts {
41-
let unevaluated = match fx.monomorphize(constant.literal) {
42-
ConstantKind::Ty(_) => unreachable!(),
43-
ConstantKind::Unevaluated(uv, _) => uv,
44-
ConstantKind::Val(..) => continue,
45-
};
46-
47-
if let Err(err) = fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
41+
if eval_mir_constant(fx, constant).is_none() {
4842
all_constants_ok = false;
49-
match err {
50-
ErrorHandled::Reported(_) => {
51-
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
52-
}
53-
ErrorHandled::TooGeneric => {
54-
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
55-
}
56-
}
5743
}
5844
}
5945
all_constants_ok
@@ -80,15 +66,15 @@ pub(crate) fn codegen_tls_ref<'tcx>(
8066
}
8167

8268
pub(crate) fn eval_mir_constant<'tcx>(
83-
fx: &mut FunctionCx<'_, '_, 'tcx>,
69+
fx: &FunctionCx<'_, '_, 'tcx>,
8470
constant: &Constant<'tcx>,
85-
) -> (ConstValue<'tcx>, Ty<'tcx>) {
71+
) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
8672
let constant_kind = fx.monomorphize(constant.literal);
8773
let uv = match constant_kind {
8874
ConstantKind::Ty(const_) => match const_.kind() {
8975
ty::ConstKind::Unevaluated(uv) => uv.expand(),
9076
ty::ConstKind::Value(val) => {
91-
return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty());
77+
return Some((fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty()));
9278
}
9379
err => span_bug!(
9480
constant.span,
@@ -102,22 +88,31 @@ pub(crate) fn eval_mir_constant<'tcx>(
10288
span_bug!(constant.span, "MIR constant refers to static");
10389
}
10490
ConstantKind::Unevaluated(uv, _) => uv,
105-
ConstantKind::Val(val, _) => return (val, constant_kind.ty()),
91+
ConstantKind::Val(val, _) => return Some((val, constant_kind.ty())),
10692
};
10793

108-
(
109-
fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| {
110-
span_bug!(constant.span, "erroneous constant not captured by required_consts");
111-
}),
112-
constant_kind.ty(),
113-
)
94+
let val = fx
95+
.tcx
96+
.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None)
97+
.map_err(|err| match err {
98+
ErrorHandled::Reported(_) => {
99+
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
100+
}
101+
ErrorHandled::TooGeneric => {
102+
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
103+
}
104+
})
105+
.ok();
106+
val.map(|val| (val, constant_kind.ty()))
114107
}
115108

116109
pub(crate) fn codegen_constant_operand<'tcx>(
117110
fx: &mut FunctionCx<'_, '_, 'tcx>,
118111
constant: &Constant<'tcx>,
119112
) -> CValue<'tcx> {
120-
let (const_val, ty) = eval_mir_constant(fx, constant);
113+
let (const_val, ty) = eval_mir_constant(fx, constant).unwrap_or_else(|| {
114+
span_bug!(constant.span, "erroneous constant not captured by required_consts")
115+
});
121116

122117
codegen_const_value(fx, const_val, ty)
123118
}
@@ -453,20 +448,13 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
453448
assert!(cx.todo.is_empty(), "{:?}", cx.todo);
454449
}
455450

451+
/// Used only for intrinsic implementations that need a compile-time constant
456452
pub(crate) fn mir_operand_get_const_val<'tcx>(
457453
fx: &FunctionCx<'_, '_, 'tcx>,
458454
operand: &Operand<'tcx>,
459455
) -> Option<ConstValue<'tcx>> {
460456
match operand {
461-
Operand::Constant(const_) => match fx.monomorphize(const_.literal) {
462-
ConstantKind::Ty(const_) => Some(
463-
const_.eval_for_mir(fx.tcx, ParamEnv::reveal_all()).try_to_value(fx.tcx).unwrap(),
464-
),
465-
ConstantKind::Val(val, _) => Some(val),
466-
ConstantKind::Unevaluated(uv, _) => {
467-
Some(fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).unwrap())
468-
}
469-
},
457+
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0),
470458
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
471459
// inside a temporary before being passed to the intrinsic requiring the const argument.
472460
// This code tries to find a single constant defining definition of the referenced local.

0 commit comments

Comments
 (0)