Skip to content

Commit 3f39cae

Browse files
committed
Auto merge of rust-lang#115165 - davidtwco:issue-9228-describe-item-member-visibility, r=wesleywiser
codegen_llvm: set `DW_AT_accessibility` Fixes rust-lang#9228. Based on rust-lang#74778. Sets the accessibility of types and fields in DWARF using `DW_AT_accessibility` attribute. `DW_AT_accessibility` (public/protected/private) isn't exactly right for Rust, but neither is `DW_AT_visibility` (local/exported/qualified), and there's no way to set `DW_AT_visbility` in LLVM's API. Debuggers will special-case the handling of these per-language anyway. r? `@wesleywiser` (visited in wg-debugging triage)
2 parents e6707df + ce29051 commit 3f39cae

File tree

14 files changed

+276
-15
lines changed

14 files changed

+276
-15
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,27 @@ fn build_field_di_node<'ll, 'tcx>(
977977
}
978978
}
979979

980+
/// Returns the `DIFlags` corresponding to the visibility of the item identified by `did`.
981+
///
982+
/// `DIFlags::Flag{Public,Protected,Private}` correspond to `DW_AT_accessibility`
983+
/// (public/protected/private) aren't exactly right for Rust, but neither is `DW_AT_visibility`
984+
/// (local/exported/qualified), and there's no way to set `DW_AT_visibility` in LLVM's API.
985+
fn visibility_di_flags<'ll, 'tcx>(
986+
cx: &CodegenCx<'ll, 'tcx>,
987+
did: DefId,
988+
type_did: DefId,
989+
) -> DIFlags {
990+
let parent_did = cx.tcx.parent(type_did);
991+
let visibility = cx.tcx.visibility(did);
992+
match visibility {
993+
Visibility::Public => DIFlags::FlagPublic,
994+
// Private fields have a restricted visibility of the module containing the type.
995+
Visibility::Restricted(did) if did == parent_did => DIFlags::FlagPrivate,
996+
// `pub(crate)`/`pub(super)` visibilities are any other restricted visibility.
997+
Visibility::Restricted(..) => DIFlags::FlagProtected,
998+
}
999+
}
1000+
9801001
/// Creates the debuginfo node for a Rust struct type. Maybe be a regular struct or a tuple-struct.
9811002
fn build_struct_type_di_node<'ll, 'tcx>(
9821003
cx: &CodegenCx<'ll, 'tcx>,
@@ -1000,7 +1021,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10001021
&compute_debuginfo_type_name(cx.tcx, struct_type, false),
10011022
size_and_align_of(struct_type_and_layout),
10021023
Some(containing_scope),
1003-
DIFlags::FlagZero,
1024+
visibility_di_flags(cx, adt_def.did(), adt_def.did()),
10041025
),
10051026
// Fields:
10061027
|cx, owner| {
@@ -1023,7 +1044,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10231044
&field_name[..],
10241045
(field_layout.size, field_layout.align.abi),
10251046
struct_type_and_layout.fields.offset(i),
1026-
DIFlags::FlagZero,
1047+
visibility_di_flags(cx, f.did, adt_def.did()),
10271048
type_di_node(cx, field_layout.ty),
10281049
)
10291050
})

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use crate::{
2626
enums::{tag_base_type, DiscrResult},
2727
file_metadata, size_and_align_of, type_di_node,
2828
type_map::{self, Stub, UniqueTypeId},
29-
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
30-
UNKNOWN_LINE_NUMBER,
29+
unknown_file_metadata, visibility_di_flags, DINodeCreationResult, SmallVec,
30+
NO_GENERICS, NO_SCOPE_METADATA, UNKNOWN_LINE_NUMBER,
3131
},
3232
utils::DIB,
3333
},
@@ -215,7 +215,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
215215
&enum_type_name,
216216
cx.size_and_align_of(enum_type),
217217
NO_SCOPE_METADATA,
218-
DIFlags::FlagZero,
218+
visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()),
219219
),
220220
|cx, enum_type_di_node| {
221221
match enum_type_and_layout.variants {
@@ -320,13 +320,15 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
320320
variant_index: VariantIdx,
321321
) -> SmallVec<&'ll DIType> {
322322
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());
323324
let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
324325
cx,
325326
enum_type_and_layout,
326327
enum_type_di_node,
327328
variant_index,
328329
enum_adt_def.variant(variant_index),
329330
variant_layout,
331+
visibility_flags,
330332
);
331333

