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, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node,
21 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 size_and_align_of(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 size_and_align_of(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 =
725 cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.kind_ty()).unwrap();
726
727 let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
728 let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
729 let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
730
731 let tag_base_type = tag_base_type(cx.tcx, coroutine_type_and_layout);
732
733 let variant_names_type_di_node = build_variant_names_type_di_node(
734 cx,
735 coroutine_type_di_node,
736 variant_range
737 .clone()
738 .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))),
739 if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
740 Some(coroutine_def_id)
741 } else {
742 None
743 },
744 );
745
746 let discriminants: IndexVec<VariantIdx, DiscrResult> = {
747 let discriminants_iter = coroutine_args.discriminants(coroutine_def_id, cx.tcx);
748 let mut discriminants: IndexVec<VariantIdx, DiscrResult> =
749 IndexVec::with_capacity(variant_count);
750 for (variant_index, discr) in discriminants_iter {
751 assert_eq!(variant_index, discriminants.next_index());
753 discriminants.push(DiscrResult::Value(discr.val));
754 }
755 discriminants
756 };
757
758 let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
760 .map(|variant_index| {
761 let variant_struct_type_di_node = super::build_coroutine_variant_struct_type_di_node(
762 cx,
763 variant_index,
764 coroutine_type_and_layout,
765 coroutine_type_di_node,
766 coroutine_layout,
767 common_upvar_names,
768 );
769
770 let span = coroutine_layout.variant_source_info[variant_index].span;
771 let source_info = if !span.is_dummy() {
772 let loc = cx.lookup_debug_loc(span.lo());
773 Some((file_metadata(cx, &loc.file), loc.line as c_uint))
774 } else {
775 None
776 };
777
778 VariantFieldInfo {
779 variant_index,
780 variant_struct_type_di_node,
781 source_info,
782 discr: discriminants[variant_index],
783 }
784 })
785 .collect();
786
787 build_union_fields_for_direct_tag_enum_or_coroutine(
788 cx,
789 coroutine_type_and_layout,
790 coroutine_type_di_node,
791 &variant_field_infos[..],
792 variant_names_type_di_node,
793 tag_base_type,
794 tag_field,
795 None,
796 DIFlags::FlagZero,
797 )
798}
799
800fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
803 cx: &CodegenCx<'ll, 'tcx>,
804 enum_type_and_layout: TyAndLayout<'tcx>,
805 enum_type_di_node: &'ll DIType,
806 variant_field_infos: &[VariantFieldInfo<'ll>],
807 discr_type_di_node: &'ll DIType,
808 tag_base_type: Ty<'tcx>,
809 tag_field: usize,
810 untagged_variant_index: Option<VariantIdx>,
811 di_flags: DIFlags,
812) -> SmallVec<&'ll DIType> {
813 let tag_base_type_di_node = type_di_node(cx, tag_base_type);
814 let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
815
816 unions_fields.extend(variant_field_infos.into_iter().map(|variant_member_info| {
818 let (file_di_node, line_number) = variant_member_info
819 .source_info
820 .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
821
822 let field_name = variant_union_field_name(variant_member_info.variant_index);
823 let (size, align) = size_and_align_of(enum_type_and_layout);
824
825 let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node(
826 cx,
827 enum_type_and_layout,
828 enum_type_di_node,
829 variant_member_info.variant_index,
830 untagged_variant_index,
831 variant_member_info.variant_struct_type_di_node,
832 discr_type_di_node,
833 tag_base_type_di_node,
834 tag_base_type,
835 variant_member_info.discr,
836 if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
837 variant_member_info.source_info
838 } else {
839 None
840 },
841 );
842
843 unsafe {
847 llvm::LLVMRustDIBuilderCreateMemberType(
848 DIB(cx),
849 enum_type_di_node,
850 field_name.as_c_char_ptr(),
851 field_name.len(),
852 file_di_node,
853 line_number,
854 size.bits(),
857 align.bits() as u32,
858 Size::ZERO.bits(),
860 di_flags,
861 variant_struct_type_wrapper,
862 )
863 }
864 }));
865
866 assert_eq!(
867 cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
868 cx.size_and_align_of(self::tag_base_type(cx.tcx, enum_type_and_layout))
869 );
870
871 let is_128_bits = cx.size_of(tag_base_type).bits() > 64;
874
875 if is_128_bits {
876 let type_di_node = type_di_node(cx, cx.tcx.types.u64);
877 let size_and_align = cx.size_and_align_of(cx.tcx.types.u64);
878
879 let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian {
880 Endian::Little => (0, 8),
881 Endian::Big => (8, 0),
882 };
883
884 let tag_field_offset = enum_type_and_layout.fields.offset(tag_field).bytes();
885 let lo_offset = Size::from_bytes(tag_field_offset + lo_offset);
886 let hi_offset = Size::from_bytes(tag_field_offset + hi_offset);
887
888 unions_fields.push(build_field_di_node(
889 cx,
890 enum_type_di_node,
891 TAG_FIELD_NAME_128_LO,
892 size_and_align,
893 lo_offset,
894 di_flags,
895 type_di_node,
896 None,
897 ));
898
899 unions_fields.push(build_field_di_node(
900 cx,
901 enum_type_di_node,
902 TAG_FIELD_NAME_128_HI,
903 size_and_align,
904 hi_offset,
905 DIFlags::FlagZero,
906 type_di_node,
907 None,
908 ));
909 } else {
910 unions_fields.push(build_field_di_node(
911 cx,
912 enum_type_di_node,
913 TAG_FIELD_NAME,
914 cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
915 enum_type_and_layout.fields.offset(tag_field),
916 di_flags,
917 tag_base_type_di_node,
918 None,
919 ));
920 }
921
922 unions_fields
923}
924
925struct VariantFieldInfo<'ll> {
927 variant_index: VariantIdx,
928 variant_struct_type_di_node: &'ll DIType,
929 source_info: Option<(&'ll DIFile, c_uint)>,
930 discr: DiscrResult,
931}
932
933fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> {
934 const PRE_ALLOCATED: [&str; 16] = [
935 "variant0",
936 "variant1",
937 "variant2",
938 "variant3",
939 "variant4",
940 "variant5",
941 "variant6",
942 "variant7",
943 "variant8",
944 "variant9",
945 "variant10",
946 "variant11",
947 "variant12",
948 "variant13",
949 "variant14",
950 "variant15",
951 ];
952
953 PRE_ALLOCATED
954 .get(variant_index.as_usize())
955 .map(|&s| Cow::from(s))
956 .unwrap_or_else(|| format!("variant{}", variant_index.as_usize()).into())
957}
958
959fn variant_struct_wrapper_type_name(variant_index: VariantIdx) -> Cow<'static, str> {
960 const PRE_ALLOCATED: [&str; 16] = [
961 "Variant0",
962 "Variant1",
963 "Variant2",
964 "Variant3",
965 "Variant4",
966 "Variant5",
967 "Variant6",
968 "Variant7",
969 "Variant8",
970 "Variant9",
971 "Variant10",
972 "Variant11",
973 "Variant12",
974 "Variant13",
975 "Variant14",
976 "Variant15",
977 ];
978
979 PRE_ALLOCATED
980 .get(variant_index.as_usize())
981 .map(|&s| Cow::from(s))
982 .unwrap_or_else(|| format!("Variant{}", variant_index.as_usize()).into())
983}