1use rustc_abi::{Integer, Primitive, Size, TagEncoding, Variants};
2use rustc_middle::bug;
3use rustc_middle::ty::layout::{IntegerExt, PrimitiveExt, TyAndLayout};
4use rustc_middle::ty::{self, Ty, TyCtxt};
56// FIXME(eddyb) find a place for this (or a way to replace it).
7pub mod type_names;
89/// Returns true if we want to generate a DW_TAG_enumeration_type description for
10/// this instead of a DW_TAG_struct_type with DW_TAG_variant_part.
11///
12/// NOTE: This is somewhat inconsistent right now: For empty enums and enums with a single
13/// fieldless variant, we generate DW_TAG_struct_type, although a
14/// DW_TAG_enumeration_type would be a better fit.
15pub fn wants_c_like_enum_debuginfo<'tcx>(
16 tcx: TyCtxt<'tcx>,
17 enum_type_and_layout: TyAndLayout<'tcx>,
18) -> bool {
19match enum_type_and_layout.ty.kind() {
20 ty::Adt(adt_def, _) => {
21if !adt_def.is_enum() {
22return false;
23 }
2425if type_names::cpp_like_debuginfo(tcx)
26 && tag_base_type_opt(tcx, enum_type_and_layout)
27 .map(|ty| ty.primitive_size(tcx).bits())
28 == Some(128)
29 {
30// C++-like debuginfo never uses the C-like representation for 128-bit enums.
31return false;
32 }
3334match adt_def.variants().len() {
350 => false,
361 => {
37// Univariant enums unless they are zero-sized
38enum_type_and_layout.size != Size::ZERO && adt_def.all_fields().count() == 0
39}
40_ => {
41// Enums with more than one variant if they have no fields
42adt_def.all_fields().count() == 0
43}
44 }
45 }
46_ => false,
47 }
48}
4950/// Extract the type with which we want to describe the tag of the given enum or coroutine.
51pub fn tag_base_type<'tcx>(tcx: TyCtxt<'tcx>, enum_type_and_layout: TyAndLayout<'tcx>) -> Ty<'tcx> {
52tag_base_type_opt(tcx, enum_type_and_layout).unwrap_or_else(|| {
53::rustc_middle::util::bug::bug_fmt(format_args!("tag_base_type() called for enum without tag: {0:?}",
enum_type_and_layout))bug!("tag_base_type() called for enum without tag: {:?}", enum_type_and_layout)54 })
55}
5657fn tag_base_type_opt<'tcx>(
58 tcx: TyCtxt<'tcx>,
59 enum_type_and_layout: TyAndLayout<'tcx>,
60) -> Option<Ty<'tcx>> {
61if !match enum_type_and_layout.ty.kind() {
ty::Coroutine(..) => true,
ty::Adt(adt_def, _) => adt_def.is_enum(),
_ => false,
} {
::core::panicking::panic("assertion failed: match enum_type_and_layout.ty.kind() {\n ty::Coroutine(..) => true,\n ty::Adt(adt_def, _) => adt_def.is_enum(),\n _ => false,\n}")
};assert!(match enum_type_and_layout.ty.kind() {
62 ty::Coroutine(..) => true,
63 ty::Adt(adt_def, _) => adt_def.is_enum(),
64_ => false,
65 });
6667match enum_type_and_layout.layout.variants() {
68// A single-variant or no-variant enum has no discriminant.
69Variants::Single { .. } | Variants::Empty => None,
7071 Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => {
72// Niche tags are always normalized to unsized integers of the correct size.
73Some(
74match tag.primitive() {
75 Primitive::Int(t, _) => t,
76 Primitive::Float(f) => Integer::from_size(f.size()).unwrap(),
77// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
78Primitive::Pointer(_) => {
79// If the niche is the NULL value of a reference, then `discr_enum_ty` will
80 // be a RawPtr. CodeView doesn't know what to do with enums whose base type
81 // is a pointer so we fix this up to just be `usize`.
82 // DWARF might be able to deal with this but with an integer type we are on
83 // the safe side there too.
84tcx.data_layout.ptr_sized_integer()
85 }
86 }
87 .to_ty(tcx, false),
88 )
89 }
9091 Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => {
92// Direct tags preserve the sign.
93Some(tag.primitive().to_ty(tcx))
94 }
95 }
96}