Skip to content

Commit

Permalink
Support #[repr(simd)] types and floats in input/output of s390x inlin…
Browse files Browse the repository at this point in the history
…e assembly
  • Loading branch information
taiki-e committed Nov 21, 2024
1 parent 75703c1 commit d0a124a
Show file tree
Hide file tree
Showing 9 changed files with 608 additions and 117 deletions.
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_gcc/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -683,9 +683,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::S390x(
S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg,
) => {
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
Expand Down Expand Up @@ -766,7 +765,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr,
) => cx.type_i32(),
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i64(), 2),
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
S390x(S390xInlineAsmRegClass::reg) => "r",
S390x(S390xInlineAsmRegClass::reg_addr) => "a",
S390x(S390xInlineAsmRegClass::freg) => "f",
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
S390x(S390xInlineAsmRegClass::vreg) => "v",
S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only")
}
Sparc(SparcInlineAsmRegClass::reg) => "r",
Expand Down Expand Up @@ -844,7 +845,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(),
S390x(S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr) => cx.type_i32(),
S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
S390x(S390xInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i64(), 2),
S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only")
}
Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2137,6 +2137,7 @@ symbols! {
vec_pop,
vec_with_capacity,
vecdeque_iter,
vector,
version,
vfp2,
vis,
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_target/src/asm/s390x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ impl S390xInlineAsmRegClass {
match self {
Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; },
Self::freg => types! { _: F32, F64; },
Self::vreg => &[],
Self::vreg => types! {
vector: F32, F64, F128,
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
},
Self::areg => &[],
}
}
Expand Down
155 changes: 152 additions & 3 deletions tests/assembly/asm/s390x-types.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//@ revisions: s390x
//@ revisions: s390x s390x_vector
//@ assembly-output: emit-asm
//@[s390x] compile-flags: --target s390x-unknown-linux-gnu
//@[s390x] needs-llvm-components: systemz
//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
//@[s390x_vector] needs-llvm-components: systemz
//@ compile-flags: -Zmerge-functions=disabled

#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![feature(no_core, lang_items, rustc_attrs, repr_simd, f128)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
Expand All @@ -27,16 +29,38 @@ trait Sized {}
#[lang = "copy"]
trait Copy {}

impl<T: Copy, const N: usize> Copy for [T; N] {}

type ptr = *const i32;

#[repr(simd)]
pub struct i8x16([i8; 16]);
#[repr(simd)]
pub struct i16x8([i16; 8]);
#[repr(simd)]
pub struct i32x4([i32; 4]);
#[repr(simd)]
pub struct i64x2([i64; 2]);
#[repr(simd)]
pub struct f32x4([f32; 4]);
#[repr(simd)]
pub struct f64x2([f64; 2]);

impl Copy for i8 {}
impl Copy for u8 {}
impl Copy for i16 {}
impl Copy for i32 {}
impl Copy for i64 {}
impl Copy for f32 {}
impl Copy for f64 {}
impl Copy for f128 {}
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 {}

