use core::ffi::c_void;
#[repr(C)]
pub struct ClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(*mut u8, *mut c_void),
payload: *mut c_void,
}
pub(crate) const IMMORTAL_REFCOUNT: u64 = 0x8000_0004_ffff_ffff;
pub(crate) fn immortal_isa() -> *const c_void {
static ISA: std::sync::OnceLock<usize> = std::sync::OnceLock::new();
*ISA.get_or_init(|| {
unsafe extern "C" {
fn dlsym(handle: *mut c_void, symbol: *const core::ffi::c_char) -> *mut c_void;
}
let obj = unsafe { dlsym((-2isize) as *mut c_void, c"_swiftEmptyArrayStorage".as_ptr()) };
if obj.is_null() {
0
} else {
unsafe { *(obj as *const *const c_void) as usize }
}
}) as *const c_void
}
impl ClosureCtx {
pub fn new(
body: unsafe extern "C" fn(*mut u8, *mut c_void),
payload: *mut c_void,
) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_swift_closure_thunk",
"_rswift_swift_closure_thunk:",
"mov x0, x8",
"mov x1, x20",
"b _rswift_swift_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_swift_closure_thunk"]
pub fn swift_closure_thunk();
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_swift_closure_dispatch(out: *mut u8, ctx: *mut ClosureCtx) {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(out, ctx.payload) };
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_index_closure_thunk",
"_rswift_index_closure_thunk:",
"mov x2, x20",
"mov x1, x0",
"mov x0, x8",
"b _rswift_index_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_index_closure_thunk"]
pub fn index_closure_thunk();
}
#[repr(C)]
pub struct IsolatedContext {
isa: *const c_void,
refcount: u64,
isolation: [u64; 2],
}
impl IsolatedContext {
pub fn nonisolated() -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, isolation: [0; 2] }
}
}
#[repr(C)]
pub struct IndexClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(*mut u8, i64, *mut c_void),
payload: *mut c_void,
}
impl IndexClosureCtx {
pub fn new(
body: unsafe extern "C" fn(*mut u8, i64, *mut c_void),
payload: *mut c_void,
) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_index_closure_dispatch(
out: *mut u8,
index: i64,
ctx: *mut IndexClosureCtx,
) {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(out, index, ctx.payload) };
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_value_closure_thunk",
"_rswift_value_closure_thunk:",
"mov x1, x20",
"b _rswift_value_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_value_closure_thunk"]
pub fn value_closure_thunk();
}
#[repr(C)]
pub struct ValueClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(*const u8, *mut c_void),
payload: *mut c_void,
}
impl ValueClosureCtx {
pub fn new(
body: unsafe extern "C" fn(*const u8, *mut c_void),
payload: *mut c_void,
) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_value_closure_dispatch(value: *const u8, ctx: *mut ValueClosureCtx) {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(value, ctx.payload) };
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_pair_closure_thunk",
"_rswift_pair_closure_thunk:",
"mov x2, x20",
"b _rswift_pair_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_pair_closure_thunk"]
pub fn pair_closure_thunk();
}
#[repr(C)]
pub struct PairClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(*const u8, *const u8, *mut c_void),
payload: *mut c_void,
}
impl PairClosureCtx {
pub fn new(
body: unsafe extern "C" fn(*const u8, *const u8, *mut c_void),
payload: *mut c_void,
) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_pair_closure_dispatch(
a: *const u8,
b: *const u8,
ctx: *mut PairClosureCtx,
) {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(a, b, ctx.payload) };
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_wide_closure_thunk",
"_rswift_wide_closure_thunk:",
"mov x3, x20",
"b _rswift_wide_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_wide_closure_thunk"]
pub fn wide_closure_thunk();
}
#[repr(C)]
pub struct WideClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(u64, u64, u64, *mut c_void),
payload: *mut c_void,
}
impl WideClosureCtx {
pub fn new(
body: unsafe extern "C" fn(u64, u64, u64, *mut c_void),
payload: *mut c_void,
) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_wide_closure_dispatch(
a0: u64,
a1: u64,
a2: u64,
ctx: *mut WideClosureCtx,
) {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(a0, a1, a2, ctx.payload) };
}
pub unsafe fn read_enum_tag(value: *const u8, metadata: *const c_void) -> u32 {
unsafe {
const ENUM_WITNESSES: usize = 8 * 8 + 8 + 8 + 4 + 4;
let vwt = *(metadata.cast::<*const u8>().offset(-1));
let get = *(vwt.add(ENUM_WITNESSES) as *const *const c_void);
type Get = unsafe extern "C" fn(*const c_void, *const c_void) -> u32;
let f: Get = core::mem::transmute(get);
f(value as *const c_void, metadata)
}
}
#[macro_export]
macro_rules! type_by_name {
($bytes:expr) => {{
static SITE: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
let hit = SITE.load(::std::sync::atomic::Ordering::Relaxed);
if hit != 0 {
hit as *const ::core::ffi::c_void
} else {
let m = $crate::abi::resolve_type_by_mangled_name($bytes);
SITE.store(m as usize, ::std::sync::atomic::Ordering::Relaxed);
m
}
}};
}
pub unsafe fn resolve_type_by_mangled_name(mangled: &[u8]) -> *const c_void {
use std::collections::HashMap;
use std::sync::{Mutex, OnceLock};
static CACHE: OnceLock<Mutex<HashMap<Vec<u8>, usize>>> = OnceLock::new();
let cache = CACHE.get_or_init(|| Mutex::new(HashMap::new()));
if let Ok(map) = cache.lock() {
if let Some(&hit) = map.get(mangled) {
return hit as *const c_void;
}
}
let resolved = unsafe {
swift_runtime_sys::RuntimeRaw::swift_getTypeByMangledNameInEnvironment(
mangled.as_ptr(),
mangled.len(),
core::ptr::null(),
0,
)
};
if !resolved.is_null() {
if let Ok(mut map) = cache.lock() {
map.insert(mangled.to_vec(), resolved as usize);
}
}
resolved
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_word_closure_thunk",
"_rswift_word_closure_thunk:",
"mov x1, x0",
"mov x0, x20",
"b _rswift_word_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_word_closure_thunk"]
pub fn word_closure_thunk();
}
#[repr(C)]
pub struct WordClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(*mut c_void, u64) -> u64,
payload: *mut c_void,
}
impl WordClosureCtx {
pub fn new(
body: unsafe extern "C" fn(*mut c_void, u64) -> u64,
payload: *mut c_void,
) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_word_closure_dispatch(ctx: *mut WordClosureCtx, arg: u64) -> u64 {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(ctx.payload, arg) }
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_float_closure_thunk",
"_rswift_float_closure_thunk:",
"mov x1, x20",
"b _rswift_float_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_float_closure_thunk"]
pub fn float_closure_thunk();
}
#[repr(C)]
pub struct FloatClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(u64, *mut c_void) -> f64,
payload: *mut c_void,
}
impl FloatClosureCtx {
pub fn new(
body: unsafe extern "C" fn(u64, *mut c_void) -> f64,
payload: *mut c_void,
) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_float_closure_dispatch(arg: u64, ctx: *mut FloatClosureCtx) -> f64 {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(arg, ctx.payload) }
}
core::arch::global_asm!(
".p2align 2",
".globl _rswift_pair_return_closure_thunk",
"_rswift_pair_return_closure_thunk:",
"mov x0, x20",
"b _rswift_pair_return_closure_dispatch",
);
unsafe extern "C" {
#[link_name = "rswift_pair_return_closure_thunk"]
pub fn pair_return_closure_thunk();
}
#[repr(C)]
pub struct Pair(pub u64, pub u64);
#[repr(C)]
pub struct PairReturnClosureCtx {
isa: *const c_void,
refcount: u64,
body: unsafe extern "C" fn(*mut c_void) -> Pair,
payload: *mut c_void,
}
impl PairReturnClosureCtx {
pub fn new(body: unsafe extern "C" fn(*mut c_void) -> Pair, payload: *mut c_void) -> Self {
Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn rswift_pair_return_closure_dispatch(ctx: *mut PairReturnClosureCtx) -> Pair {
let ctx = unsafe { &*ctx };
unsafe { (ctx.body)(ctx.payload) }
}