Skip to content

Commit 736c397

Browse files
committed
Fix clobber_abi in RV32E and RV64E inline assembly
1 parent ab3cf26 commit 736c397

File tree

5 files changed

+95
-6
lines changed

5 files changed

+95
-6
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
8080
let mut clobber_abis = FxIndexMap::default();
8181
if let Some(asm_arch) = asm_arch {
8282
for (abi_name, abi_span) in &asm.clobber_abis {
83-
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) {
83+
match asm::InlineAsmClobberAbi::parse(
84+
asm_arch,
85+
&self.tcx.sess.target,
86+
&self.tcx.sess.unstable_target_features,
87+
*abi_name,
88+
) {
8489
Ok(abi) => {
8590
// If the abi was already in the list, emit an error
8691
match clobber_abis.get(&abi) {

compiler/rustc_codegen_cranelift/src/inline_asm.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
472472
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
473473

474474
// Allocate stack slots for saving clobbered registers
475-
let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C)
476-
.unwrap()
477-
.clobbered_regs();
475+
let abi_clobber = InlineAsmClobberAbi::parse(
476+
self.arch,
477+
&self.tcx.sess.target,
478+
&self.tcx.sess.unstable_target_features,
479+
sym::C,
480+
)
481+
.unwrap()
482+
.clobbered_regs();
478483
for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) {
479484
let mut need_save = true;
480485
// If the register overlaps with a register clobbered by function call, then

compiler/rustc_target/src/asm/mod.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,7 @@ pub enum InlineAsmClobberAbi {
922922
AArch64NoX18,
923923
Arm64EC,
924924
RiscV,
925+
RiscVE,
925926
LoongArch,
926927
PowerPC,
927928
S390x,
@@ -934,6 +935,7 @@ impl InlineAsmClobberAbi {
934935
pub fn parse(
935936
arch: InlineAsmArch,
936937
target: &Target,
938+
target_features: &FxIndexSet<Symbol>,
937939
name: Symbol,
938940
) -> Result<Self, &'static [&'static str]> {
939941
let name = name.as_str();
@@ -968,7 +970,11 @@ impl InlineAsmClobberAbi {
968970
_ => Err(&["C", "system"]),
969971
},
970972
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
971-
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV),
973+
"C" | "system" | "efiapi" => Ok(if riscv::is_e(target_features) {
974+
InlineAsmClobberAbi::RiscVE
975+
} else {
976+
InlineAsmClobberAbi::RiscV
977+
}),
972978
_ => Err(&["C", "system", "efiapi"]),
973979
},
974980
InlineAsmArch::LoongArch64 => match name {
@@ -1141,6 +1147,31 @@ impl InlineAsmClobberAbi {
11411147
v24, v25, v26, v27, v28, v29, v30, v31,
11421148
}
11431149
},
1150+
InlineAsmClobberAbi::RiscVE => clobbered_regs! {
1151+
RiscV RiscVInlineAsmReg {
1152+
// Refs:
1153+
// - ILP32E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#ilp32e-calling-convention
1154+
// - LP64E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/299
1155+
1156+
// ra
1157+
x1,
1158+
// t0-t2
1159+
x5, x6, x7,
1160+
// a0-a5
1161+
x10, x11, x12, x13, x14, x15,
1162+
// ft0-ft7
1163+
f0, f1, f2, f3, f4, f5, f6, f7,
1164+
// fa0-fa7
1165+
f10, f11, f12, f13, f14, f15, f16, f17,
1166+
// ft8-ft11
1167+
f28, f29, f30, f31,
1168+
1169+
v0, v1, v2, v3, v4, v5, v6, v7,
1170+
v8, v9, v10, v11, v12, v13, v14, v15,
1171+
v16, v17, v18, v19, v20, v21, v22, v23,
1172+
v24, v25, v26, v27, v28, v29, v30, v31,
1173+
}
1174+
},
11441175
InlineAsmClobberAbi::LoongArch => clobbered_regs! {
11451176
LoongArch LoongArchInlineAsmReg {
11461177
// ra

compiler/rustc_target/src/asm/riscv.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,18 @@ impl RiscVInlineAsmRegClass {
5454
}
5555
}
5656

57+
pub(crate) fn is_e(target_features: &FxIndexSet<Symbol>) -> bool {
58+
target_features.contains(&sym::e)
59+
}
60+
5761
fn not_e(
5862
_arch: InlineAsmArch,
5963
_reloc_model: RelocModel,
6064
target_features: &FxIndexSet<Symbol>,
6165
_target: &Target,
6266
_is_clobber: bool,
6367
) -> Result<(), &'static str> {
64-
if target_features.contains(&sym::e) {
68+
if is_e(target_features) {
6569
Err("register can't be used with the `e` target feature")
6670
} else {
6771
Ok(())

tests/codegen/asm/riscv-clobbers.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ assembly-output: emit-asm
2+
//@ revisions: rv32i rv64i rv32e
3+
//@[rv32i] compile-flags: --target riscv32i-unknown-none-elf
4+
//@[rv32i] needs-llvm-components: riscv
5+
//@[rv64i] compile-flags: --target riscv64imac-unknown-none-elf
6+
//@[rv64i] needs-llvm-components: riscv
7+
//@[rv32e] compile-flags: --target riscv32e-unknown-none-elf
8+
//@[rv32e] needs-llvm-components: riscv
9+
// ignore-tidy-linelength
10+
11+
#![crate_type = "rlib"]
12+
#![feature(no_core, rustc_attrs, lang_items)]
13+
#![no_core]
14+
15+
#[lang = "sized"]
16+
trait Sized {}
17+
18+
#[rustc_builtin_macro]
19+
macro_rules! asm {
20+
() => {};
21+
}
22+
23+
// CHECK-LABEL: @flags_clobber
24+
// CHECK: call void asm sideeffect "", "~{vtype},~{vl},~{vxsat},~{vxrm}"()
25+
#[no_mangle]
26+
pub unsafe fn flags_clobber() {
27+
asm!("", options(nostack, nomem));
28+
}
29+
30+
// CHECK-LABEL: @no_clobber
31+
// CHECK: call void asm sideeffect "", ""()
32+
#[no_mangle]
33+
pub unsafe fn no_clobber() {
34+
asm!("", options(nostack, nomem, preserves_flags));
35+
}
36+
37+
// CHECK-LABEL: @clobber_abi
38+
// 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}"()
39+
// 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}"()
40+
// 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}"()
41+
#[no_mangle]
42+
pub unsafe fn clobber_abi() {
43+
asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
44+
}

0 commit comments

Comments
 (0)