Skip to content

Commit ae95005

Browse files
authored
Rollup merge of #77976 - oliviacrain:issue-77915-fix, r=matthewjasper
Mark inout asm! operands as used in liveness pass Variables used in `inout` operands in inline assembly (that is, they're used as both input and output to some arbitrary assembly instruction) are being marked as read and written, but are not marked as being used in the RWU table during the liveness pass. This can result in such expressions triggering an unused variable lint warning. This is incorrect behavior- reads without uses are currently only used for compound assignments. We conservatively assume that an `inout` operand is being read and used in the context of the assembly instruction. Closes #77915
2 parents 813066c + dc29c7a commit ae95005

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

compiler/rustc_passes/src/liveness.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
11741174
}
11751175
}
11761176
hir::InlineAsmOperand::InOut { expr, .. } => {
1177-
succ = self.write_place(expr, succ, ACC_READ | ACC_WRITE);
1177+
succ = self.write_place(expr, succ, ACC_READ | ACC_WRITE | ACC_USE);
11781178
}
11791179
hir::InlineAsmOperand::SplitInOut { out_expr, .. } => {
11801180
if let Some(expr) = out_expr {

src/test/ui/liveness/liveness-asm.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Ensure inout asm! operands are marked as used by the liveness pass
2+
3+
// only-x86_64
4+
// check-pass
5+
6+
#![feature(asm)]
7+
#![allow(dead_code)]
8+
#![warn(unused_assignments)]
9+
#![warn(unused_variables)]
10+
11+
// Test the single inout case
12+
unsafe fn f1(mut src: *const u8) {
13+
asm!("/*{0}*/", inout(reg) src); //~ WARN value assigned to `src` is never read
14+
}
15+
16+
unsafe fn f2(mut src: *const u8) -> *const u8 {
17+
asm!("/*{0}*/", inout(reg) src);
18+
src
19+
}
20+
21+
// Test the split inout case
22+
unsafe fn f3(mut src: *const u8) {
23+
asm!("/*{0}*/", inout(reg) src => src); //~ WARN value assigned to `src` is never read
24+
}
25+
26+
unsafe fn f4(mut src: *const u8) -> *const u8 {
27+
asm!("/*{0}*/", inout(reg) src => src);
28+
src
29+
}
30+
31+
// Tests the use of field projections
32+
struct S {
33+
field: *mut u8,
34+
}
35+
36+
unsafe fn f5(src: &mut S) {
37+
asm!("/*{0}*/", inout(reg) src.field);
38+
}
39+
40+
unsafe fn f6(src: &mut S) {
41+
asm!("/*{0}*/", inout(reg) src.field => src.field);
42+
}
43+
44+
fn main() {}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
warning: value assigned to `src` is never read
2+
--> $DIR/liveness-asm.rs:13:32
3+
|
4+
LL | asm!("/*{0}*/", inout(reg) src);
5+
| ^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/liveness-asm.rs:8:9
9+
|
10+
LL | #![warn(unused_assignments)]
11+
| ^^^^^^^^^^^^^^^^^^
12+
= help: maybe it is overwritten before being read?
13+
14+
warning: value assigned to `src` is never read
15+
--> $DIR/liveness-asm.rs:23:39
16+
|
17+
LL | asm!("/*{0}*/", inout(reg) src => src);
18+
| ^^^
19+
|
20+
= help: maybe it is overwritten before being read?
21+
22+
warning: 2 warnings emitted
23+

0 commit comments

Comments
 (0)