Skip to content

Commit

Permalink
Support #[repr(simd)] types in input/output of PowerPC inline assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Nov 5, 2024
1 parent 27e38f8 commit 774db12
Show file tree
Hide file tree
Showing 12 changed files with 595 additions and 352 deletions.
10 changes: 6 additions & 4 deletions compiler/rustc_codegen_gcc/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,9 +653,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
Expand Down Expand Up @@ -729,9 +729,11 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
cx.type_vector(cx.type_i32(), 4)
}
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,9 +638,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
PowerPC(PowerPCInlineAsmRegClass::cr)
| PowerPC(PowerPCInlineAsmRegClass::xer)
| PowerPC(PowerPCInlineAsmRegClass::vreg) => {
PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
unreachable!("clobber-only")
}
RiscV(RiscVInlineAsmRegClass::reg) => "r",
Expand Down Expand Up @@ -802,9 +801,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
PowerPC(PowerPCInlineAsmRegClass::cr)
| PowerPC(PowerPCInlineAsmRegClass::xer)
| PowerPC(PowerPCInlineAsmRegClass::vreg) => {
PowerPC(PowerPCInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i32(), 4),
PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
unreachable!("clobber-only")
}
RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ symbols! {
allow_fail,
allow_internal_unsafe,
allow_internal_unstable,
altivec,
alu32,
always,
and,
Expand Down Expand Up @@ -2142,6 +2143,7 @@ symbols! {
volatile_store,
vreg,
vreg_low16,
vsx,
vtable_align,
vtable_size,
warn,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_target/src/asm/powerpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ impl PowerPCInlineAsmRegClass {
}
}
Self::freg => types! { _: F32, F64; },
Self::vreg => &[],
// FIXME: vsx also supports integers and floats: https://github.com/rust-lang/rust/pull/131551#discussion_r1797651773
Self::vreg => types! {
altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4);
vsx: VecI64(2), VecF64(2);
},
Self::cr | Self::xer => &[],
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` |
| PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` |
| PowerPC | `freg` | `f[0-31]` | `f` |
| PowerPC | `vreg` | `v[0-31]` | Only clobbers |
| PowerPC | `vreg` | `v[0-31]` | `v` |
| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
| PowerPC | `xer` | `xer` | Only clobbers |
| wasm32 | `local` | None\* | `r` |
Expand Down Expand Up @@ -80,7 +80,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `freg` | None | `f32`, `f64` |
| PowerPC | `vreg` | N/A | Only clobbers |
| PowerPC | `vreg` | `altivec` | `vector_bool_char`, `vector_bool_short`, `vector_bool_int`, `vector_signed_char`, `vector_signed_short`, `vector_signed_int`, `vector_unsigned_char`, `vector_unsigned_short`, `vector_unsigned_int`, `vector_float` |
| PowerPC | `vreg` | `vsx` | `vector_bool_long`, `vector_signed_long`, `vector_unsigned_long`, `vector_double` |
| PowerPC | `cr` | N/A | Only clobbers |
| PowerPC | `xer` | N/A | Only clobbers |
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
Expand Down Expand Up @@ -192,6 +193,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| PowerPC | `reg` | None | `0` | None |
| PowerPC | `reg_nonzero` | None | `3` | None |
| PowerPC | `freg` | None | `0` | None |
| PowerPC | `vreg` | None | `0` | None |
| s390x | `reg` | None | `%r0` | None |
| s390x | `reg_addr` | None | `%r1` | None |
| s390x | `freg` | None | `%f0` | None |
Expand Down
237 changes: 235 additions & 2 deletions tests/assembly/asm/powerpc-types.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
//@ revisions: powerpc powerpc64
//@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc64 powerpc64_vsx
//@ assembly-output: emit-asm
//@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
//@[powerpc] needs-llvm-components: powerpc
//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
//@[powerpc_altivec] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec --cfg altivec
//@[powerpc_altivec] needs-llvm-components: powerpc
//@[powerpc_vsx] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec,+vsx --cfg altivec --cfg vsx
//@[powerpc_vsx] needs-llvm-components: powerpc
//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu --cfg altivec
//@[powerpc64] needs-llvm-components: powerpc
//@[powerpc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx --cfg altivec --cfg vsx
//@[powerpc64_vsx] needs-llvm-components: powerpc
//@ compile-flags: -Zmerge-functions=disabled

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

