about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-08-26 15:40:29 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-08-26 16:54:28 +0000
commit930b2e72eeabf4cacf59d07999fac565836d05bd (patch)
tree4683351a1efe16973668aca90e2320f7f8710ec0
parentf49494ecce9015a6b65a2a0c87a414b357e390c7 (diff)
downloadrust-930b2e72eeabf4cacf59d07999fac565836d05bd.tar.gz
rust-930b2e72eeabf4cacf59d07999fac565836d05bd.zip
Do not produce fragment for ZST.
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs19
-rw-r--r--tests/codegen/sroa-fragment-debuginfo.rs14
-rw-r--r--tests/ui/debuginfo/sroa-fragment-debuginfo.rs31
3 files changed, 49 insertions, 15 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index f087df4524d..4d3f1fbc91e 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 dbde2226e5a..9762777835c 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 00000000000..9c3c359e395
--- /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 };
+}