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

rust-analyser segfault with lto=thin, linker=lld-link #71504

Closed
Speedy37 opened this issue Apr 24, 2020 · 23 comments
Closed

rust-analyser segfault with lto=thin, linker=lld-link #71504

Speedy37 opened this issue Apr 24, 2020 · 23 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections ICEBreaker-LLVM Bugs identified for the LLVM ICE-breaker group P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Speedy37
Copy link

Speedy37 commented Apr 24, 2020

I was having fun compiling rust-analyser for maximizing performance on my machine.

Compiling commit ec645f2 of rust-analyser with lto=fat seems to work as expected.

But this configuration on windows:

[profile.release]
lto = "thin"
#incremental = true
debug = 0 # set this to 1 or 2 to get more useful backtraces in debugger

Result in rust-analyser segfaut:

Access violation executing location 0x0000000100785A4D.

Meta

rustc 1.43.0 (4fb7144ed 2020-04-20)
binary: rustc
commit-hash: 4fb7144ed159f94491249e86d5bbd033b5d60550
commit-date: 2020-04-20
host: x86_64-pc-windows-msvc
release: 1.43.0
LLVM version: 9.0
Backtrace

>	rust-analyzer.exe!_ZN7globset8pathutil9file_name17h08d0f1900ad67247E�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN7globset7GlobSet8is_match17hf1cf9a1f69ce8dd2E�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN77_$LT$rust_analyzer..vfs_glob..RustPackageFilter$u20$as$u20$ra_vfs..Filter$GT$11include_dir17ha6495721bf18fe0eE�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN6ra_vfs5roots16to_relative_path17hb9707874d497bdc4E�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN106_$LT$core..iter..adapters..chain..Chain$LT$A$C$B$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$8try_fold17hac44483bd652ee40E�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN108_$LT$walkdir..FilterEntry$LT$walkdir..IntoIter$C$P$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next17ha136f9b20c380477E�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN6ra_vfs2io13handle_change17h8a81e482afc2c09bE�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN6ra_vfs2io10watch_root17h425c73dcf2ce2dd1E�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN3std10sys_common9backtrace28__rust_begin_short_backtrace17hb0fd61dddb6f5a20E.llvm.14564221459209632736�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!_ZN4core3mem4drop17hab46961f8567a42bE.llvm.1531302937598756963�()	Unknown	Non-user code. Symbols loaded.
 	rust-analyzer.exe!alloc::boxed::{{impl}}::call_once<(),FnOnce<()>>() Line 1017	Unknown	Symbols loaded.
 	[Inline Frame] rust-analyzer.exe!alloc::boxed::{{impl}}::call_once() Line 1017	Unknown	Symbols loaded.
 	[Inline Frame] rust-analyzer.exe!std::sys_common::thread::start_thread() Line 13	Unknown	Symbols loaded.
 	rust-analyzer.exe!std::sys::windows::thread::{{impl}}::new::thread_start() Line 51	Unknown	Symbols loaded.

Frame 0 Assembly

_ZN7globset8pathutil9file_name17h08d0f1900ad67247E:
00007FF66A5D76B0  push        rbp  
00007FF66A5D76B1  push        r15  
00007FF66A5D76B3  push        r14  
00007FF66A5D76B5  push        r12  
00007FF66A5D76B7  push        rsi  
00007FF66A5D76B8  push        rdi  
00007FF66A5D76B9  push        rbx  
00007FF66A5D76BA  sub         rsp,60h  
00007FF66A5D76BE  lea         rbp,[rsp+60h]  
00007FF66A5D76C3  mov         qword ptr [rbp-8],0FFFFFFFFFFFFFFFEh  
00007FF66A5D76CB  mov         r12,rcx  
00007FF66A5D76CE  mov         rsi,qword ptr [rdx]  
00007FF66A5D76D1  mov         rdi,qword ptr [rdx+10h]  
00007FF66A5D76D5  cmp         rsi,1  
00007FF66A5D76D9  mov         rbx,qword ptr [rdx+18h]  
00007FF66A5D76DD  mov         r8,rdi  
00007FF66A5D76E0  cmove       r8,rbx  
00007FF66A5D76E4  test        r8,r8  
00007FF66A5D76E7  je          _ZN7globset8pathutil9file_name17h08d0f1900ad67247E+45h (07FF66A5D76F5h)  
00007FF66A5D76E9  mov         r15,qword ptr [rdx+8]  
00007FF66A5D76ED  cmp         byte ptr [r8+r15-1],2Eh  
00007FF66A5D76F3  jne         _ZN7globset8pathutil9file_name17h08d0f1900ad67247E+52h (07FF66A5D7702h)  
00007FF66A5D76F5  mov         qword ptr [r12],2  
00007FF66A5D76FD  jmp         _ZN7globset8pathutil9file_name17h08d0f1900ad67247E+14Fh (07FF66A5D77FFh)  
00007FF66A5D7702  mov         rax,qword ptr [__imp__ZN6memchr3x867memrchr2FN17h7699f2e42a7ae581E (07FF66BBC73B0h)]  
00007FF66A5D7709  mov         rax,qword ptr [rax]  
00007FF66A5D770C  mov         cl,2Fh  
00007FF66A5D770E  mov         rdx,r15  
00007FF66A5D7711  call        rax <<< rax is garbage
00007FF66A5D7713  mov         r14,rdx  
00007FF66A5D7716  add         r14,1  

