1use super::*;
6use crate::abi;
7use crate::resolve;
8use core::ffi::c_void;
9use crate::mangle::{self, swift_type};
10
11pub(crate) unsafe fn localized_string_key(s0: u64, s1: u64) -> (u64, u64, u64, u64) {
21 let (k0, k1, k2, k3): (u64, u64, u64, u64);
22 unsafe {
23 core::arch::asm!("blr {f}", f = in(reg) resolve::lsk_init(),
24 inout("x0") s0 => k0, inout("x1") s1 => k1,
25 lateout("x2") k2, lateout("x3") k3,
26 in("x20") resolve::lsk_meta(),
27 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
28 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
29 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
30 lateout("x16") _, lateout("x17") _, lateout("lr") _, clobber_abi("C"),
31 );
32 }
33 (k0, k1, k2, k3)
34}
35
36pub fn text(s: &str) -> ViewHandle {
38 unsafe {
39 let ss = abi::swift_string(s);
40 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
41 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
42
43 let (k0, k1, k2, k3) = localized_string_key(s0, s1);
44
45 let (t0, t1, t2, t3): (u64, u64, u64, u64);
54 core::arch::asm!(
55 "sub sp, sp, #32",
56 "stp xzr, xzr, [sp]",
57 "stp xzr, xzr, [sp, #16]",
58 "blr {f}",
59 "add sp, sp, #32",
60 f = in(reg) resolve::text_lsk_init(),
61 inout("x0") k0 => t0, inout("x1") k1 => t1,
62 inout("x2") k2 => t2, inout("x3") k3 => t3,
63 in("x4") 0u64, in("x5") 0u64, in("x6") 0u64, in("x7") 0u64,
64 in("x20") resolve::text_meta(),
65 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
66 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
67 lateout("x16") _, lateout("x17") _, lateout("lr") _, clobber_abi("C"),
68 );
69
70 let mut buf = [0u8; 32];
71 buf[..8].copy_from_slice(&t0.to_le_bytes());
72 buf[8..16].copy_from_slice(&t1.to_le_bytes());
73 buf[16..24].copy_from_slice(&t2.to_le_bytes());
74 buf[24..32].copy_from_slice(&t3.to_le_bytes());
75 wrap_buf(&buf, resolve::text_meta(), resolve::text_wt())
76 }
77}
78
79pub fn styled_text(s: &str, size: f64, weight: i32, r: f64, g: f64, b: f64, a: f64) -> ViewHandle {
81 let t = font(&text(s), size, weight > 0);
82 foreground_style_color(&t, r, g, b, a)
83}
84
85pub fn bold_text(s: &str, size: f64) -> ViewHandle {
87 let t = text(s);
88 if size > 0.0 { font(&t, size, true) } else { bold(&t) }
89}
90
91pub(crate) unsafe fn color_value(r: f64, g: f64, b: f64, a: f64) -> u64 {
97 let mut cs: u8 = 0; let result: u64;
99 unsafe {
100 core::arch::asm!("blr {f}", f = in(reg) resolve::color_init(),
101 in("x0") &mut cs as *mut u8, in("d0") r, in("d1") g, in("d2") b, in("d3") a,
102 in("x20") resolve::color_meta(),
103 lateout("x0") result,
104 lateout("x1") _, lateout("x2") _, lateout("x3") _,
105 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
106 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
107 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
108 lateout("x16") _, lateout("x17") _, lateout("lr") _, clobber_abi("C"),
109 );
110 }
111 result
112}
113
114pub fn color_value_of(c: crate::Color) -> u64 {
120 unsafe { color_value(c.r, c.g, c.b, c.a) }
121}
122
123pub fn color_opacity(color: u64, opacity: f64) -> u64 {
130 unsafe {
131 let out: u64;
132 core::arch::asm!("blr {f}", f = in(reg) resolve::color_opacity(),
133 in("d0") opacity,
134 in("x0") color,
135 lateout("x0") out,
136 lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
137 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
138 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
139 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
140 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
141 clobber_abi("C"),
142 );
143 out
144 }
145}
146
147pub fn color_mix(color: u64, with: u64, by: f64) -> u64 {
154 color_mix_in(color, with, by, super::GradientColorSpace::Perceptual)
155}
156
157pub fn color_mix_in(
159 color: u64,
160 with: u64,
161 by: f64,
162 in_space: super::GradientColorSpace,
163) -> u64 {
164 unsafe {
165 let space_meta = abi::metadata0(resolve::gradient_color_space_ma());
166 assert!(!space_meta.is_null(), "Gradient.ColorSpace metadata");
167 let mut space = super::static_getter_indirect(
168 in_space.resolved(),
169 space_meta,
170 abi::type_bytes(space_meta),
171 );
172 let out: u64;
173 core::arch::asm!("blr {f}", f = in(reg) resolve::color_mix(),
174 in("x0") with,
175 in("d0") by,
176 in("x1") space.as_mut_ptr(),
177 in("x2") color,
178 lateout("x0") out,
179 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
180 lateout("x7") _, lateout("x8") _, lateout("x9") _, lateout("x10") _,
181 lateout("x11") _, lateout("x12") _, lateout("x13") _, lateout("x14") _,
182 lateout("x15") _, lateout("x16") _, lateout("x17") _, lateout("lr") _,
183 lateout("x20") _, lateout("x21") _, clobber_abi("C"),
184 );
185 out
186 }
187}
188
189pub fn color_exposure_adjust(color: u64, stops: f64) -> u64 {
198 unsafe {
199 let scale = f64::exp2(stops) as f32;
200 let out: u64;
201 core::arch::asm!("blr {f}", f = in(reg) resolve::color_linear_scale(),
202 in("s0") scale,
203 in("x0") color,
204 lateout("x0") out,
205 lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
206 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
207 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
208 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
209 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
210 clobber_abi("C"),
211 );
212 out
213 }
214}
215
216pub fn color_headroom(color: u64, headroom: Option<f64>) -> u64 {
222 unsafe {
223 let (bits, tag) = match headroom {
224 Some(v) => (v.to_bits(), 0u64),
225 None => (0, 1),
226 };
227 let out: u64;
228 core::arch::asm!("blr {f}", f = in(reg) resolve::color_headroom(),
229 in("x0") bits, in("x1") tag, in("x2") color,
230 lateout("x0") out,
231 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
232 lateout("x7") _, lateout("x8") _, lateout("x9") _, lateout("x10") _,
233 lateout("x11") _, lateout("x12") _, lateout("x13") _, lateout("x14") _,
234 lateout("x15") _, lateout("x16") _, lateout("x17") _, lateout("lr") _,
235 lateout("x20") _, lateout("x21") _, clobber_abi("C"),
236 );
237 out
238 }
239}
240
241pub fn color_gradient(color: u64) -> (Vec<u8>, *const c_void, *const c_void) {
248 unsafe {
249 let out: u64;
250 core::arch::asm!("blr {f}", f = in(reg) resolve::color_gradient(),
251 in("x0") color,
252 lateout("x0") out,
253 lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
254 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
255 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
256 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
257 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
258 clobber_abi("C"),
259 );
260 (out.to_le_bytes().to_vec(), resolve::any_gradient_meta(), resolve::any_gradient_wt())
261 }
262}
263
264pub fn color_view(color: u64) -> ViewHandle {
266 unsafe {
267 let buf = color.to_le_bytes();
268 wrap_buf(&buf, resolve::color_meta(), resolve::color_wt())
269 }
270}
271
272pub fn color(r: f64, g: f64, b: f64, a: f64) -> ViewHandle {
274 unsafe {
275 let buf = color_value(r, g, b, a).to_le_bytes();
276 wrap_buf(&buf, resolve::color_meta(), resolve::color_wt())
277 }
278}
279
280pub fn spacer() -> ViewHandle {
282 unsafe {
283 let r0: u64; let r1: u64;
284 core::arch::asm!("blr {f}", f = in(reg) resolve::spacer_init(),
285 in("x0") 0u64, in("x1") 1u64, in("x20") resolve::spacer_meta(),
291 lateout("x0") r0, lateout("x1") r1,
292 lateout("x2") _, lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
293 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
294 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
295 lateout("x16") _, lateout("x17") _, lateout("lr") _, clobber_abi("C"),
296 );
297 let mut buf = [0u8; 16];
298 buf[..8].copy_from_slice(&r0.to_le_bytes());
299 buf[8..16].copy_from_slice(&r1.to_le_bytes());
300 wrap_buf(&buf, resolve::spacer_meta(), resolve::spacer_wt())
301 }
302}
303
304pub(crate) const EDGE_SET_ALL: u64 = 0b1111;
311
312pub fn empty_view() -> ViewHandle {
314 unsafe { ViewHandle::wrap(core::ptr::null(), resolve::empty_meta(), resolve::empty_wt()) }
315}
316
317pub fn divider() -> ViewHandle {
319 unsafe { ViewHandle::wrap(core::ptr::null(), resolve::divider_meta(), resolve::divider_wt()) }
320}
321
322pub fn system_image(name: &str) -> ViewHandle {
324 unsafe {
325 let ss = abi::swift_string(name);
326 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
327 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
328 let result: u64;
329 core::arch::asm!("blr {f}", f = in(reg) resolve::image_sysname_init(),
330 in("x0") s0, in("x1") s1, in("x20") resolve::image_meta(),
331 lateout("x0") result,
332 lateout("x1") _, lateout("x2") _, lateout("x3") _,
333 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
334 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
335 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
336 lateout("x16") _, lateout("x17") _, lateout("lr") _, clobber_abi("C"),
337 );
338 let buf = result.to_le_bytes();
339 wrap_buf(&buf, resolve::image_meta(), resolve::image_wt())
340 }
341}
342
343mangle::result_types! {
344 pub(crate) PROGRESS_T = ty("ProgressView").of(vec![ty("EmptyView"), ty("EmptyView")]);
347 pub(crate) TOGGLE_T = ty("Toggle").of(vec![ty("Text")]);
350 pub(crate) TOGGLE_ANY_T = ty("Toggle").of(vec![ty("AnyView")]);
352 pub(crate) TEXTFIELD_T = ty("TextField").of(vec![ty("Text")]);
355 pub(crate) SECUREFIELD_T = ty("SecureField").of(vec![ty("Text")]);
358 pub(crate) SLIDER_T = ty("Slider").of(vec![ty("EmptyView"), ty("EmptyView")]);
361}
362
363pub fn progress_indeterminate() -> ViewHandle {
369 unsafe {
370 let ty = mangle::ty("ProgressView")
371 .of(vec![mangle::ty("EmptyView"), mangle::ty("EmptyView")])
372 .mangle();
373 let meta = abi::resolve_type_by_mangled_name(ty.as_bytes());
374 assert!(!meta.is_null(), "ProgressView<EmptyView, EmptyView> metadata");
375 let mut value = vec![0u8; abi::type_bytes(meta)];
376 core::arch::asm!("blr {f}", f = in(reg) resolve::progress_indeterminate_init(),
377 in("x8") value.as_mut_ptr(),
378 in("x20") meta,
379 lateout("x0") _, lateout("x1") _, lateout("x2") _, lateout("x3") _,
380 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
381 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
382 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
383 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
384 );
385 let wt = abi::get_view_wt(meta);
386 assert!(!wt.is_null(), "ProgressView !: View");
387 wrap_buf(&value, meta, wt)
388 }
389}
390
391pub fn progress(value: f64, total: f64) -> ViewHandle {
393 unsafe {
394 let double_meta = resolve::double_meta();
397 let bfp_wt =
398 abi::get_view_wt_for_proto(double_meta, resolve::binary_floating_point_proto());
399 assert!(!bfp_wt.is_null(), "Double: BinaryFloatingPoint");
400
401 let opt_meta = abi::resolve_type_by_mangled_name(mangle::optional(mangle::DOUBLE).as_bytes());
402 assert!(!opt_meta.is_null(), "Optional<Double> metadata");
403 let mut value_buf = vec![0u8; abi::type_bytes(opt_meta)];
404 value_buf[..8].copy_from_slice(&value.to_le_bytes());
405 abi::store_optional_tag(&mut value_buf, double_meta, true);
406
407 let mut total_buf = total.to_le_bytes();
408
409 let (meta, wt, size) = result_type(&PROGRESS_T);
410 let mut result = vec![0u8; size];
411 core::arch::asm!("blr {f}", f = in(reg) resolve::progress_init(),
415 in("x0") value_buf.as_mut_ptr(),
416 in("x1") total_buf.as_mut_ptr(),
417 in("x2") double_meta,
418 in("x3") bfp_wt,
419 in("x8") result.as_mut_ptr(),
420 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
421 lateout("x9") _, lateout("x10") _, lateout("x11") _,
422 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
423 lateout("x16") _, lateout("x17") _, lateout("lr") _,
424 lateout("x20") _, lateout("x21") _,
425 clobber_abi("C"),
426 );
427 wrap_owned(result, meta, wt)
428 }
429}
430
431
432
433pub(crate) unsafe fn constant_binding(
439 value: &[u8],
440 value_meta: *const c_void,
441 binding_mangled: &[u8],
442) -> Vec<u8> {
443 unsafe {
444 let binding_meta = abi::resolve_type_by_mangled_name(binding_mangled);
445 assert!(!binding_meta.is_null(), "Binding metadata");
446 let mut val = value.to_vec();
447 let mut out = vec![0u8; abi::type_bytes(binding_meta)];
448 core::arch::asm!("blr {f}", f = in(reg) resolve::binding_constant(),
454 in("x0") val.as_mut_ptr(),
455 in("x1") value_meta,
456 in("x8") out.as_mut_ptr(),
457 lateout("x2") _, lateout("x3") _, lateout("x4") _,
458 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x9") _,
459 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
460 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
461 lateout("lr") _, lateout("x20") _, lateout("x21") _, clobber_abi("C"),
462 );
463 let _ = binding_meta;
464 out
465 }
466}
467
468pub fn toggle(label: &str, is_on: bool) -> ViewHandle {
470 unsafe {
471 let ss = abi::swift_string(label);
472 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
473 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
474 let (k0, k1, k2, k3) = localized_string_key(s0, s1);
475
476 let binding = constant_binding(&[u8::from(is_on)], resolve::sym(c"$sSbN"), mangle::bound(&swift_type!(SwiftUI.Binding), &[mangle::BOOL]).as_bytes());
477 let b0 = u64::from_le_bytes(binding[0..8].try_into().unwrap());
479 let b1 = u64::from_le_bytes(binding[8..16].try_into().unwrap());
480 let b2 = binding[16] as u64;
481
482 let (meta, wt, size) = result_type(&TOGGLE_T);
483 let mut result = vec![0u8; size];
484 core::arch::asm!("blr {f}", f = in(reg) resolve::toggle_init(),
487 in("x0") k0, in("x1") k1, in("x2") k2, in("x3") k3,
488 in("x4") b0, in("x5") b1, in("x6") b2,
489 in("x8") result.as_mut_ptr(),
490 in("x20") meta,
491 lateout("x7") _,
492 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
493 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
494 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
495 );
496 wrap_owned(result, meta, wt)
497 }
498}
499
500
501
502
503
504pub(crate) unsafe extern "C" fn noop_closure() {}
507
508pub(crate) unsafe fn string_binding(value: &str) -> [u64; 4] {
510 unsafe {
511 let ss = abi::swift_string(value);
512 let b = constant_binding(&ss, resolve::string_meta_sym(), mangle::bound(&swift_type!(SwiftUI.Binding), &[mangle::STRING]).as_bytes());
513 binding_words(&b)
514 }
515}
516
517pub(crate) fn binding_words(b: &[u8]) -> [u64; 4] {
522 let mut w = [0u64; 4];
523 for (i, slot) in w.iter_mut().enumerate() {
524 *slot = u64::from_le_bytes(b[i * 8..i * 8 + 8].try_into().expect("binding word"));
525 }
526 w
527}
528
529pub fn textfield(placeholder: &str, value: &str) -> ViewHandle {
535 unsafe { textfield_with_binding(placeholder, &string_binding(value)) }
536}
537
538pub fn textfield_bound(placeholder: &str, state: &super::BoundState<String>) -> ViewHandle {
540 unsafe { textfield_with_binding(placeholder, &binding_words(&super::text_binding(state))) }
541}
542
543unsafe fn textfield_with_binding(placeholder: &str, b: &[u64; 4]) -> ViewHandle {
545 unsafe {
546 let ss = abi::swift_string(placeholder);
547 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
548 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
549 let (k0, k1, k2, k3) = localized_string_key(s0, s1);
550
551 let (meta, wt, size) = result_type(&TEXTFIELD_T);
552 let mut result = vec![0u8; size];
553 let noop = noop_closure as *const c_void;
554 core::arch::asm!(
558 "sub sp, sp, #32",
559 "stp {n}, xzr, [sp]",
560 "stp {n}, xzr, [sp, #16]",
561 "blr {f}",
562 "add sp, sp, #32",
563 f = in(reg) resolve::textfield_init(),
564 n = in(reg) noop,
565 in("x0") k0, in("x1") k1, in("x2") k2, in("x3") k3,
566 in("x4") b[0], in("x5") b[1], in("x6") b[2], in("x7") b[3],
567 in("x8") result.as_mut_ptr(),
568 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
569 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
570 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
571 clobber_abi("C"),
572 );
573 wrap_owned(result, meta, wt)
574 }
575}
576
577pub fn textfield_axis(
584 placeholder: &str,
585 state: &super::BoundState<String>,
586 axis: super::Axis,
587) -> ViewHandle {
588 unsafe {
589 let b = binding_words(&super::text_binding(state));
590 let ss = abi::swift_string(placeholder);
591 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
592 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
593 let (k0, k1, k2, k3) = localized_string_key(s0, s1);
594
595 let (meta, wt, size) = result_type(&TEXTFIELD_T);
596 let mut result = vec![0u8; size];
597 core::arch::asm!(
602 "sub sp, sp, #16",
603 "str {a}, [sp]",
604 "blr {f}",
605 "add sp, sp, #16",
606 f = in(reg) resolve::textfield_axis_init(),
607 a = in(reg) axis as u64,
608 in("x0") k0, in("x1") k1, in("x2") k2, in("x3") k3,
609 in("x4") b[0], in("x5") b[1], in("x6") b[2], in("x7") b[3],
610 in("x8") result.as_mut_ptr(),
611 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
612 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
613 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
614 clobber_abi("C"),
615 );
616 wrap_owned(result, meta, wt)
617 }
618}
619
620pub fn securefield(placeholder: &str, value: &str) -> ViewHandle {
623 unsafe { securefield_with_binding(placeholder, &string_binding(value)) }
624}
625
626pub fn securefield_bound(placeholder: &str, state: &super::BoundState<String>) -> ViewHandle {
628 unsafe { securefield_with_binding(placeholder, &binding_words(&super::text_binding(state))) }
629}
630
631unsafe fn securefield_with_binding(placeholder: &str, b: &[u64; 4]) -> ViewHandle {
633 unsafe {
634 let ss = abi::swift_string(placeholder);
635 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
636 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
637 let (k0, k1, k2, k3) = localized_string_key(s0, s1);
638
639 let (meta, wt, size) = result_type(&SECUREFIELD_T);
640 let mut result = vec![0u8; size];
641 let noop = noop_closure as *const c_void;
642 core::arch::asm!(
644 "sub sp, sp, #16",
645 "stp {n}, xzr, [sp]",
646 "blr {f}",
647 "add sp, sp, #16",
648 f = in(reg) resolve::securefield_init(),
649 n = in(reg) noop,
650 in("x0") k0, in("x1") k1, in("x2") k2, in("x3") k3,
651 in("x4") b[0], in("x5") b[1], in("x6") b[2], in("x7") b[3],
652 in("x8") result.as_mut_ptr(),
653 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
654 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
655 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
656 clobber_abi("C"),
657 );
658 wrap_owned(result, meta, wt)
659 }
660}
661
662pub fn slider(value: f64, lower: f64, upper: f64) -> ViewHandle {
664 unsafe {
665 let mut binding = constant_binding(
666 &value.to_le_bytes(),
667 resolve::double_meta(),
668 mangle::bound(&swift_type!(SwiftUI.Binding), &[mangle::DOUBLE]).as_bytes(),
669 );
670 slider_with_binding(&mut binding, lower, upper)
671 }
672}
673
674pub(crate) unsafe fn slider_with_binding(
679 binding: &mut [u8],
680 lower: f64,
681 upper: f64,
682) -> ViewHandle {
683 unsafe {
684 let double_meta = resolve::double_meta();
685 let bfp_wt =
686 abi::get_view_wt_for_proto(double_meta, resolve::binary_floating_point_proto());
687 assert!(!bfp_wt.is_null(), "Double: BinaryFloatingPoint");
688 let mut range = [0u8; 16];
689 range[..8].copy_from_slice(&lower.to_le_bytes());
690 range[8..].copy_from_slice(&upper.to_le_bytes());
691
692 let (meta, wt, size) = result_type(&SLIDER_T);
693 let mut result = vec![0u8; size];
694 core::arch::asm!("blr {f}", f = in(reg) resolve::slider_init(),
703 in("x0") binding.as_mut_ptr(),
704 in("x1") range.as_mut_ptr(),
705 in("x2") noop_closure as *const c_void,
706 in("x3") 0u64,
707 in("x4") double_meta,
708 in("x5") bfp_wt,
709 in("x6") bfp_wt,
710 in("x8") result.as_mut_ptr(),
711 lateout("x7") _,
712 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
713 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
714 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
715 clobber_abi("C"),
716 );
717 wrap_owned(result, meta, wt)
718 }
719}
720
721pub(crate) unsafe fn slider_step_with_binding(
732 binding: &mut [u8],
733 lower: f64,
734 upper: f64,
735 step: f64,
736) -> ViewHandle {
737 unsafe {
738 let double_meta = resolve::double_meta();
739 let bfp_wt =
740 abi::get_view_wt_for_proto(double_meta, resolve::binary_floating_point_proto());
741 assert!(!bfp_wt.is_null(), "Double: BinaryFloatingPoint");
742 let mut range = [0u8; 16];
743 range[..8].copy_from_slice(&lower.to_le_bytes());
744 range[8..].copy_from_slice(&upper.to_le_bytes());
745 let mut step_bytes = step.to_le_bytes();
746
747 let (meta, wt, size) = result_type(&SLIDER_T);
748 let mut result = vec![0u8; size];
749 core::arch::asm!("blr {f}", f = in(reg) resolve::slider_step_init(),
755 in("x0") binding.as_mut_ptr(),
756 in("x1") range.as_mut_ptr(),
757 in("x2") step_bytes.as_mut_ptr(),
758 in("x3") noop_closure as *const c_void,
759 in("x4") 0u64,
760 in("x5") double_meta,
761 in("x6") bfp_wt,
762 in("x7") bfp_wt,
763 in("x8") result.as_mut_ptr(),
764 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
765 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
766 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
767 clobber_abi("C"),
768 );
769 wrap_owned(result, meta, wt)
770 }
771}
772
773pub fn padding(view: &ViewHandle, amount: f64) -> ViewHandle {
777 unsafe {
778 let (_, _, size) = PADDING_T.applied_to(view.meta);
782 let result = abi::call_modifier_d0(
783 resolve::padding_fn(), view.value_ptr(), view.meta, view.wt, amount, size);
784 wrap_modified(result, &PADDING_T, view)
785 }
786}
787
788pub fn opacity(view: &ViewHandle, value: f64) -> ViewHandle {
790 unsafe {
791 let (_, _, size) = OPACITY_T.applied_to(view.meta);
792 let result = abi::call_modifier_d0(
793 resolve::opacity_fn(), view.value_ptr(), view.meta, view.wt, value, size);
794 wrap_modified(result, &OPACITY_T, view)
795 }
796}
797
798pub fn frame(view: &ViewHandle, width: f64, height: f64) -> ViewHandle {
800 frame_aligned(view, width, height, super::Alignment::Center)
801}
802
803pub fn frame_aligned(
805 view: &ViewHandle,
806 width: f64,
807 height: f64,
808 alignment: super::Alignment,
809) -> ViewHandle {
810 frame_optional(view, Some(width), Some(height), alignment)
811}
812
813pub fn frame_optional(
819 view: &ViewHandle,
820 width: Option<f64>,
821 height: Option<f64>,
822 alignment: super::Alignment,
823) -> ViewHandle {
824 unsafe {
825 let self_storage = view.value_ptr();
826 let (_, _, size) = FRAME_T.applied_to(view.meta);
827 let mut result = vec![0u8; size];
828
829 let [align_h, align_v] = alignment.words();
834
835 core::arch::asm!("blr {func}",
841 func = in(reg) resolve::frame_fn(),
842 in("x0") width.map_or(0, f64::to_bits),
843 in("x1") u64::from(width.is_none()),
844 in("x2") height.map_or(0, f64::to_bits),
845 in("x3") u64::from(height.is_none()),
846 in("x4") align_h,
847 in("x5") align_v,
848 in("x6") view.meta,
849 in("x7") view.wt,
850 in("x8") result.as_mut_ptr(),
851 in("x20") self_storage,
852 lateout("x9") _, lateout("x10") _, lateout("x11") _,
853 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
854 lateout("x16") _, lateout("x17") _, lateout("lr") _,
855 clobber_abi("C"),
856 );
857 wrap_modified(result, &FRAME_T, view)
858 }
859}
860
861pub fn background(view: &ViewHandle, r: f64, g: f64, b: f64, a: f64) -> ViewHandle {
863 unsafe {
864 let func = resolve::bg_fn();
865 let self_storage = view.value_ptr();
866 let mut color_storage: u64 = color_value(r, g, b, a);
867 let (_, _, size) = BG_T.applied_to(view.meta);
868 let mut result = vec![0u8; size];
869 core::arch::asm!("blr {func}",
872 func = in(reg) func,
873 in("x0") &mut color_storage as *mut u64, in("x1") EDGE_SET_ALL, in("x2") view.meta, in("x3") resolve::color_meta(), in("x4") view.wt, in("x5") resolve::color_shapestyle_wt(), in("x8") result.as_mut_ptr(),
880 in("x20") self_storage,
881 lateout("x0") _, lateout("x1") _, lateout("x2") _, lateout("x3") _,
882 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
883 lateout("x9") _, lateout("x10") _, lateout("x11") _,
884 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
885 lateout("x16") _, lateout("x17") _, lateout("lr") _, clobber_abi("C"),
886 );
887 wrap_modified(result, &BG_T, view)
888 }
889}
890
891pub fn corner_radius(view: &ViewHandle, radius: f64) -> ViewHandle {
893 unsafe {
894 let (_, _, size) = CORNER_T.applied_to(view.meta);
895 let mut result = vec![0u8; size];
896 let self_storage = view.value_ptr();
897 core::arch::asm!("blr {f}", f = in(reg) resolve::corner_radius_fn(),
901 in("d0") radius,
902 in("x0") 1u64,
903 in("x1") view.meta,
904 in("x2") view.wt,
905 in("x8") result.as_mut_ptr(),
906 in("x20") self_storage,
907 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
908 lateout("x9") _, lateout("x10") _, lateout("x11") _,
909 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
910 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
911 clobber_abi("C"),
912 );
913 wrap_modified(result, &CORNER_T, view)
914 }
915}
916
917pub fn border(view: &ViewHandle, r: f64, g: f64, b: f64, width: f64) -> ViewHandle {
924 unsafe { border_value(view, color_value(r, g, b, 1.0), width) }
925}
926
927pub fn border_value(view: &ViewHandle, color: u64, width: f64) -> ViewHandle {
932 unsafe {
933 let c = color;
934 let (_, _, size) = BORDER_T.applied_to(view.meta);
935 let mut result = vec![0u8; size];
936 let self_storage = view.value_ptr();
937 let mut style: u64 = c;
938 core::arch::asm!("blr {f}", f = in(reg) resolve::border_fn(),
942 in("x0") &mut style as *mut u64,
943 in("d0") width,
944 in("x1") view.meta,
945 in("x2") resolve::color_meta(),
946 in("x3") view.wt,
947 in("x4") resolve::color_shapestyle_wt(),
948 in("x8") result.as_mut_ptr(),
949 in("x20") self_storage,
950 lateout("x5") _, lateout("x6") _, lateout("x7") _,
951 lateout("x9") _, lateout("x10") _, lateout("x11") _,
952 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
953 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
954 clobber_abi("C"),
955 );
956 wrap_modified(result, &BORDER_T, view)
957 }
958}
959
960swift_statics! {
961 pub enum SystemColor {
970 Red = c"$s7SwiftUI5ColorV3redACvgZ",
971 Orange = c"$s7SwiftUI5ColorV6orangeACvgZ",
972 Yellow = c"$s7SwiftUI5ColorV6yellowACvgZ",
973 Green = c"$s7SwiftUI5ColorV5greenACvgZ",
974 Mint = c"$s7SwiftUI5ColorV4mintACvgZ",
975 Teal = c"$s7SwiftUI5ColorV4tealACvgZ",
976 Cyan = c"$s7SwiftUI5ColorV4cyanACvgZ",
977 Blue = c"$s7SwiftUI5ColorV4blueACvgZ",
978 Indigo = c"$s7SwiftUI5ColorV6indigoACvgZ",
979 Accent = c"$s7SwiftUI5ColorV06accentC0ACvgZ",
982 Purple = c"$s7SwiftUI5ColorV6purpleACvgZ",
983 Pink = c"$s7SwiftUI5ColorV4pinkACvgZ",
984 Brown = c"$s7SwiftUI5ColorV5brownACvgZ",
985 White = c"$s7SwiftUI5ColorV5whiteACvgZ",
986 Gray = c"$s7SwiftUI5ColorV4grayACvgZ",
987 Black = c"$s7SwiftUI5ColorV5blackACvgZ",
988 Clear = c"$s7SwiftUI5ColorV5clearACvgZ",
989 Primary = c"$s7SwiftUI5ColorV7primaryACvgZ",
990 Secondary = c"$s7SwiftUI5ColorV9secondaryACvgZ",
991 }
992}
993
994pub fn system_color_value(c: SystemColor) -> u64 {
999 unsafe { abi::static_regs(resolve::sym(c.getter()), resolve::color_meta())[0] }
1000}
1001
1002pub fn system_color(c: SystemColor) -> ViewHandle {
1004 unsafe {
1005 let buf = system_color_value(c).to_le_bytes();
1006 wrap_buf(&buf, resolve::color_meta(), resolve::color_wt())
1007 }
1008}
1009
1010pub fn frame_max_infinity(view: &ViewHandle, alignment: super::Alignment) -> ViewHandle {
1019 unsafe {
1020 let (meta, wt, size) = super::opaque_result_type(
1021 resolve::frame_flexible_oret(),
1022 &[view.meta, view.wt],
1023 );
1024 let mut result = vec![0u8; size];
1025 let this = view.value_ptr();
1026 let [ah, av] = alignment.words();
1027 let inf = f64::INFINITY.to_bits();
1028 core::arch::asm!(
1033 "sub sp, sp, #64",
1034 "stp {a}, {b}, [sp]",
1035 "stp {c}, {d}, [sp, #16]",
1036 "stp {e}, {g}, [sp, #32]",
1037 "stp {h}, {i}, [sp, #48]",
1038 "blr {f}",
1039 "add sp, sp, #64",
1040 f = in(reg) resolve::frame_flexible_fn(),
1041 a = in(reg) 0u64, b = in(reg) 1u64, c = in(reg) inf, d = in(reg) 0u64, e = in(reg) ah, g = in(reg) av, h = in(reg) view.meta,
1045 i = in(reg) view.wt,
1046 in("x0") 0u64, in("x1") 1u64, in("x2") 0u64, in("x3") 1u64, in("x4") inf, in("x5") 0u64, in("x6") 0u64, in("x7") 1u64, in("x8") result.as_mut_ptr(),
1051 in("x20") this,
1052 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
1053 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
1054 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
1055 );
1056 wrap_owned(result, meta, wt)
1057 }
1058}
1059
1060pub fn frame_max_width(view: &ViewHandle, alignment: super::Alignment) -> ViewHandle {
1074 unsafe {
1075 let (meta, wt, size) = super::opaque_result_type(
1076 resolve::frame_flexible_oret(),
1077 &[view.meta, view.wt],
1078 );
1079 let mut result = vec![0u8; size];
1080 let this = view.value_ptr();
1081 let [ah, av] = alignment.words();
1082 let inf = f64::INFINITY.to_bits();
1083 core::arch::asm!(
1088 "sub sp, sp, #64",
1089 "stp {a}, {b}, [sp]",
1090 "stp {c}, {d}, [sp, #16]",
1091 "stp {e}, {g}, [sp, #32]",
1092 "stp {h}, {i}, [sp, #48]",
1093 "blr {f}",
1094 "add sp, sp, #64",
1095 f = in(reg) resolve::frame_flexible_fn(),
1096 a = in(reg) 0u64, b = in(reg) 1u64, c = in(reg) 0u64, d = in(reg) 1u64, e = in(reg) ah, g = in(reg) av, h = in(reg) view.meta,
1100 i = in(reg) view.wt,
1101 in("x0") 0u64, in("x1") 1u64, in("x2") 0u64, in("x3") 1u64, in("x4") inf, in("x5") 0u64, in("x6") 0u64, in("x7") 1u64, in("x8") result.as_mut_ptr(),
1106 in("x20") this,
1107 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
1108 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
1109 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
1110 );
1111 wrap_owned(result, meta, wt)
1112 }
1113}
1114
1115pub fn text_editor(value: &str) -> ViewHandle {
1120 unsafe {
1121 let b = string_binding(value);
1122 let (meta, wt, size) = result_type(&TEXT_EDITOR_T);
1123 let mut result = vec![0u8; size];
1124 core::arch::asm!("blr {f}", f = in(reg) resolve::text_editor_init(),
1125 in("x0") b[0], in("x1") b[1], in("x2") b[2], in("x3") b[3],
1126 in("x8") result.as_mut_ptr(),
1127 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
1128 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
1129 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
1130 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
1131 clobber_abi("C"),
1132 );
1133 wrap_owned(result, meta, wt)
1134 }
1135}
1136
1137pub fn link(title: &str, destination: &str) -> ViewHandle {
1144 unsafe {
1145 let ss = abi::swift_string(title);
1146 let s0 = u64::from_le_bytes(ss[..8].try_into().expect("lo"));
1147 let s1 = u64::from_le_bytes(ss[8..].try_into().expect("hi"));
1148 let (k0, k1, k2, k3) = localized_string_key(s0, s1);
1149 let mut url = super::optional_url(Some(destination));
1150
1151 let (meta, wt, size) = result_type(&LINK_T);
1152 let mut result = vec![0u8; size];
1153 core::arch::asm!("blr {f}", f = in(reg) resolve::link_init(),
1154 in("x0") k0, in("x1") k1, in("x2") k2, in("x3") k3,
1155 in("x4") url.as_mut_ptr(),
1156 in("x8") result.as_mut_ptr(),
1157 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x9") _,
1158 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
1159 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
1160 lateout("lr") _, lateout("x20") _, lateout("x21") _, clobber_abi("C"),
1161 );
1162 wrap_owned(result, meta, wt)
1163 }
1164}
1165
1166pub fn view_opacity(view: &ViewHandle, value: f64) -> ViewHandle {
1174 if crate::diag::type_name(view.meta) != "SwiftUI.Color" {
1175 return opacity(view, value);
1176 }
1177 unsafe {
1178 let word = (view.value_ptr() as *const u64).read_unaligned();
1180 let faded = color_opacity(word, value);
1181 wrap_buf(&faded.to_le_bytes(), view.meta, view.wt)
1182 }
1183}
1184
1185#[derive(Clone, Copy, Debug)]
1187pub enum TextPart<'a> {
1188 Literal(&'a str),
1190 Int(i64),
1192 Double(f64),
1194 Str(&'a str),
1200}
1201
1202pub trait Interpolatable {
1207 fn as_part(&self) -> TextPart<'_>;
1209}
1210
1211impl Interpolatable for i64 {
1212 fn as_part(&self) -> TextPart<'_> {
1213 TextPart::Int(*self)
1214 }
1215}
1216
1217impl Interpolatable for i32 {
1218 fn as_part(&self) -> TextPart<'_> {
1219 TextPart::Int(i64::from(*self))
1220 }
1221}
1222
1223impl Interpolatable for usize {
1224 fn as_part(&self) -> TextPart<'_> {
1225 TextPart::Int(*self as i64)
1226 }
1227}
1228
1229impl Interpolatable for f64 {
1230 fn as_part(&self) -> TextPart<'_> {
1231 TextPart::Double(*self)
1232 }
1233}
1234
1235impl Interpolatable for str {
1236 fn as_part(&self) -> TextPart<'_> {
1237 TextPart::Str(self)
1238 }
1239}
1240
1241impl Interpolatable for String {
1242 fn as_part(&self) -> TextPart<'_> {
1243 TextPart::Str(self)
1244 }
1245}
1246
1247impl<T: Interpolatable + ?Sized> Interpolatable for &T {
1248 fn as_part(&self) -> TextPart<'_> {
1249 (**self).as_part()
1250 }
1251}
1252
1253pub fn text_interpolated(parts: &[TextPart<'_>]) -> ViewHandle {
1267 unsafe {
1268 let meta = abi::resolve_type_by_mangled_name(b"7SwiftUI18LocalizedStringKeyV0D13InterpolationV");
1269 assert!(!meta.is_null(), "LocalizedStringKey.StringInterpolation metadata");
1270
1271 let literal_capacity: i64 = parts
1275 .iter()
1276 .map(|p| match p {
1277 TextPart::Literal(s) => s.len() as i64,
1278 _ => 0,
1279 })
1280 .sum();
1281 let interpolation_count = parts
1282 .iter()
1283 .filter(|p| !matches!(p, TextPart::Literal(_)))
1284 .count() as i64;
1285
1286 let mut interp = vec![0u8; abi::type_bytes(meta)];
1287 core::arch::asm!("blr {f}", f = in(reg) resolve::lsk_interp_init(),
1291 in("x0") literal_capacity,
1292 in("x1") interpolation_count,
1293 in("x8") interp.as_mut_ptr(),
1294 lateout("x2") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
1295 lateout("x6") _, lateout("x7") _, lateout("x9") _, lateout("x10") _,
1296 lateout("x11") _, lateout("x12") _, lateout("x13") _, lateout("x14") _,
1297 lateout("x15") _, lateout("x16") _, lateout("x17") _, lateout("lr") _,
1298 lateout("x20") _, lateout("x21") _, clobber_abi("C"),
1299 );
1300
1301 for part in parts {
1302 match *part {
1303 TextPart::Literal(s) => {
1304 let ss = abi::swift_string(s);
1305 let w0 = u64::from_le_bytes(ss[..8].try_into().expect("lo"));
1306 let w1 = u64::from_le_bytes(ss[8..].try_into().expect("hi"));
1307 core::arch::asm!("blr {f}", f = in(reg) resolve::lsk_append_literal(),
1310 in("x0") w0, in("x1") w1,
1311 in("x20") interp.as_mut_ptr(),
1312 lateout("x2") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
1313 lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
1314 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
1315 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
1316 lateout("lr") _, lateout("x21") _, clobber_abi("C"),
1317 );
1318 }
1319 TextPart::Str(text) => {
1320 let ss = abi::swift_string(text);
1321 let w0 = u64::from_le_bytes(ss[..8].try_into().expect("lo"));
1322 let w1 = u64::from_le_bytes(ss[8..].try_into().expect("hi"));
1323 core::arch::asm!("blr {f}", f = in(reg) resolve::lsk_append_string(),
1326 in("x0") w0, in("x1") w1,
1327 in("x20") interp.as_mut_ptr(),
1328 lateout("x2") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
1329 lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
1330 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
1331 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
1332 lateout("lr") _, lateout("x21") _, clobber_abi("C"),
1333 );
1334 }
1335 TextPart::Double(v) => {
1336 append_specified(
1337 &mut interp,
1338 &v.to_le_bytes(),
1339 "%lf",
1340 resolve::double_meta(),
1341 resolve::double_format_specifiable_wt(),
1342 );
1343 }
1344 TextPart::Int(v) => {
1345 append_specified(
1346 &mut interp,
1347 &v.to_le_bytes(),
1348 "%lld",
1349 resolve::int_meta(),
1350 resolve::int_format_specifiable_wt(),
1351 );
1352 }
1353 }
1354 }
1355
1356 let (k0, k1, k2, k3): (u64, u64, u64, u64);
1359 core::arch::asm!("blr {f}", f = in(reg) resolve::lsk_from_interp(),
1360 in("x0") interp.as_mut_ptr(),
1361 lateout("x0") k0, lateout("x1") k1, lateout("x2") k2, lateout("x3") k3,
1362 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
1363 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
1364 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
1365 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
1366 lateout("x21") _, clobber_abi("C"),
1367 );
1368
1369 text_from_key(k0, k1, k2, k3)
1370 }
1371}
1372
1373unsafe fn append_specified(
1383 interp: &mut [u8],
1384 bytes: &[u8],
1385 specifier: &str,
1386 meta: *const c_void,
1387 wt: *const c_void,
1388) {
1389 unsafe {
1390 let spec = abi::swift_string(specifier);
1391 let sp0 = u64::from_le_bytes(spec[..8].try_into().expect("lo"));
1392 let sp1 = u64::from_le_bytes(spec[8..].try_into().expect("hi"));
1393 let mut value = bytes.to_vec();
1394 core::arch::asm!("blr {f}", f = in(reg) resolve::lsk_append_interp(),
1397 in("x0") value.as_mut_ptr(),
1398 in("x1") sp0, in("x2") sp1,
1399 in("x3") meta,
1400 in("x4") wt,
1401 in("x20") interp.as_mut_ptr(),
1402 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
1403 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
1404 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
1405 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
1406 );
1407 }
1408}
1409
1410pub(crate) unsafe fn text_from_key(k0: u64, k1: u64, k2: u64, k3: u64) -> ViewHandle {
1415 unsafe {
1416 let (t0, t1, t2, t3): (u64, u64, u64, u64);
1417 core::arch::asm!(
1418 "sub sp, sp, #32",
1419 "stp xzr, xzr, [sp]",
1420 "stp xzr, xzr, [sp, #16]",
1421 "blr {f}",
1422 "add sp, sp, #32",
1423 f = in(reg) resolve::text_lsk_init(),
1424 inout("x0") k0 => t0, inout("x1") k1 => t1,
1425 inout("x2") k2 => t2, inout("x3") k3 => t3,
1426 in("x4") 0u64, in("x5") 0u64, in("x6") 0u64, in("x7") 0u64,
1427 in("x20") resolve::text_meta(),
1428 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
1429 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
1430 lateout("x16") _, lateout("x17") _, lateout("lr") _, clobber_abi("C"),
1431 );
1432 let mut buf = [0u8; 32];
1433 buf[..8].copy_from_slice(&t0.to_le_bytes());
1434 buf[8..16].copy_from_slice(&t1.to_le_bytes());
1435 buf[16..24].copy_from_slice(&t2.to_le_bytes());
1436 buf[24..32].copy_from_slice(&t3.to_le_bytes());
1437 wrap_buf(&buf, resolve::text_meta(), resolve::text_wt())
1438 }
1439}