From 23ed79bc006b2fb9ec3fd5d59edf4150078ce8fd Mon Sep 17 00:00:00 2001 From: FedericoBruzzone <federico.bruzzone.i@gmail.com> Date: Mon, 27 Jan 2025 09:14:51 +0100 Subject: [PATCH] Move `try_to_bits` from `Const` to `Valtree` Signed-off-by: FedericoBruzzone <federico.bruzzone.i@gmail.com> --- .../src/debuginfo/type_names.rs | 10 +++--- compiler/rustc_middle/src/ty/consts.rs | 12 ------- .../rustc_middle/src/ty/consts/valtree.rs | 15 +++++++++ .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 10 +++--- compiler/rustc_symbol_mangling/src/v0.rs | 4 +-- compiler/rustc_ty_utils/src/layout.rs | 31 ++++++++++++------- 6 files changed, 45 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 869798d8be194..3dc9758554bdb 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -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}") } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 310552764224e..7c340bd4b6ba6 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -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(_)) } diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 9f9bf41c3355a..2f246a0e245e8 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -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]> { diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 09648e28df471..7b6defd884ba0 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -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 @@ -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 { @@ -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}"); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 4ddf530a00d4a..d25d938d6c4b3 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -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". diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index a04c753611831..fde9a634d401d 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -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 }; } @@ -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))); } @@ -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); @@ -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)))?;