Frame 0 Registers

RBX = 00000238EB8D2FE0
RSI = 0000000000000000
RDI = 0000000000000005
R12 = 000000C631DFE620 
R13 = 000000C631DFE790
R14 = 0000000000000008
R15 = 00000238EB8D2FE0
RIP = 00007FF66A5D7713
RSP = 000000C631DFE540 
RBP = 000000C631DFE5A0 

So this function seams to be miss compiled:

https://github.com/BurntSushi/ripgrep/blob/a2e6aec7a4d9382941932245e8854f0ae5703a5e/crates/globset/src/pathutil.rs#L9

pub fn file_name<'a>(path: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
    if path.is_empty() {
        return None;
    } else if path.last_byte() == Some(b'.') {
        return None;
    }
    let last_slash = path.rfind_byte(b'/').map(|i| i + 1).unwrap_or(0);
    Some(match *path {
        Cow::Borrowed(path) => Cow::Borrowed(&path[last_slash..]),
        Cow::Owned(ref path) => {
            let mut path = path.clone();
            path.drain_bytes(..last_slash);
            Cow::Owned(path)
        }
    })
}

In particular this line:

let last_slash = path.rfind_byte(b'/').map(|i| i + 1).unwrap_or(0);
00007FF66A5D7702  mov         rax,qword ptr [__imp__ZN6memchr3x867memrchr2FN17h7699f2e42a7ae581E (07FF66BBC73B0h)]  
00007FF66A5D7709  mov         rax,qword ptr [rax]
00007FF66A5D770C  mov         cl,2Fh  
00007FF66A5D770E  mov         rdx,r15  
00007FF66A5D7711  call        rax <<< rax is garbage
@Speedy37 Speedy37 added the C-bug Category: This is a bug. label Apr 24, 2020
@jonas-schievink jonas-schievink added E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-prioritize Issue: Indicates that prioritization has been requested for this issue. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 24, 2020
@Speedy37
Copy link
Author

Speedy37 commented Apr 24, 2020

I managed to create a smaller reproducer:

[package]
name = "rust-71504"
version = "0.1.0"
authors = ["Vincent Rouillé <[email protected]>"]
edition = "2018"

[dependencies]
globset = "0.4.5"

[profile.release]
lto = "thin"
use globset::GlobSetBuilder;

fn main() {
    assert!(GlobSetBuilder::new().build().unwrap().is_match("src/tests"));
}
cargo run --release 
   Compiling rust-71504 v0.1.0 (C:\Development\GitHub\rust-71504)
    Finished release [optimized] target(s) in 4.19s
     Running `target\release\rust-71504.exe`
error: process didn't exit successfully: `target\release\rust-71504.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

@jonas-schievink
Copy link
Contributor

Does this reproduce on nightly?

@Speedy37
Copy link
Author

Speedy37 commented Apr 24, 2020

Yes with rustc 1.44.0-nightly (b2e36e6 2020-04-22)

And the generated code that crash is the same:

00007FF694210542  mov         rax,qword ptr [__imp__ZN6memchr3x867memrchr2FN17h93ee2fcbd3a00cdaE (07FF6943143B0h)]  
00007FF694210549  mov         rax,qword ptr [rax]  
00007FF69421054C  mov         cl,2Fh  
00007FF69421054E  mov         rdx,r15  
00007FF694210551  call        rax 

@Speedy37
Copy link
Author

Speedy37 commented Apr 24, 2020

globset::pathutil::file_name llvm-ir

@_ZN6memchr3x867memrchr2FN17h5bc0baf729fbe004E = external dllimport local_unnamed_addr global %"core::sync::atomic::AtomicPtr<()>"

