about summary refs log tree commit diff
path: root/compiler/rustc_target/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-10 16:44:04 +0000
committerbors <bors@rust-lang.org>2021-03-10 16:44:04 +0000
commit17a07d71bfd692f9b2dad2a566aff52bf3d4bfe2 (patch)
tree43c603cd0c9c6476ec1905969a4f283404834c21 /compiler/rustc_target/src
parent5fe790e3c40710ecb95ddaadb98b59a3bb4f8326 (diff)
parent05bf037fecfad619e140877769379a1d24952bad (diff)
downloadrust-17a07d71bfd692f9b2dad2a566aff52bf3d4bfe2.tar.gz
rust-17a07d71bfd692f9b2dad2a566aff52bf3d4bfe2.zip
Auto merge of #76570 - cratelyn:implement-rfc-2945-c-unwind-abi, r=Amanieu
Implement RFC 2945: "C-unwind" ABI

## Implement RFC 2945: "C-unwind" ABI

This branch implements [RFC 2945]. The tracking issue for this RFC is #74990.

The feature gate for the issue is `#![feature(c_unwind)]`.

This RFC was created as part of the ffi-unwind project group tracked at rust-lang/lang-team#19.

### Changes

Further details will be provided in commit messages, but a high-level overview
of the changes follows:

* A boolean `unwind` payload is added to the `C`, `System`, `Stdcall`,
and `Thiscall` variants, marking whether unwinding across FFI boundaries is
acceptable. The cases where each of these variants' `unwind` member is true
correspond with the `C-unwind`, `system-unwind`, `stdcall-unwind`, and
`thiscall-unwind` ABI strings introduced in RFC 2945 [3].

* This commit adds a `c_unwind` feature gate for the new ABI strings.
Tests for this feature gate are included in `src/test/ui/c-unwind/`, which
ensure that this feature gate works correctly for each of the new ABIs.
A new language features entry in the unstable book is added as well.

* We adjust the `rustc_middle::ty::layout::fn_can_unwind` function,
used to compute whether or not a `FnAbi` object represents a function that
should be able to unwind when `panic=unwind` is in use.

* Changes are also made to
`rustc_mir_build::build::should_abort_on_panic` so that the function ABI is
used to determind whether it should abort, assuming that the `panic=unwind`
strategy is being used, and no explicit unwind attribute was provided.