332334
let tag_base_type = cx.tcx.types.u32;
@@ -364,7 +366,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
364366
// since the later is sometimes smaller (if it has fewer fields).
365367
size_and_align_of(enum_type_and_layout),
366368
Size::ZERO,
367-
DIFlags::FlagZero,
369+
visibility_flags,
368370
variant_struct_type_wrapper_di_node,
369371
),
370372
unsafe {
@@ -376,7 +378,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
376378
unknown_file_metadata(cx),
377379
UNKNOWN_LINE_NUMBER,
378380
variant_names_type_di_node,
379-
DIFlags::FlagZero,
381+
visibility_flags,
380382
Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
381383
tag_base_type_align.bits() as u32,
382384
)
@@ -403,6 +405,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
403405
(variant_index, variant_name)
404406
}),
405407
);
408+
let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
406409

407410
let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_indices
408411
.map(|variant_index| {
@@ -417,6 +420,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
417420
variant_index,
418421
variant_def,
419422
variant_layout,
423+
visibility_flags,
420424
);
421425

422426
VariantFieldInfo {
@@ -437,6 +441,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
437441
tag_base_type,
438442
tag_field,
439443
untagged_variant_index,
444+
visibility_flags,
440445
)
441446
}
442447

@@ -744,6 +749,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
744749
tag_base_type,
745750
tag_field,
746751
None,
752+
DIFlags::FlagZero,
747753
)
748754
}
749755

@@ -758,6 +764,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
758764
tag_base_type: Ty<'tcx>,
759765
tag_field: usize,
760766
untagged_variant_index: Option<VariantIdx>,
767+
di_flags: DIFlags,
761768
) -> SmallVec<&'ll DIType> {
762769
let tag_base_type_di_node = type_di_node(cx, tag_base_type);
763770
let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
@@ -801,7 +808,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
801808
align.bits() as u32,
802809
// Union fields are always at offset zero
803810
Size::ZERO.bits(),
804-
DIFlags::FlagZero,
811+
di_flags,
805812
variant_struct_type_wrapper,
806813
)
807814
}
@@ -835,7 +842,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
835842
TAG_FIELD_NAME_128_LO,
836843
size_and_align,
837844
lo_offset,
838-
DIFlags::FlagZero,
845+
di_flags,
839846
type_di_node,
840847
));
841848

@@ -855,7 +862,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
855862
TAG_FIELD_NAME,
856863
cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
857864
enum_type_and_layout.fields.offset(tag_field),
858-
DIFlags::FlagZero,
865+
di_flags,
859866
tag_base_type_di_node,
860867
));
861868
}

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
250250
variant_index: VariantIdx,
251251
variant_def: &VariantDef,
252252
variant_layout: TyAndLayout<'tcx>,
253+
di_flags: DIFlags,
253254
) -> &'ll DIType {
254255
debug_assert_eq!(variant_layout.ty, enum_type_and_layout.ty);
255256

@@ -267,7 +268,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
267268
// NOTE: We use size and align of enum_type, not from variant_layout:
268269
size_and_align_of(enum_type_and_layout),
269270
Some(enum_type_di_node),
270-
DIFlags::FlagZero,
271+
di_flags,
271272
),
272273
|cx, struct_type_di_node| {
273274
(0..variant_layout.fields.count())
@@ -289,7 +290,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
289290
&field_name,
290291
(field_layout.size, field_layout.align.abi),
291292
variant_layout.fields.offset(field_index),
292-
DIFlags::FlagZero,
293+
di_flags,
293294
type_di_node(cx, field_layout.ty),
294295
)
295296
})

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::{
77
enums::tag_base_type,
88
file_metadata, size_and_align_of, type_di_node,
99
type_map::{self, Stub, StubInfo, UniqueTypeId},
10-
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS,
11-
UNKNOWN_LINE_NUMBER,
10+
unknown_file_metadata, visibility_di_flags, DINodeCreationResult, SmallVec,
11+
NO_GENERICS, UNKNOWN_LINE_NUMBER,
1212
},
1313
utils::{create_DIArray, get_namespace_for_item, DIB},
1414
},
@@ -63,6 +63,8 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
6363
let enum_type_and_layout = cx.layout_of(enum_type);
6464
let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
6565

66+
let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
67+
6668
debug_assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
6769