; globset::pathutil::file_name
; Function Attrs: uwtable
define void @_ZN7globset8pathutil9file_name17hbcd7b89f83326b91E(%"core::option::Option<alloc::borrow::Cow<[u8]>>"* noalias nocapture sret dereferenceable(32), %"alloc::borrow::Cow<[u8]>"* noalias nocapture readonly align 8 dereferenceable(32) %path) unnamed_addr #0 personality i32 (...)* @__CxxFrameHandler3 {
start:
  %vector.i.i.i = alloca %"alloc::vec::Vec<u8>", align 8
  %path1 = alloca %"alloc::vec::Vec<u8>", align 8
  %1 = getelementptr inbounds %"alloc::borrow::Cow<[u8]>", %"alloc::borrow::Cow<[u8]>"* %path, i64 0, i32 0, i64 0
  %_3.i = load i64, i64* %1, align 8, !range !2, !alias.scope !5129
  %switch.i = icmp eq i64 %_3.i, 1
  %owned.i = getelementptr inbounds %"alloc::borrow::Cow<[u8]>", %"alloc::borrow::Cow<[u8]>"* %path, i64 0, i32 2
  %2 = getelementptr inbounds %"alloc::borrow::Cow<[u8]>", %"alloc::borrow::Cow<[u8]>"* %path, i64 0, i32 2, i64 1
  %3 = getelementptr inbounds %"alloc::borrow::Cow<[u8]>", %"alloc::borrow::Cow<[u8]>"* %path, i64 0, i32 2, i64 2
  %_2.sroa.0.0.in.i = bitcast [3 x i64]* %owned.i to [0 x i8]**
  %_2.sroa.0.0.i = load [0 x i8]*, [0 x i8]** %_2.sroa.0.0.in.i, align 8, !alias.scope !5129, !nonnull !1
  %.val.i = load i64, i64* %3, align 8, !alias.scope !5129
  %.val3.i = load i64, i64* %2, align 8, !alias.scope !5129
  %_2.sroa.5.0.i = select i1 %switch.i, i64 %.val.i, i64 %.val3.i
  %4 = icmp eq i64 %_2.sroa.5.0.i, 0
  br i1 %4, label %bb5, label %"_ZN70_$LT$core..option..Option$LT$T$GT$$u20$as$u20$core..cmp..PartialEq$GT$2eq17h38574dfda84b4f2cE.exit"

"_ZN70_$LT$core..option..Option$LT$T$GT$$u20$as$u20$core..cmp..PartialEq$GT$2eq17h38574dfda84b4f2cE.exit": ; preds = %start
  %5 = add i64 %_2.sroa.5.0.i, -1
  %6 = getelementptr inbounds [0 x i8], [0 x i8]* %_2.sroa.0.0.i, i64 0, i64 %5
  %.val.i.i = load i8, i8* %6, align 1, !alias.scope !5132
  %7 = icmp eq i8 %.val.i.i, 46
  br i1 %7, label %bb12, label %_ZN4bstr9ext_slice9ByteSlice10rfind_byte17h49aefeba57a625e8E.exit

bb5:                                              ; preds = %start
  %8 = getelementptr inbounds %"core::option::Option<alloc::borrow::Cow<[u8]>>", %"core::option::Option<alloc::borrow::Cow<[u8]>>"* %0, i64 0, i32 0, i64 0
  store i64 2, i64* %8, align 8
  br label %bb6

bb6:                                              ; preds = %bb5, %bb12, %bb25
  ret void

_ZN4bstr9ext_slice9ByteSlice10rfind_byte17h49aefeba57a625e8E.exit: ; preds = %"_ZN70_$LT$core..option..Option$LT$T$GT$$u20$as$u20$core..cmp..PartialEq$GT$2eq17h38574dfda84b4f2cE.exit"
  %9 = load atomic i64, i64* bitcast (i8** getelementptr inbounds (%"core::sync::atomic::AtomicPtr<()>", %"core::sync::atomic::AtomicPtr<()>"* @_ZN6memchr3x867memrchr2FN17h5bc0baf729fbe004E, i64 0, i32 1) to i64*) monotonic, align 8, !noalias !5137
  %10 = inttoptr i64 %9 to { i64, i64 } (i8, [0 x i8]*, i64)*
  %11 = icmp ne i64 %9, 0
  tail call void @llvm.assume(i1 %11), !noalias !5137
  %12 = tail call { i64, i64 } %10(i8 47, [0 x i8]* noalias nonnull readonly align 1 %_2.sroa.0.0.i, i64 %_2.sroa.5.0.i)
  %.fca.0.extract.i.i = extractvalue { i64, i64 } %12, 0
  %.fca.1.extract.i.i = extractvalue { i64, i64 } %12, 1
  %switch.i41 = icmp eq i64 %.fca.0.extract.i.i, 0
  %13 = add i64 %.fca.1.extract.i.i, 1
  %..i = select i1 %switch.i41, i64 0, i64 %13
  br i1 %switch.i, label %bb17, label %bb19

bb12:                                             ; preds = %"_ZN70_$LT$core..option..Option$LT$T$GT$$u20$as$u20$core..cmp..PartialEq$GT$2eq17h38574dfda84b4f2cE.exit"
  %14 = getelementptr inbounds %"core::option::Option<alloc::borrow::Cow<[u8]>>", %"core::option::Option<alloc::borrow::Cow<[u8]>>"* %0, i64 0, i32 0, i64 0
  store i64 2, i64* %14, align 8
  br label %bb6

bb17:                                             ; preds = %_ZN4bstr9ext_slice9ByteSlice10rfind_byte17h49aefeba57a625e8E.exit
  %15 = bitcast %"alloc::vec::Vec<u8>"* %path1 to i8*
  call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %15)
  %16 = bitcast %"alloc::vec::Vec<u8>"* %vector.i.i.i to i8*
  call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull %16), !noalias !5146
  %_15.i.i.i.i.i.i = icmp eq i64 %.val.i, 0
  br i1 %_15.i.i.i.i.i.i, label %"_ZN5alloc3vec12Vec$LT$T$GT$13with_capacity17hc96a68e01ada40f4E.exit.i.i.i", label %"_ZN62_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..AllocRef$GT$5alloc17h2d3f07a62eac3ef8E.exit.i.i.i.i.i.i"