[RFC 2945]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
Diffstat (limited to 'compiler/rustc_target/src')
-rw-r--r--compiler/rustc_target/src/spec/abi.rs76
-rw-r--r--compiler/rustc_target/src/spec/arm_base.rs11
-rw-r--r--compiler/rustc_target/src/spec/mipsel_unknown_none.rs6
-rw-r--r--compiler/rustc_target/src/spec/mod.rs19
-rw-r--r--compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs6
-rw-r--r--compiler/rustc_target/src/spec/riscv_base.rs6
6 files changed, 97 insertions, 27 deletions
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index 65e8a4e8db2..17eb33b8f2e 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -8,24 +8,21 @@ mod tests;
 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum Abi {
-    // N.B., this ordering MUST match the AbiDatas array below.
-    // (This is ensured by the test indices_are_correct().)
-
     // Multiplatform / generic ABIs
     //
     // These ABIs come first because every time we add a new ABI, we
     // have to re-bless all the hashing tests. These are used in many
     // places, so giving them stable values reduces test churn. The
     // specific values are meaningless.
-    Rust = 0,
-    C = 1,
+    Rust,
+    C { unwind: bool },
 
     // Single platform ABIs
     Cdecl,
-    Stdcall,
+    Stdcall { unwind: bool },
     Fastcall,
     Vectorcall,
-    Thiscall,
+    Thiscall { unwind: bool },
     Aapcs,
     Win64,
     SysV64,
@@ -39,7 +36,7 @@ pub enum Abi {
     CCmseNonSecureCall,
 
     // Multiplatform / generic ABIs
-    System,
+    System { unwind: bool },
     RustIntrinsic,
     RustCall,
     PlatformIntrinsic,
@@ -61,13 +58,16 @@ pub struct AbiData {
 const AbiDatas: &[AbiData] = &[
     // Cross-platform ABIs
     AbiData { abi: Abi::Rust, name: "Rust", generic: true },
-    AbiData { abi: Abi::C, name: "C", generic: true },
+    AbiData { abi: Abi::C { unwind: false }, name: "C", generic: true },
+    AbiData { abi: Abi::C { unwind: true }, name: "C-unwind", generic: true },
     // Platform-specific ABIs
     AbiData { abi: Abi::Cdecl, name: "cdecl", generic: false },
-    AbiData { abi: Abi::Stdcall, name: "stdcall", generic: false },
+    AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall", generic: false },
+    AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind", generic: false },
     AbiData { abi: Abi::Fastcall, name: "fastcall", generic: false },
     AbiData { abi: Abi::Vectorcall, name: "vectorcall", generic: false },
-    AbiData { abi: Abi::Thiscall, name: "thiscall", generic: false },
+    AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall", generic: false },
+    AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind", generic: false },
     AbiData { abi: Abi::Aapcs, name: "aapcs", generic: false },
     AbiData { abi: Abi::Win64, name: "win64", generic: false },
     AbiData { abi: Abi::SysV64, name: "sysv64", generic: false },
@@ -84,7 +84,8 @@ const AbiDatas: &[AbiData] = &[
     },
     AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false },
     // Cross-platform ABIs
-    AbiData { abi: Abi::System, name: "system", generic: true },
+    AbiData { abi: Abi::System { unwind: false }, name: "system", generic: true },
+    AbiData { abi: Abi::System { unwind: true }, name: "system-unwind", generic: true },
     AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
     AbiData { abi: Abi::RustCall, name: "rust-call", generic: true },
     AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
@@ -103,7 +104,52 @@ pub fn all_names() -> Vec<&'static str> {
 impl Abi {
     #[inline]
     pub fn index(self) -> usize {
-        self as usize
+        // N.B., this ordering MUST match the AbiDatas array above.
+        // (This is ensured by the test indices_are_correct().)
+        use Abi::*;
+        let i = match self {
+            // Cross-platform ABIs
+            Rust => 0,
+            C { unwind: false } => 1,
+            C { unwind: true } => 2,
+            // Platform-specific ABIs
+            Cdecl => 3,
+            Stdcall { unwind: false } => 4,
+            Stdcall { unwind: true } => 5,
+            Fastcall => 6,
+            Vectorcall => 7,
+            Thiscall { unwind: false } => 8,
+            Thiscall { unwind: true } => 9,
+            Aapcs => 10,
+            Win64 => 11,
+            SysV64 => 12,
+            PtxKernel => 13,
+            Msp430Interrupt => 14,
+            X86Interrupt => 15,
+            AmdGpuKernel => 16,
+            EfiApi => 17,
+            AvrInterrupt => 18,
+            AvrNonBlockingInterrupt => 19,
+            CCmseNonSecureCall => 20,
+            // Cross-platform ABIs
+            System { unwind: false } => 21,
+            System { unwind: true } => 22,
+            RustIntrinsic => 23,
+            RustCall => 24,
+            PlatformIntrinsic => 25,
+            Unadjusted => 26,
+        };
+        debug_assert!(
+            AbiDatas
+                .iter()
+                .enumerate()
+                .find(|(_, AbiData { abi, .. })| *abi == self)
+                .map(|(index, _)| index)
+                .expect("abi variant has associated data")
+                == i,
+            "Abi index did not match `AbiDatas` ordering"
+        );
+        i
     }
 
     #[inline]
@@ -122,6 +168,8 @@ impl Abi {
 
 impl fmt::Display for Abi {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "\"{}\"", self.name())
+        match self {
+            abi => write!(f, "\"{}\"", abi.name()),
+        }
     }
 }
diff --git a/compiler/rustc_target/src/spec/arm_base.rs b/compiler/rustc_target/src/spec/arm_base.rs
index b74d80dc6bb..01f573313c9 100644
--- a/compiler/rustc_target/src/spec/arm_base.rs
+++ b/compiler/rustc_target/src/spec/arm_base.rs
@@ -2,5 +2,14 @@ use crate::spec::abi::Abi;
 
 // All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm
 pub fn unsupported_abis() -> Vec<Abi> {
-    vec![Abi::Stdcall, Abi::Fastcall, Abi::Vectorcall, Abi::Thiscall, Abi::Win64, Abi::SysV64]
+    vec![
+        Abi::Stdcall { unwind: false },
+        Abi::Stdcall { unwind: true },
+        Abi::Fastcall,
+        Abi::Vectorcall,
+        Abi::Thiscall { unwind: false },
+        Abi::Thiscall { unwind: true },
+        Abi::Win64,
+        Abi::SysV64,
+    ]
 }
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
index 0f9d3c3de15..110c8dd80ea 100644
--- a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
@@ -23,10 +23,12 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             unsupported_abis: vec![
-                Abi::Stdcall,
+                Abi::Stdcall { unwind: false },
+                Abi::Stdcall { unwind: true },
                 Abi::Fastcall,
                 Abi::Vectorcall,
-                Abi::Thiscall,
+                Abi::Thiscall { unwind: false },
+                Abi::Thiscall { unwind: true },
                 Abi::Win64,
                 Abi::SysV64,
             ],
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 09400a1d130..c9fffd213d7 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1284,24 +1284,31 @@ impl Target {
     /// Given a function ABI, turn it into the correct ABI for this target.
     pub fn adjust_abi(&self, abi: Abi) -> Abi {
         match abi {
-            Abi::System => {
+            Abi::System { unwind } => {
                 if self.is_like_windows && self.arch == "x86" {
-                    Abi::Stdcall
+                    Abi::Stdcall { unwind }
                 } else {
-                    Abi::C
+                    Abi::C { unwind }
                 }
             }
             // These ABI kinds are ignored on non-x86 Windows targets.
             // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
             // and the individual pages for __stdcall et al.
-            Abi::Stdcall | Abi::Fastcall | Abi::Vectorcall | Abi::Thiscall => {
-                if self.is_like_windows && self.arch != "x86" { Abi::C } else { abi }
+            Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => {
+                if self.is_like_windows && self.arch != "x86" { Abi::C { unwind } } else { abi }
+            }
+            Abi::Fastcall | Abi::Vectorcall => {
+                if self.is_like_windows && self.arch != "x86" {
+                    Abi::C { unwind: false }
+                } else {
+                    abi
+                }
             }
             Abi::EfiApi => {
                 if self.arch == "x86_64" {
                     Abi::Win64
                 } else {
-                    Abi::C
+                    Abi::C { unwind: false }
                 }
             }
             abi => abi,
diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
index 3c9c7d578fb..15d8e4843f9 100644
--- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
@@ -49,10 +49,12 @@ pub fn target() -> Target {
             // create the tests for this.
             unsupported_abis: vec![
                 Abi::Cdecl,
-                Abi::Stdcall,
+                Abi::Stdcall { unwind: false },
+                Abi::Stdcall { unwind: true },
                 Abi::Fastcall,
                 Abi::Vectorcall,
-                Abi::Thiscall,
+                Abi::Thiscall { unwind: false },
+                Abi::Thiscall { unwind: true },
                 Abi::Aapcs,
                 Abi::Win64,
                 Abi::SysV64,
diff --git a/compiler/rustc_target/src/spec/riscv_base.rs b/compiler/rustc_target/src/spec/riscv_base.rs
index 64cf890037e..5bcbb2e621b 100644
--- a/compiler/rustc_target/src/spec/riscv_base.rs
+++ b/compiler/rustc_target/src/spec/riscv_base.rs
@@ -5,10 +5,12 @@ use crate::spec::abi::Abi;
 pub fn unsupported_abis() -> Vec<Abi> {
     vec![
         Abi::Cdecl,
-        Abi::Stdcall,
+        Abi::Stdcall { unwind: false },
+        Abi::Stdcall { unwind: true },
         Abi::Fastcall,
         Abi::Vectorcall,
-        Abi::Thiscall,
+        Abi::Thiscall { unwind: false },
+        Abi::Thiscall { unwind: true },
         Abi::Aapcs,
         Abi::Win64,
         Abi::SysV64,