6870
type_map::build_type_with_children(
@@ -74,7 +76,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
7476
&enum_type_name,
7577
size_and_align_of(enum_type_and_layout),
7678
Some(containing_scope),
77-
DIFlags::FlagZero,
79+
visibility_flags,
7880
),
7981
|cx, enum_type_di_node| {
8082
// Build the struct type for each variant. These will be referenced by the
@@ -92,6 +94,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
9294
variant_index,
9395
enum_adt_def.variant(variant_index),
9496
enum_type_and_layout.for_variant(cx, variant_index),
97+
visibility_flags,
9598
),
9699
source_info: None,
97100
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// compile-flags: -C debuginfo=2
2+
// ignore-tidy-linelength
3+
4+
#![allow(dead_code)]
5+
6+
// Checks that visibility information is present in the debuginfo for crate-visibility enums.
7+
8+
mod module {
9+
use std::hint::black_box;
10+
11+
pub(crate) enum CrateFooEnum {
12+
A,
13+
B(u32),
14+
C { x: u32 },
15+
}
16+
17+
// NONMSVC: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "CrateFooEnum"{{.*}}flags: DIFlagProtected{{.*}})
18+
// MSVC: {{!.*}} = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<crate_enum::module::CrateFooEnum>"{{.*}}flags: DIFlagProtected{{.*}})
19+
pub fn use_everything() {
20+
black_box(CrateFooEnum::A);
21+
}
22+
}
23+
24+
fn main() {
25+
module::use_everything();
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// compile-flags: -C debuginfo=2
2+
3+
#![allow(dead_code)]
4+
5+
// Checks that visibility information is present in the debuginfo for crate-visibility structs.
6+
7+
mod module {
8+
use std::hint::black_box;
9+
10+
pub(crate) struct CrateFooStruct {
11+
x: u32,
12+
}
13+
14+
// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "CrateFooStruct"{{.*}}flags: DIFlagProtected{{.*}})
15+
16+
pub fn use_everything() {
17+
black_box(CrateFooStruct { x: 2 });
18+
}
19+
}
20+
21+
fn main() {
22+
module::use_everything();
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -C debuginfo=2
2+
// ignore-tidy-linelength
3+
4+
#![allow(dead_code)]
5+
6+
// Checks that visibility information is present in the debuginfo for private enums.
7+
8+
use std::hint::black_box;
9+
10+
enum PrivateFooEnum {
11+
A,
12+
B(u32),
13+
C { x: u32 },
14+
}
15+
16+
// NONMSVC: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "PrivateFooEnum"{{.*}}flags: DIFlagPrivate{{.*}})
17+
// MSVC: {{!.*}} = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<private_enum::PrivateFooEnum>"{{.*}}flags: DIFlagPrivate{{.*}})
18+
19+
fn main() {
20+
black_box(PrivateFooEnum::A);
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// compile-flags: -C debuginfo=2
2+
3+
#![allow(dead_code)]
4+
5+
// Checks that visibility information is present in the debuginfo for private structs.
6+
7+
use std::hint::black_box;
8+
9+
struct PrivateFooStruct {
10+
x: u32,
11+
}
12+
13+
// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "PrivateFooStruct"{{.*}}flags: DIFlagPrivate{{.*}})
14+
15+
fn main() {
16+
black_box(PrivateFooStruct { x: 1 });
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -C debuginfo=2
2+
// ignore-tidy-linelength
3+
4+
#![allow(dead_code)]
5+
6+
// Checks that visibility information is present in the debuginfo for types and their fields.
7+
8+
use std::hint::black_box;
9+
10+
pub enum PublicFooEnum {
11+
A,
12+
B(u32),
13+
C { x: u32 },
14+
}
15+
16+
// NONMSVC: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "PublicFooEnum"{{.*}}flags: DIFlagPublic{{.*}})
17+
// MSVC: {{!.*}} = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<public_enum::PublicFooEnum>"{{.*}}flags: DIFlagPublic{{.*}})
18+
19+
fn main() {
20+
black_box(PublicFooEnum::A);
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// compile-flags: -C debuginfo=2
2+
3+
#![allow(dead_code)]
4+
5+
// Checks that visibility information is present in the debuginfo for public structs.
6+
7+
use std::hint::black_box;
8+
9+
pub struct PublicFooStruct {
10+
x: u32,
11+
}
12+
13+
// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "PublicFooStruct"{{.*}}flags: DIFlagPublic{{.*}})
14+
15+
fn main() {
16+
black_box(PublicFooStruct { x: 4 });
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// compile-flags: -C debuginfo=2
2+
3+
#![allow(dead_code)]
4+
5+
// Checks that visibility information is present in the debuginfo for struct fields.
6+
7+
mod module {
8+
use std::hint::black_box;
9+
10+
struct StructFields {
11+
a: u32,
12+
pub(crate) b: u32,
13+
pub(super) c: u32,
14+
pub d: u32,
15+
}
16+
17+
// CHECK: [[StructFields:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "StructFields"{{.*}}flags: DIFlagPrivate{{.*}})
18+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: [[StructFields]]{{.*}}flags: DIFlagPrivate{{.*}})
19+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: [[StructFields]]{{.*}}flags: DIFlagProtected{{.*}})
20+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: [[StructFields]]{{.*}}flags: DIFlagProtected{{.*}})
21+
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: [[StructFields]]{{.*}}flags: DIFlagPublic{{.*}})
22+
23+
pub fn use_everything() {
24+
black_box(StructFields { a: 1, b: 2, c: 3, d: 4 });
25+
}
26+
}
27+
28+
fn main() {
29+
module::use_everything();
30+
}

0 commit comments

Comments
 (0)