Skip to content

Just how unspecified is repr Rust over extern C? #563

Closed
@CAD97

Description

@CAD97

Assume a C ABI which is able to be called without a function prototype (is immediately compatible with C's variadic functions without adjustment). That is, the set of assumed, preserved, and clobbered CPU state (e.g. registers) is independent of signature, and any stack space used for arguments is allocated in the caller's stack frame (caller cleanup).

In this case, the following function definition should be valid to call with any list of ffi-safe arguments for the varargs:

#[naked]
unsafe extern "C" fn f(_: i32, _: ...) {
    unsafe { naked_asm!("ret") }
}

In fact, if you define an empty variadic function on x64 Linux, after optimization the assembly is a single ret, as in this naked definition.

The question: given that an extern "C" ABI guarantees that the only difference in call ABI is performing default argument promotion in the caller, is it valid to provide a repr(Rust) as one of the variadic arguments? And if so, is it also valid to call the function through a function pointer transmuted to a non-variadic signature that mentions a repr(Rust) type?

Or, in an alternate phrasing, are all extern "C" fn guaranteed to have a way to write their effective ABI in C? Or are repr(Rust) types in a function signature allowed to arbitrarily modify the calling convention independent of the ABI string specified?

Of course, C variadic support is still unstable currently, but the same scenario as the function pointer transmute can be created on stable by linking to an external symbol.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions