Rollup merge of #133422 - taiki-e:riscv-e-clobber-abi, r=Amanieu
Fix clobber_abi in RV32E and RV64E inline assembly Currently clobber_abi in RV32E and RV64E inline assembly is implemented using InlineAsmClobberAbi::RiscV, but broken since x16-x31 cannot be used in RV32E and RV64E. ``` error: cannot use register `x16`: register can't be used with the `e` target feature --> <source>:42:14 | 42 | asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); | ^^^^^^^^^^^^^^^^ error: cannot use register `x17`: register can't be used with the `e` target feature --> <source>:42:14 | 42 | asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); | ^^^^^^^^^^^^^^^^ error: cannot use register `x28`: register can't be used with the `e` target feature --> <source>:42:14 | 42 | asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); | ^^^^^^^^^^^^^^^^ error: cannot use register `x29`: register can't be used with the `e` target feature --> <source>:42:14 | 42 | asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); | ^^^^^^^^^^^^^^^^ error: cannot use register `x30`: register can't be used with the `e` target feature --> <source>:42:14 | 42 | asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); | ^^^^^^^^^^^^^^^^ error: cannot use register `x31`: register can't be used with the `e` target feature --> <source>:42:14 | 42 | asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); | ^^^^^^^^^^^^^^^^ ``` r? `@Amanieu` `@rustbot` label O-riscv +A-inline-assembly
This commit is contained in:
commit
89ae19ee0d
5 changed files with 95 additions and 6 deletions
|
@ -82,7 +82,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let mut clobber_abis = FxIndexMap::default();
|
let mut clobber_abis = FxIndexMap::default();
|
||||||
if let Some(asm_arch) = asm_arch {
|
if let Some(asm_arch) = asm_arch {
|
||||||
for (abi_name, abi_span) in &asm.clobber_abis {
|
for (abi_name, abi_span) in &asm.clobber_abis {
|
||||||
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) {
|
match asm::InlineAsmClobberAbi::parse(
|
||||||
|
asm_arch,
|
||||||
|
&self.tcx.sess.target,
|
||||||
|
&self.tcx.sess.unstable_target_features,
|
||||||
|
*abi_name,
|
||||||
|
) {
|
||||||
Ok(abi) => {
|
Ok(abi) => {
|
||||||
// If the abi was already in the list, emit an error
|
// If the abi was already in the list, emit an error
|
||||||
match clobber_abis.get(&abi) {
|
match clobber_abis.get(&abi) {
|
||||||
|
|
|
@ -476,9 +476,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
|
||||||
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
|
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
|
||||||
|
|
||||||
// Allocate stack slots for saving clobbered registers
|
// Allocate stack slots for saving clobbered registers
|
||||||
let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C)
|
let abi_clobber = InlineAsmClobberAbi::parse(
|
||||||
.unwrap()
|
self.arch,
|
||||||
.clobbered_regs();
|
&self.tcx.sess.target,
|
||||||
|
&self.tcx.sess.unstable_target_features,
|
||||||
|
sym::C,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.clobbered_regs();
|
||||||
for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) {
|
for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) {
|
||||||
let mut need_save = true;
|
let mut need_save = true;
|
||||||
// If the register overlaps with a register clobbered by function call, then
|
// If the register overlaps with a register clobbered by function call, then
|
||||||
|
|
|
@ -929,6 +929,7 @@ pub enum InlineAsmClobberAbi {
|
||||||
AArch64NoX18,
|
AArch64NoX18,
|
||||||
Arm64EC,
|
Arm64EC,
|
||||||
RiscV,
|
RiscV,
|
||||||
|
RiscVE,
|
||||||
LoongArch,
|
LoongArch,
|
||||||
PowerPC,
|
PowerPC,
|
||||||
S390x,
|
S390x,
|
||||||
|
@ -941,6 +942,7 @@ impl InlineAsmClobberAbi {
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
arch: InlineAsmArch,
|
arch: InlineAsmArch,
|
||||||
target: &Target,
|
target: &Target,
|
||||||
|
target_features: &FxIndexSet<Symbol>,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
) -> Result<Self, &'static [&'static str]> {
|
) -> Result<Self, &'static [&'static str]> {
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
|
@ -975,7 +977,11 @@ impl InlineAsmClobberAbi {
|
||||||
_ => Err(&["C", "system"]),
|
_ => Err(&["C", "system"]),
|
||||||
},
|
},
|
||||||
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
|
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
|
||||||
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV),
|
"C" | "system" | "efiapi" => Ok(if riscv::is_e(target_features) {
|
||||||
|
InlineAsmClobberAbi::RiscVE
|
||||||
|
} else {
|
||||||
|
InlineAsmClobberAbi::RiscV
|
||||||
|
}),
|
||||||
_ => Err(&["C", "system", "efiapi"]),
|
_ => Err(&["C", "system", "efiapi"]),
|
||||||
},
|
},
|
||||||
InlineAsmArch::LoongArch64 => match name {
|
InlineAsmArch::LoongArch64 => match name {
|
||||||
|
@ -1148,6 +1154,31 @@ impl InlineAsmClobberAbi {
|
||||||
v24, v25, v26, v27, v28, v29, v30, v31,
|
v24, v25, v26, v27, v28, v29, v30, v31,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
InlineAsmClobberAbi::RiscVE => clobbered_regs! {
|
||||||
|
RiscV RiscVInlineAsmReg {
|
||||||
|
// Refs:
|
||||||
|
// - ILP32E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#ilp32e-calling-convention
|
||||||
|
// - LP64E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/299
|
||||||
|
|
||||||
|
// ra
|
||||||
|
x1,
|
||||||
|
// t0-t2
|
||||||
|
x5, x6, x7,
|
||||||
|
// a0-a5
|
||||||
|
x10, x11, x12, x13, x14, x15,
|
||||||
|
// ft0-ft7
|
||||||
|
f0, f1, f2, f3, f4, f5, f6, f7,
|
||||||
|
// fa0-fa7
|
||||||
|
f10, f11, f12, f13, f14, f15, f16, f17,
|
||||||
|
// ft8-ft11
|
||||||
|
f28, f29, f30, f31,
|
||||||
|
|
||||||
|
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||||
|
v8, v9, v10, v11, v12, v13, v14, v15,
|
||||||
|
v16, v17, v18, v19, v20, v21, v22, v23,
|
||||||
|
v24, v25, v26, v27, v28, v29, v30, v31,
|
||||||
|
}
|
||||||
|
},
|
||||||
InlineAsmClobberAbi::LoongArch => clobbered_regs! {
|
InlineAsmClobberAbi::LoongArch => clobbered_regs! {
|
||||||
LoongArch LoongArchInlineAsmReg {
|
LoongArch LoongArchInlineAsmReg {
|
||||||
// ra
|
// ra
|
||||||
|
|
|
@ -54,6 +54,10 @@ impl RiscVInlineAsmRegClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_e(target_features: &FxIndexSet<Symbol>) -> bool {
|
||||||
|
target_features.contains(&sym::e)
|
||||||
|
}
|
||||||
|
|
||||||
fn not_e(
|
fn not_e(
|
||||||
_arch: InlineAsmArch,
|
_arch: InlineAsmArch,
|
||||||
_reloc_model: RelocModel,
|
_reloc_model: RelocModel,
|
||||||
|
@ -61,7 +65,7 @@ fn not_e(
|
||||||
_target: &Target,
|
_target: &Target,
|
||||||
_is_clobber: bool,
|
_is_clobber: bool,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
if target_features.contains(&sym::e) {
|
if is_e(target_features) {
|
||||||
Err("register can't be used with the `e` target feature")
|
Err("register can't be used with the `e` target feature")
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
44
tests/codegen/asm/riscv-clobbers.rs
Normal file
44
tests/codegen/asm/riscv-clobbers.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
//@ assembly-output: emit-asm
|
||||||
|
//@ revisions: rv32i rv64i rv32e
|
||||||
|
//@[rv32i] compile-flags: --target riscv32i-unknown-none-elf
|
||||||
|
//@[rv32i] needs-llvm-components: riscv
|
||||||
|
//@[rv64i] compile-flags: --target riscv64imac-unknown-none-elf
|
||||||
|
//@[rv64i] needs-llvm-components: riscv
|
||||||
|
//@[rv32e] compile-flags: --target riscv32e-unknown-none-elf
|
||||||
|
//@[rv32e] needs-llvm-components: riscv
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
#![feature(no_core, rustc_attrs, lang_items)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! asm {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @flags_clobber
|
||||||
|
// CHECK: call void asm sideeffect "", "~{vtype},~{vl},~{vxsat},~{vxrm}"()
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn flags_clobber() {
|
||||||
|
asm!("", options(nostack, nomem));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @no_clobber
|
||||||
|
// CHECK: call void asm sideeffect "", ""()
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn no_clobber() {
|
||||||
|
asm!("", options(nostack, nomem, preserves_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @clobber_abi
|
||||||
|
// rv32i: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},={x16},={x17},={x28},={x29},={x30},={x31},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"()
|
||||||
|
// rv64i: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},={x16},={x17},={x28},={x29},={x30},={x31},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"()
|
||||||
|
// rv32e: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"()
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn clobber_abi() {
|
||||||
|
asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue