1use std::borrow::Cow;
2
3use libc::c_uint;
4use rustc_abi::{Align, Endian, FieldIdx, 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::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 create_static_member_type(
382 cx,
383 enum_type_di_node,
384 TAG_FIELD_NAME,
385 unknown_file_metadata(cx),
386 UNKNOWN_LINE_NUMBER,
387 variant_names_type_di_node,
388 visibility_flags,
389 Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
390 tag_base_type_align,
391 ),
392 ]
393}
394
395fn build_union_fields_for_enum<'ll, 'tcx>(
396 cx: &CodegenCx<'ll, 'tcx>,
397 enum_adt_def: AdtDef<'tcx>,
398 enum_type_and_layout: TyAndLayout<'tcx>,
399 enum_type_di_node: &'ll DIType,
400 variant_indices: impl Iterator<Item = VariantIdx> + Clone,
401 tag_field: FieldIdx,
402 untagged_variant_index: Option<VariantIdx>,
403) -> SmallVec<&'ll DIType> {
404 let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
405
406 let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
407 Some(enum_adt_def.did())
408 } else {
409 None
410 };
411
412 let variant_names_type_di_node = build_variant_names_type_di_node(
413 cx,
414 enum_type_di_node,
415 variant_indices.clone().map(|variant_index| {
416 let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
417 (variant_index, variant_name)
418 }),
419 enum_adt_def_id,
420 );
421 let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
422
423 let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_indices
424 .map(|variant_index| {
425 let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
426
427 let variant_def = enum_adt_def.variant(variant_index);
428
429 let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
430 cx,
431 enum_type_and_layout,
432 enum_type_di_node,
433 variant_index,
434 variant_def,
435 variant_layout,
436 visibility_flags,
437 );
438
439 VariantFieldInfo {
440 variant_index,
441 variant_struct_type_di_node,
442 source_info: None,
443 discr: super::compute_discriminant_value(cx, enum_type_and_layout, variant_index),
444 }
445 })
446 .collect();
447
448 build_union_fields_for_direct_tag_enum_or_coroutine(
449 cx,
450 enum_type_and_layout,
451 enum_type_di_node,
452 &variant_field_infos,
453 variant_names_type_di_node,
454 tag_base_type,
455 tag_field,
456 untagged_variant_index,
457 visibility_flags,
458 )
459}
460
461fn variant_names_enum_base_type<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> Ty<'tcx> {
465 cx.tcx.types.u32
466}
467
468fn build_variant_names_type_di_node<'ll, 'tcx>(
474 cx: &CodegenCx<'ll, 'tcx>,
475 containing_scope: &'ll DIType,
476 variants: impl Iterator<Item = (VariantIdx, Cow<'tcx, str>)>,
477 enum_def_id: Option<rustc_span::def_id::DefId>,
478) -> &'ll DIType {
479 super::build_enumeration_type_di_node(
481 cx,
482 "VariantNames",
483 variant_names_enum_base_type(cx),
484 variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())),
485 enum_def_id,
486 containing_scope,
487 )
488}
489
490fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
491 cx: &CodegenCx<'ll, 'tcx>,
492 enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>,
493 enum_or_coroutine_type_di_node: &'ll DIType,
494 variant_index: VariantIdx,
495 untagged_variant_index: Option<VariantIdx>,
496 variant_struct_type_di_node: &'ll DIType,
497 variant_names_type_di_node: &'ll DIType,
498 tag_base_type_di_node: &'ll DIType,
499 tag_base_type: Ty<'tcx>,
500 discr: DiscrResult,
501 source_info: Option<(&'ll DIFile, c_uint)>,
502) -> &'ll DIType {
503 type_map::build_type_with_children(
504 cx,
505 type_map::stub(
506 cx,
507 Stub::Struct,
508 UniqueTypeId::for_enum_variant_struct_type_wrapper(
509 cx.tcx,
510 enum_or_coroutine_type_and_layout.ty,
511 variant_index,
512 ),
513 &variant_struct_wrapper_type_name(variant_index),
514 source_info,
515 size_and_align_of(enum_or_coroutine_type_and_layout),
517 Some(enum_or_coroutine_type_di_node),
518 DIFlags::FlagZero,
519 ),
520 |cx, wrapper_struct_type_di_node| {
521 enum DiscrKind {
522 Exact(u64),
523 Exact128(u128),
524 Range(u64, u64),
525 Range128(u128, u128),
526 }
527
528 let (tag_base_type_size, tag_base_type_align) = cx.size_and_align_of(tag_base_type);
529 let is_128_bits = tag_base_type_size.bits() > 64;
530
531 let discr = match discr {
532 DiscrResult::NoDiscriminant => DiscrKind::Exact(SINGLE_VARIANT_VIRTUAL_DISR),
533 DiscrResult::Value(discr_val) => {
534 if is_128_bits {
535 DiscrKind::Exact128(discr_val)
536 } else {
537 assert_eq!(discr_val, discr_val as u64 as u128);
538 DiscrKind::Exact(discr_val as u64)
539 }
540 }
541 DiscrResult::Range(min, max) => {
542 assert_eq!(Some(variant_index), untagged_variant_index);
543 if is_128_bits {
544 DiscrKind::Range128(min, max)
545 } else {
546 assert_eq!(min, min as u64 as u128);
547 assert_eq!(max, max as u64 as u128);
548 DiscrKind::Range(min as u64, max as u64)
549 }
550 }
551 };
552
553 let mut fields = SmallVec::new();
554
555 fields.push(build_field_di_node(
557 cx,
558 wrapper_struct_type_di_node,
559 "value",
560 enum_or_coroutine_type_and_layout,
561 Size::ZERO,
562 DIFlags::FlagZero,
563 variant_struct_type_di_node,
564 None,
565 ));
566
567 let build_assoc_const = |name: &str,
568 type_di_node_: &'ll DIType,
569 value: u64,
570 align: Align|
571 -> &'ll llvm::Metadata {
572 let (t_di, align) = if name == ASSOC_CONST_DISCR_NAME {
577 (type_di_node_, align)
578 } else {
579 let ty_u64 = Ty::new_uint(cx.tcx, ty::UintTy::U64);
580 (type_di_node(cx, ty_u64), Align::EIGHT)
581 };
582
583 let field_type = unsafe {
585 llvm::LLVMDIBuilderCreateQualifiedType(DIB(cx), DW_TAG_const_type, t_di)
586 };
587
588 create_static_member_type(
589 cx,
590 wrapper_struct_type_di_node,
591 name,
592 unknown_file_metadata(cx),
593 UNKNOWN_LINE_NUMBER,
594 field_type,
595 DIFlags::FlagZero,
596 Some(cx.const_u64(value)),
597 align,
598 )
599 };
600
601 fields.push(build_assoc_const(
604 ASSOC_CONST_DISCR_NAME,
605 variant_names_type_di_node,
606 variant_index.as_u32() as u64,
607 cx.align_of(variant_names_enum_base_type(cx)),
608 ));
609
610 match discr {
612 DiscrKind::Exact(discr_val) => {
613 fields.push(build_assoc_const(
614 ASSOC_CONST_DISCR_EXACT,
615 tag_base_type_di_node,
616 discr_val,
617 tag_base_type_align,
618 ));
619 }
620 DiscrKind::Exact128(discr_val) => {
621 let align = cx.align_of(cx.tcx.types.u64);
622 let type_di_node = type_di_node(cx, cx.tcx.types.u64);
623 let Split128 { hi, lo } = split_128(discr_val);
624
625 fields.push(build_assoc_const(
626 ASSOC_CONST_DISCR128_EXACT_LO,
627 type_di_node,
628 lo,
629 align,
630 ));
631
632 fields.push(build_assoc_const(
633 ASSOC_CONST_DISCR128_EXACT_HI,
634 type_di_node,
635 hi,
636 align,
637 ));
638 }
639 DiscrKind::Range(begin, end) => {
640 fields.push(build_assoc_const(
641 ASSOC_CONST_DISCR_BEGIN,
642 tag_base_type_di_node,
643 begin,
644 tag_base_type_align,
645 ));
646
647 fields.push(build_assoc_const(
648 ASSOC_CONST_DISCR_END,
649 tag_base_type_di_node,
650 end,
651 tag_base_type_align,
652 ));
653 }
654 DiscrKind::Range128(begin, end) => {
655 let align = cx.align_of(cx.tcx.types.u64);
656 let type_di_node = type_di_node(cx, cx.tcx.types.u64);
657 let Split128 { hi: begin_hi, lo: begin_lo } = split_128(begin);
658 let Split128 { hi: end_hi, lo: end_lo } = split_128(end);
659
660 fields.push(build_assoc_const(
661 ASSOC_CONST_DISCR128_BEGIN_HI,
662 type_di_node,
663 begin_hi,
664 align,
665 ));
666
667 fields.push(build_assoc_const(
668 ASSOC_CONST_DISCR128_BEGIN_LO,
669 type_di_node,
670 begin_lo,
671 align,
672 ));
673
674 fields.push(build_assoc_const(
675 ASSOC_CONST_DISCR128_END_HI,
676 type_di_node,
677 end_hi,
678 align,
679 ));
680
681 fields.push(build_assoc_const(
682 ASSOC_CONST_DISCR128_END_LO,
683 type_di_node,
684 end_lo,
685 align,
686 ));
687 }
688 }
689
690 fields
691 },
692 NO_GENERICS,
693 )
694 .di_node
695}
696
697struct Split128 {
698 hi: u64,
699 lo: u64,
700}
701
702fn split_128(value: u128) -> Split128 {
703 Split128 { hi: (value >> 64) as u64, lo: value as u64 }
704}
705
706fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
707 cx: &CodegenCx<'ll, 'tcx>,
708 coroutine_type_and_layout: TyAndLayout<'tcx>,
709 coroutine_type_di_node: &'ll DIType,
710) -> SmallVec<&'ll DIType> {
711 let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } =
712 coroutine_type_and_layout.variants
713 else {
714 bug!("This function only supports layouts with directly encoded tags.")
715 };
716
717 let (coroutine_def_id, coroutine_args) = match coroutine_type_and_layout.ty.kind() {
718 &ty::Coroutine(def_id, args) => (def_id, args.as_coroutine()),
719 _ => unreachable!(),
720 };
721
722 let coroutine_layout = cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.args).unwrap();
723
724 let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
725 let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
726 let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
727
728 let tag_base_type = tag_base_type(cx.tcx, coroutine_type_and_layout);
729
730 let variant_names_type_di_node = build_variant_names_type_di_node(
731 cx,
732 coroutine_type_di_node,
733 variant_range
734 .clone()
735 .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))),
736 if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
737 Some(coroutine_def_id)
738 } else {
739 None
740 },
741 );
742
743 let discriminants: IndexVec<VariantIdx, DiscrResult> = {
744 let discriminants_iter = coroutine_args.discriminants(coroutine_def_id, cx.tcx);
745 let mut discriminants: IndexVec<VariantIdx, DiscrResult> =
746 IndexVec::with_capacity(variant_count);
747 for (variant_index, discr) in discriminants_iter {
748 assert_eq!(variant_index, discriminants.next_index());
750 discriminants.push(DiscrResult::Value(discr.val));
751 }
752 discriminants
753 };
754
755 let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
757 .map(|variant_index| {
758 let variant_struct_type_di_node = super::build_coroutine_variant_struct_type_di_node(
759 cx,
760 variant_index,
761 coroutine_type_and_layout,
762 coroutine_type_di_node,
763 coroutine_layout,
764 common_upvar_names,
765 );
766
767 let span = coroutine_layout.variant_source_info[variant_index].span;
768 let source_info = if !span.is_dummy() {
769 let loc = cx.lookup_debug_loc(span.lo());
770 Some((file_metadata(cx, &loc.file), loc.line as c_uint))
771 } else {
772 None
773 };
774
775 VariantFieldInfo {
776 variant_index,
777 variant_struct_type_di_node,
778 source_info,
779 discr: discriminants[variant_index],
780 }
781 })
782 .collect();
783
784 build_union_fields_for_direct_tag_enum_or_coroutine(
785 cx,
786 coroutine_type_and_layout,
787 coroutine_type_di_node,
788 &variant_field_infos[..],
789 variant_names_type_di_node,
790 tag_base_type,
791 tag_field,
792 None,
793 DIFlags::FlagZero,
794 )
795}
796
797fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
800 cx: &CodegenCx<'ll, 'tcx>,
801 enum_type_and_layout: TyAndLayout<'tcx>,
802 enum_type_di_node: &'ll DIType,
803 variant_field_infos: &[VariantFieldInfo<'ll>],
804 discr_type_di_node: &'ll DIType,
805 tag_base_type: Ty<'tcx>,
806 tag_field: FieldIdx,
807 untagged_variant_index: Option<VariantIdx>,
808 di_flags: DIFlags,
809) -> SmallVec<&'ll DIType> {
810 let tag_base_type_di_node = type_di_node(cx, tag_base_type);
811 let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
812
813 unions_fields.extend(variant_field_infos.into_iter().map(|variant_member_info| {
815 let (file_di_node, line_number) = variant_member_info
816 .source_info
817 .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
818
819 let field_name = variant_union_field_name(variant_member_info.variant_index);
820
821 let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node(
822 cx,
823 enum_type_and_layout,
824 enum_type_di_node,
825 variant_member_info.variant_index,
826 untagged_variant_index,
827 variant_member_info.variant_struct_type_di_node,
828 discr_type_di_node,
829 tag_base_type_di_node,
830 tag_base_type,
831 variant_member_info.discr,
832 if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
833 variant_member_info.source_info
834 } else {
835 None
836 },
837 );
838
839 create_member_type(
843 cx,
844 enum_type_di_node,
845 &field_name,
846 file_di_node,
847 line_number,
848 enum_type_and_layout,
851 Size::ZERO,
853 di_flags,
854 variant_struct_type_wrapper,
855 )
856 }));
857
858 assert_eq!(
859 cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field.as_usize()).ty),
860 cx.size_and_align_of(self::tag_base_type(cx.tcx, enum_type_and_layout))
861 );
862
863 let is_128_bits = cx.size_of(tag_base_type).bits() > 64;
866
867 if is_128_bits {
868 let type_di_node = type_di_node(cx, cx.tcx.types.u64);
869 let u64_layout = cx.layout_of(cx.tcx.types.u64);
870
871 let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian {
872 Endian::Little => (0, 8),
873 Endian::Big => (8, 0),
874 };
875
876 let tag_field_offset = enum_type_and_layout.fields.offset(tag_field.as_usize()).bytes();
877 let lo_offset = Size::from_bytes(tag_field_offset + lo_offset);
878 let hi_offset = Size::from_bytes(tag_field_offset + hi_offset);
879
880 unions_fields.push(build_field_di_node(
881 cx,
882 enum_type_di_node,
883 TAG_FIELD_NAME_128_LO,
884 u64_layout,
885 lo_offset,
886 di_flags,
887 type_di_node,
888 None,
889 ));
890
891 unions_fields.push(build_field_di_node(
892 cx,
893 enum_type_di_node,
894 TAG_FIELD_NAME_128_HI,
895 u64_layout,
896 hi_offset,
897 DIFlags::FlagZero,
898 type_di_node,
899 None,
900 ));
901 } else {
902 unions_fields.push(build_field_di_node(
903 cx,
904 enum_type_di_node,
905 TAG_FIELD_NAME,
906 enum_type_and_layout.field(cx, tag_field.as_usize()),
907 enum_type_and_layout.fields.offset(tag_field.as_usize()),
908 di_flags,
909 tag_base_type_di_node,
910 None,
911 ));
912 }
913
914 unions_fields
915}
916
917struct VariantFieldInfo<'ll> {
919 variant_index: VariantIdx,
920 variant_struct_type_di_node: &'ll DIType,
921 source_info: Option<(&'ll DIFile, c_uint)>,
922 discr: DiscrResult,
923}
924
925fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> {
926 const PRE_ALLOCATED: [&str; 16] = [
927 "variant0",
928 "variant1",
929 "variant2",
930 "variant3",
931 "variant4",
932 "variant5",
933 "variant6",
934 "variant7",
935 "variant8",
936 "variant9",
937 "variant10",
938 "variant11",
939 "variant12",
940 "variant13",
941 "variant14",
942 "variant15",
943 ];
944
945 PRE_ALLOCATED
946 .get(variant_index.as_usize())
947 .map(|&s| Cow::from(s))
948 .unwrap_or_else(|| format!("variant{}", variant_index.as_usize()).into())
949}
950
951fn variant_struct_wrapper_type_name(variant_index: VariantIdx) -> Cow<'static, str> {
952 const PRE_ALLOCATED: [&str; 16] = [
953 "Variant0",
954 "Variant1",
955 "Variant2",
956 "Variant3",
957 "Variant4",
958 "Variant5",
959 "Variant6",
960 "Variant7",
961 "Variant8",
962 "Variant9",
963 "Variant10",
964 "Variant11",
965 "Variant12",
966 "Variant13",
967 "Variant14",
968 "Variant15",
969 ];
970
971 PRE_ALLOCATED
972 .get(variant_index.as_usize())
973 .map(|&s| Cow::from(s))
974 .unwrap_or_else(|| format!("Variant{}", variant_index.as_usize()).into())
975}
976
977fn create_static_member_type<'ll>(
978 cx: &CodegenCx<'ll, '_>,
979 scope: &'ll llvm::Metadata,
980 name: &str,
981 file: &'ll llvm::Metadata,
982 line_number: c_uint,
983 ty: &'ll llvm::Metadata,
984 flags: DIFlags,
985 value: Option<&'ll llvm::Value>,
986 align: Align,
987) -> &'ll llvm::Metadata {
988 unsafe {
989 llvm::LLVMDIBuilderCreateStaticMemberType(
990 DIB(cx),
991 scope,
992 name.as_ptr(),
993 name.len(),
994 file,
995 line_number,
996 ty,
997 flags,
998 value,
999 align.bits() as c_uint,
1000 )
1001 }
1002}