Add support for high byte registers on x86
This commit is contained in:
parent
93e2946d0c
commit
7dfa486d4a
12 changed files with 198 additions and 123 deletions
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]+}}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue