1use std::borrow::Cow;
2
3use libc::c_uint;
4use rustc_abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
5use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
6use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
7use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods};
8use rustc_index::IndexVec;
9use rustc_middle::bug;
10use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
11use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty};
12use smallvec::smallvec;
13
14use crate::common::{AsCCharPtr, CodegenCx};
15use crate::debuginfo::dwarf_const::DW_TAG_const_type;
16use crate::debuginfo::metadata::enums::DiscrResult;
17use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId};
18use crate::debuginfo::metadata::{
19 DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER,
20 build_field_di_node, create_member_type, file_metadata, file_metadata_from_def_id,
21 size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags,
22};
23use crate::debuginfo::utils::DIB;
24use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
25use crate::llvm::{self};
26
27const ASSOC_CONST_DISCR_NAME: &str = "NAME";
30const ASSOC_CONST_DISCR_EXACT: &str = "DISCR_EXACT";
31const ASSOC_CONST_DISCR_BEGIN: &str = "DISCR_BEGIN";
32const ASSOC_CONST_DISCR_END: &str = "DISCR_END";
33
34const ASSOC_CONST_DISCR128_EXACT_LO: &str = "DISCR128_EXACT_LO";
35const ASSOC_CONST_DISCR128_EXACT_HI: &str = "DISCR128_EXACT_HI";
36const ASSOC_CONST_DISCR128_BEGIN_LO: &str = "DISCR128_BEGIN_LO";
37const ASSOC_CONST_DISCR128_BEGIN_HI: &str = "DISCR128_BEGIN_HI";
38const ASSOC_CONST_DISCR128_END_LO: &str = "DISCR128_END_LO";
39const ASSOC_CONST_DISCR128_END_HI: &str = "DISCR128_END_HI";
40
41const TAG_FIELD_NAME: &str = "tag";
43const TAG_FIELD_NAME_128_LO: &str = "tag128_lo";
44const TAG_FIELD_NAME_128_HI: &str = "tag128_hi";
45
46const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
49
50pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
183 cx: &CodegenCx<'ll, 'tcx>,
184 unique_type_id: UniqueTypeId<'tcx>,
185) -> DINodeCreationResult<'ll> {
186 let enum_type = unique_type_id.expect_ty();
187 let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
188 bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
189 };
190
191 let enum_type_and_layout = cx.layout_of(enum_type);
192 let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
193
194 assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout));
195
196 let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
197 Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did())))
198 } else {
199 None
200 };
201
202 type_map::build_type_with_children(
203 cx,
204 type_map::stub(
205 cx,
206 type_map::Stub::Union,
207 unique_type_id,
208 &enum_type_name,
209 def_location,
210 cx.size_and_align_of(enum_type),
211 NO_SCOPE_METADATA,
212 visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()),
213 ),
214 |cx, enum_type_di_node| {
215 match enum_type_and_layout.variants {
216 Variants::Empty => {
217 return smallvec![];
219 }
220 Variants::Single { index: variant_index } => build_single_variant_union_fields(
221 cx,
222 enum_adt_def,
223 enum_type_and_layout,
224 enum_type_di_node,
225 variant_index,
226 ),
227 Variants::Multiple {
228 tag_encoding: TagEncoding::Direct,
229 ref variants,
230 tag_field,
231 ..
232 } => build_union_fields_for_enum(
233 cx,
234 enum_adt_def,
235 enum_type_and_layout,
236 enum_type_di_node,
237 variants.indices(),
238 tag_field,
239 None,
240 ),
241 Variants::Multiple {
242 tag_encoding: TagEncoding::Niche { untagged_variant, .. },
243 ref variants,
244 tag_field,
245 ..
246 } => build_union_fields_for_enum(
247 cx,
248 enum_adt_def,
249 enum_type_and_layout,
250 enum_type_di_node,
251 variants.indices(),
252 tag_field,
253 Some(untagged_variant),
254 ),
255 }
256 },
257 NO_GENERICS,
258 )
259}
260
261pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
265 cx: &CodegenCx<'ll, 'tcx>,
266 unique_type_id: UniqueTypeId<'tcx>,
267) -> DINodeCreationResult<'ll> {
268 let coroutine_type = unique_type_id.expect_ty();
269 let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
270 let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else {
271 bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
272 };
273 Some(file_metadata_from_def_id(cx, Some(coroutine_def_id)))
274 } else {
275 None
276 };
277 let coroutine_type_and_layout = cx.layout_of(coroutine_type);
278 let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
279
280 assert!(!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout));
281
282 type_map::build_type_with_children(
283 cx,
284 type_map::stub(
285 cx,
286 type_map::Stub::Union,
287 unique_type_id,
288 &coroutine_type_name,
289 def_location,
290 size_and_align_of(coroutine_type_and_layout),
291 NO_SCOPE_METADATA,
292 DIFlags::FlagZero,
293 ),
294 |cx, coroutine_type_di_node| match coroutine_type_and_layout.variants {
295 Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => {
296 build_union_fields_for_direct_tag_coroutine(
297 cx,
298 coroutine_type_and_layout,
299 coroutine_type_di_node,
300 )
301 }
302 Variants::Single { .. }
303 | Variants::Empty
304 | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => {
305 bug!(
306 "Encountered coroutine with non-direct-tag layout: {:?}",
307 coroutine_type_and_layout
308 )
309 }
310 },
311 NO_GENERICS,
312 )
313}
314
315fn build_single_variant_union_fields<'ll, 'tcx>(
316 cx: &CodegenCx<'ll, 'tcx>,
317 enum_adt_def: AdtDef<'tcx>,
318 enum_type_and_layout: TyAndLayout<'tcx>,
319 enum_type_di_node: &'ll DIType,
320 variant_index: VariantIdx,
321) -> SmallVec<&'ll DIType> {
322 let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
323 let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
324 let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
325 cx,
326 enum_type_and_layout,
327 enum_type_di_node,
328 variant_index,
329 enum_adt_def.variant(variant_index),
330 variant_layout,
331 visibility_flags,
332 );
333
334 let tag_base_type = cx.tcx.types.u32;
335 let tag_base_type_di_node = type_di_node(cx, tag_base_type);
336 let tag_base_type_align = cx.align_of(tag_base_type);
337
338 let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
339 Some(enum_adt_def.did())
340 } else {
341 None
342 };
343
344 let variant_names_type_di_node = build_variant_names_type_di_node(
345 cx,
346 enum_type_di_node,
347 std::iter::once((
348 variant_index,
349 Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
350 )),
351 enum_adt_def_id,
352 );
353
354 let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node(
355 cx,
356 enum_type_and_layout,
357 enum_type_di_node,
358 variant_index,
359 None,
360 variant_struct_type_di_node,
361 variant_names_type_di_node,
362 tag_base_type_di_node,
363 tag_base_type,
364 DiscrResult::NoDiscriminant,
365 None,
366 );
367
368 smallvec![
369 build_field_di_node(
370 cx,
371 enum_type_di_node,
372 &variant_union_field_name(variant_index),
373 enum_type_and_layout,
376 Size::ZERO,
377 visibility_flags,
378 variant_struct_type_wrapper_di_node,
379 None,
380 ),
381 unsafe {
382 llvm::LLVMRustDIBuilderCreateStaticMemberType(
383 DIB(cx),
384 enum_type_di_node,
385 TAG_FIELD_NAME.as_c_char_ptr(),
386 TAG_FIELD_NAME.len(),
387 unknown_file_metadata(cx),
388 UNKNOWN_LINE_NUMBER,
389 variant_names_type_di_node,
390 visibility_flags,
391 Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
392 tag_base_type_align.bits() as u32,
393 )
394 }
395 ]
396}
397
398fn build_union_fields_for_enum<'ll, 'tcx>(
399 cx: &CodegenCx<'ll, 'tcx>,
400 enum_adt_def: AdtDef<'tcx>,
401 enum_type_and_layout: TyAndLayout<'tcx>,
402 enum_type_di_node: &'ll DIType,
403 variant_indices: impl Iterator<Item = VariantIdx> + Clone,
404 tag_field: usize,
405 untagged_variant_index: Option<VariantIdx>,
406) -> SmallVec<&'ll DIType> {
407 let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
408
409 let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
410 Some(enum_adt_def.did())
411 } else {
412 None
413 };
414
415 let variant_names_type_di_node = build_variant_names_type_di_node(
416 cx,
417 enum_type_di_node,
418 variant_indices.clone().map(|variant_index| {
419 let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
420 (variant_index, variant_name)
421 }),
422 enum_adt_def_id,
423 );
424 let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
425
426 let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_indices
427 .map(|variant_index| {
428 let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
429
430 let variant_def = enum_adt_def.variant(variant_index);
431
432 let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
433 cx,
434 enum_type_and_layout,
435 enum_type_di_node,
436 variant_index,
437 variant_def,
438 variant_layout,
439 visibility_flags,
440 );
441
442 VariantFieldInfo {
443 variant_index,
444 variant_struct_type_di_node,
445 source_info: None,
446 discr: super::compute_discriminant_value(cx, enum_type_and_layout, variant_index),
447 }
448 })
449 .collect();
450
451 build_union_fields_for_direct_tag_enum_or_coroutine(
452 cx,
453 enum_type_and_layout,
454 enum_type_di_node,
455 &variant_field_infos,
456 variant_names_type_di_node,
457 tag_base_type,
458 tag_field,
459 untagged_variant_index,
460 visibility_flags,
461 )
462}
463
464fn variant_names_enum_base_type<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> Ty<'tcx> {
468 cx.tcx.types.u32
469}
470
471fn build_variant_names_type_di_node<'ll, 'tcx>(
477 cx: &CodegenCx<'ll, 'tcx>,
478 containing_scope: &'ll DIType,
479 variants: impl Iterator<Item = (VariantIdx, Cow<'tcx, str>)>,
480 enum_def_id: Option<rustc_span::def_id::DefId>,
481) -> &'ll DIType {
482 super::build_enumeration_type_di_node(
484 cx,
485 "VariantNames",
486 variant_names_enum_base_type(cx),
487 variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())),
488 enum_def_id,
489 containing_scope,
490 )
491}
492
493fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
494 cx: &CodegenCx<'ll, 'tcx>,
495 enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>,
496 enum_or_coroutine_type_di_node: &'ll DIType,
497 variant_index: VariantIdx,
498 untagged_variant_index: Option<VariantIdx>,
499 variant_struct_type_di_node: &'ll DIType,
500 variant_names_type_di_node: &'ll DIType,
501 tag_base_type_di_node: &'ll DIType,
502 tag_base_type: Ty<'tcx>,
503 discr: DiscrResult,
504 source_info: Option<(&'ll DIFile, c_uint)>,
505) -> &'ll DIType {
506 type_map::build_type_with_children(
507 cx,
508 type_map::stub(
509 cx,
510 Stub::Struct,
511 UniqueTypeId::for_enum_variant_struct_type_wrapper(
512 cx.tcx,
513 enum_or_coroutine_type_and_layout.ty,
514 variant_index,
515 ),
516 &variant_struct_wrapper_type_name(variant_index),
517 source_info,
518 size_and_align_of(enum_or_coroutine_type_and_layout),
520 Some(enum_or_coroutine_type_di_node),
521 DIFlags::FlagZero,
522 ),
523 |cx, wrapper_struct_type_di_node| {
524 enum DiscrKind {
525 Exact(u64),
526 Exact128(u128),
527 Range(u64, u64),
528 Range128(u128, u128),
529 }
530
531 let (tag_base_type_size, tag_base_type_align) = cx.size_and_align_of(tag_base_type);
532 let is_128_bits = tag_base_type_size.bits() > 64;
533
534 let discr = match discr {
535 DiscrResult::NoDiscriminant => DiscrKind::Exact(SINGLE_VARIANT_VIRTUAL_DISR),
536 DiscrResult::Value(discr_val) => {
537 if is_128_bits {
538 DiscrKind::Exact128(discr_val)
539 } else {
540 assert_eq!(discr_val, discr_val as u64 as u128);
541 DiscrKind::Exact(discr_val as u64)
542 }
543 }
544 DiscrResult::Range(min, max) => {
545 assert_eq!(Some(variant_index), untagged_variant_index);
546 if is_128_bits {
547 DiscrKind::Range128(min, max)
548 } else {
549 assert_eq!(min, min as u64 as u128);
550 assert_eq!(max, max as u64 as u128);
551 DiscrKind::Range(min as u64, max as u64)
552 }
553 }
554 };
555
556 let mut fields = SmallVec::new();
557
558 fields.push(build_field_di_node(
560 cx,
561 wrapper_struct_type_di_node,
562 "value",
563 enum_or_coroutine_type_and_layout,
564 Size::ZERO,
565 DIFlags::FlagZero,
566 variant_struct_type_di_node,
567 None,
568 ));
569
570 let build_assoc_const = |name: &str,
571 type_di_node_: &'ll DIType,
572 value: u64,
573 align: Align| unsafe {
574 let (t_di, align) = if name == ASSOC_CONST_DISCR_NAME {
579 (type_di_node_, align.bits() as u32)
580 } else {
581 let ty_u64 = Ty::new_uint(cx.tcx, ty::UintTy::U64);
582 (type_di_node(cx, ty_u64), Align::EIGHT.bits() as u32)
583 };
584
585 let field_type =
587 llvm::LLVMRustDIBuilderCreateQualifiedType(DIB(cx), DW_TAG_const_type, t_di);
588
589 llvm::LLVMRustDIBuilderCreateStaticMemberType(
590 DIB(cx),
591 wrapper_struct_type_di_node,
592 name.as_c_char_ptr(),
593 name.len(),
594 unknown_file_metadata(cx),
595 UNKNOWN_LINE_NUMBER,
596 field_type,
597 DIFlags::FlagZero,
598 Some(cx.const_u64(value)),
599 align,
600 )
601 };
602
603 fields.push(build_assoc_const(
606 ASSOC_CONST_DISCR_NAME,
607 variant_names_type_di_node,
608 variant_index.as_u32() as u64,
609 cx.align_of(variant_names_enum_base_type(cx)),
610 ));
611
612 match discr {
614 DiscrKind::Exact(discr_val) => {
615 fields.push(build_assoc_const(
616 ASSOC_CONST_DISCR_EXACT,
617 tag_base_type_di_node,
618 discr_val,
619 tag_base_type_align,
620 ));
621 }
622 DiscrKind::Exact128(discr_val) => {
623 let align = cx.align_of(cx.tcx.types.u64);
624 let type_di_node = type_di_node(cx, cx.tcx.types.u64);
625 let Split128 { hi, lo } = split_128(discr_val);
626
627 fields.push(build_assoc_const(
628 ASSOC_CONST_DISCR128_EXACT_LO,
629 type_di_node,
630 lo,
631 align,
632 ));
633
634 fields.push(build_assoc_const(
635 ASSOC_CONST_DISCR128_EXACT_HI,
636 type_di_node,
637 hi,
638 align,
639 ));
640 }
641 DiscrKind::Range(begin, end) => {
642 fields.push(build_assoc_const(
643 ASSOC_CONST_DISCR_BEGIN,
644 tag_base_type_di_node,
645 begin,
646 tag_base_type_align,
647 ));
648
649 fields.push(build_assoc_const(
650 ASSOC_CONST_DISCR_END,
651 tag_base_type_di_node,
652 end,
653 tag_base_type_align,
654 ));
655 }
656 DiscrKind::Range128(begin, end) => {
657 let align = cx.align_of(cx.tcx.types.u64);
658 let type_di_node = type_di_node(cx, cx.tcx.types.u64);
659 let Split128 { hi: begin_hi, lo: begin_lo } = split_128(begin);
660 let Split128 { hi: end_hi, lo: end_lo } = split_128(end);
661
662 fields.push(build_assoc_const(
663 ASSOC_CONST_DISCR128_BEGIN_HI,
664 type_di_node,
665 begin_hi,
666 align,
667 ));
668
669 fields.push(build_assoc_const(
670 ASSOC_CONST_DISCR128_BEGIN_LO,
671 type_di_node,
672 begin_lo,
673 align,
674 ));
675
676 fields.push(build_assoc_const(
677 ASSOC_CONST_DISCR128_END_HI,
678 type_di_node,
679 end_hi,
680 align,
681 ));
682
683 fields.push(build_assoc_const(
684 ASSOC_CONST_DISCR128_END_LO,
685 type_di_node,
686 end_lo,
687 align,
688 ));
689 }
690 }
691
692 fields
693 },
694 NO_GENERICS,
695 )
696 .di_node
697}
698
699struct Split128 {
700 hi: u64,
701 lo: u64,
702}
703
704fn split_128(value: u128) -> Split128 {
705 Split128 { hi: (value >> 64) as u64, lo: value as u64 }
706}
707
708fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
709 cx: &CodegenCx<'ll, 'tcx>,
710 coroutine_type_and_layout: TyAndLayout<'tcx>,
711 coroutine_type_di_node: &'ll DIType,
712) -> SmallVec<&'ll DIType> {
713 let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } =
714 coroutine_type_and_layout.variants
715 else {
716 bug!("This function only supports layouts with directly encoded tags.")
717 };
718
719 let (coroutine_def_id, coroutine_args) = match coroutine_type_and_layout.ty.kind() {
720 &ty::Coroutine(def_id, args) => (def_id, args.as_coroutine()),
721 _ => unreachable!(),
722 };
723
724 let coroutine_layout = cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.args).unwrap();
725
726 let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
727 let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
728 let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
729
730 let tag_base_type = tag_base_type(cx.tcx, coroutine_type_and_layout);
731
732 let variant_names_type_di_node = build_variant_names_type_di_node(
733 cx,
734 coroutine_type_di_node,
735 variant_range
736 .clone()
737 .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))),
738 if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
739 Some(coroutine_def_id)
740 } else {
741 None
742 },
743 );
744
745 let discriminants: IndexVec<VariantIdx, DiscrResult> = {
746 let discriminants_iter = coroutine_args.discriminants(coroutine_def_id, cx.tcx);
747 let mut discriminants: IndexVec<VariantIdx, DiscrResult> =
748 IndexVec::with_capacity(variant_count);
749 for (variant_index, discr) in discriminants_iter {
750 assert_eq!(variant_index, discriminants.next_index());
752 discriminants.push(DiscrResult::Value(discr.val));
753 }
754 discriminants
755 };
756
757 let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
759 .map(|variant_index| {
760 let variant_struct_type_di_node = super::build_coroutine_variant_struct_type_di_node(
761 cx,
762 variant_index,
763 coroutine_type_and_layout,
764 coroutine_type_di_node,
765 coroutine_layout,
766 common_upvar_names,
767 );
768
769 let span = coroutine_layout.variant_source_info[variant_index].span;
770 let source_info = if !span.is_dummy() {
771 let loc = cx.lookup_debug_loc(span.lo());
772 Some((file_metadata(cx, &loc.file), loc.line as c_uint))
773 } else {
774 None
775 };
776
777 VariantFieldInfo {
778 variant_index,
779 variant_struct_type_di_node,
780 source_info,
781 discr: discriminants[variant_index],
782 }
783 })
784 .collect();
785
786 build_union_fields_for_direct_tag_enum_or_coroutine(
787 cx,
788 coroutine_type_and_layout,
789 coroutine_type_di_node,
790 &variant_field_infos[..],
791 variant_names_type_di_node,
792 tag_base_type,
793 tag_field,
794 None,
795 DIFlags::FlagZero,
796 )
797}
798
799fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
802 cx: &CodegenCx<'ll, 'tcx>,
803 enum_type_and_layout: TyAndLayout<'tcx>,
804 enum_type_di_node: &'ll DIType,
805 variant_field_infos: &[VariantFieldInfo<'ll>],
806 discr_type_di_node: &'ll DIType,
807 tag_base_type: Ty<'tcx>,
808 tag_field: usize,
809 untagged_variant_index: Option<VariantIdx>,
810 di_flags: DIFlags,
811) -> SmallVec<&'ll DIType> {
812 let tag_base_type_di_node = type_di_node(cx, tag_base_type);
813 let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
814
815 unions_fields.extend(variant_field_infos.into_iter().map(|variant_member_info| {
817 let (file_di_node, line_number) = variant_member_info
818 .source_info
819 .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
820
821 let field_name = variant_union_field_name(variant_member_info.variant_index);
822
823 let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node(
824 cx,
825 enum_type_and_layout,
826 enum_type_di_node,
827 variant_member_info.variant_index,
828 untagged_variant_index,
829 variant_member_info.variant_struct_type_di_node,
830 discr_type_di_node,
831 tag_base_type_di_node,
832 tag_base_type,
833 variant_member_info.discr,
834 if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
835 variant_member_info.source_info
836 } else {
837 None
838 },
839 );
840
841 create_member_type(
845 cx,
846 enum_type_di_node,
847 &field_name,
848 file_di_node,
849 line_number,
850 enum_type_and_layout,
853 Size::ZERO,
855 di_flags,
856 variant_struct_type_wrapper,
857 )
858 }));
859
860 assert_eq!(
861 cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
862 cx.size_and_align_of(self::tag_base_type(cx.tcx, enum_type_and_layout))
863 );
864
865 let is_128_bits = cx.size_of(tag_base_type).bits() > 64;
868
869 if is_128_bits {
870 let type_di_node = type_di_node(cx, cx.tcx.types.u64);
871 let u64_layout = cx.layout_of(cx.tcx.types.u64);
872
873 let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian {
874 Endian::Little => (0, 8),
875 Endian::Big => (8, 0),
876 };
877
878 let tag_field_offset = enum_type_and_layout.fields.offset(tag_field).bytes();
879 let lo_offset = Size::from_bytes(tag_field_offset + lo_offset);
880 let hi_offset = Size::from_bytes(tag_field_offset + hi_offset);
881
882 unions_fields.push(build_field_di_node(
883 cx,
884 enum_type_di_node,
885 TAG_FIELD_NAME_128_LO,
886 u64_layout,
887 lo_offset,
888 di_flags,
889 type_di_node,
890 None,
891 ));
892
893 unions_fields.push(build_field_di_node(
894 cx,
895 enum_type_di_node,
896 TAG_FIELD_NAME_128_HI,
897 u64_layout,
898 hi_offset,
899 DIFlags::FlagZero,
900 type_di_node,
901 None,
902 ));
903 } else {
904 unions_fields.push(build_field_di_node(
905 cx,
906 enum_type_di_node,
907 TAG_FIELD_NAME,
908 enum_type_and_layout.field(cx, tag_field),
909 enum_type_and_layout.fields.offset(tag_field),
910 di_flags,
911 tag_base_type_di_node,
912 None,
913 ));
914 }
915
916 unions_fields
917}
918
919struct VariantFieldInfo<'ll> {
921 variant_index: VariantIdx,
922 variant_struct_type_di_node: &'ll DIType,
923 source_info: Option<(&'ll DIFile, c_uint)>,
924 discr: DiscrResult,
925}
926
927fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> {
928 const PRE_ALLOCATED: [&str; 16] = [
929 "variant0",
930 "variant1",
931 "variant2",
932 "variant3",
933 "variant4",
934 "variant5",
935 "variant6",
936 "variant7",
937 "variant8",
938 "variant9",
939 "variant10",
940 "variant11",
941 "variant12",
942 "variant13",
943 "variant14",
944 "variant15",
945 ];
946
947 PRE_ALLOCATED
948 .get(variant_index.as_usize())
949 .map(|&s| Cow::from(s))
950 .unwrap_or_else(|| format!("variant{}", variant_index.as_usize()).into())
951}
952
953fn variant_struct_wrapper_type_name(variant_index: VariantIdx) -> Cow<'static, str> {
954 const PRE_ALLOCATED: [&str; 16] = [
955 "Variant0",
956 "Variant1",
957 "Variant2",
958 "Variant3",
959 "Variant4",
960 "Variant5",
961 "Variant6",
962 "Variant7",
963 "Variant8",
964 "Variant9",
965 "Variant10",
966 "Variant11",
967 "Variant12",
968 "Variant13",
969 "Variant14",
970 "Variant15",
971 ];
972
973 PRE_ALLOCATED
974 .get(variant_index.as_usize())
975 .map(|&s| Cow::from(s))
976 .unwrap_or_else(|| format!("Variant{}", variant_index.as_usize()).into())
977}