Repository: rust
Issue: Keep track of how scopes and locals are duplicated during inlining so that they can be correctly de-duplicated when emitting debug info
Labels: A-debuginfo,T-compiler,C-bug,WG-debugging

# Background

## Original issue

The call to `panic` within a function like `Option::unwrap` is translated to LLVM as a `tail call` (as it will never return), when multiple calls to the same function like this are inlined LLVM will notice the common `tail call` block (i.e., loading the same panic string + location info and then calling `panic`) and merge them together.

When merging these instructions together, LLVM will also attempt to merge the debug locations as well, but this fails (i.e., debug info is dropped) as Rust emits a new `DISubprogram` at each inline site thus LLVM doesn't recognize that these are actually the same function and so thinks that there isn't a common debug location.

As an example of this, consider the following program:
```rust
#[no_mangle]
fn add_numbers(x: &Option<i32>, y: &Option<i32>) -> i32 {
    let x1 = x.unwrap();
    let y1 = y.unwrap();

    x1 + y1
}
```

 When building for x86_64 Windows using 1.72 it generates (note the lack of `.cv_loc` before the call to `panic`, thus it will be attributed to the same line at the `addq` instruction):

```llvm
	.cv_loc	0 1 3 0                        # src\lib.rs:3:0
	addq	$40, %rsp
	retq
	leaq	.Lalloc_f570dea0a53168780ce9a91e67646421(%rip), %rcx
	leaq	.Lalloc_629ace53b7e5b76aaa810d549cc84ea3(%rip), %r8
	movl	$43, %edx
	callq	_ZN4core9panicking5panic17h12e60b9063f6dee8E
	int3
```

Ideally, we would generate debug information that would allow LLVM to (partially) merge the locations together and thus maintain the correct inlining information and partial line info (since the inlined function was de-duplicated, we can't give the exact line number as that is ambiguous between the two inline sites, but we also shouldn't show an incorrect line number).

For example, we could generate something like below (which shows the `panic!` was inlined from `unwrap` in `option.rs` at line 935 into the current function in `lib.rs` at line 0):
```llvm
	.cv_loc	0 1 3 0                        # src\lib.rs:3:0
	addq	$40, %rsp
	retq
	.cv_inline_site_id 6 within 0 inlined_at 1 0 0
	.cv_loc	6 2 935 0                       # library\core\src\option.rs:935:0
	leaq	.Lalloc_5f55955de67e57c79064b537689facea(%rip), %rcx
	leaq	.Lalloc_e741d4de8cb5801e1fd7a6c6795c1559(%rip), %r8
	movl	$43, %edx
	callq	_ZN4core9panicking5panic17hde1558f32d5b1c04E
	int3
```

## New issue

I attempted to fix this by deduplicating sub-program, lexical block and variable debug info in #114643 however this resulted in asserts in LLVM when attempting to build for Linux (see #115156).

The root cause of those asserts is that Rust was generating overlapping `DW_OP_LLVM_fragment` info for the same local variable in two different `@llvm.dbg.declare` calls (i.e., that two different stack allocations represented the same part ("fragment") of the same local variable).

My current plan (#115417) is to work around this by not deduplicating lexical scopes and variables, but instead create a new lexical scope every time that a function is inlined so that subsequent lexical scopes and variables do not appear to be duplicates (from LLVM's perspective).

# Long-term fix

Given that LLVM relies on exact matching to merge together debug locations, and that Clang appears to do this deduplicating in its debug information, it seems that the correct long-term fix is for Rust to also do this deduplicating.

However, to do this Rust needs to keep careful track of how locals and scopes are duplicated while inlining - either to avoid the duplication at the point of inlining or to be able to deduplicate them when emitting debug information.