Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLVM assertion with `-C lto -g -O` on static lib #23566

Closed
japaric opened this Issue Mar 20, 2015 · 5 comments

Comments

Projects
None yet
6 participants
@japaric
Copy link
Member

japaric commented Mar 20, 2015

STR

#![crate_type = "staticlib"]
#![feature(core)]
#![feature(lang_items)]
#![feature(no_std)]
#![no_std]

extern crate core;

mod lang_items {
    use core::fmt::Arguments;

    #[lang = "stack_exhausted"]
    extern "C" fn stack_exhausted() { }

    #[lang = "eh_personality"]
    extern "C" fn eh_personality() { }

    #[lang = "panic_fmt"]
    fn panic_fmt(_: &Arguments, _: &(&'static str, usize)) -> !  {
        loop  {}
    }
}

pub enum Input {
    Floating,
}

pub mod low {
    use super::Mode;

    pub enum Pin {
        _0,
    }

    pub struct Cr(u32);

    impl Cr {
        pub fn set(&mut self, pin: Pin, mode: Mode) {
            self.0 |= mode.value() << (4 * pin as u8)
        }
    }
}

pub mod high {
    use super::Mode;

    pub enum Pin {
        _8,
    }

    pub struct Cr(u32);

    impl Cr {
        pub fn set(&mut self, pin: Pin, mode: Mode) {
            self.0 |= mode.value() << (4 * pin as u8)
        }
    }
}

pub enum Mode { Input(Input) }

impl Mode {
    fn value(&self) -> u32 {
        match *self {
            Mode::Input(Input::Floating) => 4,
        }
    }
}

Output

rustc: /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/llvm/lib/CodeGen/LexicalScopes.cpp:179: llvm::LexicalScope* llvm::LexicalScopes::getOrCreateRegularScope(llvm::MDNode*): Assertion `DISubprogram(Scope).describes(MF->getFunction())' failed.

cc @michaelwoerister Same error message as #17677, but I don't know if it's the same bug, this one needs -O.

@rprichard

This comment has been minimized.

Copy link
Contributor

rprichard commented Mar 20, 2015

I reduced the test case to:

#![crate_type = "staticlib"]
pub fn set1(x: &mut u32) { *x = 123 }
pub fn set2(x: &mut u32) { *x = 123 }

The compiler options are the same (-C lto -g -O). The interesting thing is that the bodies of set1 and set2 must be identical. Perhaps there's an LLVM optimization that's merging the two, and that's breaking debug information?

@japaric

This comment has been minimized.

Copy link
Member Author

japaric commented Mar 20, 2015

@rprichard Thanks for the reduced test case!

The interesting thing is that the bodies of set1 and set2 must be identical.

Yeah, I was under the impression that this may be the cause.

Perhaps there's an LLVM optimization that's merging the two, and that's breaking debug information?

Could be, I'm not familiar with LLVM to confirm this. @dotdash ^^^ do you know if LLVM has an optimization pass that does that?

@michaelwoerister

This comment has been minimized.

Copy link
Contributor

michaelwoerister commented Mar 26, 2015

Thanks for the report. This looks sufficiently different from #17677 to warrant it's own issue. I haven't look into it closely but I think the root cause for this error is not the same as for #17677 (where I don't think it is related to two functions having the same body).

@dotdash

This comment has been minimized.

Copy link
Contributor

dotdash commented Apr 6, 2015

Perhaps there's an LLVM optimization that's merging the two, and that's breaking debug information?

Could be, I'm not familiar with LLVM to confirm this. @dotdash ^^^ do you know if LLVM has an optimization pass that does that?

Yes, the mergefunc pass does that. The problem here seems to be that mergefunc turns set2 into a jump to set1, but then LTO inlines set1 into set2 again, producing bad debug metadata.

After optimizations:

define void @_ZN4set120h703cb75c1e01d663eaaE(i32* noalias nocapture dereferenceable(4)) unnamed_addr #0 {
entry-block:
  tail call void @llvm.dbg.value(metadata i32* %0, i64 0, metadata !14, metadata !20), !dbg !21
  store i32 123, i32* %0, align 4, !dbg !22
  ret void, !dbg !21
}

define void @_ZN4set220h34cbfe792e780cc1paaE(i32* noalias nocapture dereferenceable(4)) unnamed_addr #0 {
  tail call void @_ZN4set120h703cb75c1e01d663eaaE(i32* %0)
  ret void
}

After LTO:

define void @_ZN4set120h703cb75c1e01d663eaaE(i32* noalias nocapture dereferenceable(4)) unnamed_addr #0 {
entry-block:
  tail call void @llvm.dbg.value(metadata i32* %0, i64 0, metadata !14, metadata !20), !dbg !21
  store i32 123, i32* %0, align 4, !dbg !22
  ret void, !dbg !21
}

define void @_ZN4set220h34cbfe792e780cc1paaE(i32* noalias nocapture dereferenceable(4)) unnamed_addr #0 {
  tail call void @llvm.dbg.value(metadata i32* %0, i64 0, metadata !14, metadata !20), !dbg !21
  store i32 123, i32* %0, align 4, !dbg !22, !alias.scope !24
  ret void
}

Relevant metadata:

!4 = !{!"0x2e\00set1\00set1\00_ZN10issue235664set1E\002\000\001\000\000\00256\001\002", !5, !6, !7, null, void (i32*)* @_ZN4set120h703cb75c1e01d663eaaE, !2, null, !13} ; [ DW_TAG_subprogram ] [line 2] [def] [set1]
!21 = !MDLocation(line: 2, scope: !4)

So both functions claim to have the scope of set1, and that triggers the assertion.

Changing set2 to:

pub fn2(x: &mut u32) { set1(x) }

Triggers the inlining even without mergefunc, and we get:

define void @_Z4set2Pi(i32* nocapture %x) #0 {
  tail call void @llvm.dbg.value(metadata i32* %x, i64 0, metadata !14, metadata !18), !dbg !26
  tail call void @llvm.dbg.value(metadata i32* %x, i64 0, metadata !27, metadata !18), !dbg !29
  store i32 123, i32* %x, align 4, !dbg !30, !tbaa !21
  ret void, !dbg !31
}

I suppose the re-declaration of %x is just ignored and thus the error doesn't happen.

For now, I suppose that it would be sensible to disable mergefunc when compiling with debug information.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jul 6, 2015

This no longer causes an assert on nightly, so closing as fixed. Yay!

nox added a commit to nox/rust that referenced this issue Mar 29, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

bors added a commit that referenced this issue Mar 29, 2018

Auto merge of #49479 - nox:merge-funcs, r=<try>
Reenable the MergeFunctions pass

The crash that happened in #23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

nox added a commit to nox/rust that referenced this issue Mar 29, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

bors added a commit that referenced this issue Apr 22, 2018

Auto merge of #49479 - nox:merge-funcs, r=nagisa
Reenable the MergeFunctions pass

The crash that happened in #23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

nox added a commit to nox/rust that referenced this issue May 10, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

nox added a commit to nox/rust that referenced this issue May 10, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

nox added a commit to nox/rust that referenced this issue May 11, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

bors added a commit that referenced this issue May 11, 2018

Auto merge of #49479 - nox:merge-funcs, r=alexcrichton
Reenable the MergeFunctions pass

The crash that happened in #23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

For those wondering, [here are the docs from LLVM about this pass](http://llvm.org/docs/MergeFunctions.html).

nox added a commit to nox/rust that referenced this issue May 12, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

bors added a commit that referenced this issue May 12, 2018

Auto merge of #49479 - nox:merge-funcs, r=alexcrichton
Reenable the MergeFunctions pass

The crash that happened in #23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

For those wondering, [here are the docs from LLVM about this pass](http://llvm.org/docs/MergeFunctions.html).

bors added a commit that referenced this issue May 13, 2018

Auto merge of #49479 - nox:merge-funcs, r=<try>
Reenable the MergeFunctions pass

The crash that happened in #23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

For those wondering, [here are the docs from LLVM about this pass](http://llvm.org/docs/MergeFunctions.html).

nox added a commit to nox/rust that referenced this issue May 15, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

nox added a commit to nox/rust that referenced this issue May 15, 2018

Reenable the MergeFunctions pass
The crash that happened in rust-lang#23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

bors added a commit that referenced this issue May 16, 2018

Auto merge of #49479 - nox:merge-funcs, r=nagisa
Reenable the MergeFunctions pass

The crash that happened in #23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

For those wondering, [here are the docs from LLVM about this pass](http://llvm.org/docs/MergeFunctions.html).

bors added a commit that referenced this issue May 16, 2018

Auto merge of #49479 - nox:merge-funcs, r=nagisa
Reenable the MergeFunctions pass

The crash that happened in #23566 doesn't happen anymore with the LLVM mergefunc
pass enabled and it hugely reduces code size (for example it shaves off 10% of the
final Servo executable). This patch reenables it.

For those wondering, [here are the docs from LLVM about this pass](http://llvm.org/docs/MergeFunctions.html).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.