#[cfg_attr(altivec, cfg(not(target_feature = "altivec")))]
#[cfg_attr(not(altivec), cfg(target_feature = "altivec"))]
compile_error!("altivec cfg and target feature mismatch");
#[cfg_attr(vsx, cfg(not(target_feature = "vsx")))]
#[cfg_attr(not(vsx), cfg(target_feature = "vsx"))]
compile_error!("vsx cfg and target feature mismatch");

#[rustc_builtin_macro]
macro_rules! asm {
() => {};
Expand All @@ -29,8 +42,23 @@ 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 {}
Expand All @@ -39,6 +67,13 @@ impl Copy for i64 {}
impl Copy for f32 {}
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 {}

extern "C" {
fn extern_func();
static extern_static: u8;
Expand Down Expand Up @@ -124,6 +159,72 @@ check!(reg_f32, f32, freg, "fmr");
// CHECK: #NO_APP
check!(reg_f64, f64, freg, "fmr");

// powerpc_altivec-LABEL: vreg_i8x16:
// powerpc_altivec: #APP
// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i8x16:
// powerpc64: #APP
// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc64: #NO_APP
#[cfg(altivec)]
check!(vreg_i8x16, i8x16, vreg, "vmr");

// powerpc_altivec-LABEL: vreg_i16x8:
// powerpc_altivec: #APP
// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i16x8:
// powerpc64: #APP
// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc64: #NO_APP
#[cfg(altivec)]
check!(vreg_i16x8, i16x8, vreg, "vmr");

// powerpc_altivec-LABEL: vreg_i32x4:
// powerpc_altivec: #APP
// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i32x4:
// powerpc64: #APP
// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc64: #NO_APP
#[cfg(altivec)]
check!(vreg_i32x4, i32x4, vreg, "vmr");

// powerpc_vsx-LABEL: vreg_i64x2:
// powerpc_vsx: #APP
// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc_vsx: #NO_APP
// powerpc64_vsx-LABEL: vreg_i64x2:
// powerpc64_vsx: #APP
// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc64_vsx: #NO_APP
#[cfg(vsx)]
check!(vreg_i64x2, i64x2, vreg, "vmr");

// powerpc_altivec-LABEL: vreg_f32x4:
// powerpc_altivec: #APP
// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_f32x4:
// powerpc64: #APP
// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc64: #NO_APP
#[cfg(altivec)]
check!(vreg_f32x4, f32x4, vreg, "vmr");

// powerpc_vsx-LABEL: vreg_f64x2:
// powerpc_vsx: #APP
// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc_vsx: #NO_APP
// powerpc64_vsx-LABEL: vreg_f64x2:
// powerpc64_vsx: #APP
// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}}
// powerpc64_vsx: #NO_APP
#[cfg(vsx)]
check!(vreg_f64x2, f64x2, vreg, "vmr");

// CHECK-LABEL: reg_i8_r0:
// CHECK: #APP
// CHECK: mr 0, 0
Expand Down Expand Up @@ -197,3 +298,135 @@ check_reg!(reg_f32_f18, f32, "18", "f18", "fmr");
// CHECK: fmr 18, 18
// CHECK: #NO_APP
check_reg!(reg_f64_f18, f64, "18", "f18", "fmr");

// powerpc_altivec-LABEL: vreg_i8x16_v0:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 0, 0
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i8x16_v0:
// powerpc64: #APP
// powerpc64: vmr 0, 0
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_i8x16_v0, i8x16, "0", "v0", "vmr");

// powerpc_altivec-LABEL: vreg_i16x8_v0:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 0, 0
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i16x8_v0:
// powerpc64: #APP
// powerpc64: vmr 0, 0
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_i16x8_v0, i16x8, "0", "v0", "vmr");

