Rollup merge of #93503 - michaelwoerister:fix-vtable-holder-debuginfo-regression, r=wesleywiser
debuginfo: Fix DW_AT_containing_type vtable debuginfo regression This PR brings back the `DW_AT_containing_type` attribute for vtables after it has accidentally been removed in #89597. It also implements a more accurate description of vtables. Instead of describing them as an array of void pointers, the compiler will now emit a struct type description with a field for each entry of the vtable. r? ``@wesleywiser`` This PR should fix issue https://github.com/rust-lang/rust/issues/93164. ~~The PR is blocked on https://github.com/rust-lang/rust/pull/93154 because both of them modify the `codegen/debug-vtable.rs` test case.~~
This commit is contained in:
commit
6d40850e09
@ -21,6 +21,7 @@
|
||||
|
||||
use cstr::cstr;
|
||||
use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
|
||||
use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@ -276,6 +277,12 @@ fn get_unique_type_id_str_of_enum_variant_part(
|
||||
) -> String {
|
||||
format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id))
|
||||
}
|
||||
|
||||
/// Gets the `UniqueTypeId` for the type of a vtable.
|
||||
fn get_unique_type_id_of_vtable_type(&mut self, vtable_type_name: &str) -> UniqueTypeId {
|
||||
let interner_key = self.unique_id_interner.intern(vtable_type_name);
|
||||
interner_key
|
||||
}
|
||||
}
|
||||
|
||||
/// A description of some recursive type. It can either be already finished (as
|
||||
@ -351,14 +358,15 @@ fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
|
||||
|
||||
// ... then create the member descriptions ...
|
||||
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
||||
let type_params = compute_type_parameters(cx, unfinished_type);
|
||||
|
||||
// ... and attach them to the stub to complete it.
|
||||
set_members_of_composite_type(
|
||||
cx,
|
||||
unfinished_type,
|
||||
member_holding_stub,
|
||||
member_descriptions,
|
||||
None,
|
||||
type_params,
|
||||
);
|
||||
MetadataCreationResult::new(metadata_stub, true)
|
||||
}
|
||||
@ -983,7 +991,17 @@ fn foreign_type_metadata<'ll, 'tcx>(
|
||||
debug!("foreign_type_metadata: {:?}", t);
|
||||
|
||||
let name = compute_debuginfo_type_name(cx.tcx, t, false);
|
||||
create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero)
|
||||
let (size, align) = cx.size_and_align_of(t);
|
||||
create_struct_stub(
|
||||
cx,
|
||||
size,
|
||||
align,
|
||||
&name,
|
||||
unique_type_id,
|
||||
NO_SCOPE_METADATA,
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
fn param_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
||||
@ -1299,14 +1317,17 @@ fn prepare_struct_metadata<'ll, 'tcx>(
|
||||
};
|
||||
|
||||
let containing_scope = get_namespace_for_item(cx, struct_def_id);
|
||||
let (size, align) = cx.size_and_align_of(struct_type);
|
||||
|
||||
let struct_metadata_stub = create_struct_stub(
|
||||
cx,
|
||||
struct_type,
|
||||
size,
|
||||
align,
|
||||
&struct_name,
|
||||
unique_type_id,
|
||||
Some(containing_scope),
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
);
|
||||
|
||||
create_and_register_recursive_type_forward_declaration(
|
||||
@ -1398,15 +1419,18 @@ fn prepare_tuple_metadata<'ll, 'tcx>(
|
||||
unique_type_id: UniqueTypeId,
|
||||
containing_scope: Option<&'ll DIScope>,
|
||||
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
||||
let (size, align) = cx.size_and_align_of(tuple_type);
|
||||
let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false);
|
||||
|
||||
let struct_stub = create_struct_stub(
|
||||
cx,
|
||||
tuple_type,
|
||||
size,
|
||||
align,
|
||||
&tuple_name[..],
|
||||
unique_type_id,
|
||||
containing_scope,
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
);
|
||||
|
||||
create_and_register_recursive_type_forward_declaration(
|
||||
@ -1581,13 +1605,14 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
|
||||
describe_enum_variant(cx, self.layout, variant_info, self_metadata);
|
||||
|
||||
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
||||
let type_params = compute_type_parameters(cx, self.enum_type);
|
||||
|
||||
set_members_of_composite_type(
|
||||
cx,
|
||||
self.enum_type,
|
||||
variant_type_metadata,
|
||||
member_descriptions,
|
||||
Some(&self.common_members),
|
||||
type_params,
|
||||
);
|
||||
vec![MemberDescription {
|
||||
name: variant_info.variant_name(),
|
||||
@ -1648,13 +1673,14 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
|
||||
|
||||
let member_descriptions =
|
||||
member_desc_factory.create_member_descriptions(cx);
|
||||
let type_params = compute_type_parameters(cx, self.enum_type);
|
||||
|
||||
set_members_of_composite_type(
|
||||
cx,
|
||||
self.enum_type,
|
||||
variant_type_metadata,
|
||||
member_descriptions,
|
||||
Some(&self.common_members),
|
||||
type_params,
|
||||
);
|
||||
|
||||
MemberDescription {
|
||||
@ -1777,13 +1803,14 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
|
||||
);
|
||||
|
||||
let member_descriptions = member_desc_factory.create_member_descriptions(cx);
|
||||
let type_params = compute_type_parameters(cx, self.enum_type);
|
||||
|
||||
set_members_of_composite_type(
|
||||
cx,
|
||||
self.enum_type,
|
||||
variant_type_metadata,
|
||||
member_descriptions,
|
||||
Some(&self.common_members),
|
||||
type_params,
|
||||
);
|
||||
|
||||
let (size, align) =
|
||||
@ -1823,13 +1850,14 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
|
||||
|
||||
let member_descriptions =
|
||||
member_desc_factory.create_member_descriptions(cx);
|
||||
let type_params = compute_type_parameters(cx, self.enum_type);
|
||||
|
||||
set_members_of_composite_type(
|
||||
cx,
|
||||
self.enum_type,
|
||||
variant_type_metadata,
|
||||
member_descriptions,
|
||||
Some(&self.common_members),
|
||||
type_params,
|
||||
);
|
||||
|
||||
let niche_value = calculate_niche_value(i);
|
||||
@ -1965,13 +1993,18 @@ fn describe_enum_variant<'ll, 'tcx>(
|
||||
.type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name);
|
||||
|
||||
let (size, align) = cx.size_and_align_of(layout.ty);
|
||||
|
||||
create_struct_stub(
|
||||
cx,
|
||||
layout.ty,
|
||||
size,
|
||||
align,
|
||||
variant_name,
|
||||
unique_type_id,
|
||||
Some(containing_scope),
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
)
|
||||
});
|
||||
|
||||
@ -2308,22 +2341,27 @@ fn composite_type_metadata<'ll, 'tcx>(
|
||||
member_descriptions: Vec<MemberDescription<'ll>>,
|
||||
containing_scope: Option<&'ll DIScope>,
|
||||
) -> &'ll DICompositeType {
|
||||
let (size, align) = cx.size_and_align_of(composite_type);
|
||||
|
||||
// Create the (empty) struct metadata node ...
|
||||
let composite_type_metadata = create_struct_stub(
|
||||
cx,
|
||||
composite_type,
|
||||
size,
|
||||
align,
|
||||
composite_type_name,
|
||||
composite_type_unique_id,
|
||||
containing_scope,
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
);
|
||||
|
||||
// ... and immediately create and add the member descriptions.
|
||||
set_members_of_composite_type(
|
||||
cx,
|
||||
composite_type,
|
||||
composite_type_metadata,
|
||||
member_descriptions,
|
||||
None,
|
||||
compute_type_parameters(cx, composite_type),
|
||||
);
|
||||
|
||||
composite_type_metadata
|
||||
@ -2331,10 +2369,10 @@ fn composite_type_metadata<'ll, 'tcx>(
|
||||
|
||||
fn set_members_of_composite_type<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
composite_type: Ty<'tcx>,
|
||||
composite_type_metadata: &'ll DICompositeType,
|
||||
member_descriptions: Vec<MemberDescription<'ll>>,
|
||||
common_members: Option<&Vec<Option<&'ll DIType>>>,
|
||||
type_params: &'ll DIArray,
|
||||
) {
|
||||
// In some rare cases LLVM metadata uniquing would lead to an existing type
|
||||
// description being used instead of a new one created in
|
||||
@ -2361,13 +2399,12 @@ fn set_members_of_composite_type<'ll, 'tcx>(
|
||||
member_metadata.extend(other_members.iter());
|
||||
}
|
||||
|
||||
let type_params = compute_type_parameters(cx, composite_type);
|
||||
unsafe {
|
||||
let type_array = create_DIArray(DIB(cx), &member_metadata);
|
||||
let field_array = create_DIArray(DIB(cx), &member_metadata);
|
||||
llvm::LLVMRustDICompositeTypeReplaceArrays(
|
||||
DIB(cx),
|
||||
composite_type_metadata,
|
||||
Some(type_array),
|
||||
Some(field_array),
|
||||
Some(type_params),
|
||||
);
|
||||
}
|
||||
@ -2420,14 +2457,14 @@ fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<S
|
||||
/// with `set_members_of_composite_type()`.
|
||||
fn create_struct_stub<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
struct_type: Ty<'tcx>,
|
||||
struct_type_name: &str,
|
||||
size: Size,
|
||||
align: Align,
|
||||
type_name: &str,
|
||||
unique_type_id: UniqueTypeId,
|
||||
containing_scope: Option<&'ll DIScope>,
|
||||
flags: DIFlags,
|
||||
vtable_holder: Option<&'ll DIType>,
|
||||
) -> &'ll DICompositeType {
|
||||
let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
|
||||
|
||||
let type_map = debug_context(cx).type_map.borrow();
|
||||
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||
|
||||
@ -2440,17 +2477,17 @@ fn create_struct_stub<'ll, 'tcx>(
|
||||
llvm::LLVMRustDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
struct_type_name.as_ptr().cast(),
|
||||
struct_type_name.len(),
|
||||
type_name.as_ptr().cast(),
|
||||
type_name.len(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
struct_size.bits(),
|
||||
struct_align.bits() as u32,
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
flags,
|
||||
None,
|
||||
empty_array,
|
||||
0,
|
||||
None,
|
||||
vtable_holder,
|
||||
unique_type_id.as_ptr().cast(),
|
||||
unique_type_id.len(),
|
||||
)
|
||||
@ -2556,6 +2593,14 @@ pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, g
|
||||
}
|
||||
|
||||
/// Generates LLVM debuginfo for a vtable.
|
||||
///
|
||||
/// The vtable type looks like a struct with a field for each function pointer and super-trait
|
||||
/// pointer it contains (plus the `size` and `align` fields).
|
||||
///
|
||||
/// Except for `size`, `align`, and `drop_in_place`, the field names don't try to mirror
|
||||
/// the name of the method they implement. This can be implemented in the future once there
|
||||
/// is a proper disambiguation scheme for dealing with methods from different traits that have
|
||||
/// the same name.
|
||||
fn vtable_type_metadata<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
@ -2572,16 +2617,81 @@ fn vtable_type_metadata<'ll, 'tcx>(
|
||||
COMMON_VTABLE_ENTRIES
|
||||
};
|
||||
|
||||
// FIXME: We describe the vtable as an array of *const () pointers. The length of the array is
|
||||
// correct - but we could create a more accurate description, e.g. by describing it
|
||||
// as a struct where each field has a name that corresponds to the name of the method
|
||||
// it points to.
|
||||
// However, this is not entirely straightforward because there might be multiple
|
||||
// methods with the same name if the vtable is for multiple traits. So for now we keep
|
||||
// things simple instead of adding some ad-hoc disambiguation scheme.
|
||||
let vtable_type = tcx.mk_array(tcx.mk_imm_ptr(tcx.types.unit), vtable_entries.len() as u64);
|
||||
// All function pointers are described as opaque pointers. This could be improved in the future
|
||||
// by describing them as actual function pointers.
|
||||
let void_pointer_ty = tcx.mk_imm_ptr(tcx.types.unit);
|
||||
let void_pointer_type_debuginfo = type_metadata(cx, void_pointer_ty);
|
||||
let usize_debuginfo = type_metadata(cx, tcx.types.usize);
|
||||
let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty);
|
||||
// If `usize` is not pointer-sized and -aligned then the size and alignment computations
|
||||
// for the vtable as a whole would be wrong. Let's make sure this holds even on weird
|
||||
// platforms.
|
||||
assert_eq!(cx.size_and_align_of(tcx.types.usize), (pointer_size, pointer_align));
|
||||
|
||||
type_metadata(cx, vtable_type)
|
||||
let vtable_type_name =
|
||||
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::Type);
|
||||
let unique_type_id = debug_context(cx)
|
||||
.type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_of_vtable_type(&vtable_type_name);
|
||||
let size = pointer_size * vtable_entries.len() as u64;
|
||||
|
||||
// This gets mapped to a DW_AT_containing_type attribute which allows GDB to correlate
|
||||
// the vtable to the type it is for.
|
||||
let vtable_holder = type_metadata(cx, ty);
|
||||
|
||||
let vtable_type_metadata = create_struct_stub(
|
||||
cx,
|
||||
size,
|
||||
pointer_align,
|
||||
&vtable_type_name,
|
||||
unique_type_id,
|
||||
NO_SCOPE_METADATA,
|
||||
DIFlags::FlagArtificial,
|
||||
Some(vtable_holder),
|
||||
);
|
||||
|
||||
// Create a field for each entry in the vtable.
|
||||
let fields: Vec<_> = vtable_entries
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, vtable_entry)| {
|
||||
let (field_name, field_type) = match vtable_entry {
|
||||
ty::VtblEntry::MetadataDropInPlace => {
|
||||
("drop_in_place".to_string(), void_pointer_type_debuginfo)
|
||||
}
|
||||
ty::VtblEntry::Method(_) => {
|
||||
// Note: This code does not try to give a proper name to each method
|
||||
// because there might be multiple methods with the same name
|
||||
// (coming from different traits).
|
||||
(format!("__method{}", index), void_pointer_type_debuginfo)
|
||||
}
|
||||
ty::VtblEntry::TraitVPtr(_) => {
|
||||
// Note: In the future we could try to set the type of this pointer
|
||||
// to the type that we generate for the corresponding vtable.
|
||||
(format!("__super_trait_ptr{}", index), void_pointer_type_debuginfo)
|
||||
}
|
||||
ty::VtblEntry::MetadataAlign => ("align".to_string(), usize_debuginfo),
|
||||
ty::VtblEntry::MetadataSize => ("size".to_string(), usize_debuginfo),
|
||||
ty::VtblEntry::Vacant => return None,
|
||||
};
|
||||
|
||||
Some(MemberDescription {
|
||||
name: field_name,
|
||||
type_metadata: field_type,
|
||||
offset: pointer_size * index as u64,
|
||||
size: pointer_size,
|
||||
align: pointer_align,
|
||||
flags: DIFlags::FlagZero,
|
||||
discriminant: None,
|
||||
source_info: None,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
let type_params = create_DIArray(DIB(cx), &[]);
|
||||
set_members_of_composite_type(cx, vtable_type_metadata, fields, None, type_params);
|
||||
vtable_type_metadata
|
||||
}
|
||||
|
||||
/// Creates debug information for the given vtable, which is for the
|
||||
@ -2603,11 +2713,12 @@ pub fn create_vtable_metadata<'ll, 'tcx>(
|
||||
return;
|
||||
}
|
||||
|
||||
let vtable_name = compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref);
|
||||
let vtable_name =
|
||||
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);
|
||||
let vtable_type = vtable_type_metadata(cx, ty, poly_trait_ref);
|
||||
let linkage_name = "";
|
||||
|
||||
unsafe {
|
||||
let linkage_name = "";
|
||||
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
||||
DIB(cx),
|
||||
NO_SCOPE_METADATA,
|
||||
|
@ -469,7 +469,14 @@ fn pop_auto_trait_separator(output: &mut String) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes a name for the global variable storing a vtable.
|
||||
pub enum VTableNameKind {
|
||||
// Is the name for the const/static holding the vtable?
|
||||
GlobalVariable,
|
||||
// Is the name for the type of the vtable?
|
||||
Type,
|
||||
}
|
||||
|
||||
/// Computes a name for the global variable storing a vtable (or the type of that global variable).
|
||||
///
|
||||
/// The name is of the form:
|
||||
///
|
||||
@ -478,10 +485,15 @@ fn pop_auto_trait_separator(output: &mut String) {
|
||||
/// or, when generating C++-like names:
|
||||
///
|
||||
/// `impl$<path::to::SomeType, path::to::SomeTrait>::vtable$`
|
||||
///
|
||||
/// If `kind` is `VTableNameKind::Type` then the last component is `{vtable_ty}` instead of just
|
||||
/// `{vtable}`, so that the type and the corresponding global variable get assigned different
|
||||
/// names.
|
||||
pub fn compute_debuginfo_vtable_name<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
t: Ty<'tcx>,
|
||||
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
kind: VTableNameKind,
|
||||
) -> String {
|
||||
let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
|
||||
|
||||
@ -514,7 +526,12 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
|
||||
|
||||
push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name);
|
||||
|
||||
let suffix = if cpp_like_debuginfo { "::vtable$" } else { "::{vtable}" };
|
||||
let suffix = match (cpp_like_debuginfo, kind) {
|
||||
(true, VTableNameKind::GlobalVariable) => "::vtable$",
|
||||
(false, VTableNameKind::GlobalVariable) => "::{vtable}",
|
||||
(true, VTableNameKind::Type) => "::vtable_type$",
|
||||
(false, VTableNameKind::Type) => "::{vtable_type}",
|
||||
};
|
||||
|
||||
vtable_name.reserve_exact(suffix.len());
|
||||
vtable_name.push_str(suffix);
|
||||
|
@ -9,19 +9,41 @@
|
||||
// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// NONMSVC: ![[USIZE:[0-9]+]] = !DIBasicType(name: "usize"
|
||||
// MSVC: ![[USIZE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_typedef, name: "usize"
|
||||
// NONMSVC: ![[PTR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()"
|
||||
// MSVC: ![[PTR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$<tuple$<> >"
|
||||
|
||||
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable}"
|
||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable$"
|
||||
// NONMSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()",
|
||||
// MSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$<tuple$<> >",
|
||||
// CHECK: !DISubrange(count: 5
|
||||
|
||||
// NONMSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable_type}", {{.*}} size: {{320|160}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}} vtableHolder: ![[FOO_TYPE:[0-9]+]],
|
||||
// MSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable_type$", {{.*}} size: {{320|160}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}} vtableHolder: ![[FOO_TYPE:[0-9]+]],
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method3", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{192|96}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method4", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{256|128}})
|
||||
// CHECK: ![[FOO_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo",
|
||||
|
||||
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable}"
|
||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable$"
|
||||
// CHECK: !DISubrange(count: 4
|
||||
|
||||
// NONMSVC: ![[VTABLE_TY1:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable_type}", {{.*}}, size: {{256|128}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
|
||||
// MSVC: ![[VTABLE_TY1:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable_type$", {{.*}}, size: {{256|128}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method3", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{192|96}})
|
||||
|
||||
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as _>::{vtable}"
|
||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, _>::vtable$"
|
||||
// CHECK: !DISubrange(count: 3
|
||||
|
||||
// NONMSVC: ![[VTABLE_TY2:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as _>::{vtable_type}", {{.*}}, size: {{192|96}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
|
||||
// MSVC: ![[VTABLE_TY2:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$<debug_vtable::Foo, _>::vtable_type$", {{.*}}, size: {{192|96}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]],
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}})
|
||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}})
|
||||
|
||||
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::bar::{closure_env#0} as core::ops::function::FnOnce<(core::option::Option<&dyn core::ops::function::Fn<(), Output=()>>)>>::{vtable}"
|
||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure_env$0, core::ops::function::FnOnce<tuple$<enum$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$"
|
||||
@ -34,6 +56,9 @@
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Force emission for debuginfo for usize and *const() early..
|
||||
pub static mut XYZ: Option<(usize, *const ())> = None;
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
pub trait SomeTrait {
|
||||
|
@ -17,35 +17,34 @@
|
||||
|
||||
// compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0
|
||||
|
||||
|
||||
// CHECK: [[non_generic_closure_NAMESPACE:!.*]] = !DINamespace(name: "non_generic_closure"
|
||||
// CHECK: [[function_containing_closure_NAMESPACE:!.*]] = !DINamespace(name: "function_containing_closure"
|
||||
// CHECK: [[generic_async_function_NAMESPACE:!.*]] = !DINamespace(name: "generic_async_function"
|
||||
// CHECK: [[generic_async_block_NAMESPACE:!.*]] = !DINamespace(name: "generic_async_block"
|
||||
|
||||
// non_generic_closure()
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[non_generic_closure_NAMESPACE]]
|
||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: [[non_generic_closure_NAMESPACE]]
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]],
|
||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]],
|
||||
// CHECK: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure"
|
||||
|
||||
// CHECK: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure"
|
||||
// CHECK: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function"
|
||||
// CHECK: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block"
|
||||
|
||||
// function_containing_closure<u32>()
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: [[function_containing_closure_NAMESPACE]]
|
||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: [[function_containing_closure_NAMESPACE]]
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||
|
||||
// generic_async_function<Foo>()
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[generic_async_function_NAMESPACE]]
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_function_NAMESPACE]]
|
||||
|
||||
// generic_async_function<u32>()
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: [[generic_async_function_NAMESPACE]]
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: ![[generic_async_function_NAMESPACE]]
|
||||
|
||||
// generic_async_block<Foo>()
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[generic_async_block_NAMESPACE]]
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_block_NAMESPACE]]
|
||||
|
||||
// generic_async_block<u32>()
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: [[generic_async_block_NAMESPACE]]
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: ![[generic_async_block_NAMESPACE]]
|
||||
|
||||
// function_containing_closure<Foo>()
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[function_containing_closure_NAMESPACE]]
|
||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: [[function_containing_closure_NAMESPACE]]
|
||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||
|
||||
|
||||
#![crate_type = "lib"]
|
||||
@ -54,15 +53,14 @@
|
||||
pub struct Foo;
|
||||
|
||||
pub fn non_generic_closure(x: Foo) -> Box<dyn FnOnce() -> Foo> {
|
||||
// This static only exists to trigger generating the namespace debuginfo for
|
||||
// `function_containing_closure` at a predictable, early point, which makes
|
||||
// writing the FileCheck tests above simpler.
|
||||
static _X: u8 = 0;
|
||||
return Box::new(move || x);
|
||||
}
|
||||
|
||||
fn function_containing_closure<T: 'static>(x: T) -> impl FnOnce() -> T {
|
||||
static _X: u8 = 0; // Same as above
|
||||
// This static only exists to trigger generating the namespace debuginfo for
|
||||
// `function_containing_closure` at a predictable, early point, which makes
|
||||
// writing the FileCheck tests above simpler.
|
||||
static _X: u8 = 0;
|
||||
|
||||
return move || x;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user