1
Fork 0

Add tag_for_variant query

This query allows for sharing code between `rustc_const_eval` and
`rustc_transmutability`.

Also moves `DummyMachine` to `rustc_const_eval`.
This commit is contained in:
Jack Wrenn 2024-03-20 17:45:14 +00:00
parent 9023f908cf
commit 2de9010f66
13 changed files with 347 additions and 292 deletions

View file

@ -174,10 +174,10 @@ pub(crate) mod rustc {
use crate::layout::rustc::{Def, Ref};
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::AdtDef;
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::ParamEnv;
use rustc_middle::ty::ScalarInt;
use rustc_middle::ty::VariantDef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::ErrorGuaranteed;
@ -331,14 +331,15 @@ pub(crate) mod rustc {
trace!(?adt_def, "treeifying enum");
let mut tree = Tree::uninhabited();
for (idx, discr) in adt_def.discriminants(tcx) {
for (idx, variant) in adt_def.variants().iter_enumerated() {
let tag = tcx.tag_for_variant((ty, idx));
tree = tree.or(Self::from_repr_c_variant(
ty,
*adt_def,
args_ref,
&layout_summary,
Some(discr),
adt_def.variant(idx),
tag,
variant,
tcx,
)?);
}
@ -393,7 +394,7 @@ pub(crate) mod rustc {
adt_def: AdtDef<'tcx>,
args_ref: GenericArgsRef<'tcx>,
layout_summary: &LayoutSummary,
discr: Option<Discr<'tcx>>,
tag: Option<ScalarInt>,
variant_def: &'tcx VariantDef,
tcx: TyCtxt<'tcx>,
) -> Result<Self, Err> {
@ -403,9 +404,6 @@ pub(crate) mod rustc {
let min_align = repr.align.unwrap_or(Align::ONE);
let max_align = repr.pack.unwrap_or(Align::MAX);
let clamp =
|align: Align| align.clamp(min_align, max_align).bytes().try_into().unwrap();
let variant_span = trace_span!(
"treeifying variant",
min_align = ?min_align,
@ -419,17 +417,12 @@ pub(crate) mod rustc {
)
.unwrap();
// The layout of the variant is prefixed by the discriminant, if any.
if let Some(discr) = discr {
trace!(?discr, "treeifying discriminant");
let discr_layout = alloc::Layout::from_size_align(
layout_summary.discriminant_size,
clamp(layout_summary.discriminant_align),
)
.unwrap();
trace!(?discr_layout, "computed discriminant layout");
variant_layout = variant_layout.extend(discr_layout).unwrap().0;
tree = tree.then(Self::from_discr(discr, tcx, layout_summary.discriminant_size));
// The layout of the variant is prefixed by the tag, if any.
if let Some(tag) = tag {
let tag_layout =
alloc::Layout::from_size_align(tag.size().bytes_usize(), 1).unwrap();
tree = tree.then(Self::from_tag(tag, tcx));
variant_layout = variant_layout.extend(tag_layout).unwrap().0;
}
// Next come fields.
@ -469,18 +462,19 @@ pub(crate) mod rustc {
Ok(tree)
}
pub fn from_discr(discr: Discr<'tcx>, tcx: TyCtxt<'tcx>, size: usize) -> Self {
pub fn from_tag(tag: ScalarInt, tcx: TyCtxt<'tcx>) -> Self {
use rustc_target::abi::Endian;
let size = tag.size();
let bits = tag.to_bits(size).unwrap();
let bytes: [u8; 16];
let bytes = match tcx.data_layout.endian {
Endian::Little => {
bytes = discr.val.to_le_bytes();
&bytes[..size]
bytes = bits.to_le_bytes();
&bytes[..size.bytes_usize()]
}
Endian::Big => {
bytes = discr.val.to_be_bytes();
&bytes[bytes.len() - size..]
bytes = bits.to_be_bytes();
&bytes[bytes.len() - size.bytes_usize()..]
}
};
Self::Seq(bytes.iter().map(|&b| Self::from_bits(b)).collect())