From fb204cb92f5da2cd0b630ee4b6be85b02404823e Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 12 Oct 2018 07:34:14 -0600 Subject: [PATCH] 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 <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 #9224 --- .../debuginfo/metadata.rs | 66 +++++++++++++++++-- src/librustc_codegen_llvm/llvm/ffi.rs | 7 +- src/rustllvm/RustWrapper.cpp | 10 +-- src/test/codegen/generic-debug.rs | 28 ++++++++ src/test/debuginfo/associated-types.rs | 4 +- .../generic-method-on-generic-struct.rs | 5 +- src/test/debuginfo/generic-struct.rs | 5 +- .../debuginfo/generic-tuple-style-enum.rs | 4 +- .../debuginfo/method-on-generic-struct.rs | 4 +- 9 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 src/test/codegen/generic-debug.rs diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 81f2769800d2f..cd21ef6bfa834 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -22,7 +22,7 @@ use abi; use value::Value; use llvm; -use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, +use llvm::debuginfo::{DIArray, DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock, DIFlags}; use llvm_util; @@ -35,12 +35,14 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc::ty::Instance; use common::CodegenCx; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutOf, +use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout}; +use rustc::ty::subst::UnpackedKind; use rustc::session::config; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path2cstr; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_target::abi::HasDataLayout; use libc::{c_uint, c_longlong}; use std::ffi::CString; @@ -273,6 +275,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> { // ... and attach them to the stub to complete it. set_members_of_composite_type(cx, + unfinished_type, member_holding_stub, member_descriptions); return MetadataCreationResult::new(metadata_stub, true); @@ -1214,6 +1217,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { member_description_factory.create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, member_descriptions); vec![ @@ -1254,6 +1258,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { .create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, member_descriptions); MemberDescription { @@ -1295,6 +1300,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { member_description_factory.create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, variant_member_descriptions); @@ -1354,6 +1360,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { .create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, member_descriptions); @@ -1765,13 +1772,15 @@ fn composite_type_metadata( containing_scope); // ... and immediately create and add the member descriptions. set_members_of_composite_type(cx, + composite_type, composite_type_metadata, member_descriptions); composite_type_metadata } -fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, +fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>, + composite_type: Ty<'tcx>, composite_type_metadata: &'ll DICompositeType, member_descriptions: Vec>) { // In some rare cases LLVM metadata uniquing would lead to an existing type @@ -1815,10 +1824,57 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, }) .collect(); + let type_params = compute_type_parameters(cx, composite_type); unsafe { let type_array = create_DIArray(DIB(cx), &member_metadata[..]); - llvm::LLVMRustDICompositeTypeSetTypeArray( - DIB(cx), composite_type_metadata, type_array); + llvm::LLVMRustDICompositeTypeReplaceArrays( + DIB(cx), composite_type_metadata, Some(type_array), type_params); + } +} + +// Compute the type parameters for a type, if any, for the given +// metadata. +fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> { + if let ty::Adt(def, substs) = ty.sty { + if !substs.types().next().is_none() { + let generics = cx.tcx.generics_of(def.did); + let names = get_parameter_names(cx, generics); + let template_params: Vec<_> = substs.iter().zip(names).filter_map(|(kind, name)| { + if let UnpackedKind::Type(ty) = kind.unpack() { + let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); + let actual_type_metadata = + type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); + let name = SmallCStr::new(&name.as_str()); + Some(unsafe { + + Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( + DIB(cx), + None, + name.as_ptr(), + actual_type_metadata, + unknown_file_metadata(cx), + 0, + 0, + )) + }) + } else { + None + } + }).collect(); + + return Some(create_DIArray(DIB(cx), &template_params[..])); + } + } + return Some(create_DIArray(DIB(cx), &[])); + + fn get_parameter_names(cx: &CodegenCx, + generics: &ty::Generics) + -> Vec { + let mut names = generics.parent.map_or(vec![], |def_id| { + get_parameter_names(cx, cx.tcx.generics_of(def_id)) + }); + names.extend(generics.params.iter().map(|param| param.name)); + names } } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index f1a966d765438..88915c2beb027 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1586,9 +1586,10 @@ extern "C" { LineNo: c_uint) -> &'a DINameSpace; - pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: &DIBuilder<'a>, - CompositeType: &'a DIType, - TypeArray: &'a DIArray); + pub fn LLVMRustDICompositeTypeReplaceArrays(Builder: &DIBuilder<'a>, + CompositeType: &'a DIType, + Elements: Option<&'a DIArray>, + Params: Option<&'a DIArray>); pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context, diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index b6e07942f8667..908518d87a37e 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -824,11 +824,13 @@ LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder, } extern "C" void -LLVMRustDICompositeTypeSetTypeArray(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef CompositeTy, - LLVMMetadataRef TyArray) { +LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder, + LLVMMetadataRef CompositeTy, + LLVMMetadataRef Elements, + LLVMMetadataRef Params) { DICompositeType *Tmp = unwrapDI(CompositeTy); - Builder->replaceArrays(Tmp, DINodeArray(unwrap(TyArray))); + Builder->replaceArrays(Tmp, DINodeArray(unwrap(Elements)), + DINodeArray(unwrap(Params))); } extern "C" LLVMValueRef diff --git a/src/test/codegen/generic-debug.rs b/src/test/codegen/generic-debug.rs new file mode 100644 index 0000000000000..9d5dbf1cc0a09 --- /dev/null +++ b/src/test/codegen/generic-debug.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength +// ignore-windows + +// compile-flags: -g -C no-prepopulate-passes + +// CHECK-LABEL: @main +// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "Generic",{{.*}} +// CHECK: {{.*}}DITemplateTypeParameter{{.*}}name: "Type",{{.*}} + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + +pub struct Generic(Type); + +fn main () { + let generic = Generic(10); +} diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs index 229f9466b5122..c9c2395534882 100644 --- a/src/test/debuginfo/associated-types.rs +++ b/src/test/debuginfo/associated-types.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// min-lldb-version: 310 +// Some versions of the non-rust-enabled LLDB print the wrong generic +// parameter type names in this test. +// rust-lldb // compile-flags:-g diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 97bb9aa98e87b..df1f1e3d4ee2f 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -11,7 +11,10 @@ // ignore-tidy-linelength // compile-flags:-g -// min-lldb-version: 310 + +// Some versions of the non-rust-enabled LLDB print the wrong generic +// parameter type names in this test. +// rust-lldb // === GDB TESTS =================================================================================== diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 4e06a15e1cdf0..ebaac96946c19 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -9,7 +9,10 @@ // except according to those terms. // ignore-tidy-linelength -// min-lldb-version: 310 + +// Some versions of the non-rust-enabled LLDB print the wrong generic +// parameter type names in this test. +// rust-lldb // compile-flags:-g diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index ebd43daf46479..8bda0e419151a 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -41,7 +41,7 @@ // lldb-command:run // lldb-command:print case1 -// lldbr-check:(generic_tuple_style_enum::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 } +// lldbr-check:(generic_tuple_style_enum::Regular::Case1) case1 = { __0 = 0 __1 = 31868 __2 = 31868 __3 = 31868 __4 = 31868 } // lldb-command:print case2 // lldbr-check:(generic_tuple_style_enum::Regular::Case2) case2 = Regular::Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 } @@ -50,7 +50,7 @@ // lldbr-check:(generic_tuple_style_enum::Regular::Case3) case3 = Regular::Case3 { Case1: 0, Case2: 6438275382588823897 } // lldb-command:print univariant -// lldbr-check:(generic_tuple_style_enum::Univariant) univariant = { TheOnlyCase = { = -1 } } +// lldbr-check:(generic_tuple_style_enum::Univariant) univariant = Univariant { TheOnlyCase: Univariant::TheOnlyCase(-1) } #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 57238961e3fa3..f4f7bdcecc65a 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// min-lldb-version: 310 +// Some versions of the non-rust-enabled LLDB print the wrong generic +// parameter type names in this test. +// rust-lldb // compile-flags:-g