Skip to content

ScalarReplacementOfAggregates causes rustc to emit invalid LLVM debuginfo (and sometimes rustc segfaults) #115113

@saethlin

Description

@saethlin

https://rust.godbolt.org/z/9YvvvcMKj

pub struct Endian;

#[allow(dead_code)]
pub struct EndianSlice<'input> {
    slice: &'input [u8],
    endian: Endian,
}

pub fn test(s: &[u8]) {
    let slice = EndianSlice { slice: s, endian: Endian };
}

Compiled with

--emit=llvm-ir -C debuginfo=2 -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates

Becomes this:

define void @example::test(ptr align 1 %s.0, i64 %s.1) unnamed_addr #0 !dbg !7 {
start:
  %slice.dbg.spill1 = alloca { ptr, i64 }, align 8
  %slice.dbg.spill = alloca %Endian, align 1
  %s.dbg.spill = alloca { ptr, i64 }, align 8
  %0 = getelementptr inbounds { ptr, i64 }, ptr %s.dbg.spill, i32 0, i32 0
  store ptr %s.0, ptr %0, align 8
  %1 = getelementptr inbounds { ptr, i64 }, ptr %s.dbg.spill, i32 0, i32 1
  store i64 %s.1, ptr %1, align 8
  call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata !22, metadata !DIExpression()), !dbg !30
  call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata !23, metadata !DIExpression()), !dbg !31
  %2 = getelementptr inbounds { ptr, i64 }, ptr %slice.dbg.spill1, i32 0, i32 0, !dbg !32
  store ptr %s.0, ptr %2, align 8, !dbg !32
  %3 = getelementptr inbounds { ptr, i64 }, ptr %slice.dbg.spill1, i32 0, i32 1, !dbg !32
  store i64 %s.1, ptr %3, align 8, !dbg !32
  call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata !23, metadata !DIExpression()), !dbg !31
  ret void, !dbg !33
}
<snip>
!22 = !DILocalVariable(name: "s", arg: 1, scope: !7, file: !8, line: 9, type: !12)
!23 = !DILocalVariable(name: "slice", scope: !24, file: !8, line: 10, type: !25, align: 8)

ScalarReplacementOfAggregates is on by default in the stable toolchain that is currently being released, and it was turned on in #112002. There is an LLVM assertion which can catch some manifestations of this problem, but in the wild it seems rather hard to actually hit the assertion.

To the best of my knowledge https://bugzilla.redhat.com/show_bug.cgi?id=2226564 is the closest we have to someone hitting this in the wild. I hit it on my own by using -Cdebuginfo=2 -Zinline-mir-threshold=1000 -Zinline-mir-hint-threshold=1000 with -Zbuild-std.

If this becomes a problem when 1.72 goes out, an emergency fix would be just reverting the change to is_enabled in the linked PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-debuginfoArea: Debugging information in compiled programs (DWARF, PDB, etc.)A-mir-optArea: MIR optimizationsC-bugCategory: This is a bug.P-criticalCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions