rustc_target: factor out common fields of non-Single Variants.
This commit is contained in:
parent
70a497a437
commit
5b7f4e9e21
@ -913,11 +913,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Ok(tcx.intern_layout(LayoutDetails {
|
return Ok(tcx.intern_layout(LayoutDetails {
|
||||||
variants: Variants::NicheFilling {
|
variants: Variants::Multiple {
|
||||||
|
discr: niche_scalar,
|
||||||
|
discr_kind: DiscriminantKind::Niche {
|
||||||
dataful_variant: i,
|
dataful_variant: i,
|
||||||
niche_variants,
|
niche_variants,
|
||||||
niche: niche_scalar,
|
|
||||||
niche_start,
|
niche_start,
|
||||||
|
},
|
||||||
variants: st,
|
variants: st,
|
||||||
},
|
},
|
||||||
fields: FieldPlacement::Arbitrary {
|
fields: FieldPlacement::Arbitrary {
|
||||||
@ -1137,8 +1139,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tcx.intern_layout(LayoutDetails {
|
tcx.intern_layout(LayoutDetails {
|
||||||
variants: Variants::Tagged {
|
variants: Variants::Multiple {
|
||||||
tag,
|
discr: tag,
|
||||||
|
discr_kind: DiscriminantKind::Tag,
|
||||||
variants: layout_variants,
|
variants: layout_variants,
|
||||||
},
|
},
|
||||||
fields: FieldPlacement::Arbitrary {
|
fields: FieldPlacement::Arbitrary {
|
||||||
@ -1293,8 +1296,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants::NicheFilling { .. } |
|
Variants::Multiple { ref discr, ref discr_kind, .. } => {
|
||||||
Variants::Tagged { .. } => {
|
|
||||||
debug!("print-type-size `{:#?}` adt general variants def {}",
|
debug!("print-type-size `{:#?}` adt general variants def {}",
|
||||||
layout.ty, adt_def.variants.len());
|
layout.ty, adt_def.variants.len());
|
||||||
let variant_infos: Vec<_> =
|
let variant_infos: Vec<_> =
|
||||||
@ -1306,8 +1308,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||||||
layout.for_variant(self, i))
|
layout.for_variant(self, i))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
record(adt_kind.into(), adt_packed, match layout.variants {
|
record(adt_kind.into(), adt_packed, match discr_kind {
|
||||||
Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)),
|
DiscriminantKind::Tag => Some(discr.value.size(self)),
|
||||||
_ => None
|
_ => None
|
||||||
}, variant_infos);
|
}, variant_infos);
|
||||||
}
|
}
|
||||||
@ -1627,8 +1629,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants::NicheFilling { ref variants, .. } |
|
Variants::Multiple { ref variants, .. } => {
|
||||||
Variants::Tagged { ref variants, .. } => {
|
|
||||||
&variants[variant_index]
|
&variants[variant_index]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1735,8 +1736,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Discriminant field for enums (where applicable).
|
// Discriminant field for enums (where applicable).
|
||||||
Variants::Tagged { tag: ref discr, .. } |
|
Variants::Multiple { ref discr, .. } => {
|
||||||
Variants::NicheFilling { niche: ref discr, .. } => {
|
|
||||||
assert_eq!(i, 0);
|
assert_eq!(i, 0);
|
||||||
let layout = LayoutDetails::scalar(cx, discr.clone());
|
let layout = LayoutDetails::scalar(cx, discr.clone());
|
||||||
return MaybeResult::from_ok(TyLayout {
|
return MaybeResult::from_ok(TyLayout {
|
||||||
@ -1881,26 +1881,37 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
|
|||||||
Single { index } => {
|
Single { index } => {
|
||||||
index.hash_stable(hcx, hasher);
|
index.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
Tagged {
|
Multiple {
|
||||||
ref tag,
|
ref discr,
|
||||||
|
ref discr_kind,
|
||||||
ref variants,
|
ref variants,
|
||||||
} => {
|
} => {
|
||||||
tag.hash_stable(hcx, hasher);
|
discr.hash_stable(hcx, hasher);
|
||||||
|
discr_kind.hash_stable(hcx, hasher);
|
||||||
variants.hash_stable(hcx, hasher);
|
variants.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
NicheFilling {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'a>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
use crate::ty::layout::DiscriminantKind::*;
|
||||||
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Tag => {}
|
||||||
|
Niche {
|
||||||
dataful_variant,
|
dataful_variant,
|
||||||
ref niche_variants,
|
ref niche_variants,
|
||||||
ref niche,
|
|
||||||
niche_start,
|
niche_start,
|
||||||
ref variants,
|
|
||||||
} => {
|
} => {
|
||||||
dataful_variant.hash_stable(hcx, hasher);
|
dataful_variant.hash_stable(hcx, hasher);
|
||||||
niche_variants.start().hash_stable(hcx, hasher);
|
niche_variants.start().hash_stable(hcx, hasher);
|
||||||
niche_variants.end().hash_stable(hcx, hasher);
|
niche_variants.end().hash_stable(hcx, hasher);
|
||||||
niche.hash_stable(hcx, hasher);
|
|
||||||
niche_start.hash_stable(hcx, hasher);
|
niche_start.hash_stable(hcx, hasher);
|
||||||
variants.hash_stable(hcx, hasher);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1235,7 +1235,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { ref variants, .. } => {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Tag,
|
||||||
|
ref variants,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
let discriminant_info = if fallback {
|
let discriminant_info = if fallback {
|
||||||
RegularDiscriminant(self.discriminant_type_metadata
|
RegularDiscriminant(self.discriminant_type_metadata
|
||||||
.expect(""))
|
.expect(""))
|
||||||
@ -1277,12 +1281,14 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||||||
}
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
layout::Variants::NicheFilling {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Niche {
|
||||||
ref niche_variants,
|
ref niche_variants,
|
||||||
niche_start,
|
niche_start,
|
||||||
ref variants,
|
|
||||||
dataful_variant,
|
dataful_variant,
|
||||||
ref niche,
|
},
|
||||||
|
ref discr,
|
||||||
|
ref variants,
|
||||||
} => {
|
} => {
|
||||||
if fallback {
|
if fallback {
|
||||||
let variant = self.layout.for_variant(cx, dataful_variant);
|
let variant = self.layout.for_variant(cx, dataful_variant);
|
||||||
@ -1369,7 +1375,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|||||||
let value = (i.as_u32() as u128)
|
let value = (i.as_u32() as u128)
|
||||||
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
||||||
.wrapping_add(niche_start);
|
.wrapping_add(niche_start);
|
||||||
let value = truncate(value, niche.value.size(cx));
|
let value = truncate(value, discr.value.size(cx));
|
||||||
|
// NOTE(eddyb) do *NOT* remove this assert, until
|
||||||
|
// we pass the full 128-bit value to LLVM, otherwise
|
||||||
|
// truncation will be silent and remain undetected.
|
||||||
|
assert_eq!(value as u64 as u128, value);
|
||||||
Some(value as u64)
|
Some(value as u64)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1586,8 +1596,11 @@ fn prepare_enum_metadata(
|
|||||||
let layout = cx.layout_of(enum_type);
|
let layout = cx.layout_of(enum_type);
|
||||||
|
|
||||||
match (&layout.abi, &layout.variants) {
|
match (&layout.abi, &layout.variants) {
|
||||||
(&layout::Abi::Scalar(_), &layout::Variants::Tagged {ref tag, .. }) =>
|
(&layout::Abi::Scalar(_), &layout::Variants::Multiple {
|
||||||
return FinalMetadata(discriminant_type_metadata(tag.value)),
|
discr_kind: layout::DiscriminantKind::Tag,
|
||||||
|
ref discr,
|
||||||
|
..
|
||||||
|
}) => return FinalMetadata(discriminant_type_metadata(discr.value)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1599,9 +1612,16 @@ fn prepare_enum_metadata(
|
|||||||
if use_enum_fallback(cx) {
|
if use_enum_fallback(cx) {
|
||||||
let discriminant_type_metadata = match layout.variants {
|
let discriminant_type_metadata = match layout.variants {
|
||||||
layout::Variants::Single { .. } |
|
layout::Variants::Single { .. } |
|
||||||
layout::Variants::NicheFilling { .. } => None,
|
layout::Variants::Multiple {
|
||||||
layout::Variants::Tagged { ref tag, .. } => {
|
discr_kind: layout::DiscriminantKind::Niche { .. },
|
||||||
Some(discriminant_type_metadata(tag.value))
|
..
|
||||||
|
} => None,
|
||||||
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Tag,
|
||||||
|
ref discr,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
Some(discriminant_type_metadata(discr.value))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1636,16 +1656,20 @@ fn prepare_enum_metadata(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let discriminator_metadata = match &layout.variants {
|
let discriminator_metadata = match layout.variants {
|
||||||
// A single-variant enum has no discriminant.
|
// A single-variant enum has no discriminant.
|
||||||
&layout::Variants::Single { .. } => None,
|
layout::Variants::Single { .. } => None,
|
||||||
|
|
||||||
&layout::Variants::NicheFilling { ref niche, .. } => {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Niche { .. },
|
||||||
|
ref discr,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
// Find the integer type of the correct size.
|
// Find the integer type of the correct size.
|
||||||
let size = niche.value.size(cx);
|
let size = discr.value.size(cx);
|
||||||
let align = niche.value.align(cx);
|
let align = discr.value.align(cx);
|
||||||
|
|
||||||
let discr_type = match niche.value {
|
let discr_type = match discr.value {
|
||||||
layout::Int(t, _) => t,
|
layout::Int(t, _) => t,
|
||||||
layout::Float(layout::FloatTy::F32) => Integer::I32,
|
layout::Float(layout::FloatTy::F32) => Integer::I32,
|
||||||
layout::Float(layout::FloatTy::F64) => Integer::I64,
|
layout::Float(layout::FloatTy::F64) => Integer::I64,
|
||||||
@ -1668,8 +1692,12 @@ fn prepare_enum_metadata(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
&layout::Variants::Tagged { ref tag, .. } => {
|
layout::Variants::Multiple {
|
||||||
let discr_type = tag.value.to_ty(cx.tcx);
|
discr_kind: layout::DiscriminantKind::Tag,
|
||||||
|
ref discr,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let discr_type = discr.value.to_ty(cx.tcx);
|
||||||
let (size, align) = cx.size_and_align_of(discr_type);
|
let (size, align) = cx.size_and_align_of(discr_type);
|
||||||
|
|
||||||
let discr_metadata = basic_type_metadata(cx, discr_type);
|
let discr_metadata = basic_type_metadata(cx, discr_type);
|
||||||
|
@ -452,7 +452,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
|
|||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
let mut data_variant = match self.variants {
|
let mut data_variant = match self.variants {
|
||||||
layout::Variants::NicheFilling { dataful_variant, .. } => {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Niche {
|
||||||
|
dataful_variant,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
} => {
|
||||||
// Only the niche itself is always initialized,
|
// Only the niche itself is always initialized,
|
||||||
// so only check for a pointer at its offset.
|
// so only check for a pointer at its offset.
|
||||||
//
|
//
|
||||||
|
@ -216,37 +216,36 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||||||
if self.layout.abi.is_uninhabited() {
|
if self.layout.abi.is_uninhabited() {
|
||||||
return bx.cx().const_undef(cast_to);
|
return bx.cx().const_undef(cast_to);
|
||||||
}
|
}
|
||||||
match self.layout.variants {
|
let (discr_scalar, discr_kind) = match self.layout.variants {
|
||||||
layout::Variants::Single { index } => {
|
layout::Variants::Single { index } => {
|
||||||
let discr_val = self.layout.ty.ty_adt_def().map_or(
|
let discr_val = self.layout.ty.ty_adt_def().map_or(
|
||||||
index.as_u32() as u128,
|
index.as_u32() as u128,
|
||||||
|def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
|
|def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
|
||||||
return bx.cx().const_uint_big(cast_to, discr_val);
|
return bx.cx().const_uint_big(cast_to, discr_val);
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { .. } |
|
layout::Variants::Multiple { ref discr, ref discr_kind, .. } => {
|
||||||
layout::Variants::NicheFilling { .. } => {},
|
(discr, discr_kind)
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let discr = self.project_field(bx, 0);
|
let discr = self.project_field(bx, 0);
|
||||||
let lldiscr = bx.load_operand(discr).immediate();
|
let lldiscr = bx.load_operand(discr).immediate();
|
||||||
match self.layout.variants {
|
match *discr_kind {
|
||||||
layout::Variants::Single { .. } => bug!(),
|
layout::DiscriminantKind::Tag => {
|
||||||
layout::Variants::Tagged { ref tag, .. } => {
|
let signed = match discr_scalar.value {
|
||||||
let signed = match tag.value {
|
|
||||||
// We use `i1` for bytes that are always `0` or `1`,
|
// We use `i1` for bytes that are always `0` or `1`,
|
||||||
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
|
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
|
||||||
// let LLVM interpret the `i1` as signed, because
|
// let LLVM interpret the `i1` as signed, because
|
||||||
// then `i1 1` (i.e., E::B) is effectively `i8 -1`.
|
// then `i1 1` (i.e., E::B) is effectively `i8 -1`.
|
||||||
layout::Int(_, signed) => !tag.is_bool() && signed,
|
layout::Int(_, signed) => !discr_scalar.is_bool() && signed,
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
bx.intcast(lldiscr, cast_to, signed)
|
bx.intcast(lldiscr, cast_to, signed)
|
||||||
}
|
}
|
||||||
layout::Variants::NicheFilling {
|
layout::DiscriminantKind::Niche {
|
||||||
dataful_variant,
|
dataful_variant,
|
||||||
ref niche_variants,
|
ref niche_variants,
|
||||||
niche_start,
|
niche_start,
|
||||||
..
|
|
||||||
} => {
|
} => {
|
||||||
let niche_llty = bx.cx().immediate_backend_type(discr.layout);
|
let niche_llty = bx.cx().immediate_backend_type(discr.layout);
|
||||||
if niche_variants.start() == niche_variants.end() {
|
if niche_variants.start() == niche_variants.end() {
|
||||||
@ -291,7 +290,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||||||
layout::Variants::Single { index } => {
|
layout::Variants::Single { index } => {
|
||||||
assert_eq!(index, variant_index);
|
assert_eq!(index, variant_index);
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { .. } => {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Tag,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
let ptr = self.project_field(bx, 0);
|
let ptr = self.project_field(bx, 0);
|
||||||
let to = self.layout.ty.ty_adt_def().unwrap()
|
let to = self.layout.ty.ty_adt_def().unwrap()
|
||||||
.discriminant_for_variant(bx.tcx(), variant_index)
|
.discriminant_for_variant(bx.tcx(), variant_index)
|
||||||
@ -301,10 +303,12 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||||||
ptr.llval,
|
ptr.llval,
|
||||||
ptr.align);
|
ptr.align);
|
||||||
}
|
}
|
||||||
layout::Variants::NicheFilling {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Niche {
|
||||||
dataful_variant,
|
dataful_variant,
|
||||||
ref niche_variants,
|
ref niche_variants,
|
||||||
niche_start,
|
niche_start,
|
||||||
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if variant_index != dataful_variant {
|
if variant_index != dataful_variant {
|
||||||
|
@ -303,8 +303,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { .. } |
|
layout::Variants::Multiple { .. } => {},
|
||||||
layout::Variants::NicheFilling { .. } => {},
|
|
||||||
}
|
}
|
||||||
let llval = operand.immediate();
|
let llval = operand.immediate();
|
||||||
|
|
||||||
|
@ -842,10 +842,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
|||||||
let item_def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
|
let item_def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
|
||||||
let t = cx.tcx.type_of(item_def_id);
|
let t = cx.tcx.type_of(item_def_id);
|
||||||
let ty = cx.tcx.erase_regions(&t);
|
let ty = cx.tcx.erase_regions(&t);
|
||||||
match cx.layout_of(ty) {
|
let layout = match cx.layout_of(ty) {
|
||||||
Ok(layout) => {
|
Ok(layout) => layout,
|
||||||
let variants = &layout.variants;
|
Err(ty::layout::LayoutError::Unknown(_)) => return,
|
||||||
if let layout::Variants::Tagged { ref variants, ref tag, .. } = variants {
|
Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
|
||||||
|
bug!("failed to get layout for `{}`: {}", t, err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let (variants, tag) = match layout.variants {
|
||||||
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Tag,
|
||||||
|
ref discr,
|
||||||
|
ref variants,
|
||||||
|
} => (variants, discr),
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
let discr_size = tag.value.size(&cx.tcx).bytes();
|
let discr_size = tag.value.size(&cx.tcx).bytes();
|
||||||
|
|
||||||
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||||
@ -883,11 +895,4 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(ty::layout::LayoutError::Unknown(_)) => return,
|
|
||||||
Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
|
|
||||||
bug!("failed to get layout for `{}`: {}", t, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
|
|||||||
dest);
|
dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { .. } |
|
layout::Variants::Multiple { .. } => {},
|
||||||
layout::Variants::NicheFilling { .. } => {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
|
let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
|
||||||
|
@ -610,25 +610,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
|
|||||||
) -> EvalResult<'tcx, (u128, VariantIdx)> {
|
) -> EvalResult<'tcx, (u128, VariantIdx)> {
|
||||||
trace!("read_discriminant_value {:#?}", rval.layout);
|
trace!("read_discriminant_value {:#?}", rval.layout);
|
||||||
|
|
||||||
match rval.layout.variants {
|
let discr_kind = match rval.layout.variants {
|
||||||
layout::Variants::Single { index } => {
|
layout::Variants::Single { index } => {
|
||||||
let discr_val = rval.layout.ty.ty_adt_def().map_or(
|
let discr_val = rval.layout.ty.ty_adt_def().map_or(
|
||||||
index.as_u32() as u128,
|
index.as_u32() as u128,
|
||||||
|def| def.discriminant_for_variant(*self.tcx, index).val);
|
|def| def.discriminant_for_variant(*self.tcx, index).val);
|
||||||
return Ok((discr_val, index));
|
return Ok((discr_val, index));
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { .. } |
|
layout::Variants::Multiple { ref discr_kind, .. } => discr_kind,
|
||||||
layout::Variants::NicheFilling { .. } => {},
|
};
|
||||||
}
|
|
||||||
// read raw discriminant value
|
// read raw discriminant value
|
||||||
let discr_op = self.operand_field(rval, 0)?;
|
let discr_op = self.operand_field(rval, 0)?;
|
||||||
let discr_val = self.read_immediate(discr_op)?;
|
let discr_val = self.read_immediate(discr_op)?;
|
||||||
let raw_discr = discr_val.to_scalar_or_undef();
|
let raw_discr = discr_val.to_scalar_or_undef();
|
||||||
trace!("discr value: {:?}", raw_discr);
|
trace!("discr value: {:?}", raw_discr);
|
||||||
// post-process
|
// post-process
|
||||||
Ok(match rval.layout.variants {
|
Ok(match *discr_kind {
|
||||||
layout::Variants::Single { .. } => bug!(),
|
layout::DiscriminantKind::Tag => {
|
||||||
layout::Variants::Tagged { .. } => {
|
|
||||||
let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
|
let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
|
||||||
Ok(raw_discr) => raw_discr,
|
Ok(raw_discr) => raw_discr,
|
||||||
Err(_) => return err!(InvalidDiscriminant(raw_discr.erase_tag())),
|
Err(_) => return err!(InvalidDiscriminant(raw_discr.erase_tag())),
|
||||||
@ -657,11 +656,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
|
|||||||
.ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
|
.ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
|
||||||
(real_discr, index.0)
|
(real_discr, index.0)
|
||||||
},
|
},
|
||||||
layout::Variants::NicheFilling {
|
layout::DiscriminantKind::Niche {
|
||||||
dataful_variant,
|
dataful_variant,
|
||||||
ref niche_variants,
|
ref niche_variants,
|
||||||
niche_start,
|
niche_start,
|
||||||
..
|
|
||||||
} => {
|
} => {
|
||||||
let variants_start = niche_variants.start().as_u32() as u128;
|
let variants_start = niche_variants.start().as_u32() as u128;
|
||||||
let variants_end = niche_variants.end().as_u32() as u128;
|
let variants_end = niche_variants.end().as_u32() as u128;
|
||||||
|
@ -958,7 +958,11 @@ where
|
|||||||
layout::Variants::Single { index } => {
|
layout::Variants::Single { index } => {
|
||||||
assert_eq!(index, variant_index);
|
assert_eq!(index, variant_index);
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { ref tag, .. } => {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Tag,
|
||||||
|
ref discr,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
let adt_def = dest.layout.ty.ty_adt_def().unwrap();
|
let adt_def = dest.layout.ty.ty_adt_def().unwrap();
|
||||||
assert!(variant_index.as_usize() < adt_def.variants.len());
|
assert!(variant_index.as_usize() < adt_def.variants.len());
|
||||||
let discr_val = adt_def
|
let discr_val = adt_def
|
||||||
@ -968,16 +972,18 @@ where
|
|||||||
// raw discriminants for enums are isize or bigger during
|
// raw discriminants for enums are isize or bigger during
|
||||||
// their computation, but the in-memory tag is the smallest possible
|
// their computation, but the in-memory tag is the smallest possible
|
||||||
// representation
|
// representation
|
||||||
let size = tag.value.size(self);
|
let size = discr.value.size(self);
|
||||||
let discr_val = truncate(discr_val, size);
|
let discr_val = truncate(discr_val, size);
|
||||||
|
|
||||||
let discr_dest = self.place_field(dest, 0)?;
|
let discr_dest = self.place_field(dest, 0)?;
|
||||||
self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
|
self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
|
||||||
}
|
}
|
||||||
layout::Variants::NicheFilling {
|
layout::Variants::Multiple {
|
||||||
|
discr_kind: layout::DiscriminantKind::Niche {
|
||||||
dataful_variant,
|
dataful_variant,
|
||||||
ref niche_variants,
|
ref niche_variants,
|
||||||
niche_start,
|
niche_start,
|
||||||
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -241,8 +241,7 @@ macro_rules! make_value_visitor {
|
|||||||
// If this is a multi-variant layout, we have find the right one and proceed with
|
// If this is a multi-variant layout, we have find the right one and proceed with
|
||||||
// that.
|
// that.
|
||||||
match v.layout().variants {
|
match v.layout().variants {
|
||||||
layout::Variants::NicheFilling { .. } |
|
layout::Variants::Multiple { .. } => {
|
||||||
layout::Variants::Tagged { .. } => {
|
|
||||||
let op = v.to_op(self.ecx())?;
|
let op = v.to_op(self.ecx())?;
|
||||||
let idx = self.ecx().read_discriminant(op)?.1;
|
let idx = self.ecx().read_discriminant(op)?.1;
|
||||||
let inner = v.project_downcast(self.ecx(), idx)?;
|
let inner = v.project_downcast(self.ecx(), idx)?;
|
||||||
|
@ -61,8 +61,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &ArgType<'a, Ty>)
|
|||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
abi::Variants::Tagged { .. } |
|
abi::Variants::Multiple { .. } => return Err(Memory),
|
||||||
abi::Variants::NicheFilling { .. } => return Err(Memory),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -828,15 +828,22 @@ pub enum Variants {
|
|||||||
index: VariantIdx,
|
index: VariantIdx,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// General-case enums: for each case there is a struct, and they all have
|
/// Enums with more than one inhabited variant: for each case there is
|
||||||
/// all space reserved for the tag, and their first field starts
|
/// a struct, and they all have space reserved for the discriminant,
|
||||||
/// at a non-0 offset, after where the tag would go.
|
/// which is the sole field of the enum layout.
|
||||||
Tagged {
|
Multiple {
|
||||||
tag: Scalar,
|
discr: Scalar,
|
||||||
|
discr_kind: DiscriminantKind,
|
||||||
variants: IndexVec<VariantIdx, LayoutDetails>,
|
variants: IndexVec<VariantIdx, LayoutDetails>,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
/// Multiple cases distinguished by a niche (values invalid for a type):
|
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub enum DiscriminantKind {
|
||||||
|
/// Integer tag holding the discriminant value itself.
|
||||||
|
Tag,
|
||||||
|
|
||||||
|
/// Niche (values invalid for a type) encoding the discriminant:
|
||||||
/// the variant `dataful_variant` contains a niche at an arbitrary
|
/// the variant `dataful_variant` contains a niche at an arbitrary
|
||||||
/// offset (field 0 of the enum), which for a variant with discriminant
|
/// offset (field 0 of the enum), which for a variant with discriminant
|
||||||
/// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
|
/// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
|
||||||
@ -844,13 +851,11 @@ pub enum Variants {
|
|||||||
/// For example, `Option<(usize, &T)>` is represented such that
|
/// For example, `Option<(usize, &T)>` is represented such that
|
||||||
/// `None` has a null pointer for the second tuple field, and
|
/// `None` has a null pointer for the second tuple field, and
|
||||||
/// `Some` is the identity function (with a non-null reference).
|
/// `Some` is the identity function (with a non-null reference).
|
||||||
NicheFilling {
|
Niche {
|
||||||
dataful_variant: VariantIdx,
|
dataful_variant: VariantIdx,
|
||||||
niche_variants: RangeInclusive<VariantIdx>,
|
niche_variants: RangeInclusive<VariantIdx>,
|
||||||
niche: Scalar,
|
|
||||||
niche_start: u128,
|
niche_start: u128,
|
||||||
variants: IndexVec<VariantIdx, LayoutDetails>,
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||||
|
Loading…
Reference in New Issue
Block a user