Fix miscompilation of inline assembly with outputs in cases where we emit an inv...
source link: https://github.com/rust-lang/rust/pull/95864
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
We ran into this bug where rustc would segfault while trying to compile certain uses of inline assembly.
Here is a simple repro that demonstrates the issue:
#![feature(asm_unwind)] fn main() { let _x = String::from("string here just cause we need something with a non-trivial drop"); let foo: u64; unsafe { std::arch::asm!( "mov {}, 1", out(reg) foo, options(may_unwind) ); } println!("{}", foo); }
But crucially feature(asm_unwind)
is not actually needed and this can be triggered on stable as a result of the way async functions/generators are handled in the compiler. e.g.:
extern crate futures; // 0.3.21 async fn bar() { let foo: u64; unsafe { std::arch::asm!( "mov {}, 1", out(reg) foo, ); } println!("{}", foo); } fn main() { futures::executor::block_on(bar()); }
An example of the incorrect LLVM generated:
bb1: ; preds = %start %1 = invoke i64 asm sideeffect alignstack inteldialect unwind "mov ${0:q}, 1", "=&r,~{dirflag},~{fpsr},~{flags},~{memory}"() to label %bb2 unwind label %cleanup, !srcloc !9 store i64 %1, i64* %foo, align 8 bb2: [...snip...]
The store should not be placed after the asm invoke but rather should be in the normal control flow basic block (bb2
in this case).
Here is a writeup of the investigation that lead to finding this.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK