Files
rust/compiler/rustc_codegen_ssa/src/mir/constant.rs

119 lines
4.5 KiB
Rust
Raw Normal View History

use crate::errors;
2019-12-22 17:42:04 -05:00
use crate::mir::operand::OperandRef;
use crate::traits::*;
2020-03-29 16:41:09 +02:00
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
use rustc_middle::ty::layout::HasTyCtxt;
2020-03-29 16:41:09 +02:00
use rustc_middle::ty::{self, Ty};
use rustc_target::abi::Abi;
use super::FunctionCx;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn eval_mir_constant_to_operand(
&self,
bx: &mut Bx,
constant: &mir::Constant<'tcx>,
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
let val = self.eval_mir_constant(constant)?;
let ty = self.monomorphize(constant.ty());
Ok(OperandRef::from_const(bx, val, ty))
}
2019-03-14 10:19:31 +01:00
pub fn eval_mir_constant(
&self,
2019-03-14 10:19:31 +01:00
constant: &mir::Constant<'tcx>,
) -> Result<ConstValue<'tcx>, ErrorHandled> {
let ct = self.monomorphize(constant.literal);
let uv = match ct {
mir::ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => uv.expand(),
ty::ConstKind::Value(val) => {
return Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val)));
}
err => span_bug!(
constant.span,
"encountered bad ConstKind after monomorphizing: {:?}",
err
),
},
mir::ConstantKind::Unevaluated(uv, _) => uv,
2021-03-15 11:23:44 +00:00
mir::ConstantKind::Val(val, _) => return Ok(val),
};
self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
match err {
ErrorHandled::Reported(_) => {
self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span });
}
ErrorHandled::TooGeneric => {
self.cx
.tcx()
.sess
.diagnostic()
.emit_bug(errors::PolymorphicConstantTooGeneric { span: constant.span });
}
}
err
})
2017-01-02 11:00:42 -07:00
}
/// 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 constant.literal {
mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
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,
constant: &mir::Constant<'tcx>,
) -> (Bx::Value, Ty<'tcx>) {
let ty = self.monomorphize(constant.ty());
let val = self
.eval_unevaluated_mir_constant_to_valtree(constant)
2023-06-16 16:02:11 +00:00
.ok()
.flatten()
.map(|val| {
let field_ty = ty.builtin_index().unwrap();
2023-06-16 16:02:11 +00:00
let values: Vec<_> = val
.unwrap_branch()
.iter()
2019-12-22 17:42:04 -05:00
.map(|field| {
if let Some(prim) = field.try_to_scalar() {
2019-12-22 17:42:04 -05:00
let layout = bx.layout_of(field_ty);
2022-02-19 00:48:49 +01:00
let Abi::Scalar(scalar) = layout.abi else {
bug!("from_const: invalid ByVal layout: {:#?}", layout);
2019-12-22 17:42:04 -05:00
};
bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
} else {
bug!("simd shuffle field {:?}", field)
}
})
.collect();
2023-06-16 16:02:11 +00:00
bx.const_struct(&values, false)
2018-01-16 09:31:48 +01:00
})
2023-06-16 16:02:11 +00:00
.unwrap_or_else(|| {
bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span: constant.span });
2018-01-16 09:31:48 +01:00
// We've errored, so we don't have to produce working code.
let llty = bx.backend_type(bx.layout_of(ty));
2023-06-16 16:02:11 +00:00
bx.const_undef(llty)
});
(val, ty)
2017-01-02 11:00:42 -07:00
}
}