"_ZN62_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..AllocRef$GT$5alloc17h2d3f07a62eac3ef8E.exit.i.i.i.i.i.i": ; preds = %bb17
  %17 = tail call i8* @__rust_alloc(i64 %.val.i, i64 1) #16, !noalias !5156
  %18 = icmp eq i8* %17, null
  br i1 %18, label %bb18.i.i.i.i.i.i, label %"_ZN5alloc3vec12Vec$LT$T$GT$13with_capacity17hc96a68e01ada40f4E.exit.i.i.i"

bb18.i.i.i.i.i.i:                                 ; preds = %"_ZN62_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..AllocRef$GT$5alloc17h2d3f07a62eac3ef8E.exit.i.i.i.i.i.i"
; call alloc::alloc::handle_alloc_error
  tail call void @_ZN5alloc5alloc18handle_alloc_error17h31c2c94a892ecbd6E(i64 %.val.i, i64 1) #16, !noalias !5156
  unreachable

"_ZN5alloc3vec12Vec$LT$T$GT$13with_capacity17hc96a68e01ada40f4E.exit.i.i.i": ; preds = %"_ZN62_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..AllocRef$GT$5alloc17h2d3f07a62eac3ef8E.exit.i.i.i.i.i.i", %bb17
  %ptr.0.i.i.i.i.i.i = phi i8* [ inttoptr (i64 1 to i8*), %bb17 ], [ %17, %"_ZN62_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..AllocRef$GT$5alloc17h2d3f07a62eac3ef8E.exit.i.i.i.i.i.i" ]
  %19 = bitcast %"alloc::vec::Vec<u8>"* %vector.i.i.i to i8**
  store i8* %ptr.0.i.i.i.i.i.i, i8** %19, align 8, !alias.scope !5159, !noalias !5146
  %20 = getelementptr inbounds %"alloc::vec::Vec<u8>", %"alloc::vec::Vec<u8>"* %vector.i.i.i, i64 0, i32 1, i32 1
  store i64 %.val.i, i64* %20, align 8, !alias.scope !5159, !noalias !5146
  %21 = getelementptr inbounds %"alloc::vec::Vec<u8>", %"alloc::vec::Vec<u8>"* %vector.i.i.i, i64 0, i32 3
  store i64 0, i64* %21, align 8, !alias.scope !5159, !noalias !5146
; invoke alloc::vec::Vec<T>::reserve
  invoke fastcc void @"_ZN5alloc3vec12Vec$LT$T$GT$7reserve17h8328aa9ad9c26b4cE"(%"alloc::vec::Vec<u8>"* nonnull align 8 dereferenceable(24) %vector.i.i.i, i64 %.val.i)
          to label %"_ZN63_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..clone..Clone$GT$5clone17ha8687e9b953bbe67E.exit" unwind label %funclet_bb5.i.i.i, !noalias !5146

funclet_bb5.i.i.i:                                ; preds = %"_ZN5alloc3vec12Vec$LT$T$GT$13with_capacity17hc96a68e01ada40f4E.exit.i.i.i"
  %cleanuppad.i.i.i = cleanuppad within none []
  call fastcc void bitcast (void (%"alloc::string::String"*)* @_ZN4core3ptr13drop_in_place17h16849cb7958e75d3E to void (%"alloc::vec::Vec<u8>"*)*)(%"alloc::vec::Vec<u8>"* nonnull %vector.i.i.i) #22 [ "funclet"(token %cleanuppad.i.i.i) ], !noalias !5146
  cleanupret from %cleanuppad.i.i.i unwind to caller

"_ZN63_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..clone..Clone$GT$5clone17ha8687e9b953bbe67E.exit": ; preds = %"_ZN5alloc3vec12Vec$LT$T$GT$13with_capacity17hc96a68e01ada40f4E.exit.i.i.i"
  %22 = getelementptr inbounds [0 x i8], [0 x i8]* %_2.sroa.0.0.i, i64 0, i64 0
  %self.idx.val.i.i.i.i.i = load i64, i64* %21, align 8, !noalias !5160
  %_13.i.i.i.i.i = add i64 %self.idx.val.i.i.i.i.i, %.val.i
  store i64 %_13.i.i.i.i.i, i64* %21, align 8, !noalias !5160
  %23 = bitcast %"alloc::vec::Vec<u8>"* %vector.i.i.i to [0 x i8]**
  %_3.idx.val.i1.i.i.i.i.i.i = load [0 x i8]*, [0 x i8]** %23, align 8, !noalias !5160, !nonnull !1
  %24 = getelementptr inbounds [0 x i8], [0 x i8]* %_3.idx.val.i1.i.i.i.i.i.i, i64 0, i64 %self.idx.val.i.i.i.i.i
  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 %24, i8* nonnull align 1 %22, i64 %.val.i, i1 false) #16, !noalias !5163
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 %15, i8* nonnull align 8 %16, i64 24, i1 false), !noalias !5164
  call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %16), !noalias !5146
  %self.idx.i.i = getelementptr inbounds %"alloc::vec::Vec<u8>", %"alloc::vec::Vec<u8>"* %path1, i64 0, i32 3
  %self.idx.val.i.i = load i64, i64* %self.idx.i.i, align 8, !noalias !5165
  %_26.i.i = icmp ult i64 %self.idx.val.i.i, %..i
  br i1 %_26.i.i, label %bb19.i.i, label %bb22

