1
Fork 0

Add support for high byte registers on x86

This commit is contained in:
Amanieu d'Antras 2020-04-29 00:45:58 +01:00
parent 93e2946d0c
commit 7dfa486d4a
12 changed files with 198 additions and 123 deletions

View file

@ -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(),

View file

@ -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,

View file

@ -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,
},
}

View file

@ -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
}

View file

@ -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),

View file

@ -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
}

View file

@ -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,8 +321,39 @@ 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);
@ -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;
}
}
}

View file

@ -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]+}}

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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`