diff options
Diffstat (limited to 'compiler/rustc_transmute')
-rw-r--r-- | compiler/rustc_transmute/src/layout/tree.rs | 22 | ||||
-rw-r--r-- | compiler/rustc_transmute/src/lib.rs | 19 |
2 files changed, 28 insertions, 13 deletions
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 211c813b8..acd4fa63d 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -404,7 +404,7 @@ pub(crate) mod rustc { .unwrap(); trace!(?discr_layout, "computed discriminant layout"); variant_layout = variant_layout.extend(discr_layout).unwrap().0; - tree = tree.then(Self::from_disr(discr, tcx, layout_summary.discriminant_size)); + tree = tree.then(Self::from_discr(discr, tcx, layout_summary.discriminant_size)); } // Next come fields. @@ -444,11 +444,21 @@ pub(crate) mod rustc { Ok(tree) } - pub fn from_disr(discr: Discr<'tcx>, tcx: TyCtxt<'tcx>, size: usize) -> Self { - // FIXME(@jswrenn): I'm certain this is missing needed endian nuance. - let bytes = discr.val.to_ne_bytes(); - let bytes = &bytes[..size]; - Self::Seq(bytes.into_iter().copied().map(|b| Self::from_bits(b)).collect()) + pub fn from_discr(discr: Discr<'tcx>, tcx: TyCtxt<'tcx>, size: usize) -> Self { + use rustc_target::abi::Endian; + + let bytes: [u8; 16]; + let bytes = match tcx.data_layout.endian { + Endian::Little => { + bytes = discr.val.to_le_bytes(); + &bytes[..size] + } + Endian::Big => { + bytes = discr.val.to_be_bytes(); + &bytes[bytes.len() - size..] + } + }; + Self::Seq(bytes.iter().map(|&b| Self::from_bits(b)).collect()) } } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 64cd70d36..f7cc94e53 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -80,11 +80,11 @@ mod rustc { } pub struct TransmuteTypeEnv<'cx, 'tcx> { - infcx: &'cx InferCtxt<'cx, 'tcx>, + infcx: &'cx InferCtxt<'tcx>, } impl<'cx, 'tcx> TransmuteTypeEnv<'cx, 'tcx> { - pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> Self { + pub fn new(infcx: &'cx InferCtxt<'tcx>) -> Self { Self { infcx } } @@ -115,7 +115,7 @@ mod rustc { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, c: Const<'tcx>, - ) -> Self { + ) -> Option<Self> { use rustc_middle::ty::ScalarInt; use rustc_middle::ty::TypeVisitable; use rustc_span::symbol::sym; @@ -123,10 +123,15 @@ mod rustc { let c = c.eval(tcx, param_env); if let Some(err) = c.error_reported() { - return Self { alignment: true, lifetimes: true, safety: true, validity: true }; + return Some(Self { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + }); } - let adt_def = c.ty().ty_adt_def().expect("The given `Const` must be an ADT."); + let adt_def = c.ty().ty_adt_def()?; assert_eq!( tcx.require_lang_item(LangItem::TransmuteOpts, None), @@ -148,12 +153,12 @@ mod rustc { fields[field_idx].unwrap_leaf() == ScalarInt::TRUE }; - Self { + Some(Self { alignment: get_field(sym::alignment), lifetimes: get_field(sym::lifetimes), safety: get_field(sym::safety), validity: get_field(sym::validity), - } + }) } } } |