bb19.i.i:                                         ; preds = %"_ZN63_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..clone..Clone$GT$5clone17ha8687e9b953bbe67E.exit"
; invoke core::panicking::panic
  invoke void @_ZN4core9panicking5panic17h07bec01df8643458E([0 x i8]* noalias nonnull readonly align 1 bitcast (<{ [28 x i8] }>* @anon.aed952bceef054ab22098ec10f8b5504.48 to [0 x i8]*), i64 28, %"core::panic::Location"* noalias readonly align 8 dereferenceable(24) bitcast (<{ i8*, [16 x i8] }>* @anon.aed952bceef054ab22098ec10f8b5504.40 to %"core::panic::Location"*))
          to label %.noexc unwind label %funclet_bb23

.noexc:                                           ; preds = %bb19.i.i
  unreachable

bb19:                                             ; preds = %_ZN4bstr9ext_slice9ByteSlice10rfind_byte17h49aefeba57a625e8E.exit
  %_3.i.i.i = icmp ult i64 %.val3.i, %..i
  br i1 %_3.i.i.i, label %bb2.i.i.i, label %"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h358af9de6dfcb22eE.exit"

bb2.i.i.i:                                        ; preds = %bb19
; call core::slice::slice_index_order_fail
  tail call void @_ZN4core5slice22slice_index_order_fail17h3334b3335c3bd3ecE(i64 %..i, i64 %.val3.i)
  unreachable

"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h358af9de6dfcb22eE.exit": ; preds = %bb19
  %25 = getelementptr inbounds [0 x i8], [0 x i8]* %_2.sroa.0.0.i, i64 0, i64 %..i
  %_8.i.i.i.i = sub i64 %.val3.i, %..i
  %26 = bitcast i8* %25 to [0 x i8]*
  br label %bb25

bb22:                                             ; preds = %"_ZN63_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..clone..Clone$GT$5clone17ha8687e9b953bbe67E.exit"
  store i64 0, i64* %self.idx.i.i, align 8, !noalias !5165
  %27 = bitcast %"alloc::vec::Vec<u8>"* %path1 to [0 x i8]**
  %_3.idx.val.i22.i.i = load [0 x i8]*, [0 x i8]** %27, align 8, !noalias !5165, !nonnull !1
  %_43.i.i = sub i64 %self.idx.val.i.i, %..i
  %_4.i.i.i.i.i = icmp eq i64 %_43.i.i, 0
  %28 = getelementptr inbounds [0 x i8], [0 x i8]* %_3.idx.val.i22.i.i, i64 0, i64 0
  br i1 %_4.i.i.i.i.i, label %bb24, label %bb2.i.i.i.i.i

bb2.i.i.i.i.i:                                    ; preds = %bb22
  %_11.i.i.i.i.i = icmp eq i64 %..i, 0
  br i1 %_11.i.i.i.i.i, label %bb11.i.i.i.i.i, label %bb5.i.i.i.i.i

bb5.i.i.i.i.i:                                    ; preds = %bb2.i.i.i.i.i
  %29 = getelementptr inbounds [0 x i8], [0 x i8]* %_3.idx.val.i22.i.i, i64 0, i64 %..i
  tail call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 1 %28, i8* nonnull align 1 %29, i64 %_43.i.i, i1 false) #16
  br label %bb11.i.i.i.i.i

bb11.i.i.i.i.i:                                   ; preds = %bb5.i.i.i.i.i, %bb2.i.i.i.i.i
  store i64 %_43.i.i, i64* %self.idx.i.i, align 8
  br label %bb24

bb24:                                             ; preds = %bb11.i.i.i.i.i, %bb22
  %_36.sroa.4.0..sroa_idx16 = getelementptr inbounds %"alloc::vec::Vec<u8>", %"alloc::vec::Vec<u8>"* %path1, i64 0, i32 1, i32 1
  %_36.sroa.4.0.copyload = load i64, i64* %_36.sroa.4.0..sroa_idx16, align 8
  call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull %15)
  br label %bb25

