Skip to content

Commit 5802f60

Browse files
committedAug 26, 2021
add support for clobbering xer, cr, and cr[0-7] for asm! on OpenPower/PowerPC
Fixes #88315
1 parent 0afc208 commit 5802f60

File tree

7 files changed

+135
-10
lines changed

7 files changed

+135
-10
lines changed
 

‎compiler/rustc_codegen_llvm/src/asm.rs

+8
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,10 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
615615
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
616616
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
617617
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
618+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
619+
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
620+
unreachable!("clobber-only")
621+
}
618622
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
619623
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
620624
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
@@ -751,6 +755,10 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
751755
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
752756
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
753757
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
758+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
759+
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
760+
unreachable!("clobber-only")
761+
}
754762
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
755763
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
756764
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {

‎compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ symbols! {
478478
core_panic_macro,
479479
cosf32,
480480
cosf64,
481+
cr,
481482
crate_id,
482483
crate_in_paths,
483484
crate_local,
@@ -1415,6 +1416,7 @@ symbols! {
14151416
wreg,
14161417
write_bytes,
14171418
x87_reg,
1419+
xer,
14181420
xmm_reg,
14191421
ymm_reg,
14201422
zmm_reg,

‎compiler/rustc_target/src/asm/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ impl InlineAsmReg {
344344
Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
345345
Self::AArch64(_) => cb(self),
346346
Self::RiscV(_) => cb(self),
347-
Self::PowerPC(_) => cb(self),
347+
Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))),
348348
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
349349
Self::Mips(_) => cb(self),
350350
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),

‎compiler/rustc_target/src/asm/powerpc.rs

+60-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ def_reg_class! {
77
reg,
88
reg_nonzero,
99
freg,
10+
cr,
11+
xer,
1012
}
1113
}
1214

