summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_ssa/src/mir/constant.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir/constant.rs')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs64
1 files changed, 47 insertions, 17 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 14fe84a14..babcf9bee 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -5,7 +5,6 @@ use rustc_middle::mir;
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{self, Ty};
-use rustc_span::source_map::Span;
use rustc_target::abi::Abi;
use super::FunctionCx;
@@ -59,22 +58,54 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
})
}
+ /// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
+ /// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to
+ /// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
+ pub fn eval_unevaluated_mir_constant_to_valtree(
+ &self,
+ constant: &mir::Constant<'tcx>,
+ ) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
+ let uv = match self.monomorphize(constant.literal) {
+ mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
+ mir::ConstantKind::Ty(c) => match c.kind() {
+ // A constant that came from a const generic but was then used as an argument to old-style
+ // simd_shuffle (passing as argument instead of as a generic param).
+ rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
+ other => span_bug!(constant.span, "{other:#?}"),
+ },
+ // We should never encounter `ConstantKind::Val` unless MIR opts (like const prop) evaluate
+ // a constant and write that value back into `Operand`s. This could happen, but is unlikely.
+ // Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care
+ // around intrinsics. For an issue to happen here, it would require a macro expanding to a
+ // `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but
+ // the user pass through arbitrary expressions.
+ // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real
+ // const generic.
+ other => span_bug!(constant.span, "{other:#?}"),
+ };
+ let uv = self.monomorphize(uv);
+ self.cx.tcx().const_eval_resolve_for_typeck(
+ ty::ParamEnv::reveal_all(),
+ uv,
+ Some(constant.span),
+ )
+ }
+
/// process constant containing SIMD shuffle indices
pub fn simd_shuffle_indices(
&mut self,
bx: &Bx,
- span: Span,
- ty: Ty<'tcx>,
- constant: Result<ConstValue<'tcx>, ErrorHandled>,
+ constant: &mir::Constant<'tcx>,
) -> (Bx::Value, Ty<'tcx>) {
- constant
+ let ty = self.monomorphize(constant.ty());
+ let val = self
+ .eval_unevaluated_mir_constant_to_valtree(constant)
+ .ok()
+ .flatten()
.map(|val| {
let field_ty = ty.builtin_index().unwrap();
- let c = mir::ConstantKind::from_value(val, ty);
- let values: Vec<_> = bx
- .tcx()
- .destructure_mir_constant(ty::ParamEnv::reveal_all(), c)
- .fields
+ let values: Vec<_> = val
+ .unwrap_branch()
.iter()
.map(|field| {
if let Some(prim) = field.try_to_scalar() {
@@ -88,15 +119,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
})
.collect();
- let llval = bx.const_struct(&values, false);
- (llval, c.ty())
+ bx.const_struct(&values, false)
})
- .unwrap_or_else(|_| {
- bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span });
+ .unwrap_or_else(|| {
+ bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span: constant.span });
// We've errored, so we don't have to produce working code.
- let ty = self.monomorphize(ty);
let llty = bx.backend_type(bx.layout_of(ty));
- (bx.const_undef(llty), ty)
- })
+ bx.const_undef(llty)
+ });
+ (val, ty)
}
}