Auto merge of #131341 - taiki-e:ppc-clobber-abi, r=bzEq,workingjubilee

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

This supports `clobber_abi` which is one of the requirements of stabilization mentioned in #93335.

This basically does a similar thing I did in https://github.com/rust-lang/rust/pull/130630 to implement `clobber_abi` for s390x, but for powerpc/powerpc64/powerpc64le.
- This also supports vector registers (as `vreg`) as clobber-only, which need to support clobbering of them to implement `clobber_abi`.
- `vreg` should be able to accept `#[repr(simd)]` types as input/output if the unstable `altivec` target feature is enabled, but `core::arch::{powerpc,powerpc64}` vector types, `#[repr(simd)]`, and `core::simd` are all unstable, so the fact that this is currently a clobber-only should not be considered a blocker of clobber_abi implementation or stabilization. So I have not implemented it in this PR.
  - See https://github.com/rust-lang/rust/pull/131551 (which is based on this PR) for a PR to implement this.
  - (I'm not sticking to whether that PR should be a separate PR or part of this PR, so I can merge that PR into this PR if needed.)

Refs:
- PPC32 SysV: Section "Function Calling Sequence" in [System V Application Binary Interface PowerPC Processor Supplement](https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf)
- PPC64 ELFv1: Section 3.2 "Function Calling Sequence" in [64-bit PowerPC ELF Application Binary Interface Supplement](https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-CALL)
- PPC64 ELFv2: Section 2.2 "Function Calling Sequence" in [64-Bit ELF V2 ABI Specification](https://openpowerfoundation.org/specifications/64bitelfabi/)
- AIX: [Register usage and conventions](https://www.ibm.com/docs/en/aix/7.3?topic=overview-register-usage-conventions), [Special registers in the PowerPC®](https://www.ibm.com/docs/en/aix/7.3?topic=overview-special-registers-in-powerpc), [AIX vector programming](https://www.ibm.com/docs/en/aix/7.3?topic=concepts-aix-vector-programming)
- Register definition in LLVM: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/PowerPC/PPCRegisterInfo.td#L189

If I understand the above four ABI documentations correctly, except for the PPC32 SysV's VR (Vector Registers) and 32-bit AIX (currently not supported by rustc)'s r13, there does not appear to be important differences in terms of implementing `clobber_abi`:
- The above four ABIs are consistent about FPR (0-13: volatile, 14-31: nonvolatile), CR (0-1,5-7: volatile, 2-4: nonvolatile), XER (volatile), and CTR (volatile).
- As for GPR, only the registers we are treating as reserved are slightly different
  - r0, r3-r12 are volatile
  - r1(sp, reserved), r14-31 are nonvolatile
  - r2(reserved) is TOC pointer in PPC64 ELF/AIX, system-reserved register in PPC32 SysV (AFAIK used as thread pointer in Linux/BSDs)
  - r13(reserved for non-32-bit-AIX) is thread pointer in PPC64 ELF, small data area pointer register in PPC32 SysV, "reserved under 64-bit environment; not restored across system calls[^r13]" in AIX)
- As for FPSCR, volatile in PPC64 ELFv1/AIX, some fields are volatile only in certain situations (rest are volatile) in PPC32 SysV/PPC64 ELFv2.
- As for VR (Vector Registers), it is not mentioned in PPC32 SysV, v0-v19 are volatile in both in PPC64 ELF/AIX, v20-v31 are nonvolatile in PPC64 ELF, reserved or nonvolatile depending on the ABI ([vec-extabi vs vec-default in LLVM](https://reviews.llvm.org/D89684), we are [using vec-extabi](https://github.com/rust-lang/rust/pull/131341#discussion_r1797693299)) in AIX:
  > When the default Vector enabled mode is used, these registers are reserved and must not be used.
  > In the extended ABI vector enabled mode, these registers are nonvolatile and their values are preserved across function calls

  I left [FIXME comment about PPC32 SysV](https://github.com/rust-lang/rust/pull/131341#discussion_r1790496095) and added ABI check for AIX.
- As for VRSAVE, it is not mentioned in PPC32 SysV, nonvolatile in PPC64 ELFv1, reserved in PPC64 ELFv2/AIX
- As for VSCR, it is not mentioned in PPC32 SysV/PPC64 ELFv1, some fields are volatile only in certain situations (rest are volatile) in PPC64 ELFv2, volatile in AIX

We are currently treating r1-r2, r13 (non-32-bit-AIX), r29-r31, LR, CTR, and VRSAVE as reserved.
We are currently not processing anything about FPSCR and VSCR, but I feel those are things that should be processed by `preserves_flags` rather than `clobber_abi` if we need to do something about them. (However, PPCRegisterInfo.td in LLVM does not seem to define anything about them.)

Replaces #111335 and #124279

cc `@ecnelises` `@bzEq` `@lu-zero`

r? `@Amanieu`

`@rustbot` label +O-PowerPC +A-inline-assembly

[^r13]: callee-saved, according to [LLVM](6a6af0246b/llvm/lib/Target/PowerPC/PPCCallingConv.td (L322)) and [GCC](a9173a50e7/gcc/config/rs6000/rs6000.h (L859)).
This commit is contained in:
bors 2024-11-05 03:13:47 +00:00
commit 96477c55bc
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::freg) => "f",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
}
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::freg) => cx.type_f64(),
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
}
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_nonzero) => "b",
PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
PowerPC(PowerPCInlineAsmRegClass::cr)
| PowerPC(PowerPCInlineAsmRegClass::xer)
| PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
}
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_nonzero) => cx.type_i32(),
PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
PowerPC(PowerPCInlineAsmRegClass::cr)
| PowerPC(PowerPCInlineAsmRegClass::xer)
| PowerPC(PowerPCInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
}
RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),

