From 8b230086fa4b22c647129a8c84fa0bdfc6d82a0d Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 22 Apr 2022 12:07:32 +0200 Subject: [PATCH] debuginfo: Emit ZST struct debuginfo for unit type when CPP-like debuginfo is enabled (instead of custom basic type). --- .../src/debuginfo/metadata.rs | 25 ++++--- src/test/debuginfo/unit-type.rs | 71 +++++++++++++++++++ 2 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 src/test/debuginfo/unit-type.rs diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 74e194750fadd..f2cf3b1ef5c1e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -437,11 +437,9 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() { ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { - DINodeCreationResult::new(build_basic_type_di_node(cx, t), false) - } - ty::Tuple(elements) if elements.is_empty() => { - DINodeCreationResult::new(build_basic_type_di_node(cx, t), false) + build_basic_type_di_node(cx, t) } + ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t), ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t), ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id), ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id), @@ -640,7 +638,10 @@ impl MsvcBasicName for ty::FloatTy { } } -fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +fn build_basic_type_di_node<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, +) -> DINodeCreationResult<'ll> { debug!("build_basic_type_di_node: {:?}", t); // When targeting MSVC, emit MSVC style type names for compatibility with @@ -649,7 +650,13 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) - let (name, encoding) = match t.kind() { ty::Never => ("!", DW_ATE_unsigned), - ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned), + ty::Tuple(elements) if elements.is_empty() => { + if cpp_like_debuginfo { + return build_tuple_type_di_node(cx, UniqueTypeId::for_ty(cx.tcx, t)); + } else { + ("()", DW_ATE_unsigned) + } + } ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_UTF), ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed), @@ -672,14 +679,14 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) - }; if !cpp_like_debuginfo { - return ty_di_node; + return DINodeCreationResult::new(ty_di_node, false); } 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_di_node, + _ => return DINodeCreationResult::new(ty_di_node, false), }; let typedef_di_node = unsafe { @@ -694,7 +701,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) - ) }; - typedef_di_node + DINodeCreationResult::new(typedef_di_node, false) } fn build_foreign_type_di_node<'ll, 'tcx>( diff --git a/src/test/debuginfo/unit-type.rs b/src/test/debuginfo/unit-type.rs new file mode 100644 index 0000000000000..7aab41a3e7c9b --- /dev/null +++ b/src/test/debuginfo/unit-type.rs @@ -0,0 +1,71 @@ +// compile-flags:-g + +// We only test Rust-aware versions of GDB: +// min-gdb-version: 8.2 + +// === GDB TESTS =================================================================================== + +// gdb-command: run + +// gdb-command: print _ref +// gdb-check: $1 = (*mut ()) 0x[...] + +// gdb-command: print _ptr +// gdb-check: $2 = (*mut ()) 0x[...] + +// gdb-command: print _local +// gdb-check: $3 = () + +// gdb-command: print _field +// gdb-check: $4 = unit_type::_TypeContainingUnitField {_a: 123, _unit: (), _b: 456} + +// Check that we can cast "void pointers" to their actual type in the debugger +// gdb-command: print /x *(_ptr as *const u64) +// gdb-check: $5 = 0x1122334455667788 + +// === CDB TESTS =================================================================================== + +// cdb-command: g +// cdb-check: Breakpoint 0 hit + +// cdb-command: dx _ref +// cdb-check: _ref : 0x[...] : () [Type: tuple$<> *] + +// cdb-command: dx _ptr +// cdb-check: _ptr : 0x[...] : () [Type: tuple$<> *] + +// cdb-command: dx _local +// cdb-check: _local : () [Type: tuple$<>] + +// cdb-command: dx _field,d +// cdb-check: _field,d [Type: unit_type::_TypeContainingUnitField] +// cdb-check: [+0x[...]] _a : 123 [Type: unsigned int] +// cdb-check: [+0x[...]] _unit : () [Type: tuple$<>] +// cdb-check: [+0x[...]] _b : 456 [Type: unsigned __int64] + +// Check that we can cast "void pointers" to their actual type in the debugger +// cdb-command: dx ((__int64 *)_ptr),x +// cdb-check: ((__int64 *)_ptr),x : 0x[...] : 0x1122334455667788 [Type: __int64 *] +// cdb-check: 0x1122334455667788 [Type: __int64] + +struct _TypeContainingUnitField { + _a: u32, + _unit: (), + _b: u64, +} + +fn foo(_ref: &(), _ptr: *const ()) { + let _local = (); + let _field = _TypeContainingUnitField { _a: 123, _unit: (), _b: 456 }; + + zzz(); // #break +} + +fn main() { + let pointee = 0x1122_3344_5566_7788i64; + + foo(&(), &pointee as *const i64 as *const ()); +} + +#[inline(never)] +fn zzz() {}