diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 846d505641103..3680810ea79f7 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -21,7 +21,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 rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -34,6 +34,7 @@ use rustc::ty::Instance; use common::CodegenCx; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, LayoutOf, PrimitiveExt, Size, TyLayout}; +use rustc::ty::subst::UnpackedKind; use rustc::session::config; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path2cstr; @@ -266,6 +267,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> { // ... and attach them to the stub to complete it. set_members_of_composite_type(cx, + unfinished_type, metadata_stub, member_descriptions); return MetadataCreationResult::new(metadata_stub, true); @@ -1174,6 +1176,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![ @@ -1204,6 +1207,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { .create_member_descriptions(cx); set_members_of_composite_type(cx, + self.enum_type, variant_type_metadata, member_descriptions); MemberDescription { @@ -1231,6 +1235,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); @@ -1534,13 +1539,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 @@ -1580,10 +1587,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 None; + + 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 e2b0142490933..8b38a7d5fc7e6 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1421,9 +1421,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 bf7afa1b6c068..96a34a41dbad3 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -870,11 +870,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); +}