Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debuginfo: Emit ZST struct debuginfo for unit type when CPP-like debuginfo is enabled #96316

Merged
merged 1 commit into from
Apr 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand All @@ -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),
Expand All @@ -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 {
Expand All @@ -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>(
Expand Down
71 changes: 71 additions & 0 deletions src/test/debuginfo/unit-type.rs
Original file line number Diff line number Diff line change
@@ -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() {}