Support clobber_abi and vector registers (clobber-only) in PowerPC inline assembly

This commit is contained in:
Taiki Endo 2024-11-02 20:26:08 +09:00
parent 7c7bb7dc01
commit d19517dcd0
11 changed files with 1332 additions and 18 deletions

View File

@ -654,7 +654,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
@ -729,7 +730,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),

View File

@ -638,7 +638,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
PowerPC(PowerPCInlineAsmRegClass::reg) => "r", PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
PowerPC(PowerPCInlineAsmRegClass::freg) => "f", PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { PowerPC(PowerPCInlineAsmRegClass::cr)
| PowerPC(PowerPCInlineAsmRegClass::xer)
| PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
RiscV(RiscVInlineAsmRegClass::reg) => "r", RiscV(RiscVInlineAsmRegClass::reg) => "r",
@ -800,7 +802,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { PowerPC(PowerPCInlineAsmRegClass::cr)
| PowerPC(PowerPCInlineAsmRegClass::xer)
| PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),

View File

@ -893,6 +893,7 @@ pub enum InlineAsmClobberAbi {
Arm64EC, Arm64EC,
RiscV, RiscV,
LoongArch, LoongArch,
PowerPC,
S390x, S390x,
Msp430, Msp430,
} }
@ -944,6 +945,10 @@ impl InlineAsmClobberAbi {
"C" | "system" => Ok(InlineAsmClobberAbi::LoongArch), "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch),
_ => Err(&["C", "system"]), _ => Err(&["C", "system"]),
}, },
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => match name {
"C" | "system" => Ok(InlineAsmClobberAbi::PowerPC),
_ => Err(&["C", "system"]),
},
InlineAsmArch::S390x => match name { InlineAsmArch::S390x => match name {
"C" | "system" => Ok(InlineAsmClobberAbi::S390x), "C" | "system" => Ok(InlineAsmClobberAbi::S390x),
_ => Err(&["C", "system"]), _ => Err(&["C", "system"]),
@ -1121,6 +1126,31 @@ impl InlineAsmClobberAbi {
f16, f17, f18, f19, f20, f21, f22, f23, f16, f17, f18, f19, f20, f21, f22, f23,
} }
}, },
InlineAsmClobberAbi::PowerPC => clobbered_regs! {
PowerPC PowerPCInlineAsmReg {
// r0, r3-r12
r0,
r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12,
// f0-f13
f0, f1, f2, f3, f4, f5, f6, f7,
f8, f9, f10, f11, f12, f13,
// v0-v19
// FIXME: PPC32 SysV ABI does not mention vector registers processing.
// https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
v0, v1, v2, v3, v4, v5, v6, v7,
v8, v9, v10, v11, v12, v13, v14,
v15, v16, v17, v18, v19,
// cr0-cr1, cr5-cr7, xer
cr0, cr1,
cr5, cr6, cr7,
xer,
// lr and ctr are reserved
}
},
InlineAsmClobberAbi::S390x => clobbered_regs! { InlineAsmClobberAbi::S390x => clobbered_regs! {
S390x S390xInlineAsmReg { S390x S390xInlineAsmReg {
r0, r1, r2, r3, r4, r5, r0, r1, r2, r3, r4, r5,

View File

@ -1,14 +1,17 @@
use std::fmt; use std::fmt;
use rustc_data_structures::fx::FxIndexSet;
use rustc_span::Symbol; use rustc_span::Symbol;
use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use crate::spec::{RelocModel, Target};
def_reg_class! { def_reg_class! {
PowerPC PowerPCInlineAsmRegClass { PowerPC PowerPCInlineAsmRegClass {
reg, reg,
reg_nonzero, reg_nonzero,
freg, freg,
vreg,
cr, cr,
xer, xer,
} }
@ -48,11 +51,44 @@ impl PowerPCInlineAsmRegClass {
} }
} }
Self::freg => types! { _: F32, F64; }, Self::freg => types! { _: F32, F64; },
Self::vreg => &[],
Self::cr | Self::xer => &[], Self::cr | Self::xer => &[],
} }
} }
} }
fn reserved_r13(
arch: InlineAsmArch,
_reloc_model: RelocModel,
_target_features: &FxIndexSet<Symbol>,
target: &Target,
_is_clobber: bool,
) -> Result<(), &'static str> {
if target.is_like_aix && arch == InlineAsmArch::PowerPC {
Ok(())
} else {
Err("r13 is a reserved register on this target")
}
}
fn reserved_v20to31(
_arch: InlineAsmArch,
_reloc_model: RelocModel,
_target_features: &FxIndexSet<Symbol>,
target: &Target,
_is_clobber: bool,
) -> Result<(), &'static str> {
if target.is_like_aix {
match &*target.options.abi {
"vec-default" => Err("v20-v31 are reserved on vec-default ABI"),
"vec-extabi" => Ok(()),
_ => unreachable!("unrecognized AIX ABI"),
}
} else {
Ok(())
}
}
def_regs! { def_regs! {
PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass { PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass {
r0: reg = ["r0", "0"], r0: reg = ["r0", "0"],
@ -66,6 +102,7 @@ def_regs! {
r10: reg, reg_nonzero = ["r10", "10"], r10: reg, reg_nonzero = ["r10", "10"],
r11: reg, reg_nonzero = ["r11", "11"], r11: reg, reg_nonzero = ["r11", "11"],
r12: reg, reg_nonzero = ["r12", "12"], r12: reg, reg_nonzero = ["r12", "12"],
r13: reg, reg_nonzero = ["r13", "13"] % reserved_r13,
r14: reg, reg_nonzero = ["r14", "14"], r14: reg, reg_nonzero = ["r14", "14"],
r15: reg, reg_nonzero = ["r15", "15"], r15: reg, reg_nonzero = ["r15", "15"],
r16: reg, reg_nonzero = ["r16", "16"], r16: reg, reg_nonzero = ["r16", "16"],
@ -113,6 +150,38 @@ def_regs! {
f29: freg = ["f29", "fr29"], f29: freg = ["f29", "fr29"],
f30: freg = ["f30", "fr30"], f30: freg = ["f30", "fr30"],
f31: freg = ["f31", "fr31"], f31: freg = ["f31", "fr31"],
v0: vreg = ["v0"],
v1: vreg = ["v1"],
v2: vreg = ["v2"],
v3: vreg = ["v3"],
v4: vreg = ["v4"],
v5: vreg = ["v5"],
v6: vreg = ["v6"],
v7: vreg = ["v7"],
v8: vreg = ["v8"],
v9: vreg = ["v9"],
v10: vreg = ["v10"],
v11: vreg = ["v11"],
v12: vreg = ["v12"],
v13: vreg = ["v13"],
v14: vreg = ["v14"],
v15: vreg = ["v15"],
v16: vreg = ["v16"],
v17: vreg = ["v17"],
v18: vreg = ["v18"],
v19: vreg = ["v19"],
v20: vreg = ["v20"] % reserved_v20to31,
v21: vreg = ["v21"] % reserved_v20to31,
v22: vreg = ["v22"] % reserved_v20to31,
v23: vreg = ["v23"] % reserved_v20to31,
v24: vreg = ["v24"] % reserved_v20to31,
v25: vreg = ["v25"] % reserved_v20to31,
v26: vreg = ["v26"] % reserved_v20to31,
v27: vreg = ["v27"] % reserved_v20to31,
v28: vreg = ["v28"] % reserved_v20to31,
v29: vreg = ["v29"] % reserved_v20to31,
v30: vreg = ["v30"] % reserved_v20to31,
v31: vreg = ["v31"] % reserved_v20to31,
cr: cr = ["cr"], cr: cr = ["cr"],
cr0: cr = ["cr0"], cr0: cr = ["cr0"],
cr1: cr = ["cr1"], cr1: cr = ["cr1"],
@ -127,8 +196,6 @@ def_regs! {
"the stack pointer cannot be used as an operand for inline asm", "the stack pointer cannot be used as an operand for inline asm",
#error = ["r2", "2"] => #error = ["r2", "2"] =>
"r2 is a system reserved register and cannot be used as an operand for inline asm", "r2 is a system reserved register and cannot be used as an operand for inline asm",
#error = ["r13", "13"] =>
"r13 is a system reserved register and cannot be used as an operand for inline asm",
#error = ["r29", "29"] => #error = ["r29", "29"] =>
"r29 is used internally by LLVM and cannot be used as an operand for inline asm", "r29 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r30", "30"] => #error = ["r30", "30"] =>
@ -163,13 +230,17 @@ impl PowerPCInlineAsmReg {
// Strip off the leading prefix. // Strip off the leading prefix.
do_emit! { do_emit! {
(r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7"); (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"); (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r13, "13"), (r14, "14"), (r15, "15");
(r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23"); (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"); (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"); (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"); (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"); (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"); (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
(v0, "0"), (v1, "1"), (v2, "2"), (v3, "3"), (v4, "4"), (v5, "5"), (v6, "6"), (v7, "7");
(v8, "8"), (v9, "9"), (v10, "10"), (v11, "11"), (v12, "12"), (v13, "13"), (v14, "14"), (v15, "15");
(v16, "16"), (v17, "17"), (v18, "18"), (v19, "19"), (v20, "20"), (v21, "21"), (v22, "22"), (v23, "23");
(v24, "24"), (v25, "25"), (v26, "26"), (v27, "27"), (v28, "28"), (v29, "29"), (v30, "30"), (v31, "31");
(cr, "cr"); (cr, "cr");
(cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7"); (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
(xer, "xer"); (xer, "xer");
@ -201,5 +272,6 @@ impl PowerPCInlineAsmReg {
reg_conflicts! { reg_conflicts! {
cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7; cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7;
} }
// f0-f31 (vsr0-vsr31) and v0-v31 (vsr32-vsr63) do not conflict.
} }
} }

View File

@ -31,9 +31,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| NVPTX | `reg32` | None\* | `r` | | NVPTX | `reg32` | None\* | `r` |
| NVPTX | `reg64` | None\* | `l` | | NVPTX | `reg64` | None\* | `l` |
| Hexagon | `reg` | `r[0-28]` | `r` | | Hexagon | `reg` | `r[0-28]` | `r` |
| PowerPC | `reg` | `r[0-31]` | `r` | | PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` |
| PowerPC | `reg_nonzero` | `r[1-31]` | `b` | | PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` |
| PowerPC | `freg` | `f[0-31]` | `f` | | PowerPC | `freg` | `f[0-31]` | `f` |
| PowerPC | `vreg` | `v[0-31]` | Only clobbers |
| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | | PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
| PowerPC | `xer` | `xer` | Only clobbers | | PowerPC | `xer` | `xer` | Only clobbers |
| wasm32 | `local` | None\* | `r` | | wasm32 | `local` | None\* | `r` |
@ -76,9 +77,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | | NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| PowerPC | `reg` | None | `i8`, `i16`, `i32` | | PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `freg` | None | `f32`, `f64` | | PowerPC | `freg` | None | `f32`, `f64` |
| PowerPC | `vreg` | N/A | Only clobbers |
| PowerPC | `cr` | N/A | Only clobbers | | PowerPC | `cr` | N/A | Only clobbers |
| PowerPC | `xer` | N/A | Only clobbers | | PowerPC | `xer` | N/A | Only clobbers |
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
@ -105,6 +107,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| Hexagon | `r29` | `sp` | | Hexagon | `r29` | `sp` |
| Hexagon | `r30` | `fr` | | Hexagon | `r30` | `fr` |
| Hexagon | `r31` | `lr` | | Hexagon | `r31` | `lr` |
| PowerPC | `r1` | `sp` |
| PowerPC | `r31` | `fp` |
| PowerPC | `r[0-31]` | `[0-31]` |
| PowerPC | `f[0-31]` | `fr[0-31]`|
| BPF | `r[0-10]` | `w[0-10]` | | BPF | `r[0-10]` | `w[0-10]` |
| AVR | `XH` | `r27` | | AVR | `XH` | `r27` |
| AVR | `XL` | `r26` | | AVR | `XL` | `r26` |
@ -145,14 +151,18 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| Architecture | Unsupported register | Reason | | Architecture | Unsupported register | Reason |
| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. | | All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. |
| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. | | All | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. |
| All | `r19` (Hexagon), `x19` (Arm64EC) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | | All | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. |
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
| MIPS | `$1` or `$at` | Reserved for assembler. | | MIPS | `$1` or `$at` | Reserved for assembler. |
| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. | | MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. | | MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. |
| MIPS | `$ra` | Return address cannot be used as inputs or outputs. | | MIPS | `$ra` | Return address cannot be used as inputs or outputs. |
| Hexagon | `lr` | This is the link register which cannot be used as an input or output. | | Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
| PowerPC | `r2`, `r13` | These are system reserved registers. |
| PowerPC | `lr` | The link register cannot be used as an input or output. |
| PowerPC | `ctr` | The counter register cannot be used as an input or output. |
| PowerPC | `vrsave` | The vrsave register cannot be used as an input or output. |
| AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. |
|MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | |MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. |
| M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | | M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. |

View File

@ -1,10 +1,12 @@
//@ revisions: powerpc powerpc64 powerpc64le //@ revisions: powerpc powerpc64 powerpc64le aix64
//@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
//@[powerpc] needs-llvm-components: powerpc //@[powerpc] needs-llvm-components: powerpc
//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
//@[powerpc64] needs-llvm-components: powerpc //@[powerpc64] needs-llvm-components: powerpc
//@[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu //@[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
//@[powerpc64le] needs-llvm-components: powerpc //@[powerpc64le] needs-llvm-components: powerpc
//@[aix64] compile-flags: --target powerpc64-ibm-aix
//@[aix64] needs-llvm-components: powerpc
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] #![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
@ -22,26 +24,40 @@ macro_rules! asm {
// CHECK: call void asm sideeffect "", "~{cr}"() // CHECK: call void asm sideeffect "", "~{cr}"()
#[no_mangle] #[no_mangle]
pub unsafe fn cr_clobber() { pub unsafe fn cr_clobber() {
asm!("", out("cr") _, options(nostack, nomem)); asm!("", out("cr") _, options(nostack, nomem, preserves_flags));
} }
// CHECK-LABEL: @cr0_clobber // CHECK-LABEL: @cr0_clobber
// CHECK: call void asm sideeffect "", "~{cr0}"() // CHECK: call void asm sideeffect "", "~{cr0}"()
#[no_mangle] #[no_mangle]
pub unsafe fn cr0_clobber() { pub unsafe fn cr0_clobber() {
asm!("", out("cr0") _, options(nostack, nomem)); asm!("", out("cr0") _, options(nostack, nomem, preserves_flags));
} }
// CHECK-LABEL: @cr5_clobber // CHECK-LABEL: @cr5_clobber
// CHECK: call void asm sideeffect "", "~{cr5}"() // CHECK: call void asm sideeffect "", "~{cr5}"()
#[no_mangle] #[no_mangle]
pub unsafe fn cr5_clobber() { pub unsafe fn cr5_clobber() {
asm!("", out("cr5") _, options(nostack, nomem)); asm!("", out("cr5") _, options(nostack, nomem, preserves_flags));
} }
// CHECK-LABEL: @xer_clobber // CHECK-LABEL: @xer_clobber
// CHECK: call void asm sideeffect "", "~{xer}"() // CHECK: call void asm sideeffect "", "~{xer}"()
#[no_mangle] #[no_mangle]
pub unsafe fn xer_clobber() { pub unsafe fn xer_clobber() {
asm!("", out("xer") _, options(nostack, nomem)); asm!("", out("xer") _, options(nostack, nomem, preserves_flags));
}
// CHECK-LABEL: @v0_clobber
// CHECK: call void asm sideeffect "", "~{v0}"()
#[no_mangle]
pub unsafe fn v0_clobber() {
asm!("", out("v0") _, options(nostack, nomem, preserves_flags));
}
// CHECK-LABEL: @clobber_abi
// CHECK: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"()
#[no_mangle]
pub unsafe fn clobber_abi() {
asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
} }

View File

@ -0,0 +1,264 @@
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", out("sp") _);
| ^^^^^^^^^^^
error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:34:18
|
LL | asm!("", out("r2") _);
| ^^^^^^^^^^^
error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:38:18
|
LL | asm!("", out("r29") _);
| ^^^^^^^^^^^^
error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:40:18
|
LL | asm!("", out("r30") _);
| ^^^^^^^^^^^^
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:42:18
|
LL | asm!("", out("fp") _);
| ^^^^^^^^^^^
error: invalid register `lr`: the link register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:44:18
|
LL | asm!("", out("lr") _);
| ^^^^^^^^^^^
error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:46:18
|
LL | asm!("", out("ctr") _);
| ^^^^^^^^^^^^
error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:48:18
|
LL | asm!("", out("vrsave") _);
| ^^^^^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:66:18
|
LL | asm!("", in("cr") x);
| ^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:69:18
|
LL | asm!("", out("cr") x);
| ^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:72:26
|
LL | asm!("/* {} */", in(cr) x);
| ^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:75:26
|
LL | asm!("/* {} */", out(cr) _);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:79:18
|
LL | asm!("", in("xer") x);
| ^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:82:18
|
LL | asm!("", out("xer") x);
| ^^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:85:26
|
LL | asm!("/* {} */", in(xer) x);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:88:26
|
LL | asm!("/* {} */", out(xer) _);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:93:18
|
LL | asm!("", in("v0") x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:96:18
|
LL | asm!("", out("v0") x);
| ^^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:99:26
|
LL | asm!("/* {} */", in(vreg) x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:102:26
|
LL | asm!("/* {} */", out(vreg) _);
| ^^^^^^^^^^^
error: register `cr0` conflicts with register `cr`
--> $DIR/bad-reg.rs:106:31
|
LL | asm!("", out("cr") _, out("cr0") _);
| ----------- ^^^^^^^^^^^^ register `cr0`
| |
| register `cr`
error: register `cr1` conflicts with register `cr`
--> $DIR/bad-reg.rs:108:31
|
LL | asm!("", out("cr") _, out("cr1") _);
| ----------- ^^^^^^^^^^^^ register `cr1`
| |
| register `cr`
error: register `cr2` conflicts with register `cr`
--> $DIR/bad-reg.rs:110:31
|
LL | asm!("", out("cr") _, out("cr2") _);
| ----------- ^^^^^^^^^^^^ register `cr2`
| |
| register `cr`
error: register `cr3` conflicts with register `cr`
--> $DIR/bad-reg.rs:112:31
|
LL | asm!("", out("cr") _, out("cr3") _);
| ----------- ^^^^^^^^^^^^ register `cr3`
| |
| register `cr`
error: register `cr4` conflicts with register `cr`
--> $DIR/bad-reg.rs:114:31
|
LL | asm!("", out("cr") _, out("cr4") _);
| ----------- ^^^^^^^^^^^^ register `cr4`
| |
| register `cr`
error: register `cr5` conflicts with register `cr`
--> $DIR/bad-reg.rs:116:31
|
LL | asm!("", out("cr") _, out("cr5") _);
| ----------- ^^^^^^^^^^^^ register `cr5`
| |
| register `cr`
error: register `cr6` conflicts with register `cr`
--> $DIR/bad-reg.rs:118:31
|
LL | asm!("", out("cr") _, out("cr6") _);
| ----------- ^^^^^^^^^^^^ register `cr6`
| |
| register `cr`
error: register `cr7` conflicts with register `cr`
--> $DIR/bad-reg.rs:120:31
|
LL | asm!("", out("cr") _, out("cr7") _);
| ----------- ^^^^^^^^^^^^ register `cr7`
| |
| register `cr`
error: cannot use register `r13`: r13 is a reserved register on this target
--> $DIR/bad-reg.rs:36:18
|
LL | asm!("", out("r13") _);
| ^^^^^^^^^^^^
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:66:27
|
LL | asm!("", in("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:69:28
|
LL | asm!("", out("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:72:33
|
LL | asm!("/* {} */", in(cr) x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:79:28
|
LL | asm!("", in("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:82:29
|
LL | asm!("", out("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:85:34
|
LL | asm!("/* {} */", in(xer) x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:93:27
|
LL | asm!("", in("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:96:28
|
LL | asm!("", out("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:99:35
|
LL | asm!("/* {} */", in(vreg) x);
| ^
|
= note: register class `vreg` supports these types:
error: aborting due to 38 previous errors

View File

@ -0,0 +1,264 @@
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", out("sp") _);
| ^^^^^^^^^^^
error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:34:18
|
LL | asm!("", out("r2") _);
| ^^^^^^^^^^^
error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:38:18
|
LL | asm!("", out("r29") _);
| ^^^^^^^^^^^^
error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:40:18
|
LL | asm!("", out("r30") _);
| ^^^^^^^^^^^^
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:42:18
|
LL | asm!("", out("fp") _);
| ^^^^^^^^^^^
error: invalid register `lr`: the link register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:44:18
|
LL | asm!("", out("lr") _);
| ^^^^^^^^^^^
error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:46:18
|
LL | asm!("", out("ctr") _);
| ^^^^^^^^^^^^
error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:48:18
|
LL | asm!("", out("vrsave") _);
| ^^^^^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:66:18
|
LL | asm!("", in("cr") x);
| ^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:69:18
|
LL | asm!("", out("cr") x);
| ^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:72:26
|
LL | asm!("/* {} */", in(cr) x);
| ^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:75:26
|
LL | asm!("/* {} */", out(cr) _);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:79:18
|
LL | asm!("", in("xer") x);
| ^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:82:18
|
LL | asm!("", out("xer") x);
| ^^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:85:26
|
LL | asm!("/* {} */", in(xer) x);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:88:26
|
LL | asm!("/* {} */", out(xer) _);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:93:18
|
LL | asm!("", in("v0") x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:96:18
|
LL | asm!("", out("v0") x);
| ^^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:99:26
|
LL | asm!("/* {} */", in(vreg) x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:102:26
|
LL | asm!("/* {} */", out(vreg) _);
| ^^^^^^^^^^^
error: register `cr0` conflicts with register `cr`
--> $DIR/bad-reg.rs:106:31
|
LL | asm!("", out("cr") _, out("cr0") _);
| ----------- ^^^^^^^^^^^^ register `cr0`
| |
| register `cr`
error: register `cr1` conflicts with register `cr`
--> $DIR/bad-reg.rs:108:31
|
LL | asm!("", out("cr") _, out("cr1") _);
| ----------- ^^^^^^^^^^^^ register `cr1`
| |
| register `cr`
error: register `cr2` conflicts with register `cr`
--> $DIR/bad-reg.rs:110:31
|
LL | asm!("", out("cr") _, out("cr2") _);
| ----------- ^^^^^^^^^^^^ register `cr2`
| |
| register `cr`
error: register `cr3` conflicts with register `cr`
--> $DIR/bad-reg.rs:112:31
|
LL | asm!("", out("cr") _, out("cr3") _);
| ----------- ^^^^^^^^^^^^ register `cr3`
| |
| register `cr`
error: register `cr4` conflicts with register `cr`
--> $DIR/bad-reg.rs:114:31
|
LL | asm!("", out("cr") _, out("cr4") _);
| ----------- ^^^^^^^^^^^^ register `cr4`
| |
| register `cr`
error: register `cr5` conflicts with register `cr`
--> $DIR/bad-reg.rs:116:31
|
LL | asm!("", out("cr") _, out("cr5") _);
| ----------- ^^^^^^^^^^^^ register `cr5`
| |
| register `cr`
error: register `cr6` conflicts with register `cr`
--> $DIR/bad-reg.rs:118:31
|
LL | asm!("", out("cr") _, out("cr6") _);
| ----------- ^^^^^^^^^^^^ register `cr6`
| |
| register `cr`
error: register `cr7` conflicts with register `cr`
--> $DIR/bad-reg.rs:120:31
|
LL | asm!("", out("cr") _, out("cr7") _);
| ----------- ^^^^^^^^^^^^ register `cr7`
| |
| register `cr`
error: cannot use register `r13`: r13 is a reserved register on this target
--> $DIR/bad-reg.rs:36:18
|
LL | asm!("", out("r13") _);
| ^^^^^^^^^^^^
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:66:27
|
LL | asm!("", in("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:69:28
|
LL | asm!("", out("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:72:33
|
LL | asm!("/* {} */", in(cr) x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:79:28
|
LL | asm!("", in("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:82:29
|
LL | asm!("", out("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:85:34
|
LL | asm!("/* {} */", in(xer) x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:93:27
|
LL | asm!("", in("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:96:28
|
LL | asm!("", out("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:99:35
|
LL | asm!("/* {} */", in(vreg) x);
| ^
|
= note: register class `vreg` supports these types:
error: aborting due to 38 previous errors

View File

@ -0,0 +1,264 @@
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", out("sp") _);
| ^^^^^^^^^^^
error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:34:18
|
LL | asm!("", out("r2") _);
| ^^^^^^^^^^^
error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:38:18
|
LL | asm!("", out("r29") _);
| ^^^^^^^^^^^^
error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:40:18
|
LL | asm!("", out("r30") _);
| ^^^^^^^^^^^^
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:42:18
|
LL | asm!("", out("fp") _);
| ^^^^^^^^^^^
error: invalid register `lr`: the link register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:44:18
|
LL | asm!("", out("lr") _);
| ^^^^^^^^^^^
error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:46:18
|
LL | asm!("", out("ctr") _);
| ^^^^^^^^^^^^
error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:48:18
|
LL | asm!("", out("vrsave") _);
| ^^^^^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:66:18
|
LL | asm!("", in("cr") x);
| ^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:69:18
|
LL | asm!("", out("cr") x);
| ^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:72:26
|
LL | asm!("/* {} */", in(cr) x);
| ^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:75:26
|
LL | asm!("/* {} */", out(cr) _);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:79:18
|
LL | asm!("", in("xer") x);
| ^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:82:18
|
LL | asm!("", out("xer") x);
| ^^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:85:26
|
LL | asm!("/* {} */", in(xer) x);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:88:26
|
LL | asm!("/* {} */", out(xer) _);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:93:18
|
LL | asm!("", in("v0") x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:96:18
|
LL | asm!("", out("v0") x);
| ^^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:99:26
|
LL | asm!("/* {} */", in(vreg) x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:102:26
|
LL | asm!("/* {} */", out(vreg) _);
| ^^^^^^^^^^^
error: register `cr0` conflicts with register `cr`
--> $DIR/bad-reg.rs:106:31
|
LL | asm!("", out("cr") _, out("cr0") _);
| ----------- ^^^^^^^^^^^^ register `cr0`
| |
| register `cr`
error: register `cr1` conflicts with register `cr`
--> $DIR/bad-reg.rs:108:31
|
LL | asm!("", out("cr") _, out("cr1") _);
| ----------- ^^^^^^^^^^^^ register `cr1`
| |
| register `cr`
error: register `cr2` conflicts with register `cr`
--> $DIR/bad-reg.rs:110:31
|
LL | asm!("", out("cr") _, out("cr2") _);
| ----------- ^^^^^^^^^^^^ register `cr2`
| |
| register `cr`
error: register `cr3` conflicts with register `cr`
--> $DIR/bad-reg.rs:112:31
|
LL | asm!("", out("cr") _, out("cr3") _);
| ----------- ^^^^^^^^^^^^ register `cr3`
| |
| register `cr`
error: register `cr4` conflicts with register `cr`
--> $DIR/bad-reg.rs:114:31
|
LL | asm!("", out("cr") _, out("cr4") _);
| ----------- ^^^^^^^^^^^^ register `cr4`
| |
| register `cr`
error: register `cr5` conflicts with register `cr`
--> $DIR/bad-reg.rs:116:31
|
LL | asm!("", out("cr") _, out("cr5") _);
| ----------- ^^^^^^^^^^^^ register `cr5`
| |
| register `cr`
error: register `cr6` conflicts with register `cr`
--> $DIR/bad-reg.rs:118:31
|
LL | asm!("", out("cr") _, out("cr6") _);
| ----------- ^^^^^^^^^^^^ register `cr6`
| |
| register `cr`
error: register `cr7` conflicts with register `cr`
--> $DIR/bad-reg.rs:120:31
|
LL | asm!("", out("cr") _, out("cr7") _);
| ----------- ^^^^^^^^^^^^ register `cr7`
| |
| register `cr`
error: cannot use register `r13`: r13 is a reserved register on this target
--> $DIR/bad-reg.rs:36:18
|
LL | asm!("", out("r13") _);
| ^^^^^^^^^^^^
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:66:27
|
LL | asm!("", in("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:69:28
|
LL | asm!("", out("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:72:33
|
LL | asm!("/* {} */", in(cr) x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:79:28
|
LL | asm!("", in("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:82:29
|
LL | asm!("", out("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:85:34
|
LL | asm!("/* {} */", in(xer) x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:93:27
|
LL | asm!("", in("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:96:28
|
LL | asm!("", out("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:99:35
|
LL | asm!("/* {} */", in(vreg) x);
| ^
|
= note: register class `vreg` supports these types:
error: aborting due to 38 previous errors

View File

@ -0,0 +1,264 @@
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", out("sp") _);
| ^^^^^^^^^^^
error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:34:18
|
LL | asm!("", out("r2") _);
| ^^^^^^^^^^^
error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:38:18
|
LL | asm!("", out("r29") _);
| ^^^^^^^^^^^^
error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:40:18
|
LL | asm!("", out("r30") _);
| ^^^^^^^^^^^^
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:42:18
|
LL | asm!("", out("fp") _);
| ^^^^^^^^^^^
error: invalid register `lr`: the link register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:44:18
|
LL | asm!("", out("lr") _);
| ^^^^^^^^^^^
error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:46:18
|
LL | asm!("", out("ctr") _);
| ^^^^^^^^^^^^
error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:48:18
|
LL | asm!("", out("vrsave") _);
| ^^^^^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:66:18
|
LL | asm!("", in("cr") x);
| ^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:69:18
|
LL | asm!("", out("cr") x);
| ^^^^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:72:26
|
LL | asm!("/* {} */", in(cr) x);
| ^^^^^^^^
error: register class `cr` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:75:26
|
LL | asm!("/* {} */", out(cr) _);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:79:18
|
LL | asm!("", in("xer") x);
| ^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:82:18
|
LL | asm!("", out("xer") x);
| ^^^^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:85:26
|
LL | asm!("/* {} */", in(xer) x);
| ^^^^^^^^^
error: register class `xer` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:88:26
|
LL | asm!("/* {} */", out(xer) _);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:93:18
|
LL | asm!("", in("v0") x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:96:18
|
LL | asm!("", out("v0") x);
| ^^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:99:26
|
LL | asm!("/* {} */", in(vreg) x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:102:26
|
LL | asm!("/* {} */", out(vreg) _);
| ^^^^^^^^^^^
error: register `cr0` conflicts with register `cr`
--> $DIR/bad-reg.rs:106:31
|
LL | asm!("", out("cr") _, out("cr0") _);
| ----------- ^^^^^^^^^^^^ register `cr0`
| |
| register `cr`
error: register `cr1` conflicts with register `cr`
--> $DIR/bad-reg.rs:108:31
|
LL | asm!("", out("cr") _, out("cr1") _);
| ----------- ^^^^^^^^^^^^ register `cr1`
| |
| register `cr`
error: register `cr2` conflicts with register `cr`
--> $DIR/bad-reg.rs:110:31
|
LL | asm!("", out("cr") _, out("cr2") _);
| ----------- ^^^^^^^^^^^^ register `cr2`
| |
| register `cr`
error: register `cr3` conflicts with register `cr`
--> $DIR/bad-reg.rs:112:31
|
LL | asm!("", out("cr") _, out("cr3") _);
| ----------- ^^^^^^^^^^^^ register `cr3`
| |
| register `cr`
error: register `cr4` conflicts with register `cr`
--> $DIR/bad-reg.rs:114:31
|
LL | asm!("", out("cr") _, out("cr4") _);
| ----------- ^^^^^^^^^^^^ register `cr4`
| |
| register `cr`
error: register `cr5` conflicts with register `cr`
--> $DIR/bad-reg.rs:116:31
|
LL | asm!("", out("cr") _, out("cr5") _);
| ----------- ^^^^^^^^^^^^ register `cr5`
| |
| register `cr`
error: register `cr6` conflicts with register `cr`
--> $DIR/bad-reg.rs:118:31
|
LL | asm!("", out("cr") _, out("cr6") _);
| ----------- ^^^^^^^^^^^^ register `cr6`
| |
| register `cr`
error: register `cr7` conflicts with register `cr`
--> $DIR/bad-reg.rs:120:31
|
LL | asm!("", out("cr") _, out("cr7") _);
| ----------- ^^^^^^^^^^^^ register `cr7`
| |
| register `cr`
error: cannot use register `r13`: r13 is a reserved register on this target
--> $DIR/bad-reg.rs:36:18
|
LL | asm!("", out("r13") _);
| ^^^^^^^^^^^^
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:66:27
|
LL | asm!("", in("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:69:28
|
LL | asm!("", out("cr") x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:72:33
|
LL | asm!("/* {} */", in(cr) x);
| ^
|
= note: register class `cr` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:79:28
|
LL | asm!("", in("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:82:29
|
LL | asm!("", out("xer") x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:85:34
|
LL | asm!("/* {} */", in(xer) x);
| ^
|
= note: register class `xer` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:93:27
|
LL | asm!("", in("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:96:28
|
LL | asm!("", out("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:99:35
|
LL | asm!("/* {} */", in(vreg) x);
| ^
|
= note: register class `vreg` supports these types:
error: aborting due to 38 previous errors

View File

@ -0,0 +1,124 @@
//@ revisions: powerpc powerpc64 powerpc64le aix64
//@[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
//@[aix64] compile-flags: --target powerpc64-ibm-aix
//@[aix64] needs-llvm-components: powerpc
//@ needs-asm-support
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for i32 {}
#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
fn f() {
let mut x = 0;
unsafe {
// Unsupported registers
asm!("", out("sp") _);
//~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
asm!("", out("r2") _);
//~^ ERROR invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
asm!("", out("r13") _);
//~^ ERROR cannot use register `r13`: r13 is a reserved register on this target
asm!("", out("r29") _);
//~^ ERROR invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
asm!("", out("r30") _);
//~^ ERROR invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
asm!("", out("fp") _);
//~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
asm!("", out("lr") _);
//~^ ERROR invalid register `lr`: the link register cannot be used as an operand for inline asm
asm!("", out("ctr") _);
//~^ ERROR invalid register `ctr`: the counter register cannot be used as an operand for inline asm
asm!("", out("vrsave") _);
//~^ ERROR invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
asm!("", out("v20") _);
asm!("", out("v21") _);
asm!("", out("v22") _);
asm!("", out("v23") _);
asm!("", out("v24") _);
asm!("", out("v25") _);
asm!("", out("v26") _);
asm!("", out("v27") _);
asm!("", out("v28") _);
asm!("", out("v29") _);
asm!("", out("v30") _);
asm!("", out("v31") _);
// Clobber-only registers
// cr
asm!("", out("cr") _); // ok
asm!("", in("cr") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("", out("cr") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", in(cr) x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", out(cr) _);
//~^ ERROR can only be used as a clobber
// xer
asm!("", out("xer") _); // ok
asm!("", in("xer") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("", out("xer") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", in(xer) x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", out(xer) _);
//~^ ERROR can only be used as a clobber
// vreg
asm!("", out("v0") _); // ok
// FIXME: will be supported in the subsequent patch: https://github.com/rust-lang/rust/pull/131551
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-only registers
asm!("", out("cr") _, out("cr0") _);
//~^ ERROR register `cr0` conflicts with register `cr`
asm!("", out("cr") _, out("cr1") _);
//~^ ERROR register `cr1` conflicts with register `cr`
asm!("", out("cr") _, out("cr2") _);
//~^ ERROR register `cr2` conflicts with register `cr`
asm!("", out("cr") _, out("cr3") _);
//~^ ERROR register `cr3` conflicts with register `cr`
asm!("", out("cr") _, out("cr4") _);
//~^ ERROR register `cr4` conflicts with register `cr`
asm!("", out("cr") _, out("cr5") _);
//~^ ERROR register `cr5` conflicts with register `cr`
asm!("", out("cr") _, out("cr6") _);
//~^ ERROR register `cr6` conflicts with register `cr`
asm!("", out("cr") _, out("cr7") _);
//~^ ERROR register `cr7` conflicts with register `cr`
asm!("", out("f0") _, out("v0") _); // ok
}
}