diff options
| author | Amanieu d'Antras <amanieu@gmail.com> | 2020-04-29 00:45:58 +0100 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2020-05-18 14:41:32 +0100 |
| commit | 7dfa486d4a18b7a6e514e589771f52c43eff4f3b (patch) | |
| tree | 6e9ac7f1c742cc946353074a940341798f47e681 | |
| parent | 93e2946d0c0cccd69ee03390adca7ec4f71a2113 (diff) | |
| download | rust-7dfa486d4a18b7a6e514e589771f52c43eff4f3b.tar.gz rust-7dfa486d4a18b7a6e514e589771f52c43eff4f3b.zip | |
Add support for high byte registers on x86
| -rw-r--r-- | src/librustc_codegen_llvm/asm.rs | 3 | ||||
| -rw-r--r-- | src/librustc_passes/intrinsicck.rs | 24 | ||||
| -rw-r--r-- | src/librustc_target/asm/aarch64.rs | 18 | ||||
| -rw-r--r-- | src/librustc_target/asm/arm.rs | 6 | ||||
| -rw-r--r-- | src/librustc_target/asm/mod.rs | 17 | ||||
| -rw-r--r-- | src/librustc_target/asm/riscv.rs | 6 | ||||
| -rw-r--r-- | src/librustc_target/asm/x86.rs | 141 | ||||
| -rw-r--r-- | src/test/assembly/asm/x86-types.rs | 20 | ||||
| -rw-r--r-- | src/test/ui/asm/bad-reg.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/asm/bad-reg.stderr | 36 | ||||
| -rw-r--r-- | src/test/ui/asm/type-check-3.rs | 15 | ||||
| -rw-r--r-- | src/test/ui/asm/type-check-3.stderr | 31 |
12 files changed, 198 insertions, 123 deletions
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 21322511c99..20abfbcf405 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -409,6 +409,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass) -> String { InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q", + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "r", InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", @@ -459,6 +460,7 @@ fn modifier_to_llvm( Some('r') => Some('q'), _ => unreachable!(), }, + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => None, InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::xmm_reg) | InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::ymm_reg) | InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::zmm_reg) => match (reg, modifier) { @@ -499,6 +501,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(), InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index b98ed99d04e..9e144f86cd8 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -268,6 +268,12 @@ impl ExprVisitor<'tcx> { reg_class.name(), supported_tys.join(", "), )); + if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) { + err.help(&format!( + "consider using the `{}` register class instead", + suggest.name() + )); + } err.emit(); return Some(asm_ty); } @@ -298,7 +304,7 @@ impl ExprVisitor<'tcx> { } // Check whether a modifier is suggested for using this type. - if let Some((suggested_modifier, suggested_result, switch_reg_class)) = + if let Some((suggested_modifier, suggested_result)) = reg_class.suggest_modifier(asm_arch, asm_ty) { // Search for any use of this operand without a modifier and emit @@ -323,18 +329,10 @@ impl ExprVisitor<'tcx> { let msg = "formatting may not be suitable for sub-register argument"; let mut err = lint.build(msg); err.span_label(expr.span, "for this argument"); - if let Some(switch_reg_class) = switch_reg_class { - err.help(&format!( - "use the `{}` modifier with the `{}` register class \ - to have the register formatted as `{}`", - suggested_modifier, switch_reg_class, suggested_result, - )); - } else { - err.help(&format!( - "use the `{}` modifier to have the register formatted as `{}`", - suggested_modifier, suggested_result, - )); - } + err.help(&format!( + "use the `{}` modifier to have the register formatted as `{}`", + suggested_modifier, suggested_result, + )); err.help(&format!( "or use the `{}` modifier to keep the default formatting of `{}`", default_modifier, default_result, diff --git a/src/librustc_target/asm/aarch64.rs b/src/librustc_target/asm/aarch64.rs index 16bc5d670d8..e7c9edea765 100644 --- a/src/librustc_target/asm/aarch64.rs +++ b/src/librustc_target/asm/aarch64.rs @@ -18,22 +18,26 @@ impl AArch64InlineAsmRegClass { } } + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { + None + } + pub fn suggest_modifier( self, _arch: InlineAsmArch, ty: InlineAsmType, - ) -> Option<(char, &'static str, Option<&'static str>)> { + ) -> Option<(char, &'static str)> { match self { Self::reg => match ty.size().bits() { 64 => None, - _ => Some(('w', "w0", None)), + _ => Some(('w', "w0")), }, Self::vreg | Self::vreg_low16 => match ty.size().bits() { - 8 => Some(('b', "b0", None)), - 16 => Some(('h', "h0", None)), - 32 => Some(('s', "s0", None)), - 64 => Some(('d', "d0", None)), - 128 => Some(('q', "q0", None)), + 8 => Some(('b', "b0")), + 16 => Some(('h', "h0")), + 32 => Some(('s', "s0")), + 64 => Some(('d', "d0")), + 128 => Some(('q', "q0")), _ => None, }, } diff --git a/src/librustc_target/asm/arm.rs b/src/librustc_target/asm/arm.rs index 0ceb15e297f..1798b2a0949 100644 --- a/src/librustc_target/asm/arm.rs +++ b/src/librustc_target/asm/arm.rs @@ -25,11 +25,15 @@ impl ArmInlineAsmRegClass { } } + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { + None + } + pub fn suggest_modifier( self, _arch: InlineAsmArch, _ty: InlineAsmType, - ) -> Option<(char, &'static str, Option<&'static str>)> { + ) -> Option<(char, &'static str)> { None } diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs index dda6e7cd5cd..f1e8457cacc 100644 --- a/src/librustc_target/asm/mod.rs +++ b/src/librustc_target/asm/mod.rs @@ -291,9 +291,20 @@ impl InlineAsmRegClass { } } + /// Returns a suggested register class to use for this type. This is called + /// after type checking via `supported_types` fails to give a better error + /// message to the user. + pub fn suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Self> { + match self { + Self::X86(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::X86), + Self::Arm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Arm), + Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64), + Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV), + } + } + /// Returns a suggested template modifier to use for this type and an - /// example of a register named formatted with it. Optionally also returns - /// the name of a different register class to use instead. + /// example of a register named formatted with it. /// /// Such suggestions are useful if a type smaller than the full register /// size is used and a modifier can be used to point to the subregister of @@ -302,7 +313,7 @@ impl InlineAsmRegClass { self, arch: InlineAsmArch, ty: InlineAsmType, - ) -> Option<(char, &'static str, Option<&'static str>)> { + ) -> Option<(char, &'static str)> { match self { Self::X86(r) => r.suggest_modifier(arch, ty), Self::Arm(r) => r.suggest_modifier(arch, ty), diff --git a/src/librustc_target/asm/riscv.rs b/src/librustc_target/asm/riscv.rs index f9b132c2087..7da30cc8875 100644 --- a/src/librustc_target/asm/riscv.rs +++ b/src/librustc_target/asm/riscv.rs @@ -14,11 +14,15 @@ impl RiscVInlineAsmRegClass { &[] } + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { + None + } + pub fn suggest_modifier( self, _arch: InlineAsmArch, _ty: InlineAsmType, - ) -> Option<(char, &'static str, Option<&'static str>)> { + ) -> Option<(char, &'static str)> { None } diff --git a/src/librustc_target/asm/x86.rs b/src/librustc_target/asm/x86.rs index d10bcb40ba0..6eb99b0180f 100644 --- a/src/librustc_target/asm/x86.rs +++ b/src/librustc_target/asm/x86.rs @@ -6,6 +6,7 @@ def_reg_class! { X86 X86InlineAsmRegClass { reg, reg_abcd, + reg_byte, xmm_reg, ymm_reg, zmm_reg, @@ -30,46 +31,45 @@ impl X86InlineAsmRegClass { &['l', 'h', 'x', 'e'] } } + Self::reg_byte => &[], Self::xmm_reg | Self::ymm_reg | Self::zmm_reg => &['x', 'y', 'z'], Self::kreg => &[], } } + pub fn suggest_class(self, _arch: InlineAsmArch, ty: InlineAsmType) -> Option<Self> { + match self { + Self::reg | Self::reg_abcd if ty.size().bits() == 8 => Some(Self::reg_byte), + _ => None, + } + } + pub fn suggest_modifier( self, arch: InlineAsmArch, ty: InlineAsmType, - ) -> Option<(char, &'static str, Option<&'static str>)> { + ) -> Option<(char, &'static str)> { match self { Self::reg => match ty.size().bits() { - 8 => { - if arch == InlineAsmArch::X86_64 { - Some(('l', "al", None)) - } else { - // Low byte registers require reg_abcd on x86 so we emit - // a suggestion to use that register class instead. - Some(('l', "al", Some("reg_abcd"))) - } - } - 16 => Some(('x', "ax", None)), - 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", None)), + 16 => Some(('x', "ax")), + 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax")), _ => None, }, Self::reg_abcd => match ty.size().bits() { - 8 => Some(('l', "al", None)), - 16 => Some(('x', "ax", None)), - 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", None)), + 16 => Some(('x', "ax")), + 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax")), _ => None, }, + Self::reg_byte => None, Self::xmm_reg => None, Self::ymm_reg => match ty.size().bits() { 256 => None, - _ => Some(('x', "xmm0", None)), + _ => Some(('x', "xmm0")), }, Self::zmm_reg => match ty.size().bits() { 512 => None, - 256 => Some(('y', "ymm0", None)), - _ => Some(('x', "xmm0", None)), + 256 => Some(('y', "ymm0")), + _ => Some(('x', "xmm0")), }, Self::kreg => None, } @@ -84,6 +84,7 @@ impl X86InlineAsmRegClass { Some(('e', "eax")) } } + Self::reg_byte => None, Self::xmm_reg => Some(('x', "xmm0")), Self::ymm_reg => Some(('y', "ymm0")), Self::zmm_reg => Some(('z', "zmm0")), @@ -98,11 +99,12 @@ impl X86InlineAsmRegClass { match self { Self::reg | Self::reg_abcd => { if arch == InlineAsmArch::X86_64 { - types! { _: I8, I16, I32, I64, F32, F64; } + types! { _: I16, I32, I64, F32, F64; } } else { - types! { _: I8, I16, I32, F32; } + types! { _: I16, I32, F32; } } } + Self::reg_byte => types! { _: I8; }, Self::xmm_reg => types! { "sse": I32, I64, F32, F64, VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); @@ -139,20 +141,38 @@ fn x86_64_only( def_regs! { X86 X86InlineAsmReg X86InlineAsmRegClass { - ax: reg, reg_abcd = ["ax", "al", "eax", "rax"], - bx: reg, reg_abcd = ["bx", "bl", "ebx", "rbx"], - cx: reg, reg_abcd = ["cx", "cl", "ecx", "rcx"], - dx: reg, reg_abcd = ["dx", "dl", "edx", "rdx"], - si: reg = ["si", "sil", "esi", "rsi"], - di: reg = ["di", "dil", "edi", "rdi"], - r8: reg = ["r8", "r8b", "r8w", "r8d"] % x86_64_only, - r9: reg = ["r9", "r9b", "r9w", "r9d"] % x86_64_only, - r10: reg = ["r10", "r10b", "r10w", "r10d"] % x86_64_only, - r11: reg = ["r11", "r11b", "r11w", "r11d"] % x86_64_only, - r12: reg = ["r12", "r12b", "r12w", "r12d"] % x86_64_only, - r13: reg = ["r13", "r13b", "r13w", "r13d"] % x86_64_only, - r14: reg = ["r14", "r14b", "r14w", "r14d"] % x86_64_only, - r15: reg = ["r15", "r15b", "r15w", "r15d"] % x86_64_only, + ax: reg, reg_abcd = ["ax", "eax", "rax"], + bx: reg, reg_abcd = ["bx", "ebx", "rbx"], + cx: reg, reg_abcd = ["cx", "ecx", "rcx"], + dx: reg, reg_abcd = ["dx", "edx", "rdx"], + si: reg = ["si", "esi", "rsi"], + di: reg = ["di", "edi", "rdi"], + r8: reg = ["r8", "r8w", "r8d"] % x86_64_only, + r9: reg = ["r9", "r9w", "r9d"] % x86_64_only, + r10: reg = ["r10", "r10w", "r10d"] % x86_64_only, + r11: reg = ["r11", "r11w", "r11d"] % x86_64_only, + r12: reg = ["r12", "r12w", "r12d"] % x86_64_only, + r13: reg = ["r13", "r13w", "r13d"] % x86_64_only, + r14: reg = ["r14", "r14w", "r14d"] % x86_64_only, + r15: reg = ["r15", "r15w", "r15d"] % x86_64_only, + al: reg_byte = ["al"], + ah: reg_byte = ["ah"], + bl: reg_byte = ["bl"], + bh: reg_byte = ["bh"], + cl: reg_byte = ["cl"], + ch: reg_byte = ["ch"], + dl: reg_byte = ["dl"], + dh: reg_byte = ["dh"], + sil: reg_byte = ["sil"] % x86_64_only, + dil: reg_byte = ["dil"] % x86_64_only, + r8b: reg_byte = ["r8b"] % x86_64_only, + r9b: reg_byte = ["r9b"] % x86_64_only, + r10b: reg_byte = ["r10b"] % x86_64_only, + r11b: reg_byte = ["r11b"] % x86_64_only, + r12b: reg_byte = ["r12b"] % x86_64_only, + r13b: reg_byte = ["r13b"] % x86_64_only, + r14b: reg_byte = ["r14b"] % x86_64_only, + r15b: reg_byte = ["r15b"] % x86_64_only, xmm0: xmm_reg = ["xmm0"], xmm1: xmm_reg = ["xmm1"], xmm2: xmm_reg = ["xmm2"], @@ -224,8 +244,6 @@ def_regs! { k5: kreg = ["k5"], k6: kreg = ["k6"], k7: kreg = ["k7"], - #error = ["ah", "bh", "ch", "dh"] => - "high byte registers are not currently supported as operands for inline asm", #error = ["bp", "bpl", "ebp", "rbp"] => "the frame pointer cannot be used as an operand for inline asm", #error = ["sp", "spl", "esp", "rsp"] => @@ -281,6 +299,8 @@ impl X86InlineAsmReg { 'r' => write!(out, "r{}", index), _ => unreachable!(), } + } else if self as u32 <= Self::r15b as u32 { + out.write_str(self.name()) } else if self as u32 <= Self::xmm15 as u32 { let prefix = modifier.unwrap_or('x'); let index = self as u32 - Self::xmm0 as u32; @@ -301,9 +321,40 @@ impl X86InlineAsmReg { pub fn overlapping_regs(self, mut cb: impl FnMut(X86InlineAsmReg)) { macro_rules! reg_conflicts { - ($($x:ident : $y:ident : $z:ident,)*) => { + ( + $( + $w:ident : $l:ident $h:ident + ),*; + $( + $w2:ident : $l2:ident + ),*; + $( + $x:ident : $y:ident : $z:ident + ),*; + ) => { match self { $( + Self::$w => { + cb(Self::$w); + cb(Self::$l); + cb(Self::$h); + } + Self::$l => { + cb(Self::$w); + cb(Self::$l); + } + Self::$h => { + cb(Self::$w); + cb(Self::$h); + } + )* + $( + Self::$w2 | Self::$l2 => { + cb(Self::$w2); + cb(Self::$l2); + } + )* + $( Self::$x | Self::$y | Self::$z => { cb(Self::$x); cb(Self::$y); @@ -324,6 +375,20 @@ impl X86InlineAsmReg { // registers are only available with AVX-512, so we just specify them // as aliases directly. reg_conflicts! { + ax : al ah, + bx : bl bh, + cx : cl ch, + dx : dl dh; + si : sil, + di : dil, + r8 : r8b, + r9 : r9b, + r10 : r10b, + r11 : r11b, + r12 : r12b, + r13 : r13b, + r14 : r14b, + r15 : r15b; xmm0 : ymm0 : zmm0, xmm1 : ymm1 : zmm1, xmm2 : ymm2 : zmm2, @@ -339,7 +404,7 @@ impl X86InlineAsmReg { xmm12 : ymm12 : zmm12, xmm13 : ymm13 : zmm13, xmm14 : ymm14 : zmm14, - xmm15 : ymm15 : zmm15, + xmm15 : ymm15 : zmm15; } } } diff --git a/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs index d2819ac88e7..508d6801580 100644 --- a/src/test/assembly/asm/x86-types.rs +++ b/src/test/assembly/asm/x86-types.rs @@ -266,13 +266,6 @@ macro_rules! check { }; } -// CHECK-LABEL: reg_i8: -// CHECK: #APP -// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} -// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}} -// CHECK: #NO_APP -check!(reg_i8 i8 reg "mov"); - // CHECK-LABEL: reg_i16: // CHECK: #APP // x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} @@ -315,13 +308,6 @@ check!(reg_f64 f64 reg "mov"); // CHECK: #NO_APP check!(reg_ptr ptr reg "mov"); -// CHECK-LABEL: reg_abcd_i8: -// CHECK: #APP -// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} -// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}} -// CHECK: #NO_APP -check!(reg_abcd_i8 i8 reg_abcd "mov"); - // CHECK-LABEL: reg_abcd_i16: // CHECK: #APP // x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} @@ -364,6 +350,12 @@ check!(reg_abcd_f64 f64 reg_abcd "mov"); // CHECK: #NO_APP check!(reg_abcd_ptr ptr reg_abcd "mov"); +// CHECK-LABEL: reg_byte: +// CHECK: #APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_byte i8 reg_byte "mov"); + // CHECK-LABEL: xmm_reg_i32: // CHECK: #APP // CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} diff --git a/src/test/ui/asm/bad-reg.rs b/src/test/ui/asm/bad-reg.rs index ed7faa4b156..016ea9329c4 100644 --- a/src/test/ui/asm/bad-reg.rs +++ b/src/test/ui/asm/bad-reg.rs @@ -25,8 +25,6 @@ fn main() { //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature asm!("", in("zmm0") foo); //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature - asm!("", in("ah") foo); - //~^ ERROR invalid register `ah`: high byte registers are not currently supported asm!("", in("ebp") foo); //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand asm!("", in("rsp") foo); @@ -44,7 +42,7 @@ fn main() { // (except in/lateout which don't conflict) asm!("", in("eax") foo, in("al") bar); - //~^ ERROR register `ax` conflicts with register `ax` + //~^ ERROR register `al` conflicts with register `ax` asm!("", in("rax") foo, out("rax") bar); //~^ ERROR register `ax` conflicts with register `ax` asm!("", in("al") foo, lateout("al") bar); diff --git a/src/test/ui/asm/bad-reg.stderr b/src/test/ui/asm/bad-reg.stderr index a9d872dae41..a1423f0e9c1 100644 --- a/src/test/ui/asm/bad-reg.stderr +++ b/src/test/ui/asm/bad-reg.stderr @@ -58,58 +58,52 @@ error: register class `zmm_reg` requires the `avx512f` target feature LL | asm!("", in("zmm0") foo); | ^^^^^^^^^^^^^^ -error: invalid register `ah`: high byte registers are not currently supported as operands for inline asm - --> $DIR/bad-reg.rs:28:18 - | -LL | asm!("", in("ah") foo); - | ^^^^^^^^^^^^ - error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", in("ebp") foo); | ^^^^^^^^^^^^^ error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", in("rsp") foo); | ^^^^^^^^^^^^^ error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: invalid register `st(2)`: x87 registers are not currently supported as operands for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: invalid register `mm0`: MMX registers are not currently supported as operands for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ -error: register `ax` conflicts with register `ax` - --> $DIR/bad-reg.rs:46:33 +error: register `al` conflicts with register `ax` + --> $DIR/bad-reg.rs:44:33 | LL | asm!("", in("eax") foo, in("al") bar); - | ------------- ^^^^^^^^^^^^ register `ax` + | ------------- ^^^^^^^^^^^^ register `al` | | | register `ax` error: register `ax` conflicts with register `ax` - --> $DIR/bad-reg.rs:48:33 + --> $DIR/bad-reg.rs:46:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `ax` @@ -117,13 +111,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `ax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:51:34 + --> $DIR/bad-reg.rs:49:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -131,7 +125,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:53:34 + --> $DIR/bad-reg.rs:51:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -139,10 +133,10 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:53:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors diff --git a/src/test/ui/asm/type-check-3.rs b/src/test/ui/asm/type-check-3.rs index 750d28026d7..5de15fe4906 100644 --- a/src/test/ui/asm/type-check-3.rs +++ b/src/test/ui/asm/type-check-3.rs @@ -29,7 +29,7 @@ fn main() { // Template modifier suggestions for sub-registers - asm!("{0} {0}", in(reg) 0i8); + asm!("{0} {0}", in(reg) 0i16); //~^ WARN formatting may not be suitable for sub-register argument asm!("{0} {0:x}", in(reg) 0i16); //~^ WARN formatting may not be suitable for sub-register argument @@ -39,23 +39,26 @@ fn main() { asm!("{}", in(ymm_reg) 0i64); //~^ WARN formatting may not be suitable for sub-register argument asm!("{}", in(ymm_reg) _mm256_setzero_ps()); - asm!("{:l}", in(reg) 0i8); asm!("{:l}", in(reg) 0i16); asm!("{:l}", in(reg) 0i32); asm!("{:l}", in(reg) 0i64); asm!("{:x}", in(ymm_reg) 0i64); asm!("{:x}", in(ymm_reg) _mm256_setzero_ps()); + // Suggest different register class for type + + asm!("{}", in(reg) 0i8); + //~^ ERROR type `i8` cannot be used with this register class + asm!("{}", in(reg_byte) 0i8); + // Split inout operands must have compatible types - let mut val_i8: i8; + let mut val_i16: i16; let mut val_f32: f32; let mut val_u32: u32; let mut val_u64: u64; let mut val_ptr: *mut u8; - asm!("{:r}", inout(reg) 0u8 => val_i8); - asm!("{:r}", inout(reg) 0u16 => val_i8); - //~^ ERROR incompatible types for asm inout argument + asm!("{:r}", inout(reg) 0u16 => val_i16); asm!("{:r}", inout(reg) 0u32 => val_f32); //~^ ERROR incompatible types for asm inout argument asm!("{:r}", inout(reg) 0u32 => val_ptr); diff --git a/src/test/ui/asm/type-check-3.stderr b/src/test/ui/asm/type-check-3.stderr index ccc795d1013..01dbe78db88 100644 --- a/src/test/ui/asm/type-check-3.stderr +++ b/src/test/ui/asm/type-check-3.stderr @@ -4,7 +4,7 @@ error: type `i128` cannot be used with this register class LL | asm!("{}", in(reg) 0i128); | ^^^^^ | - = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 error: type `std::arch::x86_64::__m128` cannot be used with this register class --> $DIR/type-check-3.rs:14:28 @@ -12,7 +12,7 @@ error: type `std::arch::x86_64::__m128` cannot be used with this register class LL | asm!("{}", in(reg) _mm_setzero_ps()); | ^^^^^^^^^^^^^^^^ | - = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 error: type `std::arch::x86_64::__m256` cannot be used with this register class --> $DIR/type-check-3.rs:16:28 @@ -20,7 +20,7 @@ error: type `std::arch::x86_64::__m256` cannot be used with this register class LL | asm!("{}", in(reg) _mm256_setzero_ps()); | ^^^^^^^^^^^^^^^^^^^ | - = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 error: type `u8` cannot be used with this register class --> $DIR/type-check-3.rs:18:32 @@ -41,11 +41,11 @@ LL | asm!("{}", in(kreg) 0u64); warning: formatting may not be suitable for sub-register argument --> $DIR/type-check-3.rs:32:15 | -LL | asm!("{0} {0}", in(reg) 0i8); - | ^^^ ^^^ --- for this argument +LL | asm!("{0} {0}", in(reg) 0i16); + | ^^^ ^^^ ---- for this argument | = note: `#[warn(asm_sub_register)]` on by default - = help: use the `l` modifier to have the register formatted as `al` + = help: use the `x` modifier to have the register formatted as `ax` = help: or use the `r` modifier to keep the default formatting of `rax` warning: formatting may not be suitable for sub-register argument @@ -75,18 +75,17 @@ LL | asm!("{}", in(ymm_reg) 0i64); = help: use the `x` modifier to have the register formatted as `xmm0` = help: or use the `y` modifier to keep the default formatting of `ymm0` -error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:57:33 +error: type `i8` cannot be used with this register class + --> $DIR/type-check-3.rs:50:28 | -LL | asm!("{:r}", inout(reg) 0u16 => val_i8); - | ^^^^ ^^^^^^ type `i8` - | | - | type `u16` +LL | asm!("{}", in(reg) 0i8); + | ^^^ | - = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 + = help: consider using the `reg_byte` register class instead error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:59:33 + --> $DIR/type-check-3.rs:62:33 | LL | asm!("{:r}", inout(reg) 0u32 => val_f32); | ^^^^ ^^^^^^^ type `f32` @@ -96,7 +95,7 @@ LL | asm!("{:r}", inout(reg) 0u32 => val_f32); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:61:33 + --> $DIR/type-check-3.rs:64:33 | LL | asm!("{:r}", inout(reg) 0u32 => val_ptr); | ^^^^ ^^^^^^^ type `*mut u8` @@ -106,7 +105,7 @@ LL | asm!("{:r}", inout(reg) 0u32 => val_ptr); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:63:33 + --> $DIR/type-check-3.rs:66:33 | LL | asm!("{:r}", inout(reg) main => val_u32); | ^^^^ ^^^^^^^ type `u32` |