bb25:                                             ; preds = %"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h358af9de6dfcb22eE.exit", %bb24
  %_20.sroa.8.0 = phi i64 [ undef, %"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h358af9de6dfcb22eE.exit" ], [ %_43.i.i, %bb24 ]
  %_20.sroa.7.0 = phi i64 [ %_8.i.i.i.i, %"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h358af9de6dfcb22eE.exit" ], [ %_36.sroa.4.0.copyload, %bb24 ]
  %_20.sroa.5.0 = phi [0 x i8]* [ %26, %"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h358af9de6dfcb22eE.exit" ], [ %_3.idx.val.i22.i.i, %bb24 ]
  %_20.sroa.0.0 = phi i64 [ 0, %"_ZN4core5slice74_$LT$impl$u20$core..ops..index..Index$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$5index17h358af9de6dfcb22eE.exit" ], [ 1, %bb24 ]
  %_20.sroa.0.0..sroa_idx = getelementptr inbounds %"core::option::Option<alloc::borrow::Cow<[u8]>>", %"core::option::Option<alloc::borrow::Cow<[u8]>>"* %0, i64 0, i32 0, i64 0
  store i64 %_20.sroa.0.0, i64* %_20.sroa.0.0..sroa_idx, align 8
  %_20.sroa.5.0..sroa_idx5 = getelementptr inbounds %"core::option::Option<alloc::borrow::Cow<[u8]>>", %"core::option::Option<alloc::borrow::Cow<[u8]>>"* %0, i64 0, i32 2
  %_20.sroa.5.0..sroa_cast = bitcast [3 x i64]* %_20.sroa.5.0..sroa_idx5 to [0 x i8]**
  store [0 x i8]* %_20.sroa.5.0, [0 x i8]** %_20.sroa.5.0..sroa_cast, align 8
  %30 = getelementptr inbounds %"core::option::Option<alloc::borrow::Cow<[u8]>>", %"core::option::Option<alloc::borrow::Cow<[u8]>>"* %0, i64 0, i32 2, i64 1
  store i64 %_20.sroa.7.0, i64* %30, align 8
  %31 = getelementptr inbounds %"core::option::Option<alloc::borrow::Cow<[u8]>>", %"core::option::Option<alloc::borrow::Cow<[u8]>>"* %0, i64 0, i32 2, i64 2
  store i64 %_20.sroa.8.0, i64* %31, align 8
  br label %bb6

funclet_bb23:                                     ; preds = %bb19.i.i
  %cleanuppad = cleanuppad within none []
  call fastcc void bitcast (void (%"alloc::string::String"*)* @_ZN4core3ptr13drop_in_place17h16849cb7958e75d3E to void (%"alloc::vec::Vec<u8>"*)*)(%"alloc::vec::Vec<u8>"* nonnull %path1) #22 [ "funclet"(token %cleanuppad) ]
  cleanupret from %cleanuppad unwind to caller
}

memchr::x86::memrchr::detect llvm-ir

@_ZN6memchr3x867memrchr2FN17h5bc0baf729fbe004E = local_unnamed_addr global <{ i8*, [0 x i8] }> <{ i8* bitcast ({ i64, i64 } (i8, [0 x i8]*, i64)* @_ZN6memchr3x867memrchr6detect17h517e20eb83e5ca39E to i8*), [0 x i8] zeroinitializer }>, align 8

@"\01__imp__ZN6memchr3x867memrchr2FN17h5bc0baf729fbe004E" = global i8* bitcast (<{ i8*, [0 x i8] }>* @_ZN6memchr3x867memrchr2FN17h5bc0baf729fbe004E to i8*)


; memchr::x86::memrchr::detect
; Function Attrs: uwtable
define internal { i64, i64 } @_ZN6memchr3x867memrchr6detect17h517e20eb83e5ca39E(i8 %n1, [0 x i8]* noalias nonnull readonly align 1 %haystack.0, i64 %haystack.1) unnamed_addr #2 personality i32 (...)* @__CxxFrameHandler3 {
start:
  %0 = load atomic i64, i64* getelementptr inbounds ([2 x %"std::std_detect::detect::cache::Cache"], [2 x %"std::std_detect::detect::cache::Cache"]* @_ZN3std10std_detect6detect5cache5CACHE17h36155bdd5a985257E, i64 0, i64 0, i32 1, i32 1) seq_cst, align 8
  %1 = icmp eq i64 %0, -1
  br i1 %1, label %bb7.i.i.i, label %_ZN3std10std_detect6detect4arch21__is_feature_detected4avx217hc0fbd12b9336552cE.exit

bb7.i.i.i:                                        ; preds = %start
; call std::std_detect::detect::os::detect_features
  %2 = tail call i64 @_ZN3std10std_detect6detect2os15detect_features17h30d1c684eca000e9E()
  %_6.i.i.i.i.i = and i64 %2, 9223372036854775807
  store atomic i64 %_6.i.i.i.i.i, i64* getelementptr inbounds ([2 x %"std::std_detect::detect::cache::Cache"], [2 x %"std::std_detect::detect::cache::Cache"]* @_ZN3std10std_detect6detect5cache5CACHE17h36155bdd5a985257E, i64 0, i64 0, i32 1, i32 1) seq_cst, align 8
  %_15.i.i.i.i.i = lshr i64 %2, 63
  store atomic i64 %_15.i.i.i.i.i, i64* getelementptr inbounds ([2 x %"std::std_detect::detect::cache::Cache"], [2 x %"std::std_detect::detect::cache::Cache"]* @_ZN3std10std_detect6detect5cache5CACHE17h36155bdd5a985257E, i64 0, i64 1, i32 1, i32 1) seq_cst, align 8
  br label %_ZN3std10std_detect6detect4arch21__is_feature_detected4avx217hc0fbd12b9336552cE.exit

