mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #154200 - resrever:enable-dwarf-call-sites, r=dingxiangfei2009
debuginfo: emit DW_TAG_call_site entries Set `FlagAllCallsDescribed` on function definition DIEs so LLVM emits DW_TAG_call_site entries, letting debuggers and analysis tools track tail calls.
This commit is contained in:
@@ -471,7 +471,7 @@ fn dbg_scope_fn(
|
||||
// FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
|
||||
let scope_line = loc.line;
|
||||
|
||||
let mut flags = DIFlags::FlagPrototyped;
|
||||
let mut flags = DIFlags::FlagPrototyped | DIFlags::FlagAllCallsDescribed;
|
||||
|
||||
if fn_abi.ret.layout.is_uninhabited() {
|
||||
flags |= DIFlags::FlagNoReturn;
|
||||
@@ -494,6 +494,9 @@ fn dbg_scope_fn(
|
||||
// LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
|
||||
// When we use this `decl` below, the subprogram definition gets created at the CU level
|
||||
// with a DW_AT_specification pointing back to the type's declaration.
|
||||
// FlagAllCallsDescribed cannot appear on the method declaration DIE
|
||||
// because it has no body, which LLVM's verifier rejects.
|
||||
let decl_flags = flags & !DIFlags::FlagAllCallsDescribed;
|
||||
let decl = is_method.then(|| unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateMethod(
|
||||
DIB(self),
|
||||
@@ -505,7 +508,7 @@ fn dbg_scope_fn(
|
||||
file_metadata,
|
||||
loc.line,
|
||||
function_type_metadata,
|
||||
flags,
|
||||
decl_flags,
|
||||
spflags & !DISPFlags::SPFlagDefinition,
|
||||
template_parameters,
|
||||
)
|
||||
|
||||
@@ -781,6 +781,7 @@ pub(crate) struct DIFlags: u32 {
|
||||
const FlagNonTrivial = (1 << 26);
|
||||
const FlagBigEndian = (1 << 27);
|
||||
const FlagLittleEndian = (1 << 28);
|
||||
const FlagAllCallsDescribed = (1 << 29);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -779,6 +779,7 @@ ASSERT_DIFLAG_VALUE(FlagThunk, 1 << 25);
|
||||
ASSERT_DIFLAG_VALUE(FlagNonTrivial, 1 << 26);
|
||||
ASSERT_DIFLAG_VALUE(FlagBigEndian, 1 << 27);
|
||||
ASSERT_DIFLAG_VALUE(FlagLittleEndian, 1 << 28);
|
||||
static_assert(DINode::DIFlags::FlagAllCallsDescribed == (1 << 29));
|
||||
ASSERT_DIFLAG_VALUE(FlagIndirectVirtualBase, (1 << 2) | (1 << 5));
|
||||
#undef ASSERT_DIFLAG_VALUE
|
||||
|
||||
@@ -791,7 +792,7 @@ ASSERT_DIFLAG_VALUE(FlagIndirectVirtualBase, (1 << 2) | (1 << 5));
|
||||
// to copying each bit/subvalue.
|
||||
static DINode::DIFlags fromRust(LLVMDIFlags Flags) {
|
||||
// Check that all set bits are covered by the static assertions above.
|
||||
const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 21);
|
||||
const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 21);
|
||||
if (Flags & UNKNOWN_BITS) {
|
||||
report_fatal_error("bad LLVMDIFlags");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Check that DIFlagAllCallsDescribed is set on subprogram definitions.
|
||||
|
||||
//@ ignore-msvc (CodeView does not use DIFlagAllCallsDescribed)
|
||||
//@ compile-flags: -C debuginfo=2 -C opt-level=1 -C no-prepopulate-passes
|
||||
|
||||
// CHECK: {{.*}}DISubprogram{{.*}}name: "foo"{{.*}}DIFlagAllCallsDescribed{{.*}}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
pub fn foo(x: i32) -> i32 {
|
||||
bar(x + 1)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
pub fn bar(x: i32) -> i32 {
|
||||
x * 2
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Reference in New Issue
Block a user