@@ -44,6 +46,7 @@ impl PowerPCInlineAsmRegClass {
4446
}
4547
}
4648
Self::freg => types! { _: F32, F64; },
49+
Self::cr | Self::xer => &[],
4750
}
4851
}
4952
}
@@ -108,6 +111,16 @@ def_regs! {
108111
f29: freg = ["f29", "fr29"],
109112
f30: freg = ["f30", "fr30"],
110113
f31: freg = ["f31", "fr31"],
114+
cr: cr = ["cr"],
115+
cr0: cr = ["cr0"],
116+
cr1: cr = ["cr1"],
117+
cr2: cr = ["cr2"],
118+
cr3: cr = ["cr3"],
119+
cr4: cr = ["cr4"],
120+
cr5: cr = ["cr5"],
121+
cr6: cr = ["cr6"],
122+
cr7: cr = ["cr7"],
123+
xer: xer = ["xer"],
111124
#error = ["r1", "1", "sp"] =>
112125
"the stack pointer cannot be used as an operand for inline asm",
113126
#error = ["r2", "2"] =>
@@ -136,17 +149,55 @@ impl PowerPCInlineAsmReg {
136149
_arch: InlineAsmArch,
137150
_modifier: Option<char>,
138151
) -> fmt::Result {
152+
macro_rules! do_emit {
153+
(
154+
$($(($reg:ident, $value:literal)),*;)*
155+
) => {
156+
out.write_str(match self {
157+
$($(Self::$reg => $value,)*)*
158+
})
159+
};
160+
}
139161
// Strip off the leading prefix.
140-
if self as u32 <= Self::r28 as u32 {
141-
let index = self as u32 - Self::r28 as u32;
142-
write!(out, "{}", index)
143-
} else if self as u32 >= Self::f0 as u32 && self as u32 <= Self::f31 as u32 {
144-
let index = self as u32 - Self::f31 as u32;
145-
write!(out, "{}", index)
146-
} else {
147-
unreachable!()
162+
do_emit! {
163+
(r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7");
164+
(r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r14, "14"), (r15, "15");
165+
(r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23");
166+
(r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28");
167+
(f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7");
168+
(f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15");
169+
(f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23");
170+
(f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
171+
(cr, "cr");
172+
(cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
173+
(xer, "xer");
148174
}
149175
}
150176

151-
pub fn overlapping_regs(self, mut _cb: impl FnMut(PowerPCInlineAsmReg)) {}
177+
pub fn overlapping_regs(self, mut cb: impl FnMut(PowerPCInlineAsmReg)) {
178+
macro_rules! reg_conflicts {
179+
(
180+
$(
181+
$full:ident : $($field:ident)*
182+
),*;
183+
) => {
184+
match self {
185+
$(
186+
Self::$full => {
187+
cb(Self::$full);
188+
$(cb(Self::$field);)*
189+
}
190+
$(Self::$field)|* => {
191+
cb(Self::$full);
192+
cb(self);
193+
}
194+
)*
195+
r => cb(r),
196+
}
197+
};
198+
}
199+
reg_conflicts! {
200+
cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7;
201+
}
202+
}
152203
}

‎src/doc/unstable-book/src/library-features/asm.md

+4
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,8 @@ Here is the list of currently supported register classes:
584584
| PowerPC | `reg` | `r[0-31]` | `r` |
585585
| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
586586
| PowerPC | `freg` | `f[0-31]` | `f` |
587+
| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
588+
| PowerPC | `xer` | `xer` | Only clobbers |
587589
| wasm32 | `local` | None\* | `r` |
588590
| BPF | `reg` | `r[0-10]` | `r` |
589591
| BPF | `wreg` | `w[0-10]` | `w` |
@@ -637,6 +639,8 @@ Each register class has constraints on which value types they can be used with.
637639
| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
638640
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
639641
| PowerPC | `freg` | None | `f32`, `f64` |
642+
| PowerPC | `cr` | N/A | Only clobbers |
643+
| PowerPC | `xer` | N/A | Only clobbers |
640644
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
641645
| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
642646
| BPF | `wreg` | `alu32` | `i8` `i16` `i32` |

‎src/test/assembly/asm/powerpc-types.rs

+12
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,15 @@ check_reg!(reg_f32_f0, f32, "0", "f0", "fmr");
194194
// CHECK: fmr 0, 0
195195
// CHECK: #NO_APP
196196
check_reg!(reg_f64_f0, f64, "0", "f0", "fmr");
197+
198+
// CHECK-LABEL: reg_f32_f18:
199+
// CHECK: #APP
200+
// CHECK: fmr 18, 18
201+
// CHECK: #NO_APP
202+
check_reg!(reg_f32_f18, f32, "18", "f18", "fmr");
203+
204+
// CHECK-LABEL: reg_f64_f18:
205+
// CHECK: #APP
206+
// CHECK: fmr 18, 18
207+
// CHECK: #NO_APP
208+
check_reg!(reg_f64_f18, f64, "18", "f18", "fmr");
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// min-llvm-version: 10.0.1
2+
// revisions: powerpc powerpc64 powerpc64le
3+
//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
4+
//[powerpc] needs-llvm-components: powerpc
5+
//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
6+
//[powerpc64] needs-llvm-components: powerpc
7+
//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
8+
//[powerpc64le] needs-llvm-components: powerpc
9+
10+
#![crate_type = "rlib"]
11+
#![feature(no_core, rustc_attrs, lang_items)]
12+
#![no_core]
13+
14+
#[lang = "sized"]
15+
trait Sized {}
16+
17+
#[rustc_builtin_macro]
18+
macro_rules! asm {
19+
() => {};
20+
}
21+
22+
// CHECK-LABEL: @cr_clobber
23+
// CHECK: call void asm sideeffect "", "~{cr}"()
24+
#[no_mangle]
25+
pub unsafe fn cr_clobber() {
26+
asm!("", out("cr") _, options(nostack, nomem));
27+
}
28+
29+
// CHECK-LABEL: @cr0_clobber
30+
// CHECK: call void asm sideeffect "", "~{cr0}"()
31+
#[no_mangle]
32+
pub unsafe fn cr0_clobber() {
33+
asm!("", out("cr0") _, options(nostack, nomem));
34+
}
35+
36+
// CHECK-LABEL: @cr5_clobber
37+
// CHECK: call void asm sideeffect "", "~{cr5}"()
38+
#[no_mangle]
39+
pub unsafe fn cr5_clobber() {
40+
asm!("", out("cr5") _, options(nostack, nomem));
41+
}
42+
43+
// CHECK-LABEL: @xer_clobber
44+
// CHECK: call void asm sideeffect "", "~{xer}"()
45+
#[no_mangle]
46+
pub unsafe fn xer_clobber() {
47+
asm!("", out("xer") _, options(nostack, nomem));
48+
}

0 commit comments

Comments
 (0)
Please sign in to comment.