_ZN3std10std_detect6detect4arch21__is_feature_detected4avx217hc0fbd12b9336552cE.exit: ; preds = %start, %bb7.i.i.i
  %3 = load atomic i64, i64* getelementptr inbounds ([2 x %"std::std_detect::detect::cache::Cache"], [2 x %"std::std_detect::detect::cache::Cache"]* @_ZN3std10std_detect6detect5cache5CACHE17h36155bdd5a985257E, i64 0, i64 0, i32 1, i32 1) seq_cst, align 8
  %4 = trunc i64 %3 to i16
  %5 = icmp slt i16 %4, 0
  %.sink = select i1 %5, i64 ptrtoint ({ i64, i64 } (i8, [0 x i8]*, i64)* @_ZN6memchr3x863avx7memrchr17h082fa08fb3cf7b05E to i64), i64 ptrtoint ({ i64, i64 } (i8, [0 x i8]*, i64)* @_ZN6memchr3x864sse27memrchr17h62035a598a168baeE to i64)
  %6 = select i1 %5, { i64, i64 } (i8, [0 x i8]*, i64)* @_ZN6memchr3x863avx7memrchr17h082fa08fb3cf7b05E, { i64, i64 } (i8, [0 x i8]*, i64)* @_ZN6memchr3x864sse27memrchr17h62035a598a168baeE
  store atomic i64 %.sink, i64* bitcast (<{ i8*, [0 x i8] }>* @_ZN6memchr3x867memrchr2FN17h5bc0baf729fbe004E to i64*) monotonic, align 8
  %7 = tail call { i64, i64 } %6(i8 %n1, [0 x i8]* noalias nonnull readonly align 1 %haystack.0, i64 %haystack.1)
  ret { i64, i64 } %7
}

Probable relevant part:

%9 = load atomic i64, i64* bitcast (i8** getelementptr inbounds (%"core::sync::atomic::AtomicPtr<()>", %"core::sync::atomic::AtomicPtr<()>"* @_ZN6memchr3x867memrchr2FN17h5bc0baf729fbe004E, i64 0, i32 1) to i64*) monotonic, align 8, !noalias !5137
  %10 = inttoptr i64 %9 to { i64, i64 } (i8, [0 x i8]*, i64)*
  %11 = icmp ne i64 %9, 0
  tail call void @llvm.assume(i1 %11), !noalias !5137

Assembly and llvm-ir files: deps.zip

@LeSeulArtichaut
Copy link
Contributor

Let's have more people to try and minimize that.
@rustbot ping cleanup
@rustbot ping llvm

@rustbot rustbot added the ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections label Apr 24, 2020
@rustbot
Copy link
Collaborator

rustbot commented Apr 24, 2020

Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
"Cleanup ICE-breaking candidate". In case it's useful, here are some
instructions for tackling these sorts of bugs. Maybe take a look?
Thanks! <3

cc @AminArria @chrissimpkins @contrun @DutchGhost @elshize @ethanboxx @h-michael @HallerPatrick @hdhoang @hellow554 @imtsuki @jakevossen5 @kanru @KarlK90 @LeSeulArtichaut @MAdrianMattocks @matheus-consoli @mental32 @nmccarty @Noah-Kennedy @pard68 @PeytonT @pierreN @Redblueflame @RobbieClarken @RobertoSnap @robjtede @SarthakSingh31 @senden9 @shekohex @sinato @spastorino @turboladen @woshilapin @yerke

@LeSeulArtichaut
Copy link
Contributor

@rustbot ping llvm

@rustbot rustbot added the ICEBreaker-LLVM Bugs identified for the LLVM ICE-breaker group label Apr 24, 2020
@rustbot
Copy link
Collaborator

rustbot commented Apr 24, 2020

Hey LLVM ICE-breakers! This bug has been identified as a good
"LLVM ICE-breaking candidate". In case it's useful, here are some
instructions for tackling these sorts of bugs. Maybe take a look?
Thanks! <3

cc @comex @CrazyDebugger @cuviper @DutchGhost @hanna-kruppe @hdhoang @heyrutvik @JOE1994 @jryans @mmilenko @nagisa @nikic @Noah-Kennedy @SiavoshZarrasvand @spastorino @vertexclique

@spastorino
Copy link
Member

Assigning P-critical as discussed as part of the Prioritization Working Group process and removing I-prioritize.

@spastorino spastorino added P-critical Critical priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Apr 27, 2020
@AminArria
Copy link
Contributor

AminArria commented Apr 27, 2020

I've used the example code in #71504 (comment), but can't reproduce. Neither in stable nor in nightly for windows and macOS.

$> cargo run --release
    Finished release [optimized] target(s) in 0.03s
     Running `target\release\i71504.exe`
