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

inline-asm immediate constraint with fn argument crashes LLVM #51130

Closed
roblabla opened this issue May 28, 2018 · 15 comments
Closed

inline-asm immediate constraint with fn argument crashes LLVM #51130

roblabla opened this issue May 28, 2018 · 15 comments
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) C-bug Category: This is a bug. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@roblabla
Copy link
Contributor

#![feature(asm)]
fn main() {
    unsafe { asm!("call $0" :: "i"(test) :: "intel"); }
}
extern fn test() {}

For some reason, this crashes rustc. However, the following test compiles properly in some cases:

#![feature(asm)]
fn main() {
    unsafe { asm!("call $0" :: "i"(test as *const u8) :: "intel"); }
}
extern fn test() {}

But, in a real world project, the exact same code I get errors such as error: invalid operand for inline asm constraint 'i' or compile-time segfaults.

@matthewjasper matthewjasper added the A-inline-assembly Area: Inline assembly (`asm!(…)`) label May 28, 2018
@hellow554
Copy link
Contributor

This example causes a segfault in rustc. Because this is very easy to reproduce, I think one can omit to post a full dump here, but nevertheless, here's the backtrace.

#gdb rustc 
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from rustc...done.
(gdb) r main.rs
Starting program: /home/op/.cargo/bin/rustc main.rs
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
process 15579 is executing new program: /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffe85ff700 (LWP 15584)]
[New Thread 0x7fffe7fff700 (LWP 15585)]
[New Thread 0x7fffe79ff700 (LWP 15586)]
[New Thread 0x7fffe77fe700 (LWP 15587)]
[New Thread 0x7fffe71ff700 (LWP 15588)]
[Thread 0x7fffe77fe700 (LWP 15587) exited]
[New Thread 0x7fffe77fe700 (LWP 15589)]
[Thread 0x7fffe79ff700 (LWP 15586) exited]
[New Thread 0x7fffe6bff700 (LWP 15590)]
[New Thread 0x7fffe79ff700 (LWP 15591)]
[Thread 0x7fffe77fe700 (LWP 15589) exited]
[Thread 0x7fffe6bff700 (LWP 15590) exited]
[Thread 0x7fffe71ff700 (LWP 15588) exited]
[New Thread 0x7fffe6bff700 (LWP 15592)]
[Thread 0x7fffe79ff700 (LWP 15591) exited]

Thread 10 "rustc" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe6bff700 (LWP 15592)]
0x00007fffed67f404 in llvm::X86TargetLowering::LowerAsmOperandForConstraint(llvm::SDValue, std::string&, std::vector<llvm::SDValue, std::allocator<llvm::SDValue> >&, llvm::SelectionDAG&) const () from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
(gdb) bt
#0  0x00007fffed67f404 in llvm::X86TargetLowering::LowerAsmOperandForConstraint(llvm::SDValue, std::string&, std::vector<llvm::SDValue, std::allocator<llvm::SDValue> >&, llvm::SelectionDAG&) const () from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#1  0x00007fffee19ea2f in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#2  0x00007fffee182cb8 in llvm::SelectionDAGBuilder::visit(llvm::Instruction const&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#3  0x00007fffee204d40 in llvm::SelectionDAGISel::SelectBasicBlock(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void>, false, true>, llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void>, false, true>, bool&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#4  0x00007fffee203a3e in llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#5  0x00007fffee200f73 in llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#6  0x00007fffed5ded51 in (anonymous namespace)::X86DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#7  0x00007fffee3dc7ca in llvm::MachineFunctionPass::runOnFunction(llvm::Function&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#8  0x00007fffeebc235b in llvm::FPPassManager::runOnFunction(llvm::Function&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#9  0x00007fffeebc25c3 in llvm::FPPassManager::runOnModule(llvm::Module&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#10 0x00007fffeebc29c5 in llvm::legacy::PassManagerImpl::run(llvm::Module&) ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#11 0x00007fffed546e2a in LLVMRustWriteOutputFile ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#12 0x00007fffed431d7a in rustc_codegen_llvm::back::write::write_output_file::hf698d82f9c58fbc6 ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#13 0x00007fffed3eb767 in rustc_codegen_llvm::back::write::codegen::_$u7b$$u7b$closure$u7d$$u7d$::h747b8ab31c2b9bcd ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#14 0x00007fffed3e556a in rustc::util::common::time_ext::h235dac2bffa5e147 ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#15 0x00007fffed434065 in rustc_codegen_llvm::back::write::codegen::h6094f17d63c01077 ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#16 0x00007fffed423a42 in std::sys_common::backtrace::__rust_begin_short_backtrace::h133fe52b0e7d804a ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#17 0x00007fffed449548 in std::panicking::try::do_call::h79f44434ae03a417 ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#18 0x00007ffff768d94a in __rust_maybe_catch_panic () at libpanic_unwind/lib.rs:105
#19 0x00007fffed3e24d1 in _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::h287fbe6d24a16a97 ()
   from /home/op/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#20 0x00007ffff768107b in _$LT$alloc..boxed..Box$LT$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$::call_once::h4d3c38b88e082d2c () at /checkout/src/liballoc/boxed.rs:648
