mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
add support for clobbering xer, cr, and cr[0-7] for asm! on OpenPower/PowerPC
Fixes #88315
This commit is contained in:
parent
0afc20860e
commit
5802f60355
@ -615,6 +615,10 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
||||
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
|
||||
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
|
||||
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
|
||||
@ -751,6 +755,10 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
|
||||
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::cr)
|
||||
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
|
||||
|
@ -478,6 +478,7 @@ symbols! {
|
||||
core_panic_macro,
|
||||
cosf32,
|
||||
cosf64,
|
||||
cr,
|
||||
crate_id,
|
||||
crate_in_paths,
|
||||
crate_local,
|
||||
@ -1415,6 +1416,7 @@ symbols! {
|
||||
wreg,
|
||||
write_bytes,
|
||||
x87_reg,
|
||||
xer,
|
||||
xmm_reg,
|
||||
ymm_reg,
|
||||
zmm_reg,
|
||||
|
@ -344,7 +344,7 @@ impl InlineAsmReg {
|
||||
Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
|
||||
Self::AArch64(_) => cb(self),
|
||||
Self::RiscV(_) => cb(self),
|
||||
Self::PowerPC(_) => cb(self),
|
||||
Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))),
|
||||
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
|
||||
Self::Mips(_) => cb(self),
|
||||
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
|
||||
|
@ -7,6 +7,8 @@ def_reg_class! {
|
||||
reg,
|
||||
reg_nonzero,
|
||||
freg,
|
||||
cr,
|
||||
xer,
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +46,7 @@ impl PowerPCInlineAsmRegClass {
|
||||
}
|
||||
}
|
||||
Self::freg => types! { _: F32, F64; },
|
||||
Self::cr | Self::xer => &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -108,6 +111,16 @@ def_regs! {
|
||||
f29: freg = ["f29", "fr29"],
|
||||
f30: freg = ["f30", "fr30"],
|
||||
f31: freg = ["f31", "fr31"],
|
||||
cr: cr = ["cr"],
|
||||
cr0: cr = ["cr0"],
|
||||
cr1: cr = ["cr1"],
|
||||
cr2: cr = ["cr2"],
|
||||
cr3: cr = ["cr3"],
|
||||
cr4: cr = ["cr4"],
|
||||
cr5: cr = ["cr5"],
|
||||
cr6: cr = ["cr6"],
|
||||
cr7: cr = ["cr7"],
|
||||
xer: xer = ["xer"],
|
||||
#error = ["r1", "1", "sp"] =>
|
||||
"the stack pointer cannot be used as an operand for inline asm",
|
||||
#error = ["r2", "2"] =>
|
||||
@ -136,17 +149,55 @@ impl PowerPCInlineAsmReg {
|
||||
_arch: InlineAsmArch,
|
||||
_modifier: Option<char>,
|
||||
) -> fmt::Result {
|
||||
macro_rules! do_emit {
|
||||
(
|
||||
$($(($reg:ident, $value:literal)),*;)*
|
||||
) => {
|
||||
out.write_str(match self {
|
||||
$($(Self::$reg => $value,)*)*
|
||||
})
|
||||
};
|
||||
}
|
||||
// Strip off the leading prefix.
|
||||
if self as u32 <= Self::r28 as u32 {
|
||||
let index = self as u32 - Self::r28 as u32;
|
||||
write!(out, "{}", index)
|
||||
} else if self as u32 >= Self::f0 as u32 && self as u32 <= Self::f31 as u32 {
|
||||
let index = self as u32 - Self::f31 as u32;
|
||||
write!(out, "{}", index)
|
||||
} else {
|
||||
unreachable!()
|
||||
do_emit! {
|
||||
(r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7");
|
||||
(r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r14, "14"), (r15, "15");
|
||||
(r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23");
|
||||
(r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28");
|
||||
(f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7");
|
||||
(f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15");
|
||||
(f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23");
|
||||
(f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
|
||||
(cr, "cr");
|
||||
(cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
|
||||
(xer, "xer");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn overlapping_regs(self, mut _cb: impl FnMut(PowerPCInlineAsmReg)) {}
|
||||
pub fn overlapping_regs(self, mut cb: impl FnMut(PowerPCInlineAsmReg)) {
|
||||
macro_rules! reg_conflicts {
|
||||
(
|
||||
$(
|
||||
$full:ident : $($field:ident)*
|
||||
),*;
|
||||
) => {
|
||||
match self {
|
||||
$(
|
||||
Self::$full => {
|
||||
cb(Self::$full);
|
||||
$(cb(Self::$field);)*
|
||||
}
|
||||
$(Self::$field)|* => {
|
||||
cb(Self::$full);
|
||||
cb(self);
|
||||
}
|
||||
)*
|
||||
r => cb(r),
|
||||
}
|
||||
};
|
||||
}
|
||||
reg_conflicts! {
|
||||
cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -584,6 +584,8 @@ Here is the list of currently supported register classes:
|
||||
| PowerPC | `reg` | `r[0-31]` | `r` |
|
||||
| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
|
||||
| PowerPC | `freg` | `f[0-31]` | `f` |
|
||||
| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
|
||||
| PowerPC | `xer` | `xer` | Only clobbers |
|
||||
| wasm32 | `local` | None\* | `r` |
|
||||
| BPF | `reg` | `r[0-10]` | `r` |
|
||||
| BPF | `wreg` | `w[0-10]` | `w` |
|
||||
@ -637,6 +639,8 @@ Each register class has constraints on which value types they can be used with.
|
||||
| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
|
||||
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
|
||||
| PowerPC | `freg` | None | `f32`, `f64` |
|
||||
| PowerPC | `cr` | N/A | Only clobbers |
|
||||
| PowerPC | `xer` | N/A | Only clobbers |
|
||||
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
|
||||
| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
|
||||
| BPF | `wreg` | `alu32` | `i8` `i16` `i32` |
|
||||
|
@ -194,3 +194,15 @@ check_reg!(reg_f32_f0, f32, "0", "f0", "fmr");
|
||||
// CHECK: fmr 0, 0
|
||||
// CHECK: #NO_APP
|
||||
check_reg!(reg_f64_f0, f64, "0", "f0", "fmr");
|
||||
|
||||
// CHECK-LABEL: reg_f32_f18:
|
||||
// CHECK: #APP
|
||||
// CHECK: fmr 18, 18
|
||||
// CHECK: #NO_APP
|
||||
check_reg!(reg_f32_f18, f32, "18", "f18", "fmr");
|
||||
|
||||
// CHECK-LABEL: reg_f64_f18:
|
||||
// CHECK: #APP
|
||||
// CHECK: fmr 18, 18
|
||||
// CHECK: #NO_APP
|
||||
check_reg!(reg_f64_f18, f64, "18", "f18", "fmr");
|
||||
|
48
src/test/codegen/asm-powerpc-clobbers.rs
Normal file
48
src/test/codegen/asm-powerpc-clobbers.rs
Normal file
@ -0,0 +1,48 @@
|
||||
// min-llvm-version: 10.0.1
|
||||
// revisions: powerpc powerpc64 powerpc64le
|
||||
//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
|
||||
//[powerpc] needs-llvm-components: powerpc
|
||||
//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
|
||||
//[powerpc64] needs-llvm-components: powerpc
|
||||
//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
|
||||
//[powerpc64le] needs-llvm-components: powerpc
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(no_core, rustc_attrs, lang_items)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! asm {
|
||||
() => {};
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @cr_clobber
|
||||
// CHECK: call void asm sideeffect "", "~{cr}"()
|
||||
#[no_mangle]
|
||||
pub unsafe fn cr_clobber() {
|
||||
asm!("", out("cr") _, options(nostack, nomem));
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @cr0_clobber
|
||||
// CHECK: call void asm sideeffect "", "~{cr0}"()
|
||||
#[no_mangle]
|
||||
pub unsafe fn cr0_clobber() {
|
||||
asm!("", out("cr0") _, options(nostack, nomem));
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @cr5_clobber
|
||||
// CHECK: call void asm sideeffect "", "~{cr5}"()
|
||||
#[no_mangle]
|
||||
pub unsafe fn cr5_clobber() {
|
||||
asm!("", out("cr5") _, options(nostack, nomem));
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @xer_clobber
|
||||
// CHECK: call void asm sideeffect "", "~{xer}"()
|
||||
#[no_mangle]
|
||||
pub unsafe fn xer_clobber() {
|
||||
asm!("", out("xer") _, options(nostack, nomem));
|
||||
}
|
Loading…
Reference in New Issue
Block a user