thread 'main' panicked at 'assertion failed: GlobSetBuilder::new().build().unwrap().is_match("src/tests")', src\main.rs:4:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\release\i71504.exe` (exit code: 101)
$> rustc -vV
rustc 1.43.0 (4fb7144ed 2020-04-20)
binary: rustc
commit-hash: 4fb7144ed159f94491249e86d5bbd033b5d60550
commit-date: 2020-04-20
host: x86_64-pc-windows-msvc
release: 1.43.0
LLVM version: 9.0

@Speedy37
Copy link
Author

Speedy37 commented Apr 28, 2020

I'm sorry, I forgot to unset my global linker setting, I was using "lld-link".

With the official link.exe, this bug doesn't occur.

So this is an lld (LLVM 10) bug, the first I encounter. So I guess this is out of rust-lang scope.

I there any target where lld is the official linker? Might be a COFF only bug tho.

Changing the linker back to the default one, also fixed the compilation of rust-analyser, lto=fat, target-cpu=native btw (52s total vs 100s with the official build, I'm happy).

@Speedy37 Speedy37 changed the title rust-analyser segfault with lto=thin rust-analyser segfault with lto=thin, linker=lld-link Apr 28, 2020
@jonas-schievink
Copy link
Contributor

cc @Gankra (relevant to the LLD-by-default plans)

@jonas-schievink jonas-schievink added A-linkage Area: linking into static, shared libraries and binaries and removed I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness labels Apr 28, 2020
@jonas-schievink
Copy link
Contributor

Removing I-unsound as this is an upstream bug. Maybe it should be closed outright, since having an issue for every problem in LLVM isn't terribly helpful, but with the plans for using LLD by default this might be helpful.

@jonas-schievink
Copy link
Contributor

I there any target where lld is the official linker?

Yes, embedded ARM targets use it by default. They're ELF targets though, and LLD's ELF backend is fairly reliable (I've only witnessed it corrupting debuginfo once, not cause crashes like this).

@Speedy37
Copy link
Author

Well I'have been using lld-link as default rust linker on windows for about 2 years now: no issue.

PS: I was able to reproduce it with lld-link 9.0.1 and 10.0.0

@spastorino
Copy link
Member

After some discussion during triage meeting, we've decided to change the priority to P-high.

@spastorino spastorino removed the P-critical Critical priority label Apr 30, 2020
@spastorino spastorino added P-high High priority I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness labels Apr 30, 2020
@wesleywiser
Copy link
Member

I was able to repro this with the following steps:

  1. rustup update nightly

  2. Install lld-link.exe. On Windows, the easiest thing I found was to install LLVM from their downloads page. I did not add LLVM to my system path.

  3. Setup the repro crate as described in rust-analyser segfault with lto=thin, linker=lld-link #71504 (comment)

  4. Inside the root of the repro crate, create .cargo/config and put this in it:

[target.x86_64-pc-windows-msvc]
linker = "lld-link.exe"
  1. Run cargo with this invocation and observe the issue (note I use git-bash):
$ PATH=/c/Program\ Files/LLVM/bin/:$PATH cargo +nightly run --release
   Compiling memchr v2.3.3
   Compiling log v0.4.8
   Compiling regex-syntax v0.6.17
   Compiling aho-corasick v0.7.10
   Compiling bstr v0.2.12
   Compiling regex v1.3.7
   Compiling globset v0.4.5
   Compiling test_ice v0.1.0 (C:\projects\temp\test_ice)
    Finished release [optimized] target(s) in 16.54s
     Running `target\release\test_ice.exe`
error: process didn't exit successfully: `target\release\test_ice.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
Segmentation fault

I can confirm that this is lld specific, using the native Windows linker does not cause an issue.

@Elinvynia Elinvynia added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Jun 9, 2020
@LeSeulArtichaut LeSeulArtichaut removed the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Jun 9, 2020
@Aaron1011
Copy link
Member

Aaron1011 commented Sep 23, 2020

This no longer occurs on the latest nightly. I bisected the fix to 63d0377 (in nightly-2020-05-08)

The relevant change seems to be rust-lang/cargo#8192. Were the 'unused' object files somehow affecting LTO?

@Aaron1011
Copy link
Member

Aaron1011 commented Sep 23, 2020

Minimized:

fn main() {
	memchr::memrchr(b'a', b"b");
}

given "memchr" = "2.1.2", and the setup described in #71504 (comment)

@Aaron1011
Copy link
Member

Aaron1011 commented Sep 23, 2020

Minimized even further:

// lib.rs
use std::sync::atomic::{AtomicPtr, Ordering};

#[inline(always)]
pub fn memrchr() {
    fn detect() {}
		
    static FN: AtomicPtr<()> = AtomicPtr::new(detect as *mut ());
	
    unsafe {
        let fun = FN.load(Ordering::SeqCst);
        std::mem::transmute::<*mut (), fn()>(fun)()
    }
}	

// main.rs
fn main() {
	badlld::memrchr();
}

These functions must be in two different crates, and be compiled with the setup described in #71504 (comment)

@Gankra
Copy link
Contributor

Gankra commented Nov 26, 2020

Closing based on the comments by @Aaron1011

@Gankra Gankra closed this as completed Nov 26, 2020
@Aaron1011
Copy link
Member

Should this be closed without a regression test being committed?

@Gankra
Copy link
Contributor

Gankra commented Nov 26, 2020

Can we just toss your example in a compile-fail?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections ICEBreaker-LLVM Bugs identified for the LLVM ICE-breaker group P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

10 participants