Skip to content

Add more *-unwind ABI variants #93561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,54 @@ impl<'a> PostExpansionVisitor<'a> {
"thiscall-unwind ABI is experimental and subject to change"
);
}
"cdecl-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"cdecl-unwind ABI is experimental and subject to change"
);
}
"fastcall-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"fastcall-unwind ABI is experimental and subject to change"
);
}
"vectorcall-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"vectorcall-unwind ABI is experimental and subject to change"
);
}
"aapcs-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"aapcs-unwind ABI is experimental and subject to change"
);
}
"win64-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"win64-unwind ABI is experimental and subject to change"
);
}
"sysv64-unwind" => {
gate_feature_post!(
&self,
c_unwind,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to say these may want their own feature gate. I could see us wanting to consider the stabilization of the C-unwind separately from most of the others.

But IIRC c_unwind feature right now not only allows user to use the -unwind ABI but also fundamentally changes the behaviour of the programs, so I guess using the same gate here as well is fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the stabilization should be tied to that of C-unwind (except for ABIs that are unstable for other reasons). If we decide to describe ABIs with the "*-unwind" pattern then this should cover all ABIs where it makes sense.

span,
"sysv64-unwind ABI is experimental and subject to change"
);
}
"wasm" => {
gate_feature_post!(
&self,
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,11 +404,13 @@ impl Collector<'_> {
fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
let calling_convention = if self.tcx.sess.target.arch == "x86" {
match abi {
Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
Abi::Stdcall { .. } | Abi::System { .. } => {
DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
}
Abi::Fastcall => DllCallingConvention::Fastcall(self.i686_arg_list_size(item)),
Abi::Fastcall { .. } => {
DllCallingConvention::Fastcall(self.i686_arg_list_size(item))
}
// Vectorcall is intentionally not supported at this time.
_ => {
self.tcx.sess.span_fatal(
Expand All @@ -419,7 +421,7 @@ impl Collector<'_> {
}
} else {
match abi {
Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C,
Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
_ => {
self.tcx.sess.span_fatal(
item.span,
Expand Down
31 changes: 17 additions & 14 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2773,17 +2773,20 @@ pub fn fn_can_unwind<'tcx>(
// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
use SpecAbi::*;
match abi {
C { unwind } | Stdcall { unwind } | System { unwind } | Thiscall { unwind } => {
C { unwind }
| System { unwind }
| Cdecl { unwind }
| Stdcall { unwind }
| Fastcall { unwind }
| Vectorcall { unwind }
| Thiscall { unwind }
| Aapcs { unwind }
| Win64 { unwind }
| SysV64 { unwind } => {
unwind
|| (!tcx.features().c_unwind && tcx.sess.panic_strategy() == PanicStrategy::Unwind)
}
Cdecl
| Fastcall
| Vectorcall
| Aapcs
| Win64
| SysV64
| PtxKernel
PtxKernel
| Msp430Interrupt
| X86Interrupt
| AmdGpuKernel
Expand All @@ -2810,14 +2813,14 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
EfiApi => bug!("eficall abi should be selected elsewhere"),

Stdcall { .. } => Conv::X86Stdcall,
Fastcall => Conv::X86Fastcall,
Vectorcall => Conv::X86VectorCall,
Fastcall { .. } => Conv::X86Fastcall,
Vectorcall { .. } => Conv::X86VectorCall,
Thiscall { .. } => Conv::X86ThisCall,
C { .. } => Conv::C,
Unadjusted => Conv::C,
Win64 => Conv::X86_64Win64,
SysV64 => Conv::X86_64SysV,
Aapcs => Conv::ArmAapcs,
Win64 { .. } => Conv::X86_64Win64,
SysV64 { .. } => Conv::X86_64SysV,
Aapcs { .. } => Conv::ArmAapcs,
CCmseNonSecureCall => Conv::CCmseNonSecureCall,
PtxKernel => Conv::PtxKernel,
Msp430Interrupt => Conv::Msp430Intr,
Expand All @@ -2828,7 +2831,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
Wasm => Conv::C,

// These API constants ought to be more specific...
Cdecl => Conv::C,
Cdecl { .. } => Conv::C,
}
}

Expand Down
20 changes: 11 additions & 9 deletions compiler/rustc_target/src/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,22 +658,24 @@ impl<'a, Ty> FnAbi<'a, Ty> {

match &cx.target_spec().arch[..] {
"x86" => {
let flavor = if abi == spec::abi::Abi::Fastcall {
let flavor = if let spec::abi::Abi::Fastcall { .. } = abi {
x86::Flavor::Fastcall
} else {
x86::Flavor::General
};
x86::compute_abi_info(cx, self, flavor);
}
"x86_64" => {
if abi == spec::abi::Abi::SysV64 {
x86_64::compute_abi_info(cx, self);
} else if abi == spec::abi::Abi::Win64 || cx.target_spec().is_like_windows {
x86_win64::compute_abi_info(self);
} else {
x86_64::compute_abi_info(cx, self);
"x86_64" => match abi {
spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self),
_ => {
if cx.target_spec().is_like_windows {
x86_win64::compute_abi_info(self)
} else {
x86_64::compute_abi_info(cx, self)
}
}
}
},
"aarch64" => aarch64::compute_abi_info(cx, self),
"amdgpu" => amdgpu::compute_abi_info(cx, self),
"arm" => arm::compute_abi_info(cx, self),
Expand Down
86 changes: 49 additions & 37 deletions compiler/rustc_target/src/spec/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ pub enum Abi {
// churn. The specific values are meaningless.
Rust,
C { unwind: bool },
Cdecl,
Cdecl { unwind: bool },
Stdcall { unwind: bool },
Fastcall,
Vectorcall,
Fastcall { unwind: bool },
Vectorcall { unwind: bool },
Thiscall { unwind: bool },
Aapcs,
Win64,
SysV64,
Aapcs { unwind: bool },
Win64 { unwind: bool },
SysV64 { unwind: bool },
PtxKernel,
Msp430Interrupt,
X86Interrupt,
Expand Down Expand Up @@ -50,16 +50,22 @@ const AbiDatas: &[AbiData] = &[
AbiData { abi: Abi::Rust, name: "Rust" },
AbiData { abi: Abi::C { unwind: false }, name: "C" },
AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
AbiData { abi: Abi::Cdecl, name: "cdecl" },
AbiData { abi: Abi::Cdecl { unwind: false }, name: "cdecl" },
AbiData { abi: Abi::Cdecl { unwind: true }, name: "cdecl-unwind" },
AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" },
AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" },
AbiData { abi: Abi::Fastcall, name: "fastcall" },
AbiData { abi: Abi::Vectorcall, name: "vectorcall" },
AbiData { abi: Abi::Fastcall { unwind: false }, name: "fastcall" },
AbiData { abi: Abi::Fastcall { unwind: true }, name: "fastcall-unwind" },
AbiData { abi: Abi::Vectorcall { unwind: false }, name: "vectorcall" },
AbiData { abi: Abi::Vectorcall { unwind: true }, name: "vectorcall-unwind" },
AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" },
AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" },
AbiData { abi: Abi::Aapcs, name: "aapcs" },
AbiData { abi: Abi::Win64, name: "win64" },
AbiData { abi: Abi::SysV64, name: "sysv64" },
AbiData { abi: Abi::Aapcs { unwind: false }, name: "aapcs" },
AbiData { abi: Abi::Aapcs { unwind: true }, name: "aapcs-unwind" },
AbiData { abi: Abi::Win64 { unwind: false }, name: "win64" },
AbiData { abi: Abi::Win64 { unwind: true }, name: "win64-unwind" },
AbiData { abi: Abi::SysV64 { unwind: false }, name: "sysv64" },
AbiData { abi: Abi::SysV64 { unwind: true }, name: "sysv64-unwind" },
AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" },
AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" },
AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" },
Expand Down Expand Up @@ -101,32 +107,38 @@ impl Abi {
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,
Wasm => 21,
Cdecl { unwind: false } => 3,
Cdecl { unwind: true } => 4,
Stdcall { unwind: false } => 5,
Stdcall { unwind: true } => 6,
Fastcall { unwind: false } => 7,
Fastcall { unwind: true } => 8,
Vectorcall { unwind: false } => 9,
Vectorcall { unwind: true } => 10,
Thiscall { unwind: false } => 11,
Thiscall { unwind: true } => 12,
Aapcs { unwind: false } => 13,
Aapcs { unwind: true } => 14,
Win64 { unwind: false } => 15,
Win64 { unwind: true } => 16,
SysV64 { unwind: false } => 17,
SysV64 { unwind: true } => 18,
PtxKernel => 19,
Msp430Interrupt => 20,
X86Interrupt => 21,
AmdGpuKernel => 22,
EfiApi => 23,
AvrInterrupt => 24,
AvrNonBlockingInterrupt => 25,
CCmseNonSecureCall => 26,
Wasm => 27,
// Cross-platform ABIs
System { unwind: false } => 22,
System { unwind: true } => 23,
RustIntrinsic => 24,
RustCall => 25,
PlatformIntrinsic => 26,
Unadjusted => 27,
System { unwind: false } => 28,
System { unwind: true } => 29,
RustIntrinsic => 30,
RustCall => 31,
PlatformIntrinsic => 32,
Unadjusted => 33,
};
debug_assert!(
AbiDatas
Expand Down
22 changes: 11 additions & 11 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1556,15 +1556,15 @@ impl Target {
Abi::Stdcall { unwind }
}
Abi::System { unwind } => Abi::C { unwind },
Abi::EfiApi if self.arch == "x86_64" => Abi::Win64,
Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false },
Abi::EfiApi => Abi::C { unwind: false },

// See commentary in `is_abi_supported`.
Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi,
Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind },
Abi::Fastcall if self.arch == "x86" => abi,
Abi::Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
Abi::Fastcall | Abi::Vectorcall => Abi::C { unwind: false },
Abi::Fastcall { .. } if self.arch == "x86" => abi,
Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
Abi::Fastcall { unwind } | Abi::Vectorcall { unwind } => Abi::C { unwind },

abi => abi,
}
Expand All @@ -1581,12 +1581,12 @@ impl Target {
| RustCall
| PlatformIntrinsic
| Unadjusted
| Cdecl
| Cdecl { .. }
| EfiApi => true,
X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
Aapcs => "arm" == self.arch,
Aapcs { .. } => "arm" == self.arch,
CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
Win64 | SysV64 => self.arch == "x86_64",
Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
PtxKernel => self.arch == "nvptx64",
Msp430Interrupt => self.arch == "msp430",
AmdGpuKernel => self.arch == "amdgcn",
Expand Down Expand Up @@ -1623,13 +1623,13 @@ impl Target {
// > convention is used.
//
// -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
Stdcall { .. } | Fastcall | Vectorcall if self.is_like_windows => true,
Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
// Outside of Windows we want to only support these calling conventions for the
// architectures for which these calling conventions are actually well defined.
Stdcall { .. } | Fastcall if self.arch == "x86" => true,
Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
// Return a `None` for other cases so that we know to emit a future compat lint.
Stdcall { .. } | Fastcall | Vectorcall => return None,
Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => return None,
})
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ use bounds::Bounds;
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
match (decl.c_variadic, abi) {
// The function has the correct calling convention, or isn't a "C-variadic" function.
(false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl) => {}
(false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl { .. }) => {}
// The function is a "C-variadic" function with an incorrect calling convention.
(true, _) => {
let mut err = struct_span_err!(
Expand Down
17 changes: 14 additions & 3 deletions src/doc/unstable-book/src/language-features/c-unwind.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,20 @@ The tracking issue for this feature is: [#74990]

------------------------

Introduces four new ABI strings: "C-unwind", "stdcall-unwind",
"thiscall-unwind", and "system-unwind". These enable unwinding from other
languages (such as C++) into Rust frames and from Rust into other languages.
Introduces new ABI strings:
- "C-unwind"
- "cdecl-unwind"
- "stdcall-unwind"
- "fastcall-unwind"
- "vectorcall-unwind"
- "thiscall-unwind"
- "aapcs-unwind"
- "win64-unwind"
- "sysv64-unwind"
- "system-unwind"

These enable unwinding from other languages (such as C++) into Rust frames and
from Rust into other languages.

See [RFC 2945] for more information.

Expand Down
Loading