about summary refs log tree commit diff
path: root/compiler/rustc_target
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_target')
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs25
-rw-r--r--compiler/rustc_target/src/json.rs5
-rw-r--r--compiler/rustc_target/src/spec/abi.rs30
-rw-r--r--compiler/rustc_target/src/spec/abi/tests.rs6
-rw-r--r--compiler/rustc_target/src/spec/mod.rs3
5 files changed, 63 insertions, 6 deletions
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 3d2ea017d8f..e4989bdfbcd 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -603,6 +603,25 @@ pub enum Conv {
     AmdGpuKernel,
     AvrInterrupt,
     AvrNonBlockingInterrupt,
+
+    RiscvInterrupt {
+        kind: RiscvInterruptKind,
+    },
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+pub enum RiscvInterruptKind {
+    Machine,
+    Supervisor,
+}
+
+impl RiscvInterruptKind {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Self::Machine => "machine",
+            Self::Supervisor => "supervisor",
+        }
+    }
 }
 
 /// Metadata describing how the arguments to a native function
@@ -753,6 +772,12 @@ impl FromStr for Conv {
             "AmdGpuKernel" => Ok(Conv::AmdGpuKernel),
             "AvrInterrupt" => Ok(Conv::AvrInterrupt),
             "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt),
+            "RiscvInterrupt(machine)" => {
+                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine })
+            }
+            "RiscvInterrupt(supervisor)" => {
+                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor })
+            }
             _ => Err(format!("'{s}' is not a valid value for entry function call convention.")),
         }
     }
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index 75bb76a9de0..af455b6432f 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -92,6 +92,7 @@ impl<A: ToJson> ToJson for Option<A> {
 
 impl ToJson for crate::abi::call::Conv {
     fn to_json(&self) -> Json {
+        let buf: String;
         let s = match self {
             Self::C => "C",
             Self::Rust => "Rust",
@@ -110,6 +111,10 @@ impl ToJson for crate::abi::call::Conv {
             Self::AmdGpuKernel => "AmdGpuKernel",
             Self::AvrInterrupt => "AvrInterrupt",
             Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt",
+            Self::RiscvInterrupt { kind } => {
+                buf = format!("RiscvInterrupt({})", kind.as_str());
+                &buf
+            }
         };
         Json::String(s.to_owned())
     }
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index dc233121f66..550cdf6bda6 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -38,6 +38,8 @@ pub enum Abi {
     PlatformIntrinsic,
     Unadjusted,
     RustCold,
+    RiscvInterruptM,
+    RiscvInterruptS,
 }
 
 impl Abi {
@@ -107,11 +109,29 @@ const AbiDatas: &[AbiData] = &[
     AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" },
     AbiData { abi: Abi::Unadjusted, name: "unadjusted" },
     AbiData { abi: Abi::RustCold, name: "rust-cold" },
+    AbiData { abi: Abi::RiscvInterruptM, name: "riscv-interrupt-m" },
+    AbiData { abi: Abi::RiscvInterruptS, name: "riscv-interrupt-s" },
 ];
 
+#[derive(Copy, Clone, Debug)]
+pub enum AbiUnsupported {
+    Unrecognized,
+    Reason { explain: &'static str },
+}
+
 /// Returns the ABI with the given name (if any).
-pub fn lookup(name: &str) -> Option<Abi> {
-    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
+pub fn lookup(name: &str) -> Result<Abi, AbiUnsupported> {
+    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi).ok_or_else(|| match name {
+        "riscv-interrupt" => AbiUnsupported::Reason {
+            explain: "please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively",
+        },
+        "riscv-interrupt-u" => AbiUnsupported::Reason {
+            explain: "user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314",
+        },
+
+        _ => AbiUnsupported::Unrecognized,
+
+    })
 }
 
 pub fn all_names() -> Vec<&'static str> {
@@ -200,6 +220,10 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
             feature: sym::abi_avr_interrupt,
             explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change",
         }),
+        "riscv-interrupt-m" | "riscv-interrupt-s" => Err(AbiDisabled::Unstable {
+            feature: sym::abi_riscv_interrupt,
+            explain: "riscv-interrupt ABIs are experimental and subject to change",
+        }),
         "C-cmse-nonsecure-call" => Err(AbiDisabled::Unstable {
             feature: sym::abi_c_cmse_nonsecure_call,
             explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
@@ -260,6 +284,8 @@ impl Abi {
             PlatformIntrinsic => 32,
             Unadjusted => 33,
             RustCold => 34,
+            RiscvInterruptM => 35,
+            RiscvInterruptS => 36,
         };
         debug_assert!(
             AbiDatas
diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_target/src/spec/abi/tests.rs
index 8bea5e5efe3..251a12fe7aa 100644
--- a/compiler/rustc_target/src/spec/abi/tests.rs
+++ b/compiler/rustc_target/src/spec/abi/tests.rs
@@ -4,19 +4,19 @@ use super::*;
 #[test]
 fn lookup_Rust() {
     let abi = lookup("Rust");
-    assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
+    assert!(abi.is_ok() && abi.unwrap().data().name == "Rust");
 }
 
 #[test]
 fn lookup_cdecl() {
     let abi = lookup("cdecl");
-    assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
+    assert!(abi.is_ok() && abi.unwrap().data().name == "cdecl");
 }
 
 #[test]
 fn lookup_baz() {
     let abi = lookup("baz");
-    assert!(abi.is_none());
+    assert!(matches!(abi, Err(AbiUnsupported::Unrecognized)))
 }
 
 #[test]
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index c215a7c4b6e..523a64441c7 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2267,6 +2267,7 @@ impl Target {
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
             AmdGpuKernel => self.arch == "amdgcn",
+            RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]),
             AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
             Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
             Thiscall { .. } => self.arch == "x86",
@@ -2698,7 +2699,7 @@ impl Target {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
                     match lookup_abi(s) {
-                        Some(abi) => base.$key_name = Some(abi),
+                        Ok(abi) => base.$key_name = Some(abi),
                         _ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
                     }
                     Some(Ok(()))