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