From f8eb81ba4e85b02d90cfc33fcba0a6a7d5cbf810 Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Wed, 24 Jun 2020 19:28:12 -0700 Subject: [PATCH 1/2] Modify type names on MSVC to make tuples .natvis compatible. - Mangles (T0, T1) as tuple, possibly unblocking rust-lang/rust#70052 "Update hashbrown to 0.8.0" - Prettifies Rust tuples similar to VS2017's std::tuple - Improves debuginfo test coverage --- src/etc/natvis/intrinsic.natvis | 124 ++++++++++++++++++ .../debuginfo/type_names.rs | 14 +- src/test/debuginfo/simple-tuple.rs | 42 ++++++ src/test/debuginfo/tuple-in-tuple.rs | 67 ++++++++++ 4 files changed, 245 insertions(+), 2 deletions(-) diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 1611d8660ef65..874550da8b0c9 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -21,4 +21,128 @@ + + () + + + ({__0}) + + __0 + + + + ({__0}, {__1}) + + __0 + __1 + + + + ({__0}, {__1}, {__2}) + + __0 + __1 + __2 + + + + ({__0}, {__1}, {__2}, {__3}) + + __0 + __1 + __2 + __3 + + + + ({__0}, {__1}, {__2}, {__3}, {__4}) + + __0 + __1 + __2 + __3 + __4 + + + + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}) + + __0 + __1 + __2 + __3 + __4 + __5 + + + + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}) + + __0 + __1 + __2 + __3 + __4 + __5 + __6 + + + + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}) + + __0 + __1 + __2 + __3 + __4 + __5 + __6 + __7 + + + + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}) + + __0 + __1 + __2 + __3 + __4 + __5 + __6 + __7 + __8 + + + + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}) + + __0 + __1 + __2 + __3 + __4 + __5 + __6 + __7 + __8 + __9 + + + + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}, ...) + + __0 + __1 + __2 + __3 + __4 + __5 + __6 + __7 + __8 + __9 + ... + + diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index a64489c04c81d..20d440433cbb0 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -47,7 +47,12 @@ pub fn push_debuginfo_type_name<'tcx>( push_type_params(tcx, substs, output, visited); } ty::Tuple(component_types) => { - output.push('('); + if cpp_like_names { + output.push_str("tuple<"); + } else { + output.push('('); + } + for component_type in component_types { push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); output.push_str(", "); @@ -56,7 +61,12 @@ pub fn push_debuginfo_type_name<'tcx>( output.pop(); output.pop(); } - output.push(')'); + + if cpp_like_names { + output.push('>'); + } else { + output.push(')'); + } } ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { if !cpp_like_names { diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index c2db5218e6842..b7fcfeef090aa 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -123,6 +123,48 @@ // lldbg-check:[...]$6 = { 0 = 15 1 = 16 } // lldbr-check:((i32, i16)) paddingAtEnd = { 0 = 15 1 = 16 } + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command:dx noPadding8,d +// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple] +// cdb-check:[...][0] : -100 [Type: [...]] +// cdb-check:[...][1] : 100 [Type: [...]] +// cdb-command:dx noPadding16,d +// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple] +// cdb-check:[...][0] : 0 [Type: [...]] +// cdb-check:[...][1] : 1 [Type: [...]] +// cdb-check:[...][2] : 2 [Type: [...]] +// cdb-command:dx noPadding32,d +// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple] +// cdb-check:[...][0] : 3 [Type: [...]] +// cdb-check:[...][1] : 4.5[...] [Type: [...]] +// cdb-check:[...][2] : 5 [Type: [...]] +// cdb-command:dx noPadding64,d +// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple] +// cdb-check:[...][0] : 6 [Type: [...]] +// cdb-check:[...][1] : 7.500000 [Type: [...]] +// cdb-check:[...][2] : 8 [Type: [...]] + +// cdb-command:dx internalPadding1,d +// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple] +// cdb-check:[...][0] : 9 [Type: short] +// cdb-check:[...][1] : 10 [Type: int] +// cdb-command:dx internalPadding2,d +// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple] +// cdb-check:[...][0] : 11 [Type: [...]] +// cdb-check:[...][1] : 12 [Type: [...]] +// cdb-check:[...][2] : 13 [Type: [...]] +// cdb-check:[...][3] : 14 [Type: [...]] + +// cdb-command:dx paddingAtEnd,d +// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple] +// cdb-check:[...][0] : 15 [Type: [...]] +// cdb-check:[...][1] : 16 [Type: [...]] + + #![allow(unused_variables)] #![allow(dead_code)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index e0f940ca7a1c1..0447d8e9ddeb0 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -59,6 +59,73 @@ // lldbg-check:[...]$6 = { 0 = { 0 = 21 1 = 22 } 1 = 23 } // lldbr-check:(((i32, i16), i32)) padding_at_end2 = { 0 = { 0 = 21 1 = 22 } 1 = 23 } + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command:dx no_padding1,d +// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple, u32, u32>] +// cdb-check:[...][0] : (0, 1) [Type: tuple] +// cdb-check:[...][1] : 2 [Type: [...]] +// cdb-check:[...][2] : 3 [Type: [...]] +// cdb-command:dx no_padding1.__0,d +// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple] +// cdb-check:[...][0] : 0 [Type: [...]] +// cdb-check:[...][1] : 1 [Type: [...]] +// cdb-command:dx no_padding2,d +// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple, u32>] +// cdb-check:[...][0] : 4 [Type: [...]] +// cdb-check:[...][1] : (5, 6) [Type: tuple] +// cdb-check:[...][2] : 7 [Type: [...]] +// cdb-command:dx no_padding2.__1,d +// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple] +// cdb-check:[...][0] : 5 [Type: [...]] +// cdb-check:[...][1] : 6 [Type: [...]] +// cdb-command:dx no_padding3,d +// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple>] +// cdb-check:[...][0] : 8 [Type: [...]] +// cdb-check:[...][1] : 9 [Type: [...]] +// cdb-check:[...][2] : (10, 11) [Type: tuple] +// cdb-command:dx no_padding3.__2,d +// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple] +// cdb-check:[...][0] : 10 [Type: [...]] +// cdb-check:[...][1] : 11 [Type: [...]] + +// cdb-command:dx internal_padding1,d +// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple>] +// cdb-check:[...][0] : 12 [Type: [...]] +// cdb-check:[...][1] : (13, 14) [Type: tuple] +// cdb-command:dx internal_padding1.__1,d +// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple] +// cdb-check:[...][0] : 13 [Type: [...]] +// cdb-check:[...][1] : 14 [Type: [...]] +// cdb-command:dx internal_padding2,d +// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple>] +// cdb-check:[...][0] : 15 [Type: [...]] +// cdb-check:[...][1] : (16, 17) [Type: tuple] +// cdb-command:dx internal_padding2.__1,d +// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple] +// cdb-check:[...][0] : 16 [Type: [...]] +// cdb-check:[...][1] : 17 [Type: [...]] + +// cdb-command:dx padding_at_end1,d +// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple>] +// cdb-check:[...][0] : 18 [Type: [...]] +// cdb-check:[...][1] : (19, 20) [Type: tuple] +// cdb-command:dx padding_at_end1.__1,d +// cdb-check:padding_at_end1.__1,d [...][Type: tuple] +// cdb-check:[...][0] : 19 [Type: [...]] +// cdb-check:[...][1] : 20 [Type: [...]] +// cdb-command:dx padding_at_end2,d +// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple, i32>] +// cdb-check:[...][0] : (21, 22) [Type: tuple] +// cdb-check:[...][1] : 23 [Type: [...]] +// cdb-command:dx padding_at_end2.__0,d +// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple] +// cdb-check:[...][0] : 21 [Type: [...]] +// cdb-check:[...][1] : 22 [Type: [...]] + #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] From 24a728a8eb4832568509eb757c2374934a76cb98 Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Wed, 24 Jun 2020 23:28:00 -0700 Subject: [PATCH 2/2] debuginfo: Define int/float types in terms of MSVC-recognized types. PDB debug information doesn't appear to be emitted for basic types. By defining u32 as a typedef for unsigned __int32 when targeting MSVC, we allow CDB and other debuggers to recognize "u32" as a type/expression. This in turn unblocks rust-lang#70052 "Update hashbrown to 0.8.0" by allowing $T1 ..= $T3 to resolve, which would otherwise fail to resolve when builtin types fail to parse. --- .../debuginfo/metadata.rs | 72 ++++++++++++++++++- src/librustc_codegen_llvm/llvm/ffi.rs | 10 +++ src/rustllvm/RustWrapper.cpp | 8 +++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 8a957a729fb68..ac8f28e1609a2 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -19,6 +19,7 @@ use crate::llvm::debuginfo::{ use crate::value::Value; use log::debug; +use rustc_ast::ast; use rustc_codegen_ssa::traits::*; use rustc_data_structures::const_cstr; use rustc_data_structures::fingerprint::Fingerprint; @@ -824,14 +825,60 @@ fn file_metadata_raw( } } +trait MsvcBasicName { + fn msvc_basic_name(self) -> &'static str; +} + +impl MsvcBasicName for ast::IntTy { + fn msvc_basic_name(self) -> &'static str { + match self { + ast::IntTy::Isize => "ptrdiff_t", + ast::IntTy::I8 => "__int8", + ast::IntTy::I16 => "__int16", + ast::IntTy::I32 => "__int32", + ast::IntTy::I64 => "__int64", + ast::IntTy::I128 => "__int128", + } + } +} + +impl MsvcBasicName for ast::UintTy { + fn msvc_basic_name(self) -> &'static str { + match self { + ast::UintTy::Usize => "size_t", + ast::UintTy::U8 => "unsigned __int8", + ast::UintTy::U16 => "unsigned __int16", + ast::UintTy::U32 => "unsigned __int32", + ast::UintTy::U64 => "unsigned __int64", + ast::UintTy::U128 => "unsigned __int128", + } + } +} + +impl MsvcBasicName for ast::FloatTy { + fn msvc_basic_name(self) -> &'static str { + match self { + ast::FloatTy::F32 => "float", + ast::FloatTy::F64 => "double", + } + } +} + fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("basic_type_metadata: {:?}", t); + // When targeting MSVC, emit MSVC style type names for compatibility with + // .natvis visualizers (and perhaps other existing native debuggers?) + let msvc_like_names = cx.tcx.sess.target.target.options.is_like_msvc; + let (name, encoding) = match t.kind { ty::Never => ("!", DW_ATE_unsigned), ty::Tuple(ref elements) if elements.is_empty() => ("()", DW_ATE_unsigned), ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_unsigned_char), + ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed), + ty::Uint(uint_ty) if msvc_like_names => (uint_ty.msvc_basic_name(), DW_ATE_unsigned), + ty::Float(float_ty) if msvc_like_names => (float_ty.msvc_basic_name(), DW_ATE_float), ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed), ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned), ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float), @@ -848,7 +895,30 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { ) }; - ty_metadata + if !msvc_like_names { + return ty_metadata; + } + + let typedef_name = match t.kind { + ty::Int(int_ty) => int_ty.name_str(), + ty::Uint(uint_ty) => uint_ty.name_str(), + ty::Float(float_ty) => float_ty.name_str(), + _ => return ty_metadata, + }; + + let typedef_metadata = unsafe { + llvm::LLVMRustDIBuilderCreateTypedef( + DIB(cx), + ty_metadata, + typedef_name.as_ptr().cast(), + typedef_name.len(), + unknown_file_metadata(cx), + 0, + None, + ) + }; + + typedef_metadata } fn foreign_type_metadata( diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 8063d97aa73a9..61b1cae698d0c 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1699,6 +1699,16 @@ extern "C" { Encoding: c_uint, ) -> &'a DIBasicType; + pub fn LLVMRustDIBuilderCreateTypedef( + Builder: &DIBuilder<'a>, + Type: &'a DIBasicType, + Name: *const c_char, + NameLen: size_t, + File: &'a DIFile, + LineNo: c_uint, + Scope: Option<&'a DIScope>, + ) -> &'a DIDerivedType; + pub fn LLVMRustDIBuilderCreatePointerType( Builder: &DIBuilder<'a>, PointeeTy: &'a DIType, diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index cdb3a157eab97..d78fb63fd4ef1 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -759,6 +759,14 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType( return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding)); } +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef( + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) { + return wrap(Builder->createTypedef( + unwrap(Type), StringRef(Name, NameLen), unwrap(File), + LineNo, unwrap(Scope))); +} + extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType( LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy, uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,