Skip to content

Commit 983299f

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#77915
2 parents 154acf0 + 8f0bced commit 983299f

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

compiler/rustc_passes/src/liveness.rs

+1-1
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

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