View File

@ -893,6 +893,7 @@ pub enum InlineAsmClobberAbi {
Arm64EC,
RiscV,
LoongArch,
PowerPC,
S390x,
Msp430,
}
@ -944,6 +945,10 @@ impl InlineAsmClobberAbi {
"C" | "system" => Ok(InlineAsmClobberAbi::LoongArch),
_ => Err(&["C", "system"]),
},
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => match name {
"C" | "system" => Ok(InlineAsmClobberAbi::PowerPC),
_ => Err(&["C", "system"]),
},
InlineAsmArch::S390x => match name {
"C" | "system" => Ok(InlineAsmClobberAbi::S390x),
_ => Err(&["C", "system"]),
@ -1121,6 +1126,31 @@ impl InlineAsmClobberAbi {
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! {
S390x S390xInlineAsmReg {
r0, r1, r2, r3, r4, r5,

View File

@ -1,14 +1,17 @@
use std::fmt;
use rustc_data_structures::fx::FxIndexSet;
use rustc_span::Symbol;
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use crate::spec::{RelocModel, Target};
def_reg_class! {
PowerPC PowerPCInlineAsmRegClass {
reg,
reg_nonzero,
freg,
vreg,
cr,
xer,
}
@ -48,11 +51,44 @@ impl PowerPCInlineAsmRegClass {
}
}
Self::freg => types! { _: F32, F64; },
Self::vreg => &[],
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! {
PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass {
r0: reg = ["r0", "0"],
@ -66,6 +102,7 @@ def_regs! {
r10: reg, reg_nonzero = ["r10", "10"],
r11: reg, reg_nonzero = ["r11", "11"],
r12: reg, reg_nonzero = ["r12", "12"],
r13: reg, reg_nonzero = ["r13", "13"] % reserved_r13,
r14: reg, reg_nonzero = ["r14", "14"],
r15: reg, reg_nonzero = ["r15", "15"],
r16: reg, reg_nonzero = ["r16", "16"],
@ -113,6 +150,38 @@ def_regs! {
f29: freg = ["f29", "fr29"],
f30: freg = ["f30", "fr30"],
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"],
cr0: cr = ["cr0"],
cr1: cr = ["cr1"],
@ -127,8 +196,6 @@ def_regs! {
"the stack pointer cannot be used as an operand for inline asm",
#error = ["r2", "2"] =>
"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"] =>
"r29 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r30", "30"] =>
@ -163,13 +230,17 @@ impl PowerPCInlineAsmReg {
// Strip off the leading prefix.
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");
(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");
(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");
(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");
(cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
(xer, "xer");
@ -201,5 +272,6 @@ impl PowerPCInlineAsmReg {
reg_conflicts! {
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 | `reg64` | None\* | `l` |
| Hexagon | `reg` | `r[0-28]` | `r` |
| PowerPC | `reg` | `r[0-31]` | `r` |
| PowerPC | `reg_nonzero` | `r[1-31]` | `b` |
| 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 | `cr` | `cr[0-7]`, `cr` | Only clobbers |
| PowerPC | `xer` | `xer` | Only clobbers |
| 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 | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
| 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 | `cr` | N/A | Only clobbers |
| PowerPC | `xer` | N/A | Only clobbers |
| 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 | `r30` | `fr` |
| 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]` |
| AVR | `XH` | `r27` |
| AVR | `XL` | `r26` |
@ -145,14 +151,18 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| 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 | `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 | `r19` (Hexagon), `x19` (Arm64EC) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
| 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), `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 | `$1` or `$at` | Reserved for assembler. |
| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
| MIPS | `$28`/`$gp` | Global pointer 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. |
| 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. |
|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. |

View File

@ -1,10 +1,12 @@
//@ revisions: powerpc powerpc64 powerpc64le
//@ 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
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
@ -22,26 +24,40 @@ macro_rules! asm {
// CHECK: call void asm sideeffect "", "~{cr}"()
#[no_mangle]
pub unsafe fn cr_clobber() {
asm!("", out("cr") _, options(nostack, nomem));
asm!("", out("cr") _, options(nostack, nomem, preserves_flags));
}
// CHECK-LABEL: @cr0_clobber
// CHECK: call void asm sideeffect "", "~{cr0}"()
#[no_mangle]
pub unsafe fn cr0_clobber() {
asm!("", out("cr0") _, options(nostack, nomem));
asm!("", out("cr0") _, options(nostack, nomem, preserves_flags));
}
// CHECK-LABEL: @cr5_clobber
// CHECK: call void asm sideeffect "", "~{cr5}"()
#[no_mangle]
pub unsafe fn cr5_clobber() {
asm!("", out("cr5") _, options(nostack, nomem));
asm!("", out("cr5") _, options(nostack, nomem, preserves_flags));
}
// CHECK-LABEL: @xer_clobber
// CHECK: call void asm sideeffect "", "~{xer}"()
#[no_mangle]
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
}
}