Skip to main content

swiftui_native/abi/
mod.rs

1//! Driving the Swift runtime directly: the ABI this crate speaks.
2//!
3//! Nothing here goes through a Swift source file. A SwiftUI view is built by
4//! finding a mangled symbol with `dlsym`, arranging registers the way the
5//! Swift compiler would have, and branching to it. That works because Swift's
6//! arm64 convention is stable and documented — but three of its registers have
7//! no counterpart in a Rust signature, so every call has to be written out:
8//!
9//! | register | role |
10//! |----------|------|
11//! | `x0`–`x7` | integer and pointer arguments, then any generic metadata, then any witness tables |
12//! | `d0`–`d7` | floating-point arguments |
13//! | `x8` | address of an indirect (`@out`) result |
14//! | `x20` | the *self* register: a receiver, or a type's metadata for an initialiser or static |
15//! | `x21` | the error register, which nothing here throws through and everything clobbers |
16//!
17//! Whether a value travels *in* a register or *by address* is the question
18//! that decides whether a call works, and it is not visible in the symbol
19//! name. A `@frozen` type of at most four registers is passed directly; a
20//! resilient one is passed by address, because the caller is not allowed to
21//! know its size. Two traps follow from that and both cost real time here:
22//!
23//! * An `Optional`'s payload is **not** destructured. `Optional<UnitPoint>` is
24//!   two `CGFloat`s and a tag, and it arrives as three *integer* registers —
25//!   a `Double` inside an optional reaches the callee in x0, not d0.
26//! * Getting a return convention wrong rarely faults at the call. A function
27//!   that writes through x8 while the caller reads x0 hands back a stale
28//!   register, which SwiftUI stores and dereferences much later.
29//!
30//! [`call`] holds the primitives that make those choices explicit, and the
31//! rest of this module is built on them:
32//!
33//! * `value` — enum tags, optionals, strings and arrays
34//! * `metadata` — type metadata, witness tables and layout queries
35//! * `modifier` — applying a `View` modifier and wrapping the result
36//! * `closure` — Rust functions Swift can call back into
37
38
39pub mod call;
40mod closure;
41mod metadata;
42mod modifier;
43mod value;
44pub use call::{
45    call_f64, call_out, call_regs, call_spilled, ints, static_out, static_regs, Floats, Ints,
46};
47use crate::resolve;
48
49pub use closure::*;
50pub use metadata::*;
51pub use modifier::*;
52pub use value::*;