Skip to content

Commit 010c901

Browse files
committed
allow system abi to be variadic
1 parent 090d5ea commit 010c901

File tree

8 files changed

+25
-12
lines changed

8 files changed

+25
-12
lines changed

compiler/rustc_hir_analysis/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ use rustc_hir::def::DefKind;
116116
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
117117

118118
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
119-
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`";
119+
const CONVENTIONS_UNSTABLE: &str =
120+
"`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`";
120121
const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
121122
const UNSTABLE_EXPLAIN: &str =
122123
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";

compiler/rustc_metadata/src/native_libs.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,16 @@ impl<'tcx> Collector<'tcx> {
523523
let calling_convention = if self.tcx.sess.target.arch == "x86" {
524524
match abi {
525525
Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
526-
Abi::Stdcall { .. } | Abi::System { .. } => {
527-
DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
526+
Abi::Stdcall { .. } => DllCallingConvention::Stdcall(self.i686_arg_list_size(item)),
527+
Abi::System { .. } => {
528+
let c_variadic =
529+
self.tcx.type_of(item).instantiate_identity().fn_sig(self.tcx).c_variadic();
530+
531+
if c_variadic {
532+
DllCallingConvention::C
533+
} else {
534+
DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
535+
}
528536
}
529537
Abi::Fastcall { .. } => {
530538
DllCallingConvention::Fastcall(self.i686_arg_list_size(item))

compiler/rustc_target/src/abi/call/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
840840
"sparc" => sparc::compute_abi_info(cx, self),
841841
"sparc64" => sparc64::compute_abi_info(cx, self),
842842
"nvptx64" => {
843-
if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::PtxKernel {
843+
if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::PtxKernel {
844844
nvptx64::compute_ptx_kernel_abi_info(cx, self)
845845
} else {
846846
nvptx64::compute_abi_info(self)
@@ -849,7 +849,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
849849
"hexagon" => hexagon::compute_abi_info(self),
850850
"riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
851851
"wasm32" | "wasm64" => {
852-
if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm {
852+
if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::Wasm {
853853
wasm::compute_wasm_abi_info(self)
854854
} else {
855855
wasm::compute_c_abi_info(cx, self)

compiler/rustc_target/src/spec/abi/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl Abi {
7979
match self {
8080
Self::C { .. }
8181
| Self::Cdecl { .. }
82+
| Self::System { .. }
8283
| Self::Aapcs { .. }
8384
| Self::Win64 { .. }
8485
| Self::SysV64 { .. }

compiler/rustc_target/src/spec/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2399,10 +2399,10 @@ impl DerefMut for Target {
23992399

24002400
impl Target {
24012401
/// Given a function ABI, turn it into the correct ABI for this target.
2402-
pub fn adjust_abi(&self, abi: Abi) -> Abi {
2402+
pub fn adjust_abi(&self, abi: Abi, c_variadic: bool) -> Abi {
24032403
match abi {
24042404
Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi),
2405-
Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => {
2405+
Abi::System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
24062406
Abi::Stdcall { unwind }
24072407
}
24082408
Abi::System { unwind } => Abi::C { unwind },

compiler/rustc_ty_utils/src/abi.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ fn fn_sig_for_fn_abi<'tcx>(
228228
}
229229

230230
#[inline]
231-
fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
231+
fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv {
232232
use rustc_target::spec::abi::Abi::*;
233-
match tcx.sess.target.adjust_abi(abi) {
233+
match tcx.sess.target.adjust_abi(abi, c_variadic) {
234234
RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust,
235235

236236
// This is intentionally not using `Conv::Cold`, as that has to preserve
@@ -488,7 +488,7 @@ fn fn_abi_new_uncached<'tcx>(
488488
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
489489
let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig);
490490

491-
let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
491+
let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);
492492

493493
let mut inputs = sig.inputs();
494494
let extra_args = if sig.abi == RustCall {

tests/ui/c-variadic/variadic-ffi-2.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44
fn baz(f: extern "stdcall" fn(usize, ...)) {
55
//~^ ERROR: C-variadic function must have a compatible calling convention,
6-
// like C, cdecl, aapcs, win64, sysv64 or efiapi
6+
// like C, cdecl, system, aapcs, win64, sysv64 or efiapi
77
f(22, 44);
88
}
99

10+
fn system(f: extern "system" fn(usize, ...)) {
11+
f(22, 44);
12+
}
1013
fn aapcs(f: extern "aapcs" fn(usize, ...)) {
1114
f(22, 44);
1215
}

tests/ui/c-variadic/variadic-ffi-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`
1+
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`
22
--> $DIR/variadic-ffi-2.rs:4:11
33
|
44
LL | fn baz(f: extern "stdcall" fn(usize, ...)) {

0 commit comments

Comments
 (0)