Skip to content

Commit

Permalink
Move try_to_bits from Const to Valtree
Browse files Browse the repository at this point in the history
Signed-off-by: FedericoBruzzone <[email protected]>
  • Loading branch information
FedericoBruzzone committed Jan 27, 2025
1 parent 5545959 commit 23ed79b
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 37 deletions.
10 changes: 4 additions & 6 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,17 +676,15 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
ty::ConstKind::Value(ty, valtree) => {
match ty.kind() {
ty::Int(ity) => {
// FIXME: directly extract the bits from a valtree instead of evaluating an
// already evaluated `Const` in order to get the bits.
let bits = ct
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
let bits = valtree
.try_to_bits(tcx, ty, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in codegen");
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
write!(output, "{val}")
}
ty::Uint(_) => {
let val = ct
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
let val = valtree
.try_to_bits(tcx, ty, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in codegen");
write!(output, "{val}")
}
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,18 +245,6 @@ impl<'tcx> Const<'tcx> {
self.try_to_valtree()?.0.try_to_target_usize(tcx)
}

/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
/// contains const generic parameters or pointers).
#[inline]
pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
let (scalar, ty) = self.try_to_scalar()?;
let scalar = scalar.try_to_scalar_int().ok()?;
let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(ty);
let size = tcx.layout_of(input).ok()?.size;
Some(scalar.to_bits(size))
}

pub fn is_ct_infer(self) -> bool {
matches!(self.kind(), ty::ConstKind::Infer(_))
}
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_middle/src/ty/consts/valtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@ impl<'tcx> ValTree<'tcx> {
self.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
}

/// Attempts to extract the raw bits of the valtree.
///
/// Can fail if the value can't be represented as bits (e.g. because it is an aggregate).
pub fn try_to_bits(
self,
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
) -> Option<u128> {
let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(ty);
let size = tcx.layout_of(input).ok()?.size;
let scalar = self.try_to_scalar_int()?;
Some(scalar.to_bits(size))
}

/// Get the values inside the ValTree as a slice of bytes. This only works for
/// constants with types &str, &[u8], or [u8; _].
pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ fn encode_const<'tcx>(
}

// Literal arguments
ty::ConstKind::Value(ct_ty, ..) => {
ty::ConstKind::Value(ct_ty, valtree) => {
// L<element-type>[n]<element-value>E as literal argument

// Element type
Expand All @@ -132,8 +132,8 @@ fn encode_const<'tcx>(
// bool value false is encoded as 0 and true as 1.
match ct_ty.kind() {
ty::Int(ity) => {
let bits = c
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
let bits = valtree
.try_to_bits(tcx, ct_ty, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in cfi");
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
if val < 0 {
Expand All @@ -142,8 +142,8 @@ fn encode_const<'tcx>(
let _ = write!(s, "{val}");
}
ty::Uint(_) => {
let val = c
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
let val = valtree
.try_to_bits(tcx, ct_ty, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in cfi");
let _ = write!(s, "{val}");
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
ct_ty.print(self)?;

let mut bits = ct
.try_to_bits(self.tcx, ty::TypingEnv::fully_monomorphized())
let mut bits = valtree
.try_to_bits(self.tcx, ct_ty, ty::TypingEnv::fully_monomorphized())
.expect("expected const to be monomorphic");

// Negative integer values are mangled using `n` as a "sign prefix".
Expand Down
31 changes: 19 additions & 12 deletions compiler/rustc_ty_utils/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ use crate::errors::{

mod invariant;

/// The `ValTree` alongside its type.
struct ValTreeAndTy<'tcx> {
valtree: ty::ValTree<'tcx>,
ty: Ty<'tcx>,
}

pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { layout_of, ..*providers };
}
Expand Down Expand Up @@ -144,13 +150,13 @@ fn univariant_uninterned<'tcx>(
cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err))
}

fn validate_const_with_value<'tcx>(
fn extract_valtree_and_ty<'tcx>(
const_: ty::Const<'tcx>,
ty: Ty<'tcx>,
cx: &LayoutCx<'tcx>,
) -> Result<ty::Const<'tcx>, &'tcx LayoutError<'tcx>> {
) -> Result<ValTreeAndTy<'tcx>, &'tcx LayoutError<'tcx>> {
match const_.kind() {
ty::ConstKind::Value(..) => Ok(const_),
ty::ConstKind::Value(ty, valtree) => Ok(ValTreeAndTy { valtree, ty }),
ty::ConstKind::Error(guar) => {
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
Expand Down Expand Up @@ -209,14 +215,16 @@ fn layout_of_uncached<'tcx>(
&mut layout.backend_repr
{
if let Some(start) = start {
scalar.valid_range_mut().start =
validate_const_with_value(start, ty, cx)?
.try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
let ValTreeAndTy { valtree, ty } =
extract_valtree_and_ty(start, ty, cx)?;
scalar.valid_range_mut().start = valtree
.try_to_bits(tcx, ty, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
}
if let Some(end) = end {
let mut end = validate_const_with_value(end, ty, cx)?
.try_to_bits(tcx, cx.typing_env)
let ValTreeAndTy { valtree, ty } = extract_valtree_and_ty(end, ty, cx)?;
let mut end = valtree
.try_to_bits(tcx, ty, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
if !include_end {
end = end.wrapping_sub(1);
Expand Down Expand Up @@ -348,9 +356,8 @@ fn layout_of_uncached<'tcx>(

// Arrays and slices.
ty::Array(element, count) => {
let count = validate_const_with_value(count, ty, cx)?
.to_valtree()
.0
let count = extract_valtree_and_ty(count, ty, cx)?
.valtree
.try_to_target_usize(tcx)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;

Expand Down

0 comments on commit 23ed79b

Please sign in to comment.