I be loopy about constituents, because they are unbelievable.
$ cargo construct --instance basic --positive aspects usdt-probes [...snip...] error: might perhaps maybe well now not assemble `dropshot` Precipitated by: job did now not exit efficiently: `rustc [...snip...]` (trace: 11, SIGSEGV: invalid memory reference)
Achievement unlocked: rustc
segfault.
Stack hint
fffffc7fce3fcbc0 librustc_driver-77cef3efbfa7284c.so`llvm::BranchProbabilityInfo::computeEestimateBlockWeight(llvm::Feature const&, llvm::DominatorTree*, llvm::PostDominatorTree*)+0xd84()
fffffc7fce3fd370 librustc_driver-77cef3efbfa7284c.so`llvm::BranchProbabilityInfo::calculate(llvm::Feature const&, llvm::LoopInfo const&, llvm::TargetLibraryInfo const*, llvm::DominatorTree*, llvm::PostDominatorTree*)+0x131()
fffffc7fce3fd3c0 librustc_driver-77cef3efbfa7284c.so`llvm::BranchProbabilityAnalysis::lunge(llvm::Feature&, llvm::AnalysisManager<:function>&)+0x134()
fffffc7fce3fd5f0 librustc_driver-77cef3efbfa7284c.so`llvm::detail::AnalysisPassModel<:function llvm::branchprobabilityanalysis llvm::preservedanalyses llvm::analysismanager><:function>::Invalidator>::lunge(llvm::Feature&, llvm::AnalysisManager<:function>&)+0x2f()
fffffc7fce3fd6a0 librustc_driver-77cef3efbfa7284c.so`llvm::AnalysisManager<:function>::getResultImpl(llvm::AnalysisKey*, llvm::Feature&)+0x2de()
fffffc7fce3fd6d0 librustc_driver-77cef3efbfa7284c.so`llvm::BlockFrequencyAnalysis::lunge(llvm::Feature&, llvm::AnalysisManager<:function>&)+0x3f()
fffffc7fce3fd710 librustc_driver-77cef3efbfa7284c.so`llvm::detail::AnalysisPassModel<:function llvm::blockfrequencyanalysis llvm::preservedanalyses llvm::analysismanager><:function>::Invalidator>::lunge(llvm::Feature&, llvm::AnalysisManager<:function>&)+0x26()
fffffc7fce3fd7c0 librustc_driver-77cef3efbfa7284c.so`llvm::AnalysisManager<:function>::getResultImpl(llvm::AnalysisKey*, llvm::Feature&)+0x2de()
fffffc7fce3fdc30 librustc_driver-77cef3efbfa7284c.so`llvm::AlwaysInlinerPass::lunge(llvm::Module&, llvm::AnalysisManager<:module>&)+0xa2c()
fffffc7fce3fdc50 librustc_driver-77cef3efbfa7284c.so`llvm::detail::PassModel<:module llvm::alwaysinlinerpass llvm::preservedanalyses llvm::analysismanager><:module>>::lunge(llvm::Module&, llvm::AnalysisManager<:module>&)+0x15()
fffffc7fce3fddc0 librustc_driver-77cef3efbfa7284c.so`llvm::PassManager<:module llvm::analysismanager><:module>>::lunge(llvm::Module&, llvm::AnalysisManager<:module>&)+0x4b5()
fffffc7fce3ff170 librustc_driver-77cef3efbfa7284c.so`LLVMRustOptimizeWithNewPassManager+0x7f2()
fffffc7fce3ff3a0 librustc_driver-77cef3efbfa7284c.so`rustc_codegen_llvm::help::write::optimize_with_new_llvm_pass_manager+0x372()
fffffc7fce3ff5b0 librustc_driver-77cef3efbfa7284c.so`rustc_codegen_llvm::help::write::optimize+0x388()
fffffc7fce3ff900 librustc_driver-77cef3efbfa7284c.so`rustc_codegen_ssa::help::write::execute_work_item:: <:llvmcodegenbackend>+0x1f3()
fffffc7fce3ffdb0 librustc_driver-77cef3efbfa7284c.so`std::sys_common::backtrace::__rust_begin_short_backtrace::<:llvmcodegenbackend as rustc_codegen_ssa::traits::backend::extrabackendmethods>::spawn_named_thread<:back::write::spawn_work><:llvmcodegenbackend>::{closure#0}, ()>::{closure#0}, ()>+0xf7()
fffffc7fce3fff60 librustc_driver-77cef3efbfa7284c.so`::spawn_unchecked_::spawn_named_thread<:back::write::spawn_work><:llvmcodegenbackend>::{closure#0}, ()>::{closure#0}, ()>::{closure#1} as core::ops::feature::FnOnce>::call_once::{shim:vtable#0}+0xa9()
fffffc7fce3fffb0 libstd-ef15f81a900bedf3.so`std::sys::unix::thread::Thread::unique::thread_start::h24133bfe318082b5+0x27()
fffffc7fce3fffe0 libc.so.1`_thrp_setup+0x6c(fffffc7fed642280)
fffffc7fce3ffff0 libc.so.1`_lwp_start()
Okay, so we’re faulting someplace in LLVM it seems love. From Cliff’s preliminary investigation:
Anyway, yeah, something about the CFG constructing there might perhaps be producing both an empty basic block or a basic block ending in an sudden form of instruction (something that’s now not an LLVM IR terminator instruction) and triggering https://github.com/llvm/llvm-project/blob/essential/llvm/consist of/llvm/IR/BasicBlock.h#L121
First expose of industry then is to appropriate test if the IR is correct. LLVM has a lunge to attend out appropriate that and we can quiz rustc
to lunge it first by passing -Z test-llvm-ir=yes
(demonstrate we want to change to nightly to make utilize of -Z
flags):
$ RUSTFLAGS="-Z test-llvm-ir=yes" cargo +nightly construct --instance basic --positive aspects usdt-probes
Haha, nope:
Sleek Block in feature '_ZN8dropshot6server24http_request_handle_wrap28_$u7b$$u7b$closure$u7d$$u7d$17h503b14ddd4edd1deE' would now not contain terminator!
price %bb24
LLVM ERROR: Broken module stumbled on, compilation aborted!
# Demangle w/ rustfilt (c++filt works neatly ample too)
# Single quotes essential to now not misread $ as shell vars!
$ rustfilt '_ZN8dropshot6server24http_request_handle_wrap28_$u7b$$u7b$closure$u7d$$u7d$17h503b14ddd4edd1deE'
dropshot::server::http_request_handle_wrap::{{closure}}
The IR generated for a closure in dropshot::server::http_request_handle_wrap
is invalid—some basic block is lacking a terminator.
Okay, is it rustc producing the corrupt IR at once or the consequence of some transformation lunge miscompiling it?
However first, let’s cheat and appropriate glean the final failing rustc
enlighten so we don’t want to rebuild your total deps anytime we commerce RUSTFLAGS
. Re-working the failing cargo
enlighten might perhaps maybe well serene appropriate output the failing rustc
invocation:
$ cargo +nightly construct --instance basic --positive aspects usdt-probes Compiling dropshot v0.6.1-dev (/src/dropshot/dropshot) error: might perhaps maybe well now not assemble `dropshot` Precipitated by: job did now not exit efficiently: `rustc [...snip...]` (trace: 11, SIGSEGV: invalid memory reference)
From this point we can appropriate at once lunge the rustc
enlighten as outputted with a few modifications:
- add
+nightly
otherwise therustc
wrapper will are trying to make utilize of the rust model mentioned inrust-toolchain.toml
- want away the
--error-format=json
and--json=...
flags for human-readable output - add
-Z test-llvm-ir=yes
- commerce the
--emit
argument to--emit=llvm-ir
because that desires to be ample to trigger the tell and we would actually like to ogle at the IR later
Stick this in a easy shell script to without effort adjust it and lunge it; call it repro.sh
. Take a look at it serene fails as expected:
$ ./repro.sh Sleek Block in feature '_ZN8dropshot6server24http_request_handle_wrap28_$u7b$$u7b$closure$u7d$$u7d$17h503b14ddd4edd1deE' would now not contain terminator! price %bb24 LLVM ERROR: Broken module stumbled on, compilation aborted!
Now help to figuring out where this invalid IR is coming from. Even though we’re doing a debug construct, there are serene some LLVM passes that glean lunge. So if we’re attempting to envision the IR that rustc
at once generated, we want to web determined no LLVM passes are lunge at all (other than the test
lunge itself). The technique to attend out that is by ability of -C no-prepopulate-passes
so let’s edit our repro.sh
and lunge all of it another time:
Okay rustc
has been proven harmless. Appears love some LLVM lunge generates invalid IR which in actuality shouldn’t happen!
Effectively, now what? Let’s are trying to discover out what lunge is to blame!
Our first are trying is by asking LLVM to print the IR after each and each lunge—maybe we will glean lucky and anguish the offending lunge final. We provide out this by editing repro.sh
all another time:
- want away
-C no-prepopulate-passes
&-Z test-llvm-ir=yes
- add
-C llvm-args=--print-after-all
to print the IR after each and each lunge - add
-C codegen-fashions=1 -Z no-parallel-llvm
to web the output a chunk of additional readable
Alas, this doesn’t lunge the technique we want as we glean the same segfault as earlier than without any of the explicit output we needed 🙁
Okay, unique are trying. Let’s skip rustc
and anguish if we can appropriate invoke the LLVM machinery at once by ability of decide
. For that, let’s first install it:
$ rustup ingredient add --toolchain nightly llvm-tools-preview
It is miles now not the most discoverable because it appropriate will get plopped someplace into rustc
‘s sysroot directory:
$ OPT=$(discover $(rustc +nightly --print sysroot) -title decide)
We also need the explicit IR to lunge to decide
so let’s return and adjust our repro.sh
to handiest lunge -C no-prepopulate-passes
. We might perhaps maybe well serene discover our preliminary rustc
generated IR. It be also price want away the -C debuginfo=2
to web the IR a chunk of smaller:
$ ls ./goal/debug/examples/basic*.ll ./goal/debug/examples/basic-5f5f0491fbb5b7d3.ll
Let’s are trying something easy first and appropriate lunge the IR by decide
without any flags as a smoke test:
$ $OPT ./goal/debug/examples/basic-5f5f0491fbb5b7d3.ll decide: ./goal/debug/examples/basic-5f5f0491fbb5b7d3.ll: 425470:1: error: expected instruction opcode bb25: ; preds=%bb24 ^
bb24: ; [...snip...] %186=invoke i64 asm sideeffect inteldialect "990: clr rax