#21 std::sys_common::thread::start_thread::haf82b92357fb7f56 () at libstd/sys_common/thread.rs:24
#22 0x00007ffff764a7f6 in std::sys::unix::thread::Thread::new::thread_start::h184d9993e322d77a () at libstd/sys/unix/thread.rs:90
#23 0x00007ffff18e27fc in start_thread (arg=0x7fffe6bff700) at pthread_create.c:465
#24 0x00007ffff7325b0f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) 

@nikic
Copy link
Contributor

nikic commented May 29, 2018

LLVM assertion failure:

rustc: /home/nikic/rust/src/llvm/include/llvm/Support/Casting.h:92: static bool llvm::isa_impl_cl<To, From*>::doit(const From*) [with To = llvm::ConstantSDNode; From = llvm::SDNode]: Assertion `Val && "isa<> used on a null pointer"' failed.

Assertion backtrace:

#3  0x00007ffff729dc82 in __GI___assert_fail (
    assertion=0x7fffee147b98 "Val && \"isa<> used on a null pointer\"", 
    file=0x7fffee147b58 "/home/nikic/rust/src/llvm/include/llvm/Support/Casting.h", line=92, 
    function=0x7fffee463e00 <llvm::isa_impl_cl<llvm::ConstantSDNode, llvm::SDNode*>::doit(llvm::SDNode const*)::__PRETTY_FUNCTION__> "static bool llvm::isa_impl_cl<To, From*>::doit(const From*) [with To = llvm::ConstantSDNode; From = llvm::SDNode]") at assert.c:101
#4  0x00007fffec3b61a4 in llvm::cast_retty<llvm::ConstantSDNode, llvm::SDValue>::ret_type llvm::dyn_cast<llvm::ConstantSDNode, llvm::SDValue>(llvm::SDValue&) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#5  0x00007fffec44762a in llvm::X86TargetLowering::LowerAsmOperandForConstraint(llvm::SDValue, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::vector<llvm::SDValue, std::allocator<llvm::SDValue> >&, llvm::SelectionDAG&) const ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#6  0x00007fffed237f08 in llvm::SelectionDAGBuilder::visitInlineAsm(llvm::ImmutableCallSite) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#7  0x00007fffed2451d7 in llvm::SelectionDAGBuilder::visitCall(llvm::CallInst const&) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#8  0x00007fffed24c723 in llvm::SelectionDAGBuilder::visit(llvm::Instruction const&) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#9  0x00007fffed28fd69 in llvm::SelectionDAGISel::SelectBasicBlock(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, bool&) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#10 0x00007fffed2956d1 in llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#11 0x00007fffed2973e2 in llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) [clone .part.876] [clone .constprop.902] ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#12 0x00007fffec3c07c4 in (anonymous namespace)::X86DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#13 0x00007fffed510775 in llvm::MachineFunctionPass::runOnFunction(llvm::Function&) ()
   from /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#14 0x00007fffedecc2c3 in llvm::FPPassManager::runOnFunction(llvm::Function&) ()

@nikic
Copy link
Contributor

nikic commented May 29, 2018

LLVM IR:

define void @test() {
  call void asm sideeffect inteldialect "call $0", "i"({} undef)
  ret void
}

Causes assertion failure under llc.

@nikic
Copy link
Contributor

nikic commented May 29, 2018

I've reported this issue upstream: https://bugs.llvm.org/show_bug.cgi?id=37624

However, there is also a rustc issue here in that it shouldn't be generating an undef operand in the first place.

@XAMPPRocky XAMPPRocky added A-codegen Area: Code generation T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. C-bug Category: This is a bug. and removed A-codegen Area: Code generation labels Oct 2, 2018
Rahix added a commit to Rahix/atmega32u4-hal that referenced this issue Oct 9, 2018
When trying to build this crate for non-avr architectures,
the compiler segfaults due to a bug when lowering inline
assembly.  Workaround is to throw another error earlier on
and disable the avr assembly parts on other archs.

Ref rust-lang/rust#51130

Signed-off-by: Rahix <[email protected]>
@nikic
Copy link
Contributor

nikic commented Nov 3, 2018

I've looked a bit closer at what is going on here on the Rust side. The issue seems to be that we're directly using an fn item as an inline asm operand (which is treated as a ZST scalar, yielding an undef), where usually such a use should go through a ReifyFnPointer.

This is because in https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/check/mod.rs#L3946 we do not impose any type restrictions on inline asm input operands. We should be introducing a ReifyFnPointer adjustment somehow here, though I'm not sure how to actually do it (we don't really have an expected type here).

@eddyb
Copy link
Member

eddyb commented Nov 3, 2018

For variadic (FFI) calls, we error saying you should cast:

// There are a few types which get autopromoted when passed via varargs
// in C but we just error out instead and require explicit casts.

We should maybe do something similar about inline asm!.
cc @nagisa @rkruppe @nikomatsakis

@hanna-kruppe
Copy link
Contributor

We should validate lots and lots of things about the values passed to inline asm, and we currently don't do any of them. That's no reason to not fix it, but it will be a drop in the bucket.

@mark-i-m
Copy link
Member

mark-i-m commented Nov 3, 2018

Would it be possible to produce such a list and make a tracking issue for it?

@nikic
Copy link
Contributor

nikic commented Nov 3, 2018

This particular issue seems to be somewhat common. #36907 is another instance.

@levex
Copy link
Contributor

levex commented Nov 4, 2018

@mark-i-m I’ve been writing such a list (and fixing some of them) for a while now, so I guess I can make a tracking issue sometime soon.

That said, we are eventually gonna get rid of the current semantics in favor of something new. There’s already a Pre-RFC on internals, and I’d hope that we could soon write the actual RFC.

@Centril Centril added the requires-nightly This issue requires a nightly compiler in some way. label Oct 25, 2019
@steveklabnik
Copy link
Member

Triage: there hasn't really been any direct changes here, but there has been movement towards entirely re-doing inline assembly; with the current implementation moving to llvm_asm and a brand new inline asm design/implementation.

@roblabla
Copy link
Contributor Author

roblabla commented Mar 5, 2020

The equivalent version in the new asm syntax (as implemented by #69171) is:

#![feature(asm)]
fn main() {
    unsafe { asm!("call {}", sym test); }
}
extern fn test() {}

@Amanieu
Copy link
Member

Amanieu commented May 22, 2020

This issue does not apply to the new asm! (RFC 2850).

The legacy llvm_asm! is deprecated and is no longer maintained.

@Amanieu Amanieu closed this as completed May 22, 2020
@roblabla
Copy link
Contributor Author

@Amanieu The obvious equivalent in the new asm,

#![feature(asm)]
fn main() {
    unsafe { asm!("call {}", sym test); }
}
extern fn test() {}

Fails with a linking error. See https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=4c66087def8876f1661239ca3b06c976 . Should I open a new issue?

@Amanieu
Copy link
Member

Amanieu commented May 23, 2020

Yes, please open a new issue for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) C-bug Category: This is a bug. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. requires-nightly This issue requires a nightly compiler in some way. 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