From 6696649c47fd4d4d225f64b4c2db5d96c4eae400 Mon Sep 17 00:00:00 2001 From: Cathal Mullan Date: Mon, 2 Mar 2026 17:41:57 +0000 Subject: [PATCH] x86: reserve `bl` and `bh` registers to match `rbx` --- compiler/rustc_target/src/asm/mod.rs | 6 +- compiler/rustc_target/src/asm/x86.rs | 4 +- .../x86_64/bad-reg.experimental_reg.stderr | 56 +++++++++------ tests/ui/asm/x86_64/bad-reg.rs | 4 ++ tests/ui/asm/x86_64/bad-reg.stable.stderr | 68 +++++++++++-------- 5 files changed, 83 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 0012e85e8a593..27dd0b764f3b2 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -67,7 +67,7 @@ macro_rules! def_reg_class { macro_rules! def_regs { ($arch:ident $arch_reg:ident $arch_regclass:ident { $( - $reg:ident: $class:ident $(, $extra_class:ident)* = [$reg_name:literal $(, $alias:literal)*] $(% $filter:ident)?, + $reg:ident: $class:ident $(, $extra_class:ident)* = [$reg_name:literal $(, $alias:literal)*] $(% $filter:ident)*, )* $( #error = [$($bad_reg:literal),+] => $error:literal, @@ -121,7 +121,7 @@ macro_rules! def_regs { _target_features, _target, _is_clobber - )?;)? + )?;)* Ok(()) } )* @@ -142,7 +142,7 @@ macro_rules! def_regs { #[allow(unused_imports)] use super::{InlineAsmReg, InlineAsmRegClass}; $( - if $($filter(_arch, _reloc_model, _target_features, _target, false).is_ok() &&)? true { + if $($filter(_arch, _reloc_model, _target_features, _target, false).is_ok() &&)* true { if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) { set.insert(InlineAsmReg::$arch($arch_reg::$reg)); } diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 03e7fd5969608..6f0faffa32984 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -250,8 +250,8 @@ def_regs! { r15: reg = ["r15", "r15w", "r15d"] % x86_64_only, al: reg_byte = ["al"], ah: reg_byte = ["ah"] % high_byte, - bl: reg_byte = ["bl"], - bh: reg_byte = ["bh"] % high_byte, + bl: reg_byte = ["bl"] % rbx_reserved, + bh: reg_byte = ["bh"] % rbx_reserved % high_byte, cl: reg_byte = ["cl"], ch: reg_byte = ["ch"] % high_byte, dl: reg_byte = ["dl"], diff --git a/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr b/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr index 7c9b211337694..133921b894dd0 100644 --- a/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr +++ b/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr @@ -67,49 +67,49 @@ LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:39:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: register class `kreg0` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:45:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:50:20 + --> $DIR/bad-reg.rs:54:20 | LL | asm!("{}", in(x87_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:53:20 + --> $DIR/bad-reg.rs:57:20 | LL | asm!("{}", in(mmx_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:56:20 + --> $DIR/bad-reg.rs:60:20 | LL | asm!("{}", out(x87_reg) _); | ^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:58:20 + --> $DIR/bad-reg.rs:62:20 | LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `eax` - --> $DIR/bad-reg.rs:64:33 + --> $DIR/bad-reg.rs:68:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -117,7 +117,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `eax` error: register `rax` conflicts with register `rax` - --> $DIR/bad-reg.rs:67:33 + --> $DIR/bad-reg.rs:71:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `rax` @@ -125,13 +125,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `rax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:67:18 + --> $DIR/bad-reg.rs:71:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:72:34 + --> $DIR/bad-reg.rs:76:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -139,7 +139,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:74:34 + --> $DIR/bad-reg.rs:78:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -147,13 +147,25 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:74:18 + --> $DIR/bad-reg.rs:78:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ +error: cannot use register `bl`: rbx is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", in("bl") foo); + | ^^^^^^^^^^^^ + +error: cannot use register `bh`: rbx is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", in("bh") foo); + | ^^^^^^^^^^^^ + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:39:30 + --> $DIR/bad-reg.rs:43:30 | LL | asm!("", in("st(2)") foo); | ^^^ @@ -161,7 +173,7 @@ LL | asm!("", in("st(2)") foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:42:28 + --> $DIR/bad-reg.rs:46:28 | LL | asm!("", in("mm0") foo); | ^^^ @@ -169,7 +181,7 @@ LL | asm!("", in("mm0") foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:45:27 + --> $DIR/bad-reg.rs:49:27 | LL | asm!("", in("k0") foo); | ^^^ @@ -177,7 +189,7 @@ LL | asm!("", in("k0") foo); = note: register class `kreg0` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:50:32 + --> $DIR/bad-reg.rs:54:32 | LL | asm!("{}", in(x87_reg) foo); | ^^^ @@ -185,7 +197,7 @@ LL | asm!("{}", in(x87_reg) foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:53:32 + --> $DIR/bad-reg.rs:57:32 | LL | asm!("{}", in(mmx_reg) foo); | ^^^ @@ -193,7 +205,7 @@ LL | asm!("{}", in(mmx_reg) foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:64:42 + --> $DIR/bad-reg.rs:68:42 | LL | asm!("", in("eax") foo, in("al") bar); | ^^^ @@ -201,7 +213,7 @@ LL | asm!("", in("eax") foo, in("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:27 + --> $DIR/bad-reg.rs:73:27 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ @@ -209,12 +221,12 @@ LL | asm!("", in("al") foo, lateout("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:46 + --> $DIR/bad-reg.rs:73:46 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ | = note: register class `reg_byte` supports these types: i8 -error: aborting due to 28 previous errors +error: aborting due to 30 previous errors diff --git a/tests/ui/asm/x86_64/bad-reg.rs b/tests/ui/asm/x86_64/bad-reg.rs index 994dcfd77ccde..4b3005d5675b3 100644 --- a/tests/ui/asm/x86_64/bad-reg.rs +++ b/tests/ui/asm/x86_64/bad-reg.rs @@ -35,6 +35,10 @@ fn main() { //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand asm!("", in("ip") foo); //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand + asm!("", in("bl") foo); + //~^ ERROR cannot use register `bl`: rbx is used internally by LLVM and cannot be used as an operand for inline asm + asm!("", in("bh") foo); + //~^ ERROR cannot use register `bh`: rbx is used internally by LLVM and cannot be used as an operand for inline asm asm!("", in("st(2)") foo); //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output diff --git a/tests/ui/asm/x86_64/bad-reg.stable.stderr b/tests/ui/asm/x86_64/bad-reg.stable.stderr index 2b5c453d70c63..a1c2792a5b1fc 100644 --- a/tests/ui/asm/x86_64/bad-reg.stable.stderr +++ b/tests/ui/asm/x86_64/bad-reg.stable.stderr @@ -67,49 +67,49 @@ LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:39:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: register class `kreg0` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:45:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:50:20 + --> $DIR/bad-reg.rs:54:20 | LL | asm!("{}", in(x87_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:53:20 + --> $DIR/bad-reg.rs:57:20 | LL | asm!("{}", in(mmx_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:56:20 + --> $DIR/bad-reg.rs:60:20 | LL | asm!("{}", out(x87_reg) _); | ^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:58:20 + --> $DIR/bad-reg.rs:62:20 | LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `eax` - --> $DIR/bad-reg.rs:64:33 + --> $DIR/bad-reg.rs:68:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -117,7 +117,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `eax` error: register `rax` conflicts with register `rax` - --> $DIR/bad-reg.rs:67:33 + --> $DIR/bad-reg.rs:71:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `rax` @@ -125,13 +125,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `rax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:67:18 + --> $DIR/bad-reg.rs:71:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:72:34 + --> $DIR/bad-reg.rs:76:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -139,7 +139,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:74:34 + --> $DIR/bad-reg.rs:78:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -147,13 +147,25 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:74:18 + --> $DIR/bad-reg.rs:78:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ +error: cannot use register `bl`: rbx is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", in("bl") foo); + | ^^^^^^^^^^^^ + +error: cannot use register `bh`: rbx is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", in("bh") foo); + | ^^^^^^^^^^^^ + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:39:30 + --> $DIR/bad-reg.rs:43:30 | LL | asm!("", in("st(2)") foo); | ^^^ @@ -161,7 +173,7 @@ LL | asm!("", in("st(2)") foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:42:28 + --> $DIR/bad-reg.rs:46:28 | LL | asm!("", in("mm0") foo); | ^^^ @@ -169,7 +181,7 @@ LL | asm!("", in("mm0") foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:45:27 + --> $DIR/bad-reg.rs:49:27 | LL | asm!("", in("k0") foo); | ^^^ @@ -177,7 +189,7 @@ LL | asm!("", in("k0") foo); = note: register class `kreg0` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:50:32 + --> $DIR/bad-reg.rs:54:32 | LL | asm!("{}", in(x87_reg) foo); | ^^^ @@ -185,7 +197,7 @@ LL | asm!("{}", in(x87_reg) foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:53:32 + --> $DIR/bad-reg.rs:57:32 | LL | asm!("{}", in(mmx_reg) foo); | ^^^ @@ -193,7 +205,7 @@ LL | asm!("{}", in(mmx_reg) foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:64:42 + --> $DIR/bad-reg.rs:68:42 | LL | asm!("", in("eax") foo, in("al") bar); | ^^^ @@ -201,7 +213,7 @@ LL | asm!("", in("eax") foo, in("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:27 + --> $DIR/bad-reg.rs:73:27 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ @@ -209,7 +221,7 @@ LL | asm!("", in("al") foo, lateout("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:46 + --> $DIR/bad-reg.rs:73:46 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ @@ -217,7 +229,7 @@ LL | asm!("", in("al") foo, lateout("al") bar); = note: register class `reg_byte` supports these types: i8 error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:81:40 + --> $DIR/bad-reg.rs:85:40 | LL | asm!("/* {:x} */", in(xmm_reg) xmmword); // requires asm_experimental_reg | ^^^^^^^ @@ -227,7 +239,7 @@ LL | asm!("/* {:x} */", in(xmm_reg) xmmword); // requires asm_experiment = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:83:41 + --> $DIR/bad-reg.rs:87:41 | LL | asm!("/* {:x} */", out(xmm_reg) xmmword); // requires asm_experimental_reg | ^^^^^^^ @@ -237,7 +249,7 @@ LL | asm!("/* {:x} */", out(xmm_reg) xmmword); // requires asm_experimen = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:86:40 + --> $DIR/bad-reg.rs:90:40 | LL | asm!("/* {:y} */", in(ymm_reg) xmmword); // requires asm_experimental_reg | ^^^^^^^ @@ -247,7 +259,7 @@ LL | asm!("/* {:y} */", in(ymm_reg) xmmword); // requires asm_experiment = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:88:41 + --> $DIR/bad-reg.rs:92:41 | LL | asm!("/* {:y} */", out(ymm_reg) xmmword); // requires asm_experimental_reg | ^^^^^^^ @@ -257,7 +269,7 @@ LL | asm!("/* {:y} */", out(ymm_reg) xmmword); // requires asm_experimen = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:91:40 + --> $DIR/bad-reg.rs:95:40 | LL | asm!("/* {:z} */", in(zmm_reg) xmmword); // requires asm_experimental_reg | ^^^^^^^ @@ -267,7 +279,7 @@ LL | asm!("/* {:z} */", in(zmm_reg) xmmword); // requires asm_experiment = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:93:41 + --> $DIR/bad-reg.rs:97:41 | LL | asm!("/* {:z} */", out(zmm_reg) xmmword); // requires asm_experimental_reg | ^^^^^^^ @@ -276,6 +288,6 @@ LL | asm!("/* {:z} */", out(zmm_reg) xmmword); // requires asm_experimen = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 34 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0658`.