1use core::ffi::c_void;
4
5#[repr(C)]
17pub struct ClosureCtx {
18 isa: *const c_void,
19 refcount: u64,
20 body: unsafe extern "C" fn(*mut u8, *mut c_void),
21 payload: *mut c_void,
22}
23
24pub(crate) const IMMORTAL_REFCOUNT: u64 = 0x8000_0004_ffff_ffff;
26
27pub(crate) fn immortal_isa() -> *const c_void {
29 static ISA: std::sync::OnceLock<usize> = std::sync::OnceLock::new();
32 *ISA.get_or_init(|| {
33 unsafe extern "C" {
34 fn dlsym(handle: *mut c_void, symbol: *const core::ffi::c_char) -> *mut c_void;
35 }
36 let obj = unsafe { dlsym((-2isize) as *mut c_void, c"_swiftEmptyArrayStorage".as_ptr()) };
37 if obj.is_null() {
38 0
39 } else {
40 unsafe { *(obj as *const *const c_void) as usize }
41 }
42 }) as *const c_void
43}
44
45impl ClosureCtx {
46 pub fn new(
49 body: unsafe extern "C" fn(*mut u8, *mut c_void),
50 payload: *mut c_void,
51 ) -> Self {
52 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
53 }
54}
55
56core::arch::global_asm!(
61 ".p2align 2",
62 ".globl _rswift_swift_closure_thunk",
63 "_rswift_swift_closure_thunk:",
64 "mov x0, x8",
65 "mov x1, x20",
66 "b _rswift_swift_closure_dispatch",
67);
68
69unsafe extern "C" {
70 #[link_name = "rswift_swift_closure_thunk"]
72 pub fn swift_closure_thunk();
73}
74
75#[unsafe(no_mangle)]
76unsafe extern "C" fn rswift_swift_closure_dispatch(out: *mut u8, ctx: *mut ClosureCtx) {
77 let ctx = unsafe { &*ctx };
78 unsafe { (ctx.body)(out, ctx.payload) };
79}
80
81core::arch::global_asm!(
86 ".p2align 2",
87 ".globl _rswift_index_closure_thunk",
88 "_rswift_index_closure_thunk:",
89 "mov x2, x20",
90 "mov x1, x0",
91 "mov x0, x8",
92 "b _rswift_index_closure_dispatch",
93);
94
95unsafe extern "C" {
96 #[link_name = "rswift_index_closure_thunk"]
98 pub fn index_closure_thunk();
99}
100
101#[repr(C)]
113pub struct IsolatedContext {
114 isa: *const c_void,
115 refcount: u64,
116 isolation: [u64; 2],
117}
118
119impl IsolatedContext {
120 pub fn nonisolated() -> Self {
122 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, isolation: [0; 2] }
123 }
124}
125
126#[repr(C)]
128pub struct IndexClosureCtx {
129 isa: *const c_void,
130 refcount: u64,
131 body: unsafe extern "C" fn(*mut u8, i64, *mut c_void),
132 payload: *mut c_void,
133}
134
135impl IndexClosureCtx {
136 pub fn new(
137 body: unsafe extern "C" fn(*mut u8, i64, *mut c_void),
138 payload: *mut c_void,
139 ) -> Self {
140 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
141 }
142}
143
144#[unsafe(no_mangle)]
145unsafe extern "C" fn rswift_index_closure_dispatch(
146 out: *mut u8,
147 index: i64,
148 ctx: *mut IndexClosureCtx,
149) {
150 let ctx = unsafe { &*ctx };
151 unsafe { (ctx.body)(out, index, ctx.payload) };
152}
153
154core::arch::global_asm!(
158 ".p2align 2",
159 ".globl _rswift_value_closure_thunk",
160 "_rswift_value_closure_thunk:",
161 "mov x1, x20",
162 "b _rswift_value_closure_dispatch",
163);
164
165unsafe extern "C" {
166 #[link_name = "rswift_value_closure_thunk"]
168 pub fn value_closure_thunk();
169}
170
171#[repr(C)]
173pub struct ValueClosureCtx {
174 isa: *const c_void,
175 refcount: u64,
176 body: unsafe extern "C" fn(*const u8, *mut c_void),
177 payload: *mut c_void,
178}
179
180impl ValueClosureCtx {
181 pub fn new(
182 body: unsafe extern "C" fn(*const u8, *mut c_void),
183 payload: *mut c_void,
184 ) -> Self {
185 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
186 }
187}
188
189#[unsafe(no_mangle)]
190unsafe extern "C" fn rswift_value_closure_dispatch(value: *const u8, ctx: *mut ValueClosureCtx) {
191 let ctx = unsafe { &*ctx };
192 unsafe { (ctx.body)(value, ctx.payload) };
193}
194
195core::arch::global_asm!(
199 ".p2align 2",
200 ".globl _rswift_pair_closure_thunk",
201 "_rswift_pair_closure_thunk:",
202 "mov x2, x20",
203 "b _rswift_pair_closure_dispatch",
204);
205
206unsafe extern "C" {
207 #[link_name = "rswift_pair_closure_thunk"]
209 pub fn pair_closure_thunk();
210}
211
212#[repr(C)]
214pub struct PairClosureCtx {
215 isa: *const c_void,
216 refcount: u64,
217 body: unsafe extern "C" fn(*const u8, *const u8, *mut c_void),
218 payload: *mut c_void,
219}
220
221impl PairClosureCtx {
222 pub fn new(
223 body: unsafe extern "C" fn(*const u8, *const u8, *mut c_void),
224 payload: *mut c_void,
225 ) -> Self {
226 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
227 }
228}
229
230#[unsafe(no_mangle)]
231unsafe extern "C" fn rswift_pair_closure_dispatch(
232 a: *const u8,
233 b: *const u8,
234 ctx: *mut PairClosureCtx,
235) {
236 let ctx = unsafe { &*ctx };
237 unsafe { (ctx.body)(a, b, ctx.payload) };
238}
239
240core::arch::global_asm!(
247 ".p2align 2",
248 ".globl _rswift_wide_closure_thunk",
249 "_rswift_wide_closure_thunk:",
250 "mov x3, x20",
251 "b _rswift_wide_closure_dispatch",
252);
253
254unsafe extern "C" {
255 #[link_name = "rswift_wide_closure_thunk"]
258 pub fn wide_closure_thunk();
259}
260
261#[repr(C)]
263pub struct WideClosureCtx {
264 isa: *const c_void,
265 refcount: u64,
266 body: unsafe extern "C" fn(u64, u64, u64, *mut c_void),
267 payload: *mut c_void,
268}
269
270impl WideClosureCtx {
271 pub fn new(
272 body: unsafe extern "C" fn(u64, u64, u64, *mut c_void),
273 payload: *mut c_void,
274 ) -> Self {
275 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
276 }
277}
278
279#[unsafe(no_mangle)]
280unsafe extern "C" fn rswift_wide_closure_dispatch(
281 a0: u64,
282 a1: u64,
283 a2: u64,
284 ctx: *mut WideClosureCtx,
285) {
286 let ctx = unsafe { &*ctx };
287 unsafe { (ctx.body)(a0, a1, a2, ctx.payload) };
288}
289
290pub unsafe fn read_enum_tag(value: *const u8, metadata: *const c_void) -> u32 {
298 unsafe {
299 const ENUM_WITNESSES: usize = 8 * 8 + 8 + 8 + 4 + 4;
300 let vwt = *(metadata.cast::<*const u8>().offset(-1));
301 let get = *(vwt.add(ENUM_WITNESSES) as *const *const c_void);
302 type Get = unsafe extern "C" fn(*const c_void, *const c_void) -> u32;
303 let f: Get = core::mem::transmute(get);
304 f(value as *const c_void, metadata)
305 }
306}
307
308#[macro_export]
326macro_rules! type_by_name {
327 ($bytes:expr) => {{
328 static SITE: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
329 let hit = SITE.load(::std::sync::atomic::Ordering::Relaxed);
330 if hit != 0 {
331 hit as *const ::core::ffi::c_void
332 } else {
333 let m = $crate::abi::resolve_type_by_mangled_name($bytes);
334 SITE.store(m as usize, ::std::sync::atomic::Ordering::Relaxed);
335 m
336 }
337 }};
338}
339
340pub unsafe fn resolve_type_by_mangled_name(mangled: &[u8]) -> *const c_void {
344 use std::collections::HashMap;
345 use std::sync::{Mutex, OnceLock};
346 static CACHE: OnceLock<Mutex<HashMap<Vec<u8>, usize>>> = OnceLock::new();
347 let cache = CACHE.get_or_init(|| Mutex::new(HashMap::new()));
348
349 if let Ok(map) = cache.lock() {
350 if let Some(&hit) = map.get(mangled) {
351 return hit as *const c_void;
352 }
353 }
354 let resolved = unsafe {
355 swift_runtime_sys::RuntimeRaw::swift_getTypeByMangledNameInEnvironment(
356 mangled.as_ptr(),
357 mangled.len(),
358 core::ptr::null(),
359 0,
360 )
361 };
362 if !resolved.is_null() {
363 if let Ok(mut map) = cache.lock() {
364 map.insert(mangled.to_vec(), resolved as usize);
365 }
366 }
367 resolved
368}
369
370core::arch::global_asm!(
374 ".p2align 2",
375 ".globl _rswift_word_closure_thunk",
376 "_rswift_word_closure_thunk:",
377 "mov x1, x0",
378 "mov x0, x20",
379 "b _rswift_word_closure_dispatch",
380);
381
382unsafe extern "C" {
383 #[link_name = "rswift_word_closure_thunk"]
385 pub fn word_closure_thunk();
386}
387
388#[repr(C)]
393pub struct WordClosureCtx {
394 isa: *const c_void,
395 refcount: u64,
396 body: unsafe extern "C" fn(*mut c_void, u64) -> u64,
397 payload: *mut c_void,
398}
399
400impl WordClosureCtx {
401 pub fn new(
402 body: unsafe extern "C" fn(*mut c_void, u64) -> u64,
403 payload: *mut c_void,
404 ) -> Self {
405 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
406 }
407}
408
409#[unsafe(no_mangle)]
410unsafe extern "C" fn rswift_word_closure_dispatch(ctx: *mut WordClosureCtx, arg: u64) -> u64 {
411 let ctx = unsafe { &*ctx };
412 unsafe { (ctx.body)(ctx.payload, arg) }
413}
414
415core::arch::global_asm!(
418 ".p2align 2",
419 ".globl _rswift_float_closure_thunk",
420 "_rswift_float_closure_thunk:",
421 "mov x1, x20",
422 "b _rswift_float_closure_dispatch",
423);
424
425unsafe extern "C" {
426 #[link_name = "rswift_float_closure_thunk"]
428 pub fn float_closure_thunk();
429}
430
431#[repr(C)]
433pub struct FloatClosureCtx {
434 isa: *const c_void,
435 refcount: u64,
436 body: unsafe extern "C" fn(u64, *mut c_void) -> f64,
437 payload: *mut c_void,
438}
439
440impl FloatClosureCtx {
441 pub fn new(
442 body: unsafe extern "C" fn(u64, *mut c_void) -> f64,
443 payload: *mut c_void,
444 ) -> Self {
445 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
446 }
447}
448
449#[unsafe(no_mangle)]
450unsafe extern "C" fn rswift_float_closure_dispatch(arg: u64, ctx: *mut FloatClosureCtx) -> f64 {
451 let ctx = unsafe { &*ctx };
452 unsafe { (ctx.body)(arg, ctx.payload) }
453}
454
455core::arch::global_asm!(
460 ".p2align 2",
461 ".globl _rswift_pair_return_closure_thunk",
462 "_rswift_pair_return_closure_thunk:",
463 "mov x0, x20",
464 "b _rswift_pair_return_closure_dispatch",
465);
466
467unsafe extern "C" {
468 #[link_name = "rswift_pair_return_closure_thunk"]
470 pub fn pair_return_closure_thunk();
471}
472
473#[repr(C)]
475pub struct Pair(pub u64, pub u64);
476
477#[repr(C)]
479pub struct PairReturnClosureCtx {
480 isa: *const c_void,
481 refcount: u64,
482 body: unsafe extern "C" fn(*mut c_void) -> Pair,
483 payload: *mut c_void,
484}
485
486impl PairReturnClosureCtx {
487 pub fn new(body: unsafe extern "C" fn(*mut c_void) -> Pair, payload: *mut c_void) -> Self {
488 Self { isa: immortal_isa(), refcount: IMMORTAL_REFCOUNT, body, payload }
489 }
490}
491
492#[unsafe(no_mangle)]
493unsafe extern "C" fn rswift_pair_return_closure_dispatch(ctx: *mut PairReturnClosureCtx) -> Pair {
494 let ctx = unsafe { &*ctx };
495 unsafe { (ctx.body)(ctx.payload) }
496}