extern "C" {
fn extern_func();
Expand Down Expand Up @@ -65,7 +89,6 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
// CHECK: #APP
// CHECK: brasl %r14, extern_func
// CHECK: #NO_APP
#[cfg(s390x)]
#[no_mangle]
pub unsafe fn sym_fn_32() {
asm!("brasl %r14, {}", sym extern_func);
Expand Down Expand Up @@ -146,6 +169,69 @@ check!(reg_f64, f64, freg, "ldr");
// CHECK: #NO_APP
check!(reg_ptr, ptr, reg, "lgr");

// s390x_vector-LABEL: vreg_i8x16:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i8x16, i8x16, vreg, "vlr");

// s390x_vector-LABEL: vreg_i16x8:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i16x8, i16x8, vreg, "vlr");

// s390x_vector-LABEL: vreg_i32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i32x4, i32x4, vreg, "vlr");

// s390x_vector-LABEL: vreg_i64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i64x2, i64x2, vreg, "vlr");

// s390x_vector-LABEL: vreg_f32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f32x4, f32x4, vreg, "vlr");

// s390x_vector-LABEL: vreg_f64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f64x2, f64x2, vreg, "vlr");

// s390x_vector-LABEL: vreg_f32:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f32, f32, vreg, "vlr");

// s390x_vector-LABEL: vreg_f64:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f64, f64, vreg, "vlr");

// s390x_vector-LABEL: vreg_f128:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f128, f128, vreg, "vlr");

// CHECK-LABEL: r0_i8:
// CHECK: #APP
// CHECK: lr %r0, %r0
Expand Down Expand Up @@ -181,3 +267,66 @@ check_reg!(f0_f32, f32, "f0", "ler");
// CHECK: ldr %f0, %f0
// CHECK: #NO_APP
check_reg!(f0_f64, f64, "f0", "ldr");

// s390x_vector-LABEL: v0_i8x16:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i8x16, i8x16, "v0", "vlr");

// s390x_vector-LABEL: v0_i16x8:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i16x8, i16x8, "v0", "vlr");

// s390x_vector-LABEL: v0_i32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i32x4, i32x4, "v0", "vlr");

// s390x_vector-LABEL: v0_i64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i64x2, i64x2, "v0", "vlr");

// s390x_vector-LABEL: v0_f32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f32x4, f32x4, "v0", "vlr");

// s390x_vector-LABEL: v0_f64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f64x2, f64x2, "v0", "vlr");

// s390x_vector-LABEL: v0_f32:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f32, f32, "v0", "vlr");

// s390x_vector-LABEL: v0_f64:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f64, f64, "v0", "vlr");

// s390x_vector-LABEL: v0_f128:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f128, f128, "v0", "vlr");
1 change: 1 addition & 0 deletions tests/auxiliary/minicore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl_marker_trait!(
impl<'a, T: ?Sized> Copy for &'a T {}
impl<T: ?Sized> Copy for *const T {}
impl<T: ?Sized> Copy for *mut T {}
impl<T: Copy, const N: usize> Copy for [T; N] {}

#[lang = "phantom_data"]
pub struct PhantomData<T: ?Sized>;
Expand Down
49 changes: 31 additions & 18 deletions tests/ui/asm/s390x/bad-reg.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
//@ add-core-stubs
//@ needs-asm-support
//@ revisions: s390x
//@ revisions: s390x s390x_vector
//@[s390x] compile-flags: --target s390x-unknown-linux-gnu
//@[s390x] needs-llvm-components: systemz
//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
//@[s390x_vector] needs-llvm-components: systemz

#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs)]
#![feature(asm_experimental_arch)]
#![feature(no_core, rustc_attrs, repr_simd)]
#![no_core]
#![allow(non_camel_case_types)]

extern crate minicore;
use minicore::*;

#[repr(simd)]
pub struct i64x2([i64; 2]);

impl Copy for i64x2 {}

fn f() {
let mut x = 0;
let mut v = i64x2([0; 2]);
unsafe {
// Unsupported registers
asm!("", out("r11") _);
Expand Down Expand Up @@ -57,6 +65,26 @@ fn f() {
asm!("", out("a1") _);
//~^ ERROR invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm

// vreg
asm!("", out("v0") _); // always ok
asm!("", in("v0") v); // requires vector
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
asm!("", out("v0") v); // requires vector
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
asm!("", in("v0") x);
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector]~^^ ERROR type `i32` cannot be used with this register class
asm!("", out("v0") x);
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector]~^^ ERROR type `i32` cannot be used with this register class
asm!("/* {} */", in(vreg) v); // requires vector
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
asm!("/* {} */", in(vreg) x);
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector]~^^ ERROR type `i32` cannot be used with this register class
asm!("/* {} */", out(vreg) _); // requires vector
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature

// Clobber-only registers
// areg
asm!("", out("a2") _); // ok
Expand All @@ -72,21 +100,6 @@ fn f() {
asm!("/* {} */", out(areg) _);
//~^ ERROR can only be used as a clobber

// vreg
asm!("", out("v0") _); // ok
// FIXME: will be supported in https://github.com/rust-lang/rust/pull/131664
asm!("", in("v0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("", out("v0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", in(vreg) x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", out(vreg) _);
//~^ ERROR can only be used as a clobber

// Overlapping registers
// vreg/freg
asm!("", out("v0") _, out("f0") _);
Expand Down
Loading

0 comments on commit d0a124a

Please sign in to comment.