about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTaiki Endo <te316e89@gmail.com>2024-11-25 00:36:22 +0900
committerTaiki Endo <te316e89@gmail.com>2024-11-25 00:36:22 +0900
commit736c397f41f9030e500199fc28b56a7fab703759 (patch)
treee3301420e984390d487ed22eb4e258698a350017
parentab3cf268b518f0312d86346db3bf79d5ec33b3b7 (diff)
downloadrust-736c397f41f9030e500199fc28b56a7fab703759.tar.gz
rust-736c397f41f9030e500199fc28b56a7fab703759.zip
Fix clobber_abi in RV32E and RV64E inline assembly
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs11
-rw-r--r--compiler/rustc_target/src/asm/mod.rs33
-rw-r--r--compiler/rustc_target/src/asm/riscv.rs6
-rw-r--r--tests/codegen/asm/riscv-clobbers.rs44
5 files changed, 95 insertions, 6 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 215e6d84d0f..32559a10ac3 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -80,7 +80,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let mut clobber_abis = FxIndexMap::default();
         if let Some(asm_arch) = asm_arch {
             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) => {
                         // If the abi was already in the list, emit an error
                         match clobber_abis.get(&abi) {
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 70176754f33..73ee47b2c63 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -472,9 +472,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
         let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
 
         // Allocate stack slots for saving clobbered registers
-        let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C)
-            .unwrap()
-            .clobbered_regs();
+        let abi_clobber = InlineAsmClobberAbi::parse(
+            self.arch,
+            &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))) {
             let mut need_save = true;
             // If the register overlaps with a register clobbered by function call, then
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 10778e9acf1..2c5ad1aa8bf 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -922,6 +922,7 @@ pub enum InlineAsmClobberAbi {
     AArch64NoX18,
     Arm64EC,
     RiscV,
+    RiscVE,
     LoongArch,
     PowerPC,
     S390x,
@@ -934,6 +935,7 @@ impl InlineAsmClobberAbi {
     pub fn parse(
         arch: InlineAsmArch,
         target: &Target,
+        target_features: &FxIndexSet<Symbol>,
         name: Symbol,
     ) -> Result<Self, &'static [&'static str]> {
         let name = name.as_str();
@@ -968,7 +970,11 @@ impl InlineAsmClobberAbi {
                 _ => Err(&["C", "system"]),
             },
             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"]),
             },
             InlineAsmArch::LoongArch64 => match name {
@@ -1141,6 +1147,31 @@ impl InlineAsmClobberAbi {
                     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! {
                 LoongArch LoongArchInlineAsmReg {
                     // ra
diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs
index cfd573efbc1..d6b30525379 100644
--- a/compiler/rustc_target/src/asm/riscv.rs
+++ b/compiler/rustc_target/src/asm/riscv.rs
@@ -54,6 +54,10 @@ impl RiscVInlineAsmRegClass {
     }
 }
 
+pub(crate) fn is_e(target_features: &FxIndexSet<Symbol>) -> bool {
+    target_features.contains(&sym::e)
+}
+
 fn not_e(
     _arch: InlineAsmArch,
     _reloc_model: RelocModel,
@@ -61,7 +65,7 @@ fn not_e(
     _target: &Target,
     _is_clobber: bool,
 ) -> 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")
     } else {
         Ok(())
diff --git a/tests/codegen/asm/riscv-clobbers.rs b/tests/codegen/asm/riscv-clobbers.rs
new file mode 100644
index 00000000000..59b2705a449
--- /dev/null
+++ b/tests/codegen/asm/riscv-clobbers.rs
@@ -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));
+}