Description
Consider the following code:
use std::arch::asm;
#[inline(never)]
pub fn my_test(a: u32, b: u32, c: u32, d: u32) -> u32 {
let mut g = 3;
unsafe {
asm!(
"mov {a}, {b}",
"xor {a}, {c}",
"and {a}, {d}",
"or {a}, {e}",
"not {f}",
"add {a}, {f}",
"sub {a}, {g}",
"mov {g}, {a}",
a = in(reg) a,
b = in(reg) b,
c = in(reg) c,
d = in(reg) d,
e = out(reg) _,
f = out(reg) _,
g = inout(reg) g
)
}
g
}
which uses 7 registers. If we try to compile this on i686-pc-windows-msvc
, in principle there are 7 general registers, but Rust Reference mentions that ebp
and esi
would be reserved, so I expect a compilation error.
We can put this in a lib.rs
, and in main.rs
we put:
use asm_test::my_test;
fn main() {
println!("{}", my_test(1, 2, 3, 4));
}
Instead, when compiling in release mode using cargo build --release --target i686-pc-windows-msvc
, it compiles. cargo asm --lib --target i686-pc-windows-msvc
reveals that the compiler does allocate esi
and ebp
.
cargo asm output
.section .text,"xr",one_only,asm_test::my_test
.globl asm_test::my_test
.p2align 4, 0x90
asm_test::my_test:
Lfunc_begin0:
.cv_func_id 0
.cv_file 1 "R:\\asm-test\\src\\lib.rs" "D7E84472A8BA4CD0C091D8930D59F9C5C684E1A6" 2
.cv_loc 0 1 3 0
.cv_fpo_proc asm_test::my_test 16
push ebp
.cv_fpo_pushreg ebp
push ebx
.cv_fpo_pushreg ebx
push edi
.cv_fpo_pushreg edi
push esi
.cv_fpo_pushreg esi
.cv_fpo_endprologue
mov ecx, dword ptr [esp + 20]
mov edx, dword ptr [esp + 24]
mov esi, dword ptr [esp + 28]
mov edi, dword ptr [esp + 32]
mov eax, 3
.cv_loc 0 1 6 0
#APP
mov ecx, edx
xor ecx, esi
and ecx, edi
or ecx, ebx
not ebp
add ecx, ebp
sub ecx, eax
mov eax, ecx
#NO_APP
.cv_loc 0 1 26 0
pop esi
pop edi
pop ebx
pop ebp
ret
.cv_fpo_endproc
However, if we change #[inline(never)]
to #[inline]
, the compiler correctly displays:
error: inline assembly requires more registers than available
I would expect a compilation error in both cases, and a guarantee that neither esi
nor ebp
gets allocated.
I haven't tried on x86_64
target yet simply because the number of general registers is a lot. I could try it later today.
Meta
Tried on both stable and nightly
rustc --version --verbose
:
rustc 1.66.1 (90743e729 2023-01-10)
binary: rustc
commit-hash: 90743e7298aca107ddaa0c202a4d3604e29bfeb6
commit-date: 2023-01-10
host: i686-pc-windows-msvc
release: 1.66.1
LLVM version: 15.0.2
rustc 1.68.0-nightly (1e4f90061 2023-01-11)
binary: rustc
commit-hash: 1e4f90061cc4bc566f99ab21b1f101182b10cf0c
commit-date: 2023-01-11
host: i686-pc-windows-msvc
release: 1.68.0-nightly
LLVM version: 15.0.6
No backtrace available.