From b3bbc22cb7b3670001389c07a1e4a1c2090ae76a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 23 Aug 2023 16:24:40 +0000 Subject: [PATCH 1/4] Do not forget to pass DWARF fragment information to LLVM. --- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 18 +++++++++++-- tests/codegen/sroa-fragment-debuginfo.rs | 27 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/codegen/sroa-fragment-debuginfo.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 7df830692d3e7..f087df4524d54 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -445,9 +445,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.store(place.llval, alloca.llval, alloca.align); // Point the debug info to `*alloca` for the current variable - bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None); + bx.dbg_var_addr( + dbg_var, + dbg_loc, + alloca.llval, + Size::ZERO, + &[Size::ZERO], + var.fragment, + ); } else { - bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None); + bx.dbg_var_addr( + dbg_var, + dbg_loc, + base.llval, + direct_offset, + &indirect_offsets, + var.fragment, + ); } } diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs new file mode 100644 index 0000000000000..ee103cf1c8ed0 --- /dev/null +++ b/tests/codegen/sroa-fragment-debuginfo.rs @@ -0,0 +1,27 @@ +// compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates +// compile-flags: -Cno-prepopulate-passes + +#![crate_type = "lib"] + +pub struct Endian; + +#[allow(dead_code)] +pub struct EndianSlice<'input> { + slice: &'input [u8], + endian: Endian, +} + +#[no_mangle] +pub fn test(s: &[u8]) { +// CHECK: void @test( +// CHECK: %slice.dbg.spill1 = alloca { ptr, i64 }, +// CHECK: %slice.dbg.spill = alloca %Endian, +// CHECK: %s.dbg.spill = alloca { ptr, i64 }, +// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S:.*]], metadata !DIExpression()), +// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 0)), +// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE]], metadata !DIExpression()), + let slice = EndianSlice { slice: s, endian: Endian }; +} + +// CHECK: ![[S]] = !DILocalVariable(name: "s", +// CHECK: ![[SLICE]] = !DILocalVariable(name: "slice", From f49494ecce9015a6b65a2a0c87a414b357e390c7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 24 Aug 2023 15:52:25 +0000 Subject: [PATCH 2/4] Add test with non-ZST. --- tests/codegen/sroa-fragment-debuginfo.rs | 44 +++++++++++++++++------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs index ee103cf1c8ed0..dbde2226e5acb 100644 --- a/tests/codegen/sroa-fragment-debuginfo.rs +++ b/tests/codegen/sroa-fragment-debuginfo.rs @@ -3,25 +3,43 @@ #![crate_type = "lib"] -pub struct Endian; +pub struct ExtraSlice<'input> { + slice: &'input [u8], + extra: u32, +} + +#[no_mangle] +pub fn extra(s: &[u8]) { +// CHECK: void @extra( +// CHECK: %slice.dbg.spill1 = alloca i32, +// CHECK: %slice.dbg.spill = alloca { ptr, i64 }, +// CHECK: %s.dbg.spill = alloca { ptr, i64 }, +// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_EXTRA:.*]], metadata !DIExpression()), +// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_EXTRA:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128)), +// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_EXTRA]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 32)), + let slice = ExtraSlice { slice: s, extra: s.len() as u32 }; +} + +struct Zst; -#[allow(dead_code)] -pub struct EndianSlice<'input> { +pub struct ZstSlice<'input> { slice: &'input [u8], - endian: Endian, + extra: Zst, } #[no_mangle] -pub fn test(s: &[u8]) { -// CHECK: void @test( +pub fn zst(s: &[u8]) { +// CHECK: void @zst( // CHECK: %slice.dbg.spill1 = alloca { ptr, i64 }, -// CHECK: %slice.dbg.spill = alloca %Endian, +// CHECK: %slice.dbg.spill = alloca %Zst, // CHECK: %s.dbg.spill = alloca { ptr, i64 }, -// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S:.*]], metadata !DIExpression()), -// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 0)), -// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE]], metadata !DIExpression()), - let slice = EndianSlice { slice: s, endian: Endian }; +// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_ZST:.*]], metadata !DIExpression()), +// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_ZST:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 0)), +// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_ZST]], metadata !DIExpression()), + let slice = ZstSlice { slice: s, extra: Zst }; } -// CHECK: ![[S]] = !DILocalVariable(name: "s", -// CHECK: ![[SLICE]] = !DILocalVariable(name: "slice", +// CHECK: ![[S_EXTRA]] = !DILocalVariable(name: "s", +// CHECK: ![[SLICE_EXTRA]] = !DILocalVariable(name: "slice", +// CHECK: ![[S_ZST]] = !DILocalVariable(name: "s", +// CHECK: ![[SLICE_ZST]] = !DILocalVariable(name: "slice", From 930b2e72eeabf4cacf59d07999fac565836d05bd Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 26 Aug 2023 15:40:29 +0000 Subject: [PATCH 3/4] Do not produce fragment for ZST. --- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 19 +++++++----- tests/codegen/sroa-fragment-debuginfo.rs | 14 ++++----- tests/ui/debuginfo/sroa-fragment-debuginfo.rs | 31 +++++++++++++++++++ 3 files changed, 49 insertions(+), 15 deletions(-) create mode 100644 tests/ui/debuginfo/sroa-fragment-debuginfo.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index f087df4524d54..4d3f1fbc91e77 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -584,17 +584,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let place = fragment.contents; + let fragment = if fragment_layout.size == Size::ZERO { + // Fragment is a ZST, so does not represent anything. + continue; + } else if fragment_layout.size == var_layout.size { + // Fragment covers entire variable, so as far as + // DWARF is concerned, it's not really a fragment. + None + } else { + Some(fragment_start..fragment_start + fragment_layout.size) + }; + per_local[place.local].push(PerLocalVarDebugInfo { name: var.name, source_info: var.source_info, dbg_var, - fragment: if fragment_layout.size == var_layout.size { - // Fragment covers entire variable, so as far as - // DWARF is concerned, it's not really a fragment. - None - } else { - Some(fragment_start..fragment_start + fragment_layout.size) - }, + fragment, projection: place.projection, }); } diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs index dbde2226e5acb..9762777835cb5 100644 --- a/tests/codegen/sroa-fragment-debuginfo.rs +++ b/tests/codegen/sroa-fragment-debuginfo.rs @@ -29,17 +29,15 @@ pub struct ZstSlice<'input> { #[no_mangle] pub fn zst(s: &[u8]) { + // The field `extra` is a ZST. The fragment for the field `slice` encompasses the whole + // variable, so is not a fragment. In that case, the variable must have no fragment. + // CHECK: void @zst( -// CHECK: %slice.dbg.spill1 = alloca { ptr, i64 }, -// CHECK: %slice.dbg.spill = alloca %Zst, -// CHECK: %s.dbg.spill = alloca { ptr, i64 }, -// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_ZST:.*]], metadata !DIExpression()), -// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_ZST:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 0)), -// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_ZST]], metadata !DIExpression()), +// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata !{}, metadata !DIExpression(DW_OP_LLVM_fragment, +// CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST:.*]], metadata !DIExpression()), +// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST]], let slice = ZstSlice { slice: s, extra: Zst }; } // CHECK: ![[S_EXTRA]] = !DILocalVariable(name: "s", // CHECK: ![[SLICE_EXTRA]] = !DILocalVariable(name: "slice", -// CHECK: ![[S_ZST]] = !DILocalVariable(name: "s", -// CHECK: ![[SLICE_ZST]] = !DILocalVariable(name: "slice", diff --git a/tests/ui/debuginfo/sroa-fragment-debuginfo.rs b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs new file mode 100644 index 0000000000000..9c3c359e395d5 --- /dev/null +++ b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs @@ -0,0 +1,31 @@ +// Verify that we do not trigger a LLVM assertion by creating zero-sized DWARF fragments. +// +// build-pass +// compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates +// compile-flags: -Cno-prepopulate-passes + +#![crate_type = "lib"] + +pub struct ExtraSlice<'input> { + slice: &'input [u8], + extra: u32, +} + +#[no_mangle] +pub fn extra(s: &[u8]) { + let slice = ExtraSlice { slice: s, extra: s.len() as u32 }; +} + +struct Zst; + +pub struct ZstSlice<'input> { + slice: &'input [u8], + extra: Zst, +} + +#[no_mangle] +pub fn zst(s: &[u8]) { + // The field `extra` is a ZST. The fragment for the field `slice` encompasses the whole + // variable, so is not a fragment. In that case, the variable must have no fragment. + let slice = ZstSlice { slice: s, extra: Zst }; +} From 5529e2f8933e494547423db3a55b215313d5ecde Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 26 Aug 2023 19:19:37 +0000 Subject: [PATCH 4/4] Restrict test to x86_64. --- tests/codegen/sroa-fragment-debuginfo.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs index 9762777835cb5..fb10f63beaf45 100644 --- a/tests/codegen/sroa-fragment-debuginfo.rs +++ b/tests/codegen/sroa-fragment-debuginfo.rs @@ -1,5 +1,8 @@ // compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates // compile-flags: -Cno-prepopulate-passes +// +// Tested offsets are only correct for x86_64. +// only-x86_64 #![crate_type = "lib"]