Skip to content

Commit f072775

Browse files
committed
Auto merge of #115139 - cjgillot:llvm-fragment, r=nikic
Do not forget to pass DWARF fragment information to LLVM. Fixes #115113 for the rustc part
2 parents 9558cda + 5529e2f commit f072775

File tree

3 files changed

+105
-9
lines changed

3 files changed

+105
-9
lines changed

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -435,9 +435,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
435435
bx.store(place.llval, alloca.llval, alloca.align);
436436

437437
// Point the debug info to `*alloca` for the current variable
438-
bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
438+
bx.dbg_var_addr(
439+
dbg_var,
440+
dbg_loc,
441+
alloca.llval,
442+
Size::ZERO,
443+
&[Size::ZERO],
444+
var.fragment,
445+
);
439446
} else {
440-
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None);
447+
bx.dbg_var_addr(
448+
dbg_var,
449+
dbg_loc,
450+
base.llval,
451+
direct_offset,
452+
&indirect_offsets,
453+
var.fragment,
454+
);
441455
}
442456
}
443457

@@ -560,17 +574,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
560574
}
561575

562576
let place = fragment.contents;
577+
let fragment = if fragment_layout.size == Size::ZERO {
578+
// Fragment is a ZST, so does not represent anything.
579+
continue;
580+
} else if fragment_layout.size == var_layout.size {
581+
// Fragment covers entire variable, so as far as
582+
// DWARF is concerned, it's not really a fragment.
583+
None
584+
} else {
585+
Some(fragment_start..fragment_start + fragment_layout.size)
586+
};
587+
563588
per_local[place.local].push(PerLocalVarDebugInfo {
564589
name: var.name,
565590
source_info: var.source_info,
566591
dbg_var,
567-
fragment: if fragment_layout.size == var_layout.size {
568-
// Fragment covers entire variable, so as far as
569-
// DWARF is concerned, it's not really a fragment.
570-
None
571-
} else {
572-
Some(fragment_start..fragment_start + fragment_layout.size)
573-
},
592+
fragment,
574593
projection: place.projection,
575594
});
576595
}
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates
2+
// compile-flags: -Cno-prepopulate-passes
3+
//
4+
// Tested offsets are only correct for x86_64.
5+
// only-x86_64
6+
7+
#![crate_type = "lib"]
8+
9+
pub struct ExtraSlice<'input> {
10+
slice: &'input [u8],
11+
extra: u32,
12+
}
13+
14+
#[no_mangle]
15+
pub fn extra(s: &[u8]) {
16+
// CHECK: void @extra(
17+
// CHECK: %slice.dbg.spill1 = alloca i32,
18+
// CHECK: %slice.dbg.spill = alloca { ptr, i64 },
19+
// CHECK: %s.dbg.spill = alloca { ptr, i64 },
20+
// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_EXTRA:.*]], metadata !DIExpression()),
21+
// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_EXTRA:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128)),
22+
// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_EXTRA]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 32)),
23+
let slice = ExtraSlice { slice: s, extra: s.len() as u32 };
24+
}
25+
26+
struct Zst;
27+
28+
pub struct ZstSlice<'input> {
29+
slice: &'input [u8],
30+
extra: Zst,
31+
}
32+
33+
#[no_mangle]
34+
pub fn zst(s: &[u8]) {
35+
// The field `extra` is a ZST. The fragment for the field `slice` encompasses the whole
36+
// variable, so is not a fragment. In that case, the variable must have no fragment.
37+
38+
// CHECK: void @zst(
39+
// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata !{}, metadata !DIExpression(DW_OP_LLVM_fragment,
40+
// CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST:.*]], metadata !DIExpression()),
41+
// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST]],
42+
let slice = ZstSlice { slice: s, extra: Zst };
43+
}
44+
45+
// CHECK: ![[S_EXTRA]] = !DILocalVariable(name: "s",
46+
// CHECK: ![[SLICE_EXTRA]] = !DILocalVariable(name: "slice",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Verify that we do not trigger a LLVM assertion by creating zero-sized DWARF fragments.
2+
//
3+
// build-pass
4+
// compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates
5+
// compile-flags: -Cno-prepopulate-passes
6+
7+
#![crate_type = "lib"]
8+
9+
pub struct ExtraSlice<'input> {
10+
slice: &'input [u8],
11+
extra: u32,
12+
}
13+
14+
#[no_mangle]
15+
pub fn extra(s: &[u8]) {
16+
let slice = ExtraSlice { slice: s, extra: s.len() as u32 };
17+
}
18+
19+
struct Zst;
20+
21+
pub struct ZstSlice<'input> {
22+
slice: &'input [u8],
23+
extra: Zst,
24+
}
25+
26+
#[no_mangle]
27+
pub fn zst(s: &[u8]) {
28+
// The field `extra` is a ZST. The fragment for the field `slice` encompasses the whole
29+
// variable, so is not a fragment. In that case, the variable must have no fragment.
30+
let slice = ZstSlice { slice: s, extra: Zst };
31+
}

0 commit comments

Comments
 (0)