// powerpc_altivec-LABEL: vreg_i32x4_v0:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 0, 0
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i32x4_v0:
// powerpc64: #APP
// powerpc64: vmr 0, 0
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_i32x4_v0, i32x4, "0", "v0", "vmr");

// powerpc_vsx-LABEL: vreg_i64x2_v0:
// powerpc_vsx: #APP
// powerpc_vsx: vmr 0, 0
// powerpc_vsx: #NO_APP
// powerpc64_vsx-LABEL: vreg_i64x2_v0:
// powerpc64_vsx: #APP
// powerpc64_vsx: vmr 0, 0
// powerpc64_vsx: #NO_APP
#[cfg(vsx)]
check_reg!(vreg_i64x2_v0, i64x2, "0", "v0", "vmr");

// powerpc_altivec-LABEL: vreg_f32x4_v0:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 0, 0
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_f32x4_v0:
// powerpc64: #APP
// powerpc64: vmr 0, 0
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr");

// powerpc_vsx-LABEL: vreg_f64x2_v0:
// powerpc_vsx: #APP
// powerpc_vsx: vmr 0, 0
// powerpc_vsx: #NO_APP
// powerpc64_vsx-LABEL: vreg_f64x2_v0:
// powerpc64_vsx: #APP
// powerpc64_vsx: vmr 0, 0
// powerpc64_vsx: #NO_APP
#[cfg(vsx)]
check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr");

// powerpc_altivec-LABEL: vreg_i8x16_v18:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 18, 18
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i8x16_v18:
// powerpc64: #APP
// powerpc64: vmr 18, 18
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_i8x16_v18, i8x16, "18", "v18", "vmr");

// powerpc_altivec-LABEL: vreg_i16x8_v18:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 18, 18
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i16x8_v18:
// powerpc64: #APP
// powerpc64: vmr 18, 18
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_i16x8_v18, i16x8, "18", "v18", "vmr");

// powerpc_altivec-LABEL: vreg_i32x4_v18:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 18, 18
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_i32x4_v18:
// powerpc64: #APP
// powerpc64: vmr 18, 18
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_i32x4_v18, i32x4, "18", "v18", "vmr");

// powerpc_vsx-LABEL: vreg_i64x2_v18:
// powerpc_vsx: #APP
// powerpc_vsx: vmr 18, 18
// powerpc_vsx: #NO_APP
// powerpc64_vsx-LABEL: vreg_i64x2_v18:
// powerpc64_vsx: #APP
// powerpc64_vsx: vmr 18, 18
// powerpc64_vsx: #NO_APP
#[cfg(vsx)]
check_reg!(vreg_i64x2_v18, i64x2, "18", "v18", "vmr");

// powerpc_altivec-LABEL: vreg_f32x4_v18:
// powerpc_altivec: #APP
// powerpc_altivec: vmr 18, 18
// powerpc_altivec: #NO_APP
// powerpc64-LABEL: vreg_f32x4_v18:
// powerpc64: #APP
// powerpc64: vmr 18, 18
// powerpc64: #NO_APP
#[cfg(altivec)]
check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr");

// powerpc_vsx-LABEL: vreg_f64x2_v18:
// powerpc_vsx: #APP
// powerpc_vsx: vmr 18, 18
// powerpc_vsx: #NO_APP
// powerpc64_vsx-LABEL: vreg_f64x2_v18:
// powerpc64_vsx: #APP
// powerpc64_vsx: vmr 18, 18
// powerpc64_vsx: #NO_APP
#[cfg(vsx)]
check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr");
Loading

0 comments on commit 774db12

Please sign in to comment.