1
Fork 0

Add more *-unwind ABI variants

The following *-unwind ABIs are now supported:
- "C-unwind"
- "cdecl-unwind"
- "stdcall-unwind"
- "fastcall-unwind"
- "vectorcall-unwind"
- "thiscall-unwind"
- "aapcs-unwind"
- "win64-unwind"
- "sysv64-unwind"
- "system-unwind"
This commit is contained in:
Amanieu d'Antras 2022-02-01 18:53:45 +01:00
parent 498eeb72f5
commit 547b4e601e
16 changed files with 342 additions and 80 deletions

View file

@ -196,6 +196,54 @@ impl<'a> PostExpansionVisitor<'a> {
"thiscall-unwind ABI is experimental and subject to change" "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,
span,
"sysv64-unwind ABI is experimental and subject to change"
);
}
"wasm" => { "wasm" => {
gate_feature_post!( gate_feature_post!(
&self, &self,

View file

@ -404,11 +404,13 @@ impl Collector<'_> {
fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport { fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
let calling_convention = if self.tcx.sess.target.arch == "x86" { let calling_convention = if self.tcx.sess.target.arch == "x86" {
match abi { match abi {
Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C, Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
Abi::Stdcall { .. } | Abi::System { .. } => { Abi::Stdcall { .. } | Abi::System { .. } => {
DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) 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. // Vectorcall is intentionally not supported at this time.
_ => { _ => {
self.tcx.sess.span_fatal( self.tcx.sess.span_fatal(
@ -419,7 +421,7 @@ impl Collector<'_> {
} }
} else { } else {
match abi { match abi {
Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C, Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
_ => { _ => {
self.tcx.sess.span_fatal( self.tcx.sess.span_fatal(
item.span, item.span,

View file

@ -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 // [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
use SpecAbi::*; use SpecAbi::*;
match abi { 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 unwind
|| (!tcx.features().c_unwind && tcx.sess.panic_strategy() == PanicStrategy::Unwind) || (!tcx.features().c_unwind && tcx.sess.panic_strategy() == PanicStrategy::Unwind)
} }
Cdecl PtxKernel
| Fastcall
| Vectorcall
| Aapcs
| Win64
| SysV64
| PtxKernel
| Msp430Interrupt | Msp430Interrupt
| X86Interrupt | X86Interrupt
| AmdGpuKernel | AmdGpuKernel
@ -2810,14 +2813,14 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
EfiApi => bug!("eficall abi should be selected elsewhere"), EfiApi => bug!("eficall abi should be selected elsewhere"),
Stdcall { .. } => Conv::X86Stdcall, Stdcall { .. } => Conv::X86Stdcall,
Fastcall => Conv::X86Fastcall, Fastcall { .. } => Conv::X86Fastcall,
Vectorcall => Conv::X86VectorCall, Vectorcall { .. } => Conv::X86VectorCall,
Thiscall { .. } => Conv::X86ThisCall, Thiscall { .. } => Conv::X86ThisCall,
C { .. } => Conv::C, C { .. } => Conv::C,
Unadjusted => Conv::C, Unadjusted => Conv::C,
Win64 => Conv::X86_64Win64, Win64 { .. } => Conv::X86_64Win64,
SysV64 => Conv::X86_64SysV, SysV64 { .. } => Conv::X86_64SysV,
Aapcs => Conv::ArmAapcs, Aapcs { .. } => Conv::ArmAapcs,
CCmseNonSecureCall => Conv::CCmseNonSecureCall, CCmseNonSecureCall => Conv::CCmseNonSecureCall,
PtxKernel => Conv::PtxKernel, PtxKernel => Conv::PtxKernel,
Msp430Interrupt => Conv::Msp430Intr, Msp430Interrupt => Conv::Msp430Intr,
@ -2828,7 +2831,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
Wasm => Conv::C, Wasm => Conv::C,
// These API constants ought to be more specific... // These API constants ought to be more specific...
Cdecl => Conv::C, Cdecl { .. } => Conv::C,
} }
} }

View file

@ -658,22 +658,24 @@ impl<'a, Ty> FnAbi<'a, Ty> {
match &cx.target_spec().arch[..] { match &cx.target_spec().arch[..] {
"x86" => { "x86" => {
let flavor = if abi == spec::abi::Abi::Fastcall { let flavor = if let spec::abi::Abi::Fastcall { .. } = abi {
x86::Flavor::Fastcall x86::Flavor::Fastcall
} else { } else {
x86::Flavor::General x86::Flavor::General
}; };
x86::compute_abi_info(cx, self, flavor); x86::compute_abi_info(cx, self, flavor);
} }
"x86_64" => { "x86_64" => match abi {
if abi == spec::abi::Abi::SysV64 { spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
x86_64::compute_abi_info(cx, self); spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self),
} else if abi == spec::abi::Abi::Win64 || cx.target_spec().is_like_windows { _ => {
x86_win64::compute_abi_info(self); if cx.target_spec().is_like_windows {
x86_win64::compute_abi_info(self)
} else { } else {
x86_64::compute_abi_info(cx, self); x86_64::compute_abi_info(cx, self)
} }
} }
},
"aarch64" => aarch64::compute_abi_info(cx, self), "aarch64" => aarch64::compute_abi_info(cx, self),
"amdgpu" => amdgpu::compute_abi_info(cx, self), "amdgpu" => amdgpu::compute_abi_info(cx, self),
"arm" => arm::compute_abi_info(cx, self), "arm" => arm::compute_abi_info(cx, self),

View file

@ -13,14 +13,14 @@ pub enum Abi {
// churn. The specific values are meaningless. // churn. The specific values are meaningless.
Rust, Rust,
C { unwind: bool }, C { unwind: bool },
Cdecl, Cdecl { unwind: bool },
Stdcall { unwind: bool }, Stdcall { unwind: bool },
Fastcall, Fastcall { unwind: bool },
Vectorcall, Vectorcall { unwind: bool },
Thiscall { unwind: bool }, Thiscall { unwind: bool },
Aapcs, Aapcs { unwind: bool },
Win64, Win64 { unwind: bool },
SysV64, SysV64 { unwind: bool },
PtxKernel, PtxKernel,
Msp430Interrupt, Msp430Interrupt,
X86Interrupt, X86Interrupt,
@ -50,16 +50,22 @@ const AbiDatas: &[AbiData] = &[
AbiData { abi: Abi::Rust, name: "Rust" }, AbiData { abi: Abi::Rust, name: "Rust" },
AbiData { abi: Abi::C { unwind: false }, name: "C" }, AbiData { abi: Abi::C { unwind: false }, name: "C" },
AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" }, 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: false }, name: "stdcall" },
AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" }, AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" },
AbiData { abi: Abi::Fastcall, name: "fastcall" }, AbiData { abi: Abi::Fastcall { unwind: false }, name: "fastcall" },
AbiData { abi: Abi::Vectorcall, name: "vectorcall" }, 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: false }, name: "thiscall" },
AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" }, AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" },
AbiData { abi: Abi::Aapcs, name: "aapcs" }, AbiData { abi: Abi::Aapcs { unwind: false }, name: "aapcs" },
AbiData { abi: Abi::Win64, name: "win64" }, AbiData { abi: Abi::Aapcs { unwind: true }, name: "aapcs-unwind" },
AbiData { abi: Abi::SysV64, name: "sysv64" }, 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::PtxKernel, name: "ptx-kernel" },
AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" }, AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" },
AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" }, AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" },
@ -101,32 +107,38 @@ impl Abi {
C { unwind: false } => 1, C { unwind: false } => 1,
C { unwind: true } => 2, C { unwind: true } => 2,
// Platform-specific ABIs // Platform-specific ABIs
Cdecl => 3, Cdecl { unwind: false } => 3,
Stdcall { unwind: false } => 4, Cdecl { unwind: true } => 4,
Stdcall { unwind: true } => 5, Stdcall { unwind: false } => 5,
Fastcall => 6, Stdcall { unwind: true } => 6,
Vectorcall => 7, Fastcall { unwind: false } => 7,
Thiscall { unwind: false } => 8, Fastcall { unwind: true } => 8,
Thiscall { unwind: true } => 9, Vectorcall { unwind: false } => 9,
Aapcs => 10, Vectorcall { unwind: true } => 10,
Win64 => 11, Thiscall { unwind: false } => 11,
SysV64 => 12, Thiscall { unwind: true } => 12,
PtxKernel => 13, Aapcs { unwind: false } => 13,
Msp430Interrupt => 14, Aapcs { unwind: true } => 14,
X86Interrupt => 15, Win64 { unwind: false } => 15,
AmdGpuKernel => 16, Win64 { unwind: true } => 16,
EfiApi => 17, SysV64 { unwind: false } => 17,
AvrInterrupt => 18, SysV64 { unwind: true } => 18,
AvrNonBlockingInterrupt => 19, PtxKernel => 19,
CCmseNonSecureCall => 20, Msp430Interrupt => 20,
Wasm => 21, X86Interrupt => 21,
AmdGpuKernel => 22,
EfiApi => 23,
AvrInterrupt => 24,
AvrNonBlockingInterrupt => 25,
CCmseNonSecureCall => 26,
Wasm => 27,
// Cross-platform ABIs // Cross-platform ABIs
System { unwind: false } => 22, System { unwind: false } => 28,
System { unwind: true } => 23, System { unwind: true } => 29,
RustIntrinsic => 24, RustIntrinsic => 30,
RustCall => 25, RustCall => 31,
PlatformIntrinsic => 26, PlatformIntrinsic => 32,
Unadjusted => 27, Unadjusted => 33,
}; };
debug_assert!( debug_assert!(
AbiDatas AbiDatas

View file

@ -1556,15 +1556,15 @@ impl Target {
Abi::Stdcall { unwind } Abi::Stdcall { unwind }
} }
Abi::System { unwind } => Abi::C { 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 }, Abi::EfiApi => Abi::C { unwind: false },
// See commentary in `is_abi_supported`. // See commentary in `is_abi_supported`.
Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi, Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi,
Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind }, Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind },
Abi::Fastcall if self.arch == "x86" => abi, Abi::Fastcall { .. } if self.arch == "x86" => abi,
Abi::Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => abi, Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
Abi::Fastcall | Abi::Vectorcall => Abi::C { unwind: false }, Abi::Fastcall { unwind } | Abi::Vectorcall { unwind } => Abi::C { unwind },
abi => abi, abi => abi,
} }
@ -1581,12 +1581,12 @@ impl Target {
| RustCall | RustCall
| PlatformIntrinsic | PlatformIntrinsic
| Unadjusted | Unadjusted
| Cdecl | Cdecl { .. }
| EfiApi => true, | EfiApi => true,
X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
Aapcs => "arm" == self.arch, Aapcs { .. } => "arm" == self.arch,
CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
Win64 | SysV64 => self.arch == "x86_64", Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
PtxKernel => self.arch == "nvptx64", PtxKernel => self.arch == "nvptx64",
Msp430Interrupt => self.arch == "msp430", Msp430Interrupt => self.arch == "msp430",
AmdGpuKernel => self.arch == "amdgcn", AmdGpuKernel => self.arch == "amdgcn",
@ -1623,13 +1623,13 @@ impl Target {
// > convention is used. // > convention is used.
// //
// -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions // -- 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 // Outside of Windows we want to only support these calling conventions for the
// architectures for which these calling conventions are actually well defined. // architectures for which these calling conventions are actually well defined.
Stdcall { .. } | Fastcall if self.arch == "x86" => true, Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => 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. // 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,
}) })
} }

View file

@ -121,7 +121,7 @@ use bounds::Bounds;
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
match (decl.c_variadic, abi) { match (decl.c_variadic, abi) {
// The function has the correct calling convention, or isn't a "C-variadic" function. // 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. // The function is a "C-variadic" function with an incorrect calling convention.
(true, _) => { (true, _) => {
let mut err = struct_span_err!( let mut err = struct_span_err!(

View file

@ -6,9 +6,20 @@ The tracking issue for this feature is: [#74990]
------------------------ ------------------------
Introduces four new ABI strings: "C-unwind", "stdcall-unwind", Introduces new ABI strings:
"thiscall-unwind", and "system-unwind". These enable unwinding from other - "C-unwind"
languages (such as C++) into Rust frames and from Rust into other languages. - "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. See [RFC 2945] for more information.

View file

@ -0,0 +1,31 @@
// needs-llvm-components: arm
// compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes
#![no_core]
#![feature(no_core, lang_items, c_unwind)]
#[lang="sized"]
trait Sized { }
// Test that `nounwind` atributes are correctly applied to exported `aapcs` and
// `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We
// disable optimizations above to prevent LLVM from inferring the attribute.
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "aapcs" fn rust_item_that_cannot_unwind() {
}
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
#[no_mangle]
pub extern "aapcs-unwind" fn rust_item_that_can_unwind() {
}
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
// sure that the first item is correctly marked with the `nounwind` attribute:
//
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
//
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
//
// CHECK: attributes #1 = {
// CHECK-NOT: nounwind
// CHECK: }

View file

@ -0,0 +1,29 @@
// compile-flags: -C opt-level=0
// Test that `nounwind` atributes are correctly applied to exported `cdecl` and
// `cdecl-unwind` extern functions. `cdecl-unwind` functions MUST NOT have this attribute. We
// disable optimizations above to prevent LLVM from inferring the attribute.
#![crate_type = "lib"]
#![feature(c_unwind)]
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "cdecl" fn rust_item_that_cannot_unwind() {
}
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
#[no_mangle]
pub extern "cdecl-unwind" fn rust_item_that_can_unwind() {
}
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
// sure that the first item is correctly marked with the `nounwind` attribute:
//
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
//
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
//
// CHECK: attributes #1 = {
// CHECK-NOT: nounwind
// CHECK: }

View file

@ -0,0 +1,31 @@
// needs-llvm-components: x86
// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
#![no_core]
#![feature(no_core, lang_items, c_unwind)]
#[lang="sized"]
trait Sized { }
// Test that `nounwind` atributes are correctly applied to exported `fastcall` and
// `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We
// disable optimizations above to prevent LLVM from inferring the attribute.
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "fastcall" fn rust_item_that_cannot_unwind() {
}
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
#[no_mangle]
pub extern "fastcall-unwind" fn rust_item_that_can_unwind() {
}
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
// sure that the first item is correctly marked with the `nounwind` attribute:
//
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
//
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
//
// CHECK: attributes #1 = {
// CHECK-NOT: nounwind
// CHECK: }

View file

@ -0,0 +1,31 @@
// needs-llvm-components: x86
// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes
#![no_core]
#![feature(no_core, lang_items, c_unwind)]
#[lang="sized"]
trait Sized { }
// Test that `nounwind` atributes are correctly applied to exported `sysv64` and
// `sysv64-unwind` extern functions. `sysv64-unwind` functions MUST NOT have this attribute. We
// disable optimizations above to prevent LLVM from inferring the attribute.
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "sysv64" fn rust_item_that_cannot_unwind() {
}
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
#[no_mangle]
pub extern "sysv64-unwind" fn rust_item_that_can_unwind() {
}
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
// sure that the first item is correctly marked with the `nounwind` attribute:
//
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
//
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
//
// CHECK: attributes #1 = {
// CHECK-NOT: nounwind
// CHECK: }

View file

@ -0,0 +1,31 @@
// needs-llvm-components: x86
// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
#![no_core]
#![feature(no_core, lang_items, c_unwind, abi_vectorcall)]
#[lang="sized"]
trait Sized { }
// Test that `nounwind` atributes are correctly applied to exported `vectorcall` and
// `vectorcall-unwind` extern functions. `vectorcall-unwind` functions MUST NOT have this attribute.
// We disable optimizations above to prevent LLVM from inferring the attribute.
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "vectorcall" fn rust_item_that_cannot_unwind() {
}
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
#[no_mangle]
pub extern "vectorcall-unwind" fn rust_item_that_can_unwind() {
}
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
// sure that the first item is correctly marked with the `nounwind` attribute:
//
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
//
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
//
// CHECK: attributes #1 = {
// CHECK-NOT: nounwind
// CHECK: }

View file

@ -0,0 +1,31 @@
// needs-llvm-components: x86
// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes
#![no_core]
#![feature(no_core, lang_items, c_unwind)]
#[lang="sized"]
trait Sized { }
// Test that `nounwind` atributes are correctly applied to exported `win64` and
// `win64-unwind` extern functions. `win64-unwind` functions MUST NOT have this attribute. We
// disable optimizations above to prevent LLVM from inferring the attribute.
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "win64" fn rust_item_that_cannot_unwind() {
}
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
#[no_mangle]
pub extern "win64-unwind" fn rust_item_that_can_unwind() {
}
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
// sure that the first item is correctly marked with the `nounwind` attribute:
//
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
//
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
//
// CHECK: attributes #1 = {
// CHECK-NOT: nounwind
// CHECK: }

View file

@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́`
LL | extern "路濫狼á́́" fn foo() {} LL | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^^ invalid ABI | ^^^^^^^^^ invalid ABI
| |
= help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
error: aborting due to previous error error: aborting due to previous error

View file

@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize`
LL | "invalid-ab_isize" LL | "invalid-ab_isize"
| ^^^^^^^^^^^^^^^^^^ invalid ABI | ^^^^^^^^^^^^^^^^^^ invalid ABI
| |
= help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
error: aborting due to previous error error: aborting due to previous error