Skip to content

Commit 8a3bb9a

Browse files
committed
Add template parameter debuginfo to generic types
This changes debuginfo generation to add template parameters to generic types. With this change the DWARF now has DW_TAG_template_type_param for types, not just for functions, like: <2><40d>: Abbrev Number: 6 (DW_TAG_structure_type) <40e> DW_AT_name : (indirect string, offset: 0x375): Generic<i32> <412> DW_AT_byte_size : 4 <413> DW_AT_alignment : 4 ... <3><41f>: Abbrev Number: 8 (DW_TAG_template_type_param) <420> DW_AT_type : <0x42a> <424> DW_AT_name : (indirect string, offset: 0xa65e): T Closes rust-lang#9224
1 parent a66dc8a commit 8a3bb9a

File tree

4 files changed

+96
-11
lines changed

4 files changed

+96
-11
lines changed

src/librustc_codegen_llvm/debuginfo/metadata.rs

+58-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use abi;
2121
use value::Value;
2222

2323
use llvm;
24-
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
24+
use llvm::debuginfo::{DIArray, DIType, DIFile, DIScope, DIDescriptor,
2525
DICompositeType, DILexicalBlock, DIFlags};
2626

2727
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -34,6 +34,7 @@ use rustc::ty::Instance;
3434
use common::CodegenCx;
3535
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
3636
use rustc::ty::layout::{self, Align, LayoutOf, PrimitiveExt, Size, TyLayout};
37+
use rustc::ty::subst::UnpackedKind;
3738
use rustc::session::config;
3839
use rustc::util::nodemap::FxHashMap;
3940
use rustc_fs_util::path2cstr;
@@ -266,6 +267,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> {
266267

267268
// ... and attach them to the stub to complete it.
268269
set_members_of_composite_type(cx,
270+
unfinished_type,
269271
metadata_stub,
270272
member_descriptions);
271273
return MetadataCreationResult::new(metadata_stub, true);
@@ -1174,6 +1176,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
11741176
member_description_factory.create_member_descriptions(cx);
11751177

11761178
set_members_of_composite_type(cx,
1179+
self.enum_type,
11771180
variant_type_metadata,
11781181
member_descriptions);
11791182
vec![
@@ -1204,6 +1207,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
12041207
.create_member_descriptions(cx);
12051208

12061209
set_members_of_composite_type(cx,
1210+
self.enum_type,
12071211
variant_type_metadata,
12081212
member_descriptions);
12091213
MemberDescription {
@@ -1231,6 +1235,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
12311235
member_description_factory.create_member_descriptions(cx);
12321236

12331237
set_members_of_composite_type(cx,
1238+
self.enum_type,
12341239
variant_type_metadata,
12351240
variant_member_descriptions);
12361241

@@ -1534,13 +1539,15 @@ fn composite_type_metadata(
15341539
containing_scope);
15351540
// ... and immediately create and add the member descriptions.
15361541
set_members_of_composite_type(cx,
1542+
composite_type,
15371543
composite_type_metadata,
15381544
member_descriptions);
15391545

15401546
composite_type_metadata
15411547
}
15421548

1543-
fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>,
1549+
fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>,
1550+
composite_type: Ty<'tcx>,
15441551
composite_type_metadata: &'ll DICompositeType,
15451552
member_descriptions: Vec<MemberDescription<'ll>>) {
15461553
// In some rare cases LLVM metadata uniquing would lead to an existing type
@@ -1580,10 +1587,57 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>,
15801587
})
15811588
.collect();
15821589

1590+
let type_params = compute_type_parameters(cx, composite_type);
15831591
unsafe {
15841592
let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
1585-
llvm::LLVMRustDICompositeTypeSetTypeArray(
1586-
DIB(cx), composite_type_metadata, type_array);
1593+
llvm::LLVMRustDICompositeTypeReplaceArrays(
1594+
DIB(cx), composite_type_metadata, Some(type_array), type_params);
1595+
}
1596+
}
1597+
1598+
// Compute the type parameters for a type, if any, for the given
1599+
// metadata.
1600+
fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> {
1601+
if let ty::Adt(def, substs) = ty.sty {
1602+
if !substs.types().next().is_none() {
1603+
let generics = cx.tcx.generics_of(def.did);
1604+
let names = get_parameter_names(cx, generics);
1605+
let template_params: Vec<_> = substs.iter().zip(names).filter_map(|(kind, name)| {
1606+
if let UnpackedKind::Type(ty) = kind.unpack() {
1607+
let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
1608+
let actual_type_metadata =
1609+
type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
1610+
let name = SmallCStr::new(&name.as_str());
1611+
Some(unsafe {
1612+
1613+
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
1614+
DIB(cx),
1615+
None,
1616+
name.as_ptr(),
1617+
actual_type_metadata,
1618+
unknown_file_metadata(cx),
1619+
0,
1620+
0,
1621+
))
1622+
})
1623+
} else {
1624+
None
1625+
}
1626+
}).collect();
1627+
1628+
return Some(create_DIArray(DIB(cx), &template_params[..]));
1629+
}
1630+
}
1631+
return None;
1632+
1633+
fn get_parameter_names(cx: &CodegenCx,
1634+
generics: &ty::Generics)
1635+
-> Vec<InternedString> {
1636+
let mut names = generics.parent.map_or(vec![], |def_id| {
1637+
get_parameter_names(cx, cx.tcx.generics_of(def_id))
1638+
});
1639+
names.extend(generics.params.iter().map(|param| param.name));
1640+
names
15871641
}
15881642
}
15891643

src/librustc_codegen_llvm/llvm/ffi.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1421,9 +1421,10 @@ extern "C" {
14211421
LineNo: c_uint)
14221422
-> &'a DINameSpace;
14231423

1424-
pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: &DIBuilder<'a>,
1425-
CompositeType: &'a DIType,
1426-
TypeArray: &'a DIArray);
1424+
pub fn LLVMRustDICompositeTypeReplaceArrays(Builder: &DIBuilder<'a>,
1425+
CompositeType: &'a DIType,
1426+
Elements: Option<&'a DIArray>,
1427+
Params: Option<&'a DIArray>);
14271428

14281429

14291430
pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context,

src/rustllvm/RustWrapper.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -870,11 +870,13 @@ LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
870870
}
871871

872872
extern "C" void
873-
LLVMRustDICompositeTypeSetTypeArray(LLVMRustDIBuilderRef Builder,
874-
LLVMMetadataRef CompositeTy,
875-
LLVMMetadataRef TyArray) {
873+
LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
874+
LLVMMetadataRef CompositeTy,
875+
LLVMMetadataRef Elements,
876+
LLVMMetadataRef Params) {
876877
DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
877-
Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(TyArray)));
878+
Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
879+
DINodeArray(unwrap<MDTuple>(Params)));
878880
}
879881

880882
extern "C" LLVMValueRef

src/test/codegen/generic-debug.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
// ignore-windows
13+
14+
// compile-flags: -g -C no-prepopulate-passes
15+
16+
// CHECK-LABEL: @main
17+
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "Generic<i32>",{{.*}}
18+
// CHECK: {{.*}}DITemplateTypeParameter{{.*}}name: "Type",{{.*}}
19+
20+
#![allow(dead_code)]
21+
#![allow(unused_variables)]
22+
#![allow(unused_assignments)]
23+
24+
pub struct Generic<Type>(Type);
25+
26+
fn main () {
27+
let generic = Generic(10);
28+
}

0 commit comments

Comments
 (0)