about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorJacob Lifshay <programmerjake@gmail.com>2021-08-25 21:45:37 -0700
committerJacob Lifshay <programmerjake@gmail.com>2021-08-25 22:08:27 -0700
commit5802f60355b8b9a1eaf0c0fc193de3b9c48853df (patch)
treef84b7151d6d575c4dc005b0cc9b618d7a5b88a9c /compiler
parent0afc20860eb98a29d9bbeea80f2acc5be38c6bf3 (diff)
downloadrust-5802f60355b8b9a1eaf0c0fc193de3b9c48853df.tar.gz
rust-5802f60355b8b9a1eaf0c0fc193de3b9c48853df.zip
add support for clobbering xer, cr, and cr[0-7] for asm! on OpenPower/PowerPC
Fixes #88315
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs8
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/src/asm/mod.rs2
-rw-r--r--compiler/rustc_target/src/asm/powerpc.rs69
4 files changed, 71 insertions, 10 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 4387f5301a5..527ad1c7b0b 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -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) => {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f788eb7d212..8ce2e7b06f8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -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,
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index bb24f7bb135..2a3591566a9 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -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))),
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index 42fc25c4ff5..51a4303689e 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -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;
+        }
+    }
 }