diff options
| author | Amanieu d'Antras <amanieu@gmail.com> | 2020-02-20 09:19:48 +0000 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2020-05-18 14:41:32 +0100 |
| commit | 8ab0f2d3c5a85563b98c4896116e3d53154fff9c (patch) | |
| tree | 9e4ac5efac12844c17ec1a89ff05bcb539a0d6c0 | |
| parent | abed45ff9fa3e68f2a32ca12e012f95b9153f4df (diff) | |
| download | rust-8ab0f2d3c5a85563b98c4896116e3d53154fff9c.tar.gz rust-8ab0f2d3c5a85563b98c4896116e3d53154fff9c.zip | |
Add tests for asm!
45 files changed, 3489 insertions, 40 deletions
diff --git a/src/test/assembly/asm/aarch64-modifiers.rs b/src/test/assembly/asm/aarch64-modifiers.rs new file mode 100644 index 00000000000..d4519ca7ffa --- /dev/null +++ b/src/test/assembly/asm/aarch64-modifiers.rs @@ -0,0 +1,144 @@ +// assembly-output: emit-asm +// compile-flags: -O +// compile-flags: --target aarch64-unknown-linux-gnu + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for i32 {} + +macro_rules! check { + ($func:ident $reg:ident $code:literal) => { + // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0 + #[no_mangle] + pub unsafe extern "C" fn $func() -> i32 { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!($code, out($reg) y); + y + } + }; +} + +// CHECK-LABEL: reg: +// CHECK: //APP +// CHECK: mov x0, x0 +// CHECK: //NO_APP +check!(reg reg "mov {0}, {0}"); + +// CHECK-LABEL: reg_w: +// CHECK: //APP +// CHECK: mov w0, w0 +// CHECK: //NO_APP +check!(reg_w reg "mov {0:w}, {0:w}"); + +// CHECK-LABEL: reg_x: +// CHECK: //APP +// CHECK: mov x0, x0 +// CHECK: //NO_APP +check!(reg_x reg "mov {0:x}, {0:x}"); + +// CHECK-LABEL: vreg: +// CHECK: //APP +// CHECK: add v0.4s, v0.4s, v0.4s +// CHECK: //NO_APP +check!(vreg vreg "add {0}.4s, {0}.4s, {0}.4s"); + +// CHECK-LABEL: vreg_b: +// CHECK: //APP +// CHECK: ldr b0, [x0] +// CHECK: //NO_APP +check!(vreg_b vreg "ldr {:b}, [x0]"); + +// CHECK-LABEL: vreg_h: +// CHECK: //APP +// CHECK: ldr h0, [x0] +// CHECK: //NO_APP +check!(vreg_h vreg "ldr {:h}, [x0]"); + +// CHECK-LABEL: vreg_s: +// CHECK: //APP +// CHECK: ldr s0, [x0] +// CHECK: //NO_APP +check!(vreg_s vreg "ldr {:s}, [x0]"); + +// CHECK-LABEL: vreg_d: +// CHECK: //APP +// CHECK: ldr d0, [x0] +// CHECK: //NO_APP +check!(vreg_d vreg "ldr {:d}, [x0]"); + +// CHECK-LABEL: vreg_q: +// CHECK: //APP +// CHECK: ldr q0, [x0] +// CHECK: //NO_APP +check!(vreg_q vreg "ldr {:q}, [x0]"); + +// CHECK-LABEL: vreg_v: +// CHECK: //APP +// CHECK: add v0.4s, v0.4s, v0.4s +// CHECK: //NO_APP +check!(vreg_v vreg "add {0:v}.4s, {0:v}.4s, {0:v}.4s"); + +// CHECK-LABEL: vreg_low16: +// CHECK: //APP +// CHECK: add v0.4s, v0.4s, v0.4s +// CHECK: //NO_APP +check!(vreg_low16 vreg_low16 "add {0}.4s, {0}.4s, {0}.4s"); + +// CHECK-LABEL: vreg_low16_b: +// CHECK: //APP +// CHECK: ldr b0, [x0] +// CHECK: //NO_APP +check!(vreg_low16_b vreg_low16 "ldr {:b}, [x0]"); + +// CHECK-LABEL: vreg_low16_h: +// CHECK: //APP +// CHECK: ldr h0, [x0] +// CHECK: //NO_APP +check!(vreg_low16_h vreg_low16 "ldr {:h}, [x0]"); + +// CHECK-LABEL: vreg_low16_s: +// CHECK: //APP +// CHECK: ldr s0, [x0] +// CHECK: //NO_APP +check!(vreg_low16_s vreg_low16 "ldr {:s}, [x0]"); + +// CHECK-LABEL: vreg_low16_d: +// CHECK: //APP +// CHECK: ldr d0, [x0] +// CHECK: //NO_APP +check!(vreg_low16_d vreg_low16 "ldr {:d}, [x0]"); + +// CHECK-LABEL: vreg_low16_q: +// CHECK: //APP +// CHECK: ldr q0, [x0] +// CHECK: //NO_APP +check!(vreg_low16_q vreg_low16 "ldr {:q}, [x0]"); + +// CHECK-LABEL: vreg_low16_v: +// CHECK: //APP +// CHECK: add v0.4s, v0.4s, v0.4s +// CHECK: //NO_APP +check!(vreg_low16_v vreg_low16 "add {0:v}.4s, {0:v}.4s, {0:v}.4s"); diff --git a/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs new file mode 100644 index 00000000000..8b763462e4a --- /dev/null +++ b/src/test/assembly/asm/aarch64-types.rs @@ -0,0 +1,380 @@ +// assembly-output: emit-asm +// compile-flags: --target aarch64-unknown-linux-gnu + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *mut u8; + +#[repr(simd)] +pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8); +#[repr(simd)] +pub struct i16x4(i16, i16, i16, i16); +#[repr(simd)] +pub struct i32x2(i32, i32); +#[repr(simd)] +pub struct i64x1(i64); +#[repr(simd)] +pub struct f32x2(f32, f32); +#[repr(simd)] +pub struct f64x1(f64); +#[repr(simd)] +pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +#[repr(simd)] +pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +#[repr(simd)] +pub struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +pub struct i64x2(i64, i64); +#[repr(simd)] +pub struct f32x4(f32, f32, f32, f32); +#[repr(simd)] +pub struct f64x2(f64, f64); + +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for i64 {} +impl Copy for f64 {} +impl Copy for ptr {} +impl Copy for i8x8 {} +impl Copy for i16x4 {} +impl Copy for i32x2 {} +impl Copy for i64x1 {} +impl Copy for f32x2 {} +impl Copy for f64x1 {} +impl Copy for i8x16 {} +impl Copy for i16x8 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} +impl Copy for f32x4 {} +impl Copy for f64x2 {} + +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +// CHECK-LABEL: sym_fn: +// CHECK: //APP +// CHECK: bl extern_func +// CHECK: //NO_APP +#[no_mangle] +pub unsafe fn sym_fn() { + asm!("bl {}", sym extern_func); +} + +// CHECK-LABEL: sym_static: +// CHECK: //APP +// CHECK: adr x0, extern_static +// CHECK: //NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + asm!("adr x0, {}", sym extern_static); +} + +macro_rules! check { + ($func:ident $ty:ident $class:ident $mov:literal $modifier:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!( + concat!($mov, " {:", $modifier, "}, {:", $modifier, "}"), + out($class) y, + in($class) x + ); + y + } + }; +} + +// CHECK-LABEL: reg_i8: +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_i8 i8 reg "mov" ""); + +// CHECK-LABEL: reg_i16: +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_i16 i16 reg "mov" ""); + +// CHECK-LABEL: reg_i32: +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_i32 i32 reg "mov" ""); + +// CHECK-LABEL: reg_f32: +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_f32 f32 reg "mov" ""); + +// CHECK-LABEL: reg_i64: +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_i64 i64 reg "mov" ""); + +// CHECK-LABEL: reg_f64: +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_f64 f64 reg "mov" ""); + +// CHECK-LABEL: reg_ptr: +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_ptr ptr reg "mov" ""); + +// CHECK-LABEL: vreg_i8: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i8 i8 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i16: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i16 i16 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i32: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i32 i32 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_f32: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f32 f32 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i64: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i64 i64 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_f64: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f64 f64 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_ptr: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_ptr ptr vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i8x8: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i8x8 i8x8 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i16x4: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i16x4 i16x4 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i32x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i32x2 i32x2 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i64x1: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i64x1 i64x1 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_f32x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f32x2 f32x2 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_f64x1: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f64x1 f64x1 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i8x16: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i8x16 i8x16 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i16x8: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i16x8 i16x8 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i32x4: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i32x4 i32x4 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_i64x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_i64x2 i64x2 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_f32x4: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f32x4 f32x4 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_f64x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f64x2 f64x2 vreg "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i8: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i8 i8 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i16: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i16 i16 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_f32: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f32 f32 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i64: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i64 i64 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_f64: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f64 f64 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_ptr: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_ptr ptr vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i8x8: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i8x8 i8x8 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i16x4: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i16x4 i16x4 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i32x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i32x2 i32x2 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i64x1: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i64x1 i64x1 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_f32x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f32x2 f32x2 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_f64x1: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f64x1 f64x1 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i8x16: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i8x16 i8x16 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i16x8: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i16x8 i16x8 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i32x4: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i32x4 i32x4 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_i64x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_i64x2 i64x2 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_f32x4: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f32x4 f32x4 vreg_low16 "fmov" "s"); + +// CHECK-LABEL: vreg_low16_f64x2: +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f64x2 f64x2 vreg_low16 "fmov" "s"); diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs new file mode 100644 index 00000000000..cefab9c4a67 --- /dev/null +++ b/src/test/assembly/asm/arm-modifiers.rs @@ -0,0 +1,149 @@ +// assembly-output: emit-asm +// compile-flags: -O +// compile-flags: --target armv7-unknown-linux-gnueabihf +// compile-flags: -C target-feature=+neon + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct f32x4(f32, f32, f32, f32); + +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for f64 {} +impl Copy for f32x4 {} + +macro_rules! check { + ($func:ident $modifier:literal $reg:ident $ty:ident $mov:literal) => { + // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0 + #[no_mangle] + pub unsafe extern "C" fn $func() -> $ty { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y); + y + } + }; +} + +// CHECK-LABEL: reg: +// CHECK: @APP +// CHECK: mov r0, r0 +// CHECK: @NO_APP +check!(reg "" reg i32 "mov"); + +// CHECK-LABEL: reg_thumb: +// CHECK: @APP +// CHECK: mov r0, r0 +// CHECK: @NO_APP +check!(reg_thumb "" reg_thumb i32 "mov"); + +// CHECK-LABEL: sreg: +// CHECK: @APP +// CHECK: vmov.f32 s0, s0 +// CHECK: @NO_APP +check!(sreg "" sreg f32 "vmov.f32"); + +// CHECK-LABEL: sreg_low16: +// CHECK: @APP +// CHECK: vmov.f32 s0, s0 +// CHECK: @NO_APP +check!(sreg_low16 "" sreg_low16 f32 "vmov.f32"); + +// CHECK-LABEL: dreg: +// CHECK: @APP +// CHECK: vmov.f64 d0, d0 +// CHECK: @NO_APP +check!(dreg "" dreg f64 "vmov.f64"); + +// CHECK-LABEL: dreg_low16: +// CHECK: @APP +// CHECK: vmov.f64 d0, d0 +// CHECK: @NO_APP +check!(dreg_low16 "" dreg_low16 f64 "vmov.f64"); + +// CHECK-LABEL: dreg_low8: +// CHECK: @APP +// CHECK: vmov.f64 d0, d0 +// CHECK: @NO_APP +check!(dreg_low8 "" dreg_low8 f64 "vmov.f64"); + +// CHECK-LABEL: qreg: +// CHECK: @APP +// CHECK: vorr q0, q0, q0 +// CHECK: @NO_APP +check!(qreg "" qreg f32x4 "vmov"); + +// CHECK-LABEL: qreg_e: +// CHECK: @APP +// CHECK: vmov.f64 d0, d0 +// CHECK: @NO_APP +check!(qreg_e "e" qreg f32x4 "vmov.f64"); + +// CHECK-LABEL: qreg_f: +// CHECK: @APP +// CHECK: vmov.f64 d1, d1 +// CHECK: @NO_APP +check!(qreg_f "f" qreg f32x4 "vmov.f64"); + +// CHECK-LABEL: qreg_low8: +// CHECK: @APP +// CHECK: vorr q0, q0, q0 +// CHECK: @NO_APP +check!(qreg_low8 "" qreg_low8 f32x4 "vmov"); + +// CHECK-LABEL: qreg_low8_e: +// CHECK: @APP +// CHECK: vmov.f64 d0, d0 +// CHECK: @NO_APP +check!(qreg_low8_e "e" qreg_low8 f32x4 "vmov.f64"); + +// CHECK-LABEL: qreg_low8_f: +// CHECK: @APP +// CHECK: vmov.f64 d1, d1 +// CHECK: @NO_APP +check!(qreg_low8_f "f" qreg_low8 f32x4 "vmov.f64"); + +// CHECK-LABEL: qreg_low4: +// CHECK: @APP +// CHECK: vorr q0, q0, q0 +// CHECK: @NO_APP +check!(qreg_low4 "" qreg_low4 f32x4 "vmov"); + +// CHECK-LABEL: qreg_low4_e: +// CHECK: @APP +// CHECK: vmov.f64 d0, d0 +// CHECK: @NO_APP +check!(qreg_low4_e "e" qreg_low4 f32x4 "vmov.f64"); + +// CHECK-LABEL: qreg_low4_f: +// CHECK: @APP +// CHECK: vmov.f64 d1, d1 +// CHECK: @NO_APP +check!(qreg_low4_f "f" qreg_low4 f32x4 "vmov.f64"); diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs new file mode 100644 index 00000000000..729adae66f6 --- /dev/null +++ b/src/test/assembly/asm/arm-types.rs @@ -0,0 +1,413 @@ +// assembly-output: emit-asm +// compile-flags: --target armv7-unknown-linux-gnueabihf +// compile-flags: -C target-feature=+neon + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *mut u8; + +#[repr(simd)] +pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8); +#[repr(simd)] +pub struct i16x4(i16, i16, i16, i16); +#[repr(simd)] +pub struct i32x2(i32, i32); +#[repr(simd)] +pub struct i64x1(i64); +#[repr(simd)] +pub struct f32x2(f32, f32); +#[repr(simd)] +pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +#[repr(simd)] +pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +#[repr(simd)] +pub struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +pub struct i64x2(i64, i64); +#[repr(simd)] +pub struct f32x4(f32, f32, f32, f32); + +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for i64 {} +impl Copy for f64 {} +impl Copy for ptr {} +impl Copy for i8x8 {} +impl Copy for i16x4 {} +impl Copy for i32x2 {} +impl Copy for i64x1 {} +impl Copy for f32x2 {} +impl Copy for i8x16 {} +impl Copy for i16x8 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} +impl Copy for f32x4 {} + +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +// CHECK-LABEL: sym_fn: +// CHECK: @APP +// CHECK: bl extern_func +// CHECK: @NO_APP +#[no_mangle] +pub unsafe fn sym_fn() { + asm!("bl {}", sym extern_func); +} + +// CHECK-LABEL: sym_static: +// CHECK: @APP +// CHECK: adr r0, extern_static +// CHECK: @NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + asm!("adr r0, {}", sym extern_static); +} + +macro_rules! check { + ($func:ident $ty:ident $class:ident $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x); + y + } + }; +} + +// CHECK-LABEL: reg_i8: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_i8 i8 reg "mov"); + +// CHECK-LABEL: reg_i16: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_i16 i16 reg "mov"); + +// CHECK-LABEL: reg_i32: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_i32 i32 reg "mov"); + +// CHECK-LABEL: reg_f32: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_f32 f32 reg "mov"); + +// CHECK-LABEL: reg_ptr: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_ptr ptr reg "mov"); + +// CHECK-LABEL: reg_thumb_i8: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_thumb_i8 i8 reg_thumb "mov"); + +// CHECK-LABEL: reg_thumb_i16: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_thumb_i16 i16 reg_thumb "mov"); + +// CHECK-LABEL: reg_thumb_i32: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_thumb_i32 i32 reg_thumb "mov"); + +// CHECK-LABEL: reg_thumb_f32: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_thumb_f32 f32 reg_thumb "mov"); + +// CHECK-LABEL: reg_thumb_ptr: +// CHECK: @APP +// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: @NO_APP +check!(reg_thumb_ptr ptr reg_thumb "mov"); + +// CHECK-LABEL: sreg_i32: +// CHECK: @APP +// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: @NO_APP +check!(sreg_i32 i32 sreg "vmov.f32"); + +// CHECK-LABEL: sreg_f32: +// CHECK: @APP +// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: @NO_APP +check!(sreg_f32 f32 sreg "vmov.f32"); + +// CHECK-LABEL: sreg_ptr: +// CHECK: @APP +// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: @NO_APP +check!(sreg_ptr ptr sreg "vmov.f32"); + +// CHECK-LABEL: sreg_low16_i32: +// CHECK: @APP +// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: @NO_APP +check!(sreg_low16_i32 i32 sreg_low16 "vmov.f32"); + +// CHECK-LABEL: sreg_low16_f32: +// CHECK: @APP +// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: @NO_APP +check!(sreg_low16_f32 f32 sreg_low16 "vmov.f32"); + +// CHECK-LABEL: dreg_i64: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_i64 i64 dreg "vmov.f64"); + +// CHECK-LABEL: dreg_f64: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_f64 f64 dreg "vmov.f64"); + +// CHECK-LABEL: dreg_i8x8: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_i8x8 i8x8 dreg "vmov.f64"); + +// CHECK-LABEL: dreg_i16x4: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_i16x4 i16x4 dreg "vmov.f64"); + +// CHECK-LABEL: dreg_i32x2: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_i32x2 i32x2 dreg "vmov.f64"); + +// CHECK-LABEL: dreg_i64x1: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_i64x1 i64x1 dreg "vmov.f64"); + +// CHECK-LABEL: dreg_f32x2: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_f32x2 f32x2 dreg "vmov.f64"); + +// CHECK-LABEL: dreg_low16_i64: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low16_i64 i64 dreg_low16 "vmov.f64"); + +// CHECK-LABEL: dreg_low16_f64: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low16_f64 f64 dreg_low16 "vmov.f64"); + +// CHECK-LABEL: dreg_low16_i8x8: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low16_i8x8 i8x8 dreg_low16 "vmov.f64"); + +// CHECK-LABEL: dreg_low16_i16x4: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low16_i16x4 i16x4 dreg_low16 "vmov.f64"); + +// CHECK-LABEL: dreg_low16_i32x2: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low16_i32x2 i32x2 dreg_low16 "vmov.f64"); + +// CHECK-LABEL: dreg_low16_i64x1: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low16_i64x1 i64x1 dreg_low16 "vmov.f64"); + +// CHECK-LABEL: dreg_low16_f32x2: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low16_f32x2 f32x2 dreg_low16 "vmov.f64"); + +// CHECK-LABEL: dreg_low8_i64: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low8_i64 i64 dreg_low8 "vmov.f64"); + +// CHECK-LABEL: dreg_low8_f64: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low8_f64 f64 dreg_low8 "vmov.f64"); + +// CHECK-LABEL: dreg_low8_i8x8: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low8_i8x8 i8x8 dreg_low8 "vmov.f64"); + +// CHECK-LABEL: dreg_low8_i16x4: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low8_i16x4 i16x4 dreg_low8 "vmov.f64"); + +// CHECK-LABEL: dreg_low8_i32x2: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low8_i32x2 i32x2 dreg_low8 "vmov.f64"); + +// CHECK-LABEL: dreg_low8_i64x1: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low8_i64x1 i64x1 dreg_low8 "vmov.f64"); + +// CHECK-LABEL: dreg_low8_f32x2: +// CHECK: @APP +// CHECK: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}} +// CHECK: @NO_APP +check!(dreg_low8_f32x2 f32x2 dreg_low8 "vmov.f64"); + +// CHECK-LABEL: qreg_i8x16: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_i8x16 i8x16 qreg "vmov"); + +// CHECK-LABEL: qreg_i16x8: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_i16x8 i16x8 qreg "vmov"); + +// CHECK-LABEL: qreg_i32x4: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_i32x4 i32x4 qreg "vmov"); + +// CHECK-LABEL: qreg_i64x2: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_i64x2 i64x2 qreg "vmov"); + +// CHECK-LABEL: qreg_f32x4: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_f32x4 f32x4 qreg "vmov"); + +// CHECK-LABEL: qreg_low8_i8x16: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low8_i8x16 i8x16 qreg_low8 "vmov"); + +// CHECK-LABEL: qreg_low8_i16x8: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low8_i16x8 i16x8 qreg_low8 "vmov"); + +// CHECK-LABEL: qreg_low8_i32x4: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low8_i32x4 i32x4 qreg_low8 "vmov"); + +// CHECK-LABEL: qreg_low8_i64x2: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low8_i64x2 i64x2 qreg_low8 "vmov"); + +// CHECK-LABEL: qreg_low8_f32x4: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low8_f32x4 f32x4 qreg_low8 "vmov"); + +// CHECK-LABEL: qreg_low4_i8x16: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low4_i8x16 i8x16 qreg_low4 "vmov"); + +// CHECK-LABEL: qreg_low4_i16x8: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low4_i16x8 i16x8 qreg_low4 "vmov"); + +// CHECK-LABEL: qreg_low4_i32x4: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low4_i32x4 i32x4 qreg_low4 "vmov"); + +// CHECK-LABEL: qreg_low4_i64x2: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low4_i64x2 i64x2 qreg_low4 "vmov"); + +// CHECK-LABEL: qreg_low4_f32x4: +// CHECK: @APP +// CHECK: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}} +// CHECK: @NO_APP +check!(qreg_low4_f32x4 f32x4 qreg_low4 "vmov"); diff --git a/src/test/assembly/asm/riscv-modifiers.rs b/src/test/assembly/asm/riscv-modifiers.rs new file mode 100644 index 00000000000..622d0c0dc5e --- /dev/null +++ b/src/test/assembly/asm/riscv-modifiers.rs @@ -0,0 +1,58 @@ +// assembly-output: emit-asm +// compile-flags: -O +// compile-flags: --target riscv64gc-unknown-linux-gnu +// compile-flags: -C target-feature=+f + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for f32 {} + +macro_rules! check { + ($func:ident $modifier:literal $reg:ident $mov:literal) => { + // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0 + #[no_mangle] + pub unsafe extern "C" fn $func() -> f32 { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y); + y + } + }; +} + +// CHECK-LABEL: reg: +// CHECK: #APP +// CHECK: mv a0, a0 +// CHECK: #NO_APP +check!(reg "" reg "mv"); + +// CHECK-LABEL: freg: +// CHECK: #APP +// CHECK: fmv.s fa0, fa0 +// CHECK: #NO_APP +check!(freg "" freg "fmv.s"); diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs new file mode 100644 index 00000000000..5c10753c765 --- /dev/null +++ b/src/test/assembly/asm/riscv-types.rs @@ -0,0 +1,134 @@ +// revisions: riscv64 riscv32 +// assembly-output: emit-asm +//[riscv64] compile-flags: --target riscv64imac-unknown-none-elf +//[riscv32] compile-flags: --target riscv32imac-unknown-none-elf +// compile-flags: -C target-feature=+d + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *mut u8; + +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for i64 {} +impl Copy for f64 {} +impl Copy for ptr {} + +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +// CHECK-LABEL: sym_fn: +// CHECK: #APP +// CHECK: call extern_func +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_fn() { + asm!("call {}", sym extern_func); +} + +// CHECK-LABEL: sym_static: +// CHECK: #APP +// CHECK: lb t0, extern_static +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + asm!("lb t0, {}", sym extern_static); +} + +macro_rules! check { + ($func:ident $ty:ident $class:ident $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x); + y + } + }; +} + +// CHECK-LABEL: reg_i8: +// CHECK: #APP +// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i8 i8 reg "mv"); + +// CHECK-LABEL: reg_i16: +// CHECK: #APP +// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i16 i16 reg "mv"); + +// CHECK-LABEL: reg_i32: +// CHECK: #APP +// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i32 i32 reg "mv"); + +// CHECK-LABEL: reg_f32: +// CHECK: #APP +// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_f32 f32 reg "mv"); + +// riscv64-LABEL: reg_i64: +// riscv64: #APP +// riscv64: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// riscv64: #NO_APP +#[cfg(riscv64)] +check!(reg_i64 i64 reg "mv"); + +// riscv64-LABEL: reg_f64: +// riscv64: #APP +// riscv64: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// riscv64: #NO_APP +#[cfg(riscv64)] +check!(reg_f64 f64 reg "mv"); + +// CHECK-LABEL: reg_ptr: +// CHECK: #APP +// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_ptr ptr reg "mv"); + +// CHECK-LABEL: freg_f32: +// CHECK: #APP +// CHECK: fmv.s f{{[a-z0-9]+}}, f{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(freg_f32 f32 freg "fmv.s"); + +// CHECK-LABEL: freg_f64: +// CHECK: #APP +// CHECK: fmv.d f{{[a-z0-9]+}}, f{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(freg_f64 f64 freg "fmv.d"); diff --git a/src/test/assembly/asm/x86-modifiers.rs b/src/test/assembly/asm/x86-modifiers.rs new file mode 100644 index 00000000000..460e22aa69e --- /dev/null +++ b/src/test/assembly/asm/x86-modifiers.rs @@ -0,0 +1,210 @@ +// revisions: x86_64 i686 +// assembly-output: emit-asm +// compile-flags: -O +//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//[i686] compile-flags: --target i686-unknown-linux-gnu +// compile-flags: -C llvm-args=--x86-asm-syntax=intel +// compile-flags: -C target-feature=+avx512bw + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for i32 {} + +macro_rules! check { + ($func:ident $modifier:literal $reg:ident $mov:literal) => { + // -O and extern "C" guarantee that the selected register is always ax/xmm0 + #[no_mangle] + pub unsafe extern "C" fn $func() -> i32 { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y); + y + } + }; +} + +// CHECK-LABEL: reg: +// CHECK: #APP +// x86_64: mov rax, rax +// i686: mov eax, eax +// CHECK: #NO_APP +check!(reg "" reg "mov"); + +// x86_64-LABEL: reg_l: +// x86_64: #APP +// x86_64: mov al, al +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_l "l" reg "mov"); + +// x86_64-LABEL: reg_h: +// x86_64: #APP +// x86_64: mov ah, ah +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_h "h" reg "mov"); + +// CHECK-LABEL: reg_x: +// CHECK: #APP +// CHECK: mov ax, ax +// CHECK: #NO_APP +check!(reg_x "x" reg "mov"); + +// CHECK-LABEL: reg_e: +// CHECK: #APP +// CHECK: mov eax, eax +// CHECK: #NO_APP +check!(reg_e "e" reg "mov"); + +// x86_64-LABEL: reg_r: +// x86_64: #APP +// x86_64: mov rax, rax +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_r "r" reg "mov"); + +// CHECK-LABEL: reg_abcd: +// CHECK: #APP +// x86_64: mov rax, rax +// i686: mov eax, eax +// CHECK: #NO_APP +check!(reg_abcd "" reg_abcd "mov"); + +// CHECK-LABEL: reg_abcd_l: +// CHECK: #APP +// CHECK: mov al, al +// CHECK: #NO_APP +check!(reg_abcd_l "l" reg_abcd "mov"); + +// CHECK-LABEL: reg_abcd_h: +// CHECK: #APP +// CHECK: mov ah, ah +// CHECK: #NO_APP +check!(reg_abcd_h "h" reg_abcd "mov"); + +// CHECK-LABEL: reg_abcd_x: +// CHECK: #APP +// CHECK: mov ax, ax +// CHECK: #NO_APP +check!(reg_abcd_x "x" reg_abcd "mov"); + +// CHECK-LABEL: reg_abcd_e: +// CHECK: #APP +// CHECK: mov eax, eax +// CHECK: #NO_APP +check!(reg_abcd_e "e" reg_abcd "mov"); + +// x86_64-LABEL: reg_abcd_r: +// x86_64: #APP +// x86_64: mov rax, rax +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_abcd_r "r" reg_abcd "mov"); + +// CHECK-LABEL: xmm_reg +// CHECK: #APP +// CHECK: movaps xmm0, xmm0 +// CHECK: #NO_APP +check!(xmm_reg "" xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_x +// CHECK: #APP +// CHECK: movaps xmm0, xmm0 +// CHECK: #NO_APP +check!(xmm_reg_x "x" xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_y +// CHECK: #APP +// CHECK: vmovaps ymm0, ymm0 +// CHECK: #NO_APP +check!(xmm_reg_y "y" xmm_reg "vmovaps"); + +// CHECK-LABEL: xmm_reg_z +// CHECK: #APP +// CHECK: vmovaps zmm0, zmm0 +// CHECK: #NO_APP +check!(xmm_reg_z "z" xmm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg +// CHECK: #APP +// CHECK: movaps ymm0, ymm0 +// CHECK: #NO_APP +check!(ymm_reg "" ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_x +// CHECK: #APP +// CHECK: movaps xmm0, xmm0 +// CHECK: #NO_APP +check!(ymm_reg_x "x" ymm_reg "movaps"); + +// CHECK-LABEL: ymm_reg_y +// CHECK: #APP +// CHECK: vmovaps ymm0, ymm0 +// CHECK: #NO_APP +check!(ymm_reg_y "y" ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_z +// CHECK: #APP +// CHECK: vmovaps zmm0, zmm0 +// CHECK: #NO_APP +check!(ymm_reg_z "z" ymm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg +// CHECK: #APP +// CHECK: movaps zmm0, zmm0 +// CHECK: #NO_APP +check!(zmm_reg "" zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_x +// CHECK: #APP +// CHECK: movaps xmm0, xmm0 +// CHECK: #NO_APP +check!(zmm_reg_x "x" zmm_reg "movaps"); + +// CHECK-LABEL: zmm_reg_y +// CHECK: #APP +// CHECK: vmovaps ymm0, ymm0 +// CHECK: #NO_APP +check!(zmm_reg_y "y" zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_z +// CHECK: #APP +// CHECK: vmovaps zmm0, zmm0 +// CHECK: #NO_APP +check!(zmm_reg_z "z" zmm_reg "vmovaps"); + +// Note: we don't have any way of ensuring that k1 is actually the register +// chosen by the register allocator, so this check may fail if a different +// register is chosen. + +// CHECK-LABEL: kreg: +// CHECK: #APP +// CHECK: kmovb k1, k1 +// CHECK: #NO_APP +check!(kreg "" kreg "kmovb"); diff --git a/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs new file mode 100644 index 00000000000..d2819ac88e7 --- /dev/null +++ b/src/test/assembly/asm/x86-types.rs @@ -0,0 +1,701 @@ +// revisions: x86_64 i686 +// assembly-output: emit-asm +//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//[i686] compile-flags: --target i686-unknown-linux-gnu +// compile-flags: -C llvm-args=--x86-asm-syntax=intel +// compile-flags: -C target-feature=+avx512bw + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *mut u8; + +#[repr(simd)] +pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +#[repr(simd)] +pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +#[repr(simd)] +pub struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +pub struct i64x2(i64, i64); +#[repr(simd)] +pub struct f32x4(f32, f32, f32, f32); +#[repr(simd)] +pub struct f64x2(f64, f64); + +#[repr(simd)] +pub struct i8x32( + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, +); +#[repr(simd)] +pub struct i16x16(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16); +#[repr(simd)] +pub struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32); +#[repr(simd)] +pub struct i64x4(i64, i64, i64, i64); +#[repr(simd)] +pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); +#[repr(simd)] +pub struct f64x4(f64, f64, f64, f64); + +#[repr(simd)] +pub struct i8x64( + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, + i8, +); +#[repr(simd)] +pub struct i16x32( + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, + i16, +); +#[repr(simd)] +pub struct i32x16(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32); +#[repr(simd)] +pub struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64); +#[repr(simd)] +pub struct f32x16(f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32); +#[repr(simd)] +pub struct f64x8(f64, f64, f64, f64, f64, f64, f64, f64); + +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for i64 {} +impl Copy for f64 {} +impl Copy for ptr {} +impl Copy for i8x16 {} +impl Copy for i16x8 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} +impl Copy for f32x4 {} +impl Copy for f64x2 {} +impl Copy for i8x32 {} +impl Copy for i16x16 {} +impl Copy for i32x8 {} +impl Copy for i64x4 {} +impl Copy for f32x8 {} +impl Copy for f64x4 {} +impl Copy for i8x64 {} +impl Copy for i16x32 {} +impl Copy for i32x16 {} +impl Copy for i64x8 {} +impl Copy for f32x16 {} +impl Copy for f64x8 {} + +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +// CHECK-LABEL: sym_fn: +// CHECK: #APP +// CHECK: call extern_func +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_fn() { + asm!("call {}", sym extern_func); +} + +// CHECK-LABEL: sym_static: +// CHECK: #APP +// CHECK: mov al, byte ptr [extern_static] +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + asm!("mov al, byte ptr [{}]", sym extern_static); +} + +macro_rules! check { + ($func:ident $ty:ident $class:ident $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x); + y + } + }; +} + +// 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]+}} +// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i16 i16 reg "mov"); + +// CHECK-LABEL: reg_i32: +// 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_i32 i32 reg "mov"); + +// CHECK-LABEL: reg_f32: +// 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_f32 f32 reg "mov"); + +// x86_64-LABEL: reg_i64: +// x86_64: #APP +// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_i64 i64 reg "mov"); + +// x86_64-LABEL: reg_f64: +// x86_64: #APP +// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_f64 f64 reg "mov"); + +// CHECK-LABEL: reg_ptr: +// 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_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]+}} +// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_abcd_i16 i16 reg_abcd "mov"); + +// CHECK-LABEL: reg_abcd_i32: +// 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_i32 i32 reg_abcd "mov"); + +// CHECK-LABEL: reg_abcd_f32: +// 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_f32 f32 reg_abcd "mov"); + +// x86_64-LABEL: reg_abcd_i64: +// x86_64: #APP +// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_abcd_i64 i64 reg_abcd "mov"); + +// x86_64-LABEL: reg_abcd_f64: +// x86_64: #APP +// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}} +// x86_64: #NO_APP +#[cfg(x86_64)] +check!(reg_abcd_f64 f64 reg_abcd "mov"); + +// CHECK-LABEL: reg_abcd_ptr: +// 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_ptr ptr reg_abcd "mov"); + +// CHECK-LABEL: xmm_reg_i32: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_i32 i32 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_f32: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_f32 f32 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_i64: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_i64 i64 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_f64: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_f64 f64 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_ptr: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_ptr ptr xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_i8x16: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_i8x16 i8x16 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_i16x8: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_i16x8 i16x8 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_i32x4: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_i32x4 i32x4 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_i64x2: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_i64x2 i64x2 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_f32x4: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_f32x4 f32x4 xmm_reg "movaps"); + +// CHECK-LABEL: xmm_reg_f64x2: +// CHECK: #APP +// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}} +// CHECK: #NO_APP +check!(xmm_reg_f64x2 f64x2 xmm_reg "movaps"); + +// CHECK-LABEL: ymm_reg_i32: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i32 i32 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_f32: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_f32 f32 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i64: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i64 i64 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_f64: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_f64 f64 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_ptr: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_ptr ptr ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i8x16: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i8x16 i8x16 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i16x8: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i16x8 i16x8 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i32x4: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i32x4 i32x4 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i64x2: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i64x2 i64x2 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_f32x4: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_f32x4 f32x4 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_f64x2: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_f64x2 f64x2 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i8x32: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i8x32 i8x32 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i16x16: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i16x16 i16x16 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i32x8: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i32x8 i32x8 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_i64x4: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_i64x4 i64x4 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_f32x8: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_f32x8 f32x8 ymm_reg "vmovaps"); + +// CHECK-LABEL: ymm_reg_f64x4: +// CHECK: #APP +// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}} +// CHECK: #NO_APP +check!(ymm_reg_f64x4 f64x4 ymm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i32: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i32 i32 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f32: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f32 f32 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i64: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i64 i64 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f64: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f64 f64 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_ptr: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_ptr ptr zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i8x16: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i8x16 i8x16 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i16x8: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i16x8 i16x8 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i32x4: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i32x4 i32x4 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i64x2: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i64x2 i64x2 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f32x4: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f32x4 f32x4 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f64x2: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f64x2 f64x2 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i8x32: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i8x32 i8x32 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i16x16: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i16x16 i16x16 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i32x8: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i32x8 i32x8 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i64x4: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i64x4 i64x4 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f32x8: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f32x8 f32x8 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f64x4: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f64x4 f64x4 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i8x64: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i8x64 i8x64 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i16x32: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i16x32 i16x32 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i32x16: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i32x16 i32x16 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_i64x8: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_i64x8 i64x8 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f32x16: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f32x16 f32x16 zmm_reg "vmovaps"); + +// CHECK-LABEL: zmm_reg_f64x8: +// CHECK: #APP +// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}} +// CHECK: #NO_APP +check!(zmm_reg_f64x8 f64x8 zmm_reg "vmovaps"); + +// CHECK-LABEL: kreg_i8: +// CHECK: #APP +// CHECK: kmovb k{{[0-9]+}}, k{{[0-9]+}} +// CHECK: #NO_APP +check!(kreg_i8 i8 kreg "kmovb"); + +// CHECK-LABEL: kreg_i16: +// CHECK: #APP +// CHECK: kmovw k{{[0-9]+}}, k{{[0-9]+}} +// CHECK: #NO_APP +check!(kreg_i16 i16 kreg "kmovw"); + +// CHECK-LABEL: kreg_i32: +// CHECK: #APP +// CHECK: kmovd k{{[0-9]+}}, k{{[0-9]+}} +// CHECK: #NO_APP +check!(kreg_i32 i32 kreg "kmovd"); + +// CHECK-LABEL: kreg_i64: +// CHECK: #APP +// CHECK: kmovq k{{[0-9]+}}, k{{[0-9]+}} +// CHECK: #NO_APP +check!(kreg_i64 i64 kreg "kmovq"); + +// CHECK-LABEL: kreg_ptr: +// CHECK: #APP +// CHECK: kmovq k{{[0-9]+}}, k{{[0-9]+}} +// CHECK: #NO_APP +check!(kreg_ptr ptr kreg "kmovq"); diff --git a/src/test/codegen/asm-options.rs b/src/test/codegen/asm-options.rs new file mode 100644 index 00000000000..21e7eb43796 --- /dev/null +++ b/src/test/codegen/asm-options.rs @@ -0,0 +1,96 @@ +// compile-flags: -O +// only-x86_64 + +#![crate_type = "rlib"] +#![feature(asm)] + +// CHECK-LABEL: @pure +// CHECK-NOT: asm +// CHECK: ret void +#[no_mangle] +pub unsafe fn pure(x: i32) { + let y: i32; + asm!("", out("ax") y, in("bx") x, options(pure, nomem)); +} + +// CHECK-LABEL: @noreturn +// CHECK: call void asm +// CHECK-NEXT: unreachable +#[no_mangle] +pub unsafe fn noreturn() { + asm!("", options(noreturn)); +} + +pub static mut VAR: i32 = 0; +pub static mut DUMMY_OUTPUT: i32 = 0; + +// CHECK-LABEL: @readonly +// CHECK: call i32 asm +// CHECK: ret i32 1 +#[no_mangle] +pub unsafe fn readonly() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options(pure, readonly)); + VAR +} + +// CHECK-LABEL: @not_readonly +// CHECK: call i32 asm +// CHECK: ret i32 % +#[no_mangle] +pub unsafe fn not_readonly() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options()); + VAR +} + +// CHECK-LABEL: @nomem +// CHECK-NOT: store +// CHECK: call i32 asm +// CHECK: store +// CHECK: ret i32 2 +#[no_mangle] +pub unsafe fn nomem() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options(pure, nomem)); + VAR = 2; + VAR +} + +// CHECK-LABEL: @nomem_nopure +// CHECK-NOT: store +// CHECK: call i32 asm +// CHECK: store +// CHECK: ret i32 2 +#[no_mangle] +pub unsafe fn nomem_nopure() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options(nomem)); + VAR = 2; + VAR +} + +// CHECK-LABEL: @not_nomem +// CHECK: store +// CHECK: call i32 asm +// CHECK: store +// CHECK: ret i32 2 +#[no_mangle] +pub unsafe fn not_nomem() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options(pure, readonly)); + VAR = 2; + VAR +} + +// CHECK-LABEL: @dont_remove_nonpure +// CHECK: call void asm +// CHECK: call void asm +// CHECK: call void asm +// CHECK: ret void +#[no_mangle] +pub unsafe fn dont_remove_nonpure() { + asm!("", options()); + asm!("", options(nomem)); + asm!("", options(readonly)); +} diff --git a/src/test/pretty/asm.pp b/src/test/pretty/asm.pp new file mode 100644 index 00000000000..1723e1cc1cb --- /dev/null +++ b/src/test/pretty/asm.pp @@ -0,0 +1,25 @@ +#![feature(prelude_import)] +#![no_std] +#![feature(asm)] +#[prelude_import] +use ::std::prelude::v1::*; +#[macro_use] +extern crate std; + +// pretty-mode:expanded +// pp-exact:asm.pp + +pub fn main() { + let a: i32; + let mut b = 4i32; + unsafe { + asm!(""); + asm!(""); + asm!("", options(nomem, nostack)); + asm!("{0}", in(reg) 4); + asm!("{0}", out(reg) a); + asm!("{0}", inout(reg) b); + asm!("{0} {1}", out(reg) _, inlateout(reg) b => _); + asm!("", out("al") _, lateout("rbx") _); + } +} diff --git a/src/test/pretty/asm.rs b/src/test/pretty/asm.rs new file mode 100644 index 00000000000..9812f1d97e5 --- /dev/null +++ b/src/test/pretty/asm.rs @@ -0,0 +1,19 @@ +#![feature(asm)] + +// pretty-mode:expanded +// pp-exact:asm.pp + +pub fn main() { + let a: i32; + let mut b = 4i32; + unsafe { + asm!(""); + asm!("", options()); + asm!("", options(nostack, nomem)); + asm!("{}", in(reg) 4); + asm!("{0}", out(reg) a); + asm!("{name}", name = inout(reg) b); + asm!("{} {}", out(reg) _, inlateout(reg) b => _); + asm!("", out("al") _, lateout("rbx") _); + } +} diff --git a/src/test/pretty/asm-clobbers.rs b/src/test/pretty/llvm-asm-clobbers.rs index 2c09646e47e..2c09646e47e 100644 --- a/src/test/pretty/asm-clobbers.rs +++ b/src/test/pretty/llvm-asm-clobbers.rs diff --git a/src/test/pretty/asm-options.rs b/src/test/pretty/llvm-asm-options.rs index 86a881bfbd1..86a881bfbd1 100644 --- a/src/test/pretty/asm-options.rs +++ b/src/test/pretty/llvm-asm-options.rs diff --git a/src/test/ui/asm/bad-options.rs b/src/test/ui/asm/bad-options.rs new file mode 100644 index 00000000000..755fc2ca238 --- /dev/null +++ b/src/test/ui/asm/bad-options.rs @@ -0,0 +1,18 @@ +// only-x86_64 + +#![feature(asm)] + +fn main() { + let mut foo = 0; + unsafe { + asm!("", options(nomem, readonly)); + //~^ ERROR the `nomem` and `readonly` options are mutually exclusive + asm!("", options(pure, nomem, noreturn)); + //~^ ERROR the `pure` and `noreturn` options are mutually exclusive + //~^^ ERROR asm with `pure` option must have at least one output + asm!("{}", in(reg) foo, options(pure, nomem)); + //~^ ERROR asm with `pure` option must have at least one output + asm!("{}", out(reg) foo, options(noreturn)); + //~^ ERROR asm outputs are not allowed with the `noreturn` option + } +} diff --git a/src/test/ui/asm/bad-options.stderr b/src/test/ui/asm/bad-options.stderr new file mode 100644 index 00000000000..c5e8e2ccf44 --- /dev/null +++ b/src/test/ui/asm/bad-options.stderr @@ -0,0 +1,32 @@ +error: the `nomem` and `readonly` options are mutually exclusive + --> $DIR/bad-options.rs:8:18 + | +LL | asm!("", options(nomem, readonly)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `pure` and `noreturn` options are mutually exclusive + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with `pure` option must have at least one output + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with `pure` option must have at least one output + --> $DIR/bad-options.rs:13:33 + | +LL | asm!("{}", in(reg) foo, options(pure, nomem)); + | ^^^^^^^^^^^^^^^^^^^^ + +error: asm outputs are not allowed with the `noreturn` option + --> $DIR/bad-options.rs:15:20 + | +LL | asm!("{}", out(reg) foo, options(noreturn)); + | ^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/asm/bad-reg.rs b/src/test/ui/asm/bad-reg.rs new file mode 100644 index 00000000000..ed7faa4b156 --- /dev/null +++ b/src/test/ui/asm/bad-reg.rs @@ -0,0 +1,57 @@ +// only-x86_64 +// compile-flags: -C target-feature=+avx2 + +#![feature(asm)] + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + // Bad register/register class + + asm!("{}", in(foo) foo); + //~^ ERROR invalid register class `foo`: unknown register class + asm!("", in("foo") foo); + //~^ ERROR invalid register `foo`: unknown register + asm!("{:z}", in(reg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:r}", in(xmm_reg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:a}", const 0); + //~^ ERROR asm template modifiers are not allowed for `const` arguments + asm!("{:a}", sym main); + //~^ ERROR asm template modifiers are not allowed for `sym` arguments + asm!("{}", in(zmm_reg) foo); + //~^ 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); + //~^ 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("st(2)") foo); + //~^ ERROR invalid register `st(2)`: x87 registers are not currently supported as operands + asm!("", in("mm0") foo); + //~^ ERROR invalid register `mm0`: MMX registers are not currently supported as operands + asm!("", in("k0") foo); + //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand + + // Explicit register conflicts + // (except in/lateout which don't conflict) + + asm!("", in("eax") foo, in("al") bar); + //~^ ERROR register `ax` 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); + asm!("", in("xmm0") foo, in("ymm0") bar); + //~^ ERROR register `ymm0` conflicts with register `xmm0` + asm!("", in("xmm0") foo, out("ymm0") bar); + //~^ ERROR register `ymm0` conflicts with register `xmm0` + asm!("", in("xmm0") foo, lateout("ymm0") bar); + } +} diff --git a/src/test/ui/asm/bad-reg.stderr b/src/test/ui/asm/bad-reg.stderr new file mode 100644 index 00000000000..a9d872dae41 --- /dev/null +++ b/src/test/ui/asm/bad-reg.stderr @@ -0,0 +1,148 @@ +error: invalid register class `foo`: unknown register class + --> $DIR/bad-reg.rs:12:20 + | +LL | asm!("{}", in(foo) foo); + | ^^^^^^^^^^^ + +error: invalid register `foo`: unknown register + --> $DIR/bad-reg.rs:14:18 + | +LL | asm!("", in("foo") foo); + | ^^^^^^^^^^^^^ + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:16:15 + | +LL | asm!("{:z}", in(reg) foo); + | ^^^^ ----------- argument + | | + | template modifier + | + = note: the `reg` register class supports the following template modifiers: `l`, `h`, `x`, `e`, `r` + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:18:15 + | +LL | asm!("{:r}", in(xmm_reg) foo); + | ^^^^ --------------- argument + | | + | template modifier + | + = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z` + +error: asm template modifiers are not allowed for `const` arguments + --> $DIR/bad-reg.rs:20:15 + | +LL | asm!("{:a}", const 0); + | ^^^^ ------- argument + | | + | template modifier + +error: asm template modifiers are not allowed for `sym` arguments + --> $DIR/bad-reg.rs:22:15 + | +LL | asm!("{:a}", sym main); + | ^^^^ -------- argument + | | + | template modifier + +error: register class `zmm_reg` requires the `avx512f` target feature + --> $DIR/bad-reg.rs:24:20 + | +LL | asm!("{}", in(zmm_reg) foo); + | ^^^^^^^^^^^^^^^ + +error: register class `zmm_reg` requires the `avx512f` target feature + --> $DIR/bad-reg.rs:26:18 + | +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 + | +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 + | +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 + | +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 + | +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 + | +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 + | +LL | asm!("", in("k0") foo); + | ^^^^^^^^^^^^ + +error: register `ax` conflicts with register `ax` + --> $DIR/bad-reg.rs:46:33 + | +LL | asm!("", in("eax") foo, in("al") bar); + | ------------- ^^^^^^^^^^^^ register `ax` + | | + | register `ax` + +error: register `ax` conflicts with register `ax` + --> $DIR/bad-reg.rs:48:33 + | +LL | asm!("", in("rax") foo, out("rax") bar); + | ------------- ^^^^^^^^^^^^^^ register `ax` + | | + | register `ax` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", in("rax") foo, out("rax") bar); + | ^^^^^^^^^^^^^ + +error: register `ymm0` conflicts with register `xmm0` + --> $DIR/bad-reg.rs:51:34 + | +LL | asm!("", in("xmm0") foo, in("ymm0") bar); + | -------------- ^^^^^^^^^^^^^^ register `ymm0` + | | + | register `xmm0` + +error: register `ymm0` conflicts with register `xmm0` + --> $DIR/bad-reg.rs:53:34 + | +LL | asm!("", in("xmm0") foo, out("ymm0") bar); + | -------------- ^^^^^^^^^^^^^^^ register `ymm0` + | | + | register `xmm0` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:53:18 + | +LL | asm!("", in("xmm0") foo, out("ymm0") bar); + | ^^^^^^^^^^^^^^ + +error: aborting due to 19 previous errors + diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs new file mode 100644 index 00000000000..0b333eca1ab --- /dev/null +++ b/src/test/ui/asm/bad-template.rs @@ -0,0 +1,26 @@ +// only-x86_64 + +#![feature(asm)] + +fn main() { + let mut foo = 0; + unsafe { + asm!("{}"); + //~^ ERROR invalid reference to argument at index 0 + asm!("{1}", in(reg) foo); + //~^ ERROR invalid reference to argument at index 1 + //~^^ ERROR argument never used + asm!("{a}"); + //~^ ERROR there is no argument named `a` + asm!("{}", a = in(reg) foo); + //~^ ERROR invalid reference to argument at index 0 + //~^^ ERROR argument never used + asm!("{1}", a = in(reg) foo); + //~^ ERROR invalid reference to argument at index 1 + //~^^ ERROR named argument never used + asm!("{}", in("eax") foo); + //~^ ERROR invalid reference to argument at index 0 + asm!("{:foo}", in(reg) foo); + //~^ ERROR asm template modifier must be a single character + } +} diff --git a/src/test/ui/asm/bad-template.stderr b/src/test/ui/asm/bad-template.stderr new file mode 100644 index 00000000000..2de76ef8241 --- /dev/null +++ b/src/test/ui/asm/bad-template.stderr @@ -0,0 +1,86 @@ +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:8:15 + | +LL | asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:10:15 + | +LL | asm!("{1}", in(reg) foo); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:10:21 + | +LL | asm!("{1}", in(reg) foo); + | ^^^^^^^^^^^ argument never used + +error: there is no argument named `a` + --> $DIR/bad-template.rs:13:15 + | +LL | asm!("{a}"); + | ^^^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:15:15 + | +LL | asm!("{}", a = in(reg) foo); + | ^^ --------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:15:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:15:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:18:15 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:18:21 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:21:15 + | +LL | asm!("{}", in("eax") foo); + | ^^ ------------- explicit register argument + | | + | from here + | + = note: no positional arguments were given +note: explicit register arguments cannot be used in the asm template + --> $DIR/bad-template.rs:21:20 + | +LL | asm!("{}", in("eax") foo); + | ^^^^^^^^^^^^^ + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:23:17 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^ + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/asm/noreturn.rs b/src/test/ui/asm/noreturn.rs new file mode 100644 index 00000000000..5e1ee93bfb0 --- /dev/null +++ b/src/test/ui/asm/noreturn.rs @@ -0,0 +1,17 @@ +// only-x86_64 +// check-pass + +#![feature(asm, never_type)] +#![crate_type = "rlib"] + +pub unsafe fn asm1() { + let _: () = asm!(""); +} + +pub unsafe fn asm2() { + let _: ! = asm!("", options(noreturn)); +} + +pub unsafe fn asm3() -> ! { + asm!("", options(noreturn)); +} diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/parse-error.rs new file mode 100644 index 00000000000..e6566866b22 --- /dev/null +++ b/src/test/ui/asm/parse-error.rs @@ -0,0 +1,53 @@ +// only-x86_64 + +#![feature(asm)] + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + asm!(); + //~^ ERROR requires at least a template string argument + asm!(foo); + //~^ ERROR asm template must be a string literal + asm!("{}" foo); + //~^ ERROR expected token: `,` + asm!("{}", foo); + //~^ ERROR expected one of + asm!("{}", in foo); + //~^ ERROR expected `(`, found `foo` + asm!("{}", in(reg foo)); + //~^ ERROR expected `)`, found `foo` + asm!("{}", in(reg)); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", inout(=) foo => bar); + //~^ ERROR expected register class or explicit register + asm!("{}", inout(reg) foo =>); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", in(reg) foo => bar); + //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + asm!("{}", sym foo + bar); + //~^ ERROR argument to `sym` must be a path expression + asm!("", options(foo)); + //~^ ERROR expected one of + asm!("", options(nomem foo)); + //~^ ERROR expected one of + asm!("", options(nomem, foo)); + //~^ ERROR expected one of + asm!("", options(), options()); + //~^ ERROR asm options cannot be specified twice + asm!("{}", options(), const foo); + //~^ ERROR arguments are not allowed after options + asm!("{a}", a = const foo, a = const bar); + //~^ ERROR duplicate argument named `a` + //~^^ ERROR argument never used + asm!("", a = in("eax") foo); + //~^ ERROR explicit register arguments cannot have names + asm!("{a}", in("eax") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + asm!("{a}", in("eax") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + asm!("{1}", in("eax") foo, const bar); + //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments + } +} diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr new file mode 100644 index 00000000000..a927ce13858 --- /dev/null +++ b/src/test/ui/asm/parse-error.stderr @@ -0,0 +1,146 @@ +error: requires at least a template string argument + --> $DIR/parse-error.rs:9:9 + | +LL | asm!(); + | ^^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:11:14 + | +LL | asm!(foo); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:13:19 + | +LL | asm!("{}" foo); + | ^^^ expected `,` + +error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `foo` + --> $DIR/parse-error.rs:15:20 + | +LL | asm!("{}", foo); + | ^^^ expected one of 8 possible tokens + +error: expected `(`, found `foo` + --> $DIR/parse-error.rs:17:23 + | +LL | asm!("{}", in foo); + | ^^^ expected `(` + +error: expected `)`, found `foo` + --> $DIR/parse-error.rs:19:27 + | +LL | asm!("{}", in(reg foo)); + | ^^^ expected `)` + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:21:27 + | +LL | asm!("{}", in(reg)); + | ^ expected expression + +error: expected register class or explicit register + --> $DIR/parse-error.rs:23:26 + | +LL | asm!("{}", inout(=) foo => bar); + | ^ + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:25:37 + | +LL | asm!("{}", inout(reg) foo =>); + | ^ expected expression + +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + --> $DIR/parse-error.rs:27:32 + | +LL | asm!("{}", in(reg) foo => bar); + | ^^ expected one of 7 possible tokens + +error: argument to `sym` must be a path expression + --> $DIR/parse-error.rs:29:24 + | +LL | asm!("{}", sym foo + bar); + | ^^^^^^^^^ + +error: expected one of `)`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:31:26 + | +LL | asm!("", options(foo)); + | ^^^ expected one of 7 possible tokens + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:33:32 + | +LL | asm!("", options(nomem foo)); + | ^^^ expected one of `)` or `,` + +error: expected one of `)`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:35:33 + | +LL | asm!("", options(nomem, foo)); + | ^^^ expected one of 7 possible tokens + +error: asm options cannot be specified twice + --> $DIR/parse-error.rs:37:29 + | +LL | asm!("", options(), options()); + | --------- ^^^^^^^^^ duplicate options + | | + | previously here + +error: arguments are not allowed after options + --> $DIR/parse-error.rs:39:31 + | +LL | asm!("{}", options(), const foo); + | --------- ^^^^^^^^^ argument + | | + | previous options + +error: duplicate argument named `a` + --> $DIR/parse-error.rs:41:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:41:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^^^^^^^^^^^ argument never used + +error: explicit register arguments cannot have names + --> $DIR/parse-error.rs:44:18 + | +LL | asm!("", a = in("eax") foo); + | ^^^^^^^^^^^^^^^^^ + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:46:36 + | +LL | asm!("{a}", in("eax") foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:48:36 + | +LL | asm!("{a}", in("eax") foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: positional arguments cannot follow named arguments or explicit register arguments + --> $DIR/parse-error.rs:50:36 + | +LL | asm!("{1}", in("eax") foo, const bar); + | ------------- ^^^^^^^^^ positional argument + | | + | explicit register argument + +error: aborting due to 22 previous errors + diff --git a/src/test/ui/asm/rustfix-asm.fixed b/src/test/ui/asm/rustfix-asm.fixed new file mode 100644 index 00000000000..c9271059810 --- /dev/null +++ b/src/test/ui/asm/rustfix-asm.fixed @@ -0,0 +1,16 @@ +// run-rustfix +// only-x86_64 + +#![feature(asm, llvm_asm)] + +fn main() { + unsafe { + let x = 1; + let y: i32; + llvm_asm!("" :: "r" (x)); + //~^ ERROR legacy asm! syntax is no longer supported + llvm_asm!("" : "=r" (y)); + //~^ ERROR legacy asm! syntax is no longer supported + let _ = y; + } +} diff --git a/src/test/ui/asm/rustfix-asm.rs b/src/test/ui/asm/rustfix-asm.rs new file mode 100644 index 00000000000..a108595ca1b --- /dev/null +++ b/src/test/ui/asm/rustfix-asm.rs @@ -0,0 +1,16 @@ +// run-rustfix +// only-x86_64 + +#![feature(asm, llvm_asm)] + +fn main() { + unsafe { + let x = 1; + let y: i32; + asm!("" :: "r" (x)); + //~^ ERROR legacy asm! syntax is no longer supported + asm!("" : "=r" (y)); + //~^ ERROR legacy asm! syntax is no longer supported + let _ = y; + } +} diff --git a/src/test/ui/asm/rustfix-asm.stderr b/src/test/ui/asm/rustfix-asm.stderr new file mode 100644 index 00000000000..28675b51d15 --- /dev/null +++ b/src/test/ui/asm/rustfix-asm.stderr @@ -0,0 +1,18 @@ +error: legacy asm! syntax is no longer supported + --> $DIR/rustfix-asm.rs:10:9 + | +LL | asm!("" :: "r" (x)); + | ----^^^^^^^^^^^^^^^^ + | | + | help: replace with: `llvm_asm!` + +error: legacy asm! syntax is no longer supported + --> $DIR/rustfix-asm.rs:12:9 + | +LL | asm!("" : "=r" (y)); + | ----^^^^^^^^^^^^^^^^ + | | + | help: replace with: `llvm_asm!` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs new file mode 100644 index 00000000000..7880382c3b7 --- /dev/null +++ b/src/test/ui/asm/type-check-1.rs @@ -0,0 +1,25 @@ +// only-x86_64 + +#![feature(asm)] + +fn main() { + unsafe { + // Outputs must be place expressions + + asm!("{}", in(reg) 1 + 2); + asm!("{}", out(reg) 1 + 2); + //~^ ERROR invalid asm output + asm!("{}", inout(reg) 1 + 2); + //~^ ERROR invalid asm output + + // Operands must be sized + + let v: [u64; 3] = [0, 1, 2]; + asm!("{}", in(reg) v[..]); + //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time + asm!("{}", out(reg) v[..]); + //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time + asm!("{}", inout(reg) v[..]); + //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time + } +} diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr new file mode 100644 index 00000000000..7c9c041f457 --- /dev/null +++ b/src/test/ui/asm/type-check-1.stderr @@ -0,0 +1,45 @@ +error: invalid asm output + --> $DIR/type-check-1.rs:10:29 + | +LL | asm!("{}", out(reg) 1 + 2); + | ^^^^^ cannot assign to this expression + +error: invalid asm output + --> $DIR/type-check-1.rs:12:31 + | +LL | asm!("{}", inout(reg) 1 + 2); + | ^^^^^ cannot assign to this expression + +error[E0277]: the size for values of type `[u64]` cannot be known at compilation time + --> $DIR/type-check-1.rs:18:28 + | +LL | asm!("{}", in(reg) v[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u64]` + = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> + = note: all inline asm arguments must have a statically known size + +error[E0277]: the size for values of type `[u64]` cannot be known at compilation time + --> $DIR/type-check-1.rs:20:29 + | +LL | asm!("{}", out(reg) v[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u64]` + = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> + = note: all inline asm arguments must have a statically known size + +error[E0277]: the size for values of type `[u64]` cannot be known at compilation time + --> $DIR/type-check-1.rs:22:31 + | +LL | asm!("{}", inout(reg) v[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u64]` + = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> + = note: all inline asm arguments must have a statically known size + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/asm/type-check-2.rs b/src/test/ui/asm/type-check-2.rs new file mode 100644 index 00000000000..1652e9e4c9f --- /dev/null +++ b/src/test/ui/asm/type-check-2.rs @@ -0,0 +1,104 @@ +// only-x86_64 + +#![feature(asm, repr_simd, never_type)] + +#[repr(simd)] +struct SimdNonCopy(f32, f32, f32, f32); + +fn main() { + unsafe { + // Inputs must be initialized + + let x: u64; + asm!("{}", in(reg) x); + //~^ ERROR use of possibly-uninitialized variable: `x` + let mut y: u64; + asm!("{}", inout(reg) y); + //~^ ERROR use of possibly-uninitialized variable: `y` + let _ = y; + + // Outputs require mutable places + + let v: Vec<u64> = vec![0, 1, 2]; + asm!("{}", in(reg) v[0]); + asm!("{}", out(reg) v[0]); + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + asm!("{}", inout(reg) v[0]); + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + + // Const operands must be integer or floats, and must be constants. + + let x = 0; + const C: i32 = 0; + const fn const_foo(x: i32) -> i32 { + x + } + const fn const_bar<T>(x: T) -> T { + x + } + asm!("{}", const 0i32); + asm!("{}", const 0f32); + asm!("{}", const 0 as *mut u8); + //~^ ERROR asm `const` arguments must be integer or floating-point values + asm!("{}", const &0); + //~^ ERROR asm `const` arguments must be integer or floating-point values + asm!("{}", const x); + //~^ ERROR argument 1 is required to be a constant + asm!("{}", const const_foo(0)); + asm!("{}", const const_foo(x)); + //~^ ERROR argument 1 is required to be a constant + asm!("{}", const const_bar(0)); + asm!("{}", const const_bar(x)); + //~^ ERROR argument 1 is required to be a constant + + // Sym operands must point to a function or static + + static S: i32 = 0; + asm!("{}", sym S); + asm!("{}", sym main); + asm!("{}", sym C); + //~^ ERROR asm `sym` operand must point to a fn or static + asm!("{}", sym x); + //~^ ERROR asm `sym` operand must point to a fn or static + + // Register operands must be Copy + + asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + //~^ ERROR arguments for inline assembly must be copyable + + // Register operands must be integers, floats, SIMD vectors, pointers or + // function pointers. + + asm!("{}", in(reg) 0i64); + asm!("{}", in(reg) 0f64); + asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps()); + asm!("{}", in(reg) 0 as *const u8); + asm!("{}", in(reg) 0 as *mut u8); + asm!("{}", in(reg) main as fn()); + asm!("{}", in(reg) |x: i32| x); + //~^ ERROR cannot use value of type + asm!("{}", in(reg) vec![0]); + //~^ ERROR cannot use value of type `std::vec::Vec<i32>` for inline assembly + asm!("{}", in(reg) (1, 2, 3)); + //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly + asm!("{}", in(reg) [1, 2, 3]); + //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly + + // Register inputs (but not outputs) allow references and function types + + let mut f = main; + let mut r = &mut 0; + asm!("{}", in(reg) f); + asm!("{}", inout(reg) f); + //~^ ERROR cannot use value of type `fn() {main}` for inline assembly + asm!("{}", in(reg) r); + asm!("{}", inout(reg) r); + //~^ ERROR cannot use value of type `&mut i32` for inline assembly + let _ = (f, r); + + // Type checks ignore never type + + let u: ! = unreachable!(); + asm!("{}", in(reg) u); + } +} diff --git a/src/test/ui/asm/type-check-2.stderr b/src/test/ui/asm/type-check-2.stderr new file mode 100644 index 00000000000..dc7949534f1 --- /dev/null +++ b/src/test/ui/asm/type-check-2.stderr @@ -0,0 +1,133 @@ +error: asm `const` arguments must be integer or floating-point values + --> $DIR/type-check-2.rs:41:26 + | +LL | asm!("{}", const 0 as *mut u8); + | ^^^^^^^^^^^^ + +error: asm `const` arguments must be integer or floating-point values + --> $DIR/type-check-2.rs:43:26 + | +LL | asm!("{}", const &0); + | ^^ + +error: arguments for inline assembly must be copyable + --> $DIR/type-check-2.rs:66:32 + | +LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `SimdNonCopy` does not implement the Copy trait + +error: cannot use value of type `[closure@$DIR/type-check-2.rs:78:28: 78:38]` for inline assembly + --> $DIR/type-check-2.rs:78:28 + | +LL | asm!("{}", in(reg) |x: i32| x); + | ^^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `std::vec::Vec<i32>` for inline assembly + --> $DIR/type-check-2.rs:80:28 + | +LL | asm!("{}", in(reg) vec![0]); + | ^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot use value of type `(i32, i32, i32)` for inline assembly + --> $DIR/type-check-2.rs:82:28 + | +LL | asm!("{}", in(reg) (1, 2, 3)); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `[i32; 3]` for inline assembly + --> $DIR/type-check-2.rs:84:28 + | +LL | asm!("{}", in(reg) [1, 2, 3]); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `fn() {main}` for inline assembly + --> $DIR/type-check-2.rs:92:31 + | +LL | asm!("{}", inout(reg) f); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `&mut i32` for inline assembly + --> $DIR/type-check-2.rs:95:31 + | +LL | asm!("{}", inout(reg) r); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: asm `sym` operand must point to a fn or static + --> $DIR/type-check-2.rs:59:24 + | +LL | asm!("{}", sym C); + | ^ + +error: asm `sym` operand must point to a fn or static + --> $DIR/type-check-2.rs:61:24 + | +LL | asm!("{}", sym x); + | ^ + +error: argument 1 is required to be a constant + --> $DIR/type-check-2.rs:45:9 + | +LL | asm!("{}", const x); + | ^^^^^^^^^^^^^^^^^^^^ + +error: argument 1 is required to be a constant + --> $DIR/type-check-2.rs:48:9 + | +LL | asm!("{}", const const_foo(x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: argument 1 is required to be a constant + --> $DIR/type-check-2.rs:51:9 + | +LL | asm!("{}", const const_bar(x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0381]: use of possibly-uninitialized variable: `x` + --> $DIR/type-check-2.rs:13:28 + | +LL | asm!("{}", in(reg) x); + | ^ use of possibly-uninitialized `x` + +error[E0381]: use of possibly-uninitialized variable: `y` + --> $DIR/type-check-2.rs:16:9 + | +LL | asm!("{}", inout(reg) y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y` + +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/type-check-2.rs:24:29 + | +LL | let v: Vec<u64> = vec![0, 1, 2]; + | - help: consider changing this to be mutable: `mut v` +LL | asm!("{}", in(reg) v[0]); +LL | asm!("{}", out(reg) v[0]); + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/type-check-2.rs:26:31 + | +LL | let v: Vec<u64> = vec![0, 1, 2]; + | - help: consider changing this to be mutable: `mut v` +... +LL | asm!("{}", inout(reg) v[0]); + | ^ cannot borrow as mutable + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0381, E0596. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/asm/type-check-3.rs b/src/test/ui/asm/type-check-3.rs new file mode 100644 index 00000000000..750d28026d7 --- /dev/null +++ b/src/test/ui/asm/type-check-3.rs @@ -0,0 +1,68 @@ +// only-x86_64 +// compile-flags: -C target-feature=+avx512f + +#![feature(asm)] + +use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps}; + +fn main() { + unsafe { + // Types must be in the whitelist for the register class + + asm!("{}", in(reg) 0i128); + //~^ ERROR type `i128` cannot be used with this register class + asm!("{}", in(reg) _mm_setzero_ps()); + //~^ ERROR type `std::arch::x86_64::__m128` cannot be used with this register class + asm!("{}", in(reg) _mm256_setzero_ps()); + //~^ ERROR type `std::arch::x86_64::__m256` cannot be used with this register class + asm!("{}", in(xmm_reg) 0u8); + //~^ ERROR type `u8` cannot be used with this register class + asm!("{:e}", in(reg) 0i32); + asm!("{}", in(xmm_reg) 0i32); + asm!("{:e}", in(reg) 0f32); + asm!("{}", in(xmm_reg) 0f32); + asm!("{}", in(xmm_reg) _mm_setzero_ps()); + asm!("{:x}", in(ymm_reg) _mm_setzero_ps()); + asm!("{}", in(kreg) 0u16); + asm!("{}", in(kreg) 0u64); + //~^ ERROR `avx512bw` target feature is not enabled + + // Template modifier suggestions for sub-registers + + asm!("{0} {0}", in(reg) 0i8); + //~^ 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 + asm!("{}", in(reg) 0i32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0i64); + 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()); + + // Split inout operands must have compatible types + + let mut val_i8: i8; + 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) 0u32 => val_f32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:r}", inout(reg) 0u32 => val_ptr); + //~^ ERROR incompatible types for asm inout argument + asm!("{:r}", inout(reg) main => val_u32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:r}", inout(reg) 0u64 => val_ptr); + asm!("{:r}", inout(reg) main => val_u64); + } +} diff --git a/src/test/ui/asm/type-check-3.stderr b/src/test/ui/asm/type-check-3.stderr new file mode 100644 index 00000000000..e4018ca1d42 --- /dev/null +++ b/src/test/ui/asm/type-check-3.stderr @@ -0,0 +1,123 @@ +error: type `i128` cannot be used with this register class + --> $DIR/type-check-3.rs:12:28 + | +LL | asm!("{}", in(reg) 0i128); + | ^^^^^ + | + = note: register class `reg` supports these types: i8, 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 + | +LL | asm!("{}", in(reg) _mm_setzero_ps()); + | ^^^^^^^^^^^^^^^^ + | + = note: register class `reg` supports these types: i8, 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 + | +LL | asm!("{}", in(reg) _mm256_setzero_ps()); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + +error: type `u8` cannot be used with this register class + --> $DIR/type-check-3.rs:18:32 + | +LL | asm!("{}", in(xmm_reg) 0u8); + | ^^^ + | + = note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + +error: `avx512bw` target feature is not enabled + --> $DIR/type-check-3.rs:27:29 + | +LL | asm!("{}", in(kreg) 0u64); + | ^^^^ + | + = note: this is required to use type `u64` with register class `kreg` + +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 + | + = note: `#[warn(asm_sub_register)]` on by default + = help: use the `l` modifier to have the register formatted as `al` + = help: or use the `r` modifier to keep the default formatting of `rax` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:34:15 + | +LL | asm!("{0} {0:x}", in(reg) 0i16); + | ^^^ ---- for this argument + | + = 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 + --> $DIR/type-check-3.rs:36:15 + | +LL | asm!("{}", in(reg) 0i32); + | ^^ ---- for this argument + | + = help: use the `e` modifier to have the register formatted as `eax` + = help: or use the `r` modifier to keep the default formatting of `rax` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:39:15 + | +LL | asm!("{}", in(ymm_reg) 0i64); + | ^^ ---- for this argument + | + = 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 + | +LL | asm!("{:r}", inout(reg) 0u16 => val_i8); + | ^^^^ ^^^^^^ type `i8` + | | + | type `u16` + | + = note: asm inout arguments must have the same type + = note: unless they are both pointers or integers of the same size + +error: incompatible types for asm inout argument + --> $DIR/type-check-3.rs:59:33 + | +LL | asm!("{:r}", inout(reg) 0u32 => val_f32); + | ^^^^ ^^^^^^^ type `f32` + | | + | type `u32` + | + = note: asm inout arguments must have the same type + = note: 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 + | +LL | asm!("{:r}", inout(reg) 0u32 => val_ptr); + | ^^^^ ^^^^^^^ type `*mut u8` + | | + | type `u32` + | + = note: asm inout arguments must have the same type + = note: 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 + | +LL | asm!("{:r}", inout(reg) main => val_u32); + | ^^^^ ^^^^^^^ type `u32` + | | + | type `fn()` + | + = note: asm inout arguments must have the same type + = note: unless they are both pointers or integers of the same size + +error: aborting due to 9 previous errors; 4 warnings emitted + diff --git a/src/test/ui/feature-gates/feature-gate-asm.rs b/src/test/ui/feature-gates/feature-gate-asm.rs index 70f5845550d..7eeeb4bc4e2 100644 --- a/src/test/ui/feature-gates/feature-gate-asm.rs +++ b/src/test/ui/feature-gates/feature-gate-asm.rs @@ -3,7 +3,6 @@ fn main() { unsafe { asm!(""); //~ ERROR inline assembly is not stable enough - //~^ WARN use of deprecated item 'asm' llvm_asm!(""); //~ ERROR inline assembly is not stable enough } } diff --git a/src/test/ui/feature-gates/feature-gate-asm.stderr b/src/test/ui/feature-gates/feature-gate-asm.stderr index 9d4d7b53955..1f9eaa5632e 100644 --- a/src/test/ui/feature-gates/feature-gate-asm.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm.stderr @@ -8,7 +8,7 @@ LL | asm!(""); = help: add `#![feature(asm)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change - --> $DIR/feature-gate-asm.rs:7:9 + --> $DIR/feature-gate-asm.rs:6:9 | LL | llvm_asm!(""); | ^^^^^^^^ @@ -16,14 +16,6 @@ LL | llvm_asm!(""); = note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information = help: add `#![feature(llvm_asm)]` to the crate attributes to enable -warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage - --> $DIR/feature-gate-asm.rs:5:9 - | -LL | asm!(""); - | ^^^ help: replace the use of the deprecated item: `llvm_asm` - | - = note: `#[warn(deprecated)]` on by default - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-asm2.rs b/src/test/ui/feature-gates/feature-gate-asm2.rs index e3e86592a48..666a4894f62 100644 --- a/src/test/ui/feature-gates/feature-gate-asm2.rs +++ b/src/test/ui/feature-gates/feature-gate-asm2.rs @@ -3,7 +3,6 @@ fn main() { unsafe { println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable - //~^ WARN use of deprecated item 'asm' println!("{:?}", llvm_asm!("")); //~ ERROR inline assembly is not stable } } diff --git a/src/test/ui/feature-gates/feature-gate-asm2.stderr b/src/test/ui/feature-gates/feature-gate-asm2.stderr index a3c8116d6b1..17ba66e9842 100644 --- a/src/test/ui/feature-gates/feature-gate-asm2.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm2.stderr @@ -8,7 +8,7 @@ LL | println!("{:?}", asm!("")); = help: add `#![feature(asm)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change - --> $DIR/feature-gate-asm2.rs:7:26 + --> $DIR/feature-gate-asm2.rs:6:26 | LL | println!("{:?}", llvm_asm!("")); | ^^^^^^^^ @@ -16,14 +16,6 @@ LL | println!("{:?}", llvm_asm!("")); = note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information = help: add `#![feature(llvm_asm)]` to the crate attributes to enable -warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage - --> $DIR/feature-gate-asm2.rs:5:26 - | -LL | println!("{:?}", asm!("")); - | ^^^ help: replace the use of the deprecated item: `llvm_asm` - | - = note: `#[warn(deprecated)]` on by default - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/asm-concat-src.rs b/src/test/ui/llvm-asm/llvm-asm-concat-src.rs index 1dc1c859c6b..1dc1c859c6b 100644 --- a/src/test/ui/asm-concat-src.rs +++ b/src/test/ui/llvm-asm/llvm-asm-concat-src.rs diff --git a/src/test/ui/asm-in-moved.rs b/src/test/ui/llvm-asm/llvm-asm-in-moved.rs index 35f4d92c8ff..35f4d92c8ff 100644 --- a/src/test/ui/asm-in-moved.rs +++ b/src/test/ui/llvm-asm/llvm-asm-in-moved.rs diff --git a/src/test/ui/asm-in-out-operand.rs b/src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs index acefabd8a66..acefabd8a66 100644 --- a/src/test/ui/asm-in-out-operand.rs +++ b/src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs diff --git a/src/test/ui/asm-indirect-memory.rs b/src/test/ui/llvm-asm/llvm-asm-indirect-memory.rs index 556ad83a4ea..556ad83a4ea 100644 --- a/src/test/ui/asm-indirect-memory.rs +++ b/src/test/ui/llvm-asm/llvm-asm-indirect-memory.rs diff --git a/src/test/ui/asm-out-assign.rs b/src/test/ui/llvm-asm/llvm-asm-out-assign.rs index 321f28565ff..321f28565ff 100644 --- a/src/test/ui/asm-out-assign.rs +++ b/src/test/ui/llvm-asm/llvm-asm-out-assign.rs diff --git a/src/test/ui/macros/macro-expanded-include/foo/mod.rs b/src/test/ui/macros/macro-expanded-include/foo/mod.rs index f0eb92b2be8..a8bfa0299f6 100644 --- a/src/test/ui/macros/macro-expanded-include/foo/mod.rs +++ b/src/test/ui/macros/macro-expanded-include/foo/mod.rs @@ -5,5 +5,5 @@ macro_rules! m { } macro_rules! n { - () => { unsafe { llvm_asm!(include_str!("file.txt")); } } + () => { unsafe { asm!(include_str!("file.txt")); } } } diff --git a/src/test/ui/macros/macro-expanded-include/test.rs b/src/test/ui/macros/macro-expanded-include/test.rs index abf83a5c6ff..f1a71059a89 100644 --- a/src/test/ui/macros/macro-expanded-include/test.rs +++ b/src/test/ui/macros/macro-expanded-include/test.rs @@ -1,6 +1,6 @@ // ignore-emscripten no llvm_asm! support // build-pass (FIXME(62277): could be check-pass?) -#![feature(llvm_asm)] +#![feature(asm)] #![allow(unused)] #[macro_use] diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs index cc96a5bff52..0a496c9dc3d 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.rs +++ b/src/test/ui/macros/macros-nonfatal-errors.rs @@ -3,13 +3,14 @@ // test that errors in a (selection) of macros don't kill compilation // immediately, so that we get more errors listed at a time. -#![feature(llvm_asm)] +#![feature(asm, llvm_asm)] #![feature(trace_macros, concat_idents)] #[derive(Default)] //~ ERROR enum OrDeriveThis {} fn main() { + asm!(invalid); //~ ERROR llvm_asm!(invalid); //~ ERROR concat_idents!("not", "idents"); //~ ERROR diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr index f416c70123c..6ef757a55b8 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.stderr +++ b/src/test/ui/macros/macros-nonfatal-errors.stderr @@ -6,44 +6,50 @@ LL | #[derive(Default)] | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) +error: asm template must be a string literal + --> $DIR/macros-nonfatal-errors.rs:13:10 + | +LL | asm!(invalid); + | ^^^^^^^ + error: inline assembly must be a string literal - --> $DIR/macros-nonfatal-errors.rs:13:15 + --> $DIR/macros-nonfatal-errors.rs:14:15 | LL | llvm_asm!(invalid); | ^^^^^^^ error: concat_idents! requires ident args. - --> $DIR/macros-nonfatal-errors.rs:15:5 + --> $DIR/macros-nonfatal-errors.rs:16:5 | LL | concat_idents!("not", "idents"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:17:17 + --> $DIR/macros-nonfatal-errors.rs:18:17 | LL | option_env!(invalid); | ^^^^^^^ error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:18:10 + --> $DIR/macros-nonfatal-errors.rs:19:10 | LL | env!(invalid); | ^^^^^^^ error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:19:10 + --> $DIR/macros-nonfatal-errors.rs:20:10 | LL | env!(foo, abr, baz); | ^^^ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined - --> $DIR/macros-nonfatal-errors.rs:20:5 + --> $DIR/macros-nonfatal-errors.rs:21:5 | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: format argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:22:13 + --> $DIR/macros-nonfatal-errors.rs:23:13 | LL | format!(invalid); | ^^^^^^^ @@ -54,19 +60,19 @@ LL | format!("{}", invalid); | ^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:24:14 + --> $DIR/macros-nonfatal-errors.rs:25:14 | LL | include!(invalid); | ^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:26:18 + --> $DIR/macros-nonfatal-errors.rs:27:18 | LL | include_str!(invalid); | ^^^^^^^ error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/macros-nonfatal-errors.rs:27:5 + --> $DIR/macros-nonfatal-errors.rs:28:5 | LL | include_str!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,13 +80,13 @@ LL | include_str!("i'd be quite surprised if a file with this name existed") = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:28:20 + --> $DIR/macros-nonfatal-errors.rs:29:20 | LL | include_bytes!(invalid); | ^^^^^^^ error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/macros-nonfatal-errors.rs:29:5 + --> $DIR/macros-nonfatal-errors.rs:30:5 | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,11 +94,11 @@ LL | include_bytes!("i'd be quite surprised if a file with this name existed = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: trace_macros! accepts only `true` or `false` - --> $DIR/macros-nonfatal-errors.rs:31:5 + --> $DIR/macros-nonfatal-errors.rs:32:5 | LL | trace_macros!(invalid); | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0665`. diff --git a/src/test/ui/target-feature/gate.stderr b/src/test/ui/target-feature/gate.stderr index 848538a4e92..2384a00aa47 100644 --- a/src/test/ui/target-feature/gate.stderr +++ b/src/test/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:29:18 + --> $DIR/gate.rs:30:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ |
