Closed bjorn3 closed 1 week ago
While native Cranelift support would be ideal, I believe it's possible to support varargs on arm64 macOS to a similar extent as x86-64 by just padding the argument list to use up all the registers and force the varargs into stack slots. For example, the following calls result in the same argument placements on arm64 macOS:
use std::mem::MaybeUninit;
type Pad = MaybeUninit<usize>;
const PAD: Pad = MaybeUninit::uninit();
unsafe fn call_va(path: *const i8, flags: i32, mode: i32) -> i32 {
extern "C" {
fn open(path: *const i8, flags: i32, ...) -> i32;
}
open(path, flags, mode)
}
unsafe fn call_explicit(path: *const i8, flags: i32, mode: i32) -> i32 {
extern "C" {
fn open(path: *const i8, flags: i32, _: Pad, _: Pad, _: Pad, _: Pad, _: Pad, _: Pad, mode: i32) -> i32;
}
// There are 8 integer registers to consume.
open(path, flags, PAD, PAD, PAD, PAD, PAD, PAD, mode)
}
@beetrees implemented support for varargs without needing Cranelift changes in https://github.com/rust-lang/rustc_codegen_cranelift/pull/1500.
On pretty much every target variadic functions almost the exact same ABI (on x86 you need to set
%al
to the upper bound of the amount of float args, so float args are currently forbidden by cg_clif) as non-variadic functions with the same arguments passed (after integer promotion, but rust denies vararg calls that need integer promotion anyway). This means that I can work around the lack of vararg support in Cranelift by changing the function signature of the imported function declaration to match the non-variadic counterpart. On arm64 macOS however variadic arguments are passed differently from non-variadic arguments: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Update-code-that-passes-arguments-to-variadic-functions As such we can't support vararg functions on arm64 macOS until Cranelift gets native vararg support: https://github.com/bytecodealliance/wasmtime/issues/1030