1use super::*;
6use crate::abi;
7use crate::resolve;
8use core::ffi::c_void;
9use crate::mangle::{self, swift_type};
10
11#[derive(Clone, Copy, PartialEq, Eq)]
14pub(crate) enum StackKind {
15 V,
16 H,
17 Z,
18}
19
20pub fn vstack(children: &[ViewHandle]) -> ViewHandle {
22 stack_impl(children, StackKind::V)
23}
24
25pub fn hstack(children: &[ViewHandle]) -> ViewHandle {
27 stack_impl(children, StackKind::H)
28}
29
30pub fn zstack(children: &[ViewHandle]) -> ViewHandle {
32 stack_impl(children, StackKind::Z)
33}
34
35pub fn zstack_aligned(children: &[ViewHandle], alignment: super::Alignment) -> ViewHandle {
37 match children.len() {
38 0 => empty_view(),
39 _ => unsafe { build_stack_aligned(children, StackKind::Z, None, alignment) },
40 }
41}
42
43pub(crate) fn stack_impl(children: &[ViewHandle], axis: StackKind) -> ViewHandle {
44 stack_spaced(children, axis, None)
45}
46
47pub(crate) fn stack_spaced(children: &[ViewHandle], axis: StackKind, spacing: Option<f64>) -> ViewHandle {
48 match children.len() {
49 0 => empty_view(),
50 1 if spacing.is_none() => children[0].clone(),
55 _ => unsafe { build_stack(children, axis, spacing) },
56 }
57}
58
59pub fn vstack_aligned(
61 children: &[ViewHandle],
62 alignment: super::HorizontalAlignment,
63) -> ViewHandle {
64 vstack_aligned_spacing(children, alignment, None)
65}
66
67pub fn vstack_aligned_spacing(
69 children: &[ViewHandle],
70 alignment: super::HorizontalAlignment,
71 spacing: Option<f64>,
72) -> ViewHandle {
73 unsafe {
74 build_stack_aligned_h(
75 children,
76 StackKind::V,
77 spacing,
78 super::Alignment::Center,
79 Some(alignment),
80 None,
81 )
82 }
83}
84
85pub fn hstack_aligned(
87 children: &[ViewHandle],
88 alignment: super::VerticalAlignment,
89) -> ViewHandle {
90 hstack_aligned_spacing(children, alignment, None)
91}
92
93pub fn hstack_aligned_spacing(
95 children: &[ViewHandle],
96 alignment: super::VerticalAlignment,
97 spacing: Option<f64>,
98) -> ViewHandle {
99 unsafe {
100 build_stack_aligned_h(
101 children,
102 StackKind::H,
103 spacing,
104 super::Alignment::Center,
105 None,
106 Some(alignment),
107 )
108 }
109}
110
111pub fn vstack_spacing(children: &[ViewHandle], spacing: f64) -> ViewHandle {
113 stack_spaced(children, StackKind::V, Some(spacing))
114}
115
116pub fn hstack_spacing(children: &[ViewHandle], spacing: f64) -> ViewHandle {
118 stack_spaced(children, StackKind::H, Some(spacing))
119}
120
121#[repr(C)]
124pub(crate) struct TupleChild {
125 pub(crate) value: *const c_void,
126 pub(crate) meta: *const c_void,
127 pub(crate) offset: usize,
128}
129
130#[repr(C)]
132pub(crate) struct TuplePayload {
133 pub(crate) children: *const TupleChild,
134 pub(crate) count: usize,
135}
136
137pub(crate) unsafe extern "C" fn emit_tuple(out: *mut u8, payload: *mut c_void) {
148 let p = unsafe { &*(payload as *const TuplePayload) };
149 for i in 0..p.count {
150 let c = unsafe { &*p.children.add(i) };
151 let vwt = unsafe { &*swift_runtime_sys::SwiftABI::get_value_witness_table(c.meta) };
152 if vwt.size > 0 {
153 unsafe {
154 (vwt.initialize_with_copy)(
155 out.add(c.offset) as *mut c_void,
156 c.value as *mut c_void,
157 c.meta,
158 );
159 }
160 }
161 }
162}
163
164#[derive(Clone, Copy, PartialEq, Eq)]
177pub(crate) enum Content {
178 Concrete,
180 Erased,
182}
183
184pub(crate) struct Child {
191 handle: ViewHandle,
193 word: u64,
195 kind: Content,
196}
197
198impl Child {
199 pub(crate) fn new(view: &ViewHandle, kind: Content) -> Self {
200 Child {
201 handle: view.clone(),
202 word: if kind == Content::Erased { view.to_anyview_word() } else { 0 },
203 kind,
204 }
205 }
206
207 pub(crate) fn element(&self) -> [TupleChild; 1] {
209 match self.kind {
210 Content::Concrete => [TupleChild {
211 value: self.handle.value_ptr(),
212 meta: self.handle.meta,
213 offset: 0,
214 }],
215 Content::Erased => [TupleChild {
216 value: &self.word as *const u64 as *const c_void,
217 meta: resolve::anyview_meta(),
218 offset: 0,
219 }],
220 }
221 }
222
223 pub(crate) fn leak(view: &ViewHandle, kind: Content) -> *mut c_void {
226 let kept: &'static Child = Box::leak(Box::new(Child::new(view, kind)));
227 let kids = Box::leak(Box::new(kept.element()));
228 let payload = Box::leak(Box::new(TuplePayload { children: kids.as_ptr(), count: 1 }));
229 payload as *mut TuplePayload as *mut c_void
230 }
231}
232
233pub(crate) unsafe fn static_getter_f64(getter: *const c_void, meta: *const c_void) -> f64 {
235 unsafe { abi::call_f64(getter, [0; 8], [0.0; 4], meta as u64) }
236}
237
238pub(crate) unsafe fn static_getter(getter: *const c_void, meta: *const c_void) -> (u64, u64) {
240 let r = unsafe { abi::static_regs(getter, meta) };
241 (r[0], r[1])
242}
243
244pub(crate) unsafe fn tuple_content(
266 children: &[ViewHandle],
267) -> (*const c_void, *const c_void, Vec<usize>) {
268 assert!(!children.is_empty(), "a `@ViewBuilder` body with no children is `EmptyView`");
269 if children.len() == 1 {
270 return (children[0].meta, children[0].wt, vec![0usize]);
271 }
272 unsafe {
273 let elements: Vec<*const c_void> = children.iter().map(|c| c.meta).collect();
274 let tuple_meta = abi::tuple_metadata(&elements);
275 assert!(!tuple_meta.is_null(), "tuple metadata instantiation failed");
276 let offsets = abi::tuple_element_offsets(tuple_meta, children.len());
277 let m = abi::generic_metadata1(resolve::tupleview_ma(), tuple_meta);
278 assert!(!m.is_null(), "TupleView metadata instantiation failed");
279 let w = abi::get_view_wt(m);
280 assert!(!w.is_null(), "{} !: View", crate::diag::type_name(m));
281 (m, w, offsets)
282 }
283}
284
285pub(crate) fn tuple_children(children: &[ViewHandle], offsets: &[usize]) -> Vec<TupleChild> {
291 children
292 .iter()
293 .zip(offsets)
294 .map(|(c, &offset)| TupleChild { value: c.value_ptr(), meta: c.meta, offset })
295 .collect()
296}
297
298pub(crate) unsafe fn build_stack(
303 children: &[ViewHandle],
304 axis: StackKind,
305 spacing: Option<f64>,
306) -> ViewHandle {
307 unsafe { build_stack_aligned(children, axis, spacing, super::Alignment::Center) }
308}
309
310pub(crate) unsafe fn build_stack_aligned(
316 children: &[ViewHandle],
317 axis: StackKind,
318 spacing: Option<f64>,
319 alignment: super::Alignment,
320) -> ViewHandle {
321 unsafe { build_stack_aligned_h(children, axis, spacing, alignment, None, None) }
322}
323
324pub(crate) unsafe fn build_stack_aligned_h(
330 children: &[ViewHandle],
331 axis: StackKind,
332 spacing: Option<f64>,
333 alignment: super::Alignment,
334 horizontal: Option<super::HorizontalAlignment>,
335 vertical: Option<super::VerticalAlignment>,
336) -> ViewHandle {
337 let (content_meta, content_wt, offsets) = unsafe { tuple_content(children) };
338
339 let stack_ma = match axis {
341 StackKind::V => resolve::vstack_ma(),
342 StackKind::H => resolve::hstack_ma(),
343 StackKind::Z => resolve::zstack_ma(),
344 };
345 let stack_meta = unsafe { abi::generic_metadata2(stack_ma, content_meta, content_wt) };
346 assert!(!stack_meta.is_null(), "stack metadata instantiation failed");
347 let stack_wt = unsafe { abi::get_view_wt(stack_meta) };
348 assert!(!stack_wt.is_null(), "{} !: View", crate::diag::type_name(stack_meta));
349
350 let kids = tuple_children(children, &offsets);
353 let payload = TuplePayload { children: kids.as_ptr(), count: kids.len() };
354 let mut ctx = abi::ClosureCtx::new(emit_tuple, &payload as *const TuplePayload as *mut c_void);
355 let thunk = abi::swift_closure_thunk as *const c_void;
356
357 let mut result = vec![0u8; unsafe { abi::type_bytes(stack_meta) }];
358
359 match axis {
360 StackKind::V | StackKind::H => {
361 let (align, _) = unsafe {
366 match axis {
367 StackKind::V => static_getter(
368 horizontal.map_or_else(resolve::halign_center, |h| h.resolved()),
369 resolve::halign_meta(),
370 ),
371 _ => static_getter(
372 vertical.map_or_else(resolve::valign_center, |v| v.resolved()),
373 resolve::valign_meta(),
374 ),
375 }
376 };
377 let init = if axis == StackKind::V { resolve::vstack_init() } else { resolve::hstack_init() };
378 let (spacing_bits, spacing_tag) = match spacing {
380 Some(v) => (v.to_bits(), 0u64),
381 None => (0u64, 1u64),
382 };
383 unsafe {
384 core::arch::asm!("blr {f}", f = in(reg) init,
385 in("x0") align,
386 in("x1") spacing_bits,
387 in("x2") spacing_tag,
388 in("x3") thunk,
389 in("x4") &mut ctx as *mut abi::ClosureCtx,
390 in("x5") content_meta,
391 in("x6") content_wt,
392 in("x8") result.as_mut_ptr(),
393 lateout("x0") _, lateout("x1") _, lateout("x2") _, lateout("x3") _,
394 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
395 lateout("x9") _, lateout("x10") _, lateout("x11") _,
396 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
397 lateout("x16") _, lateout("x17") _, lateout("lr") _,
398 lateout("x20") _, lateout("x21") _,
399 clobber_abi("C"),
400 );
401 }
402 }
403 StackKind::Z => {
404 let [h, v] = unsafe { alignment.words() };
409 unsafe {
410 core::arch::asm!("blr {f}", f = in(reg) resolve::zstack_init(),
411 in("x0") h,
412 in("x1") v,
413 in("x2") thunk,
414 in("x3") &mut ctx as *mut abi::ClosureCtx,
415 in("x4") content_meta,
416 in("x5") content_wt,
417 in("x8") result.as_mut_ptr(),
418 lateout("x6") _, lateout("x7") _,
419 lateout("x9") _, lateout("x10") _, lateout("x11") _,
420 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
421 lateout("x16") _, lateout("x17") _, lateout("lr") _,
422 lateout("x20") _, lateout("x21") _,
423 clobber_abi("C"),
424 );
425 }
426 }
427 }
428
429 unsafe { wrap_owned(result, stack_meta, stack_wt) }
430}
431
432mangle::result_types! {
435 pub(crate) LABEL_T = ty("Label").of(vec![ty("Text"), ty("Image")]);
438}
439
440pub fn label(title: &str, system_image: &str) -> ViewHandle {
442 unsafe {
443 let ss = abi::swift_string(title);
444 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
445 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
446 let (k0, k1, k2, k3) = localized_string_key(s0, s1);
447
448 let img = abi::swift_string(system_image);
449 let i0 = u64::from_le_bytes(img[..8].try_into().unwrap());
450 let i1 = u64::from_le_bytes(img[8..].try_into().unwrap());
451
452 let (meta, wt, size) = result_type(&LABEL_T);
453 let mut result = vec![0u8; size];
454 core::arch::asm!("blr {f}", f = in(reg) resolve::label_init(),
457 in("x0") k0, in("x1") k1, in("x2") k2, in("x3") k3,
458 in("x4") i0, in("x5") i1,
459 in("x8") result.as_mut_ptr(),
460 lateout("x6") _, lateout("x7") _,
461 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
462 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
463 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
464 clobber_abi("C"),
465 );
466 wrap_owned(result, meta, wt)
467 }
468}
469
470pub(crate) fn lazy_stack_impl(children: &[ViewHandle], vertical: bool) -> ViewHandle {
472 lazy_stack_aligned_impl(children, vertical, None, None)
473}
474
475pub(crate) fn lazy_stack_aligned_impl(
478 children: &[ViewHandle],
479 vertical: bool,
480 halign: Option<super::HorizontalAlignment>,
481 valign: Option<super::VerticalAlignment>,
482) -> ViewHandle {
483 if children.is_empty() {
484 return empty_view();
485 }
486 unsafe {
487 let (content_meta, content_wt, offsets) = if children.len() == 1 {
490 (children[0].meta, children[0].wt, vec![0usize])
491 } else {
492 let elements: Vec<*const c_void> = children.iter().map(|c| c.meta).collect();
493 let tuple_meta = abi::tuple_metadata(&elements);
494 let offsets = abi::tuple_element_offsets(tuple_meta, children.len());
495 let m = abi::generic_metadata1(resolve::tupleview_ma(), tuple_meta);
496 let w = abi::get_view_wt(m);
497 assert!(!w.is_null(), "TupleView !: View");
498 (m, w, offsets)
499 };
500
501 let ma = if vertical { resolve::lazy_vstack_ma() } else { resolve::lazy_hstack_ma() };
502 let stack_meta = abi::generic_metadata2(ma, content_meta, content_wt);
503 let stack_wt = abi::get_view_wt(stack_meta);
504 assert!(!stack_wt.is_null(), "lazy stack !: View");
505
506 let kids: Vec<TupleChild> = children
507 .iter()
508 .zip(&offsets)
509 .map(|(c, &offset)| TupleChild { value: c.value_ptr(), meta: c.meta, offset })
510 .collect();
511 let payload = TuplePayload { children: kids.as_ptr(), count: kids.len() };
512 let mut ctx =
513 abi::ClosureCtx::new(emit_tuple, &payload as *const TuplePayload as *mut c_void);
514
515 let (align, _) = if vertical {
516 static_getter(
517 halign.map_or_else(resolve::halign_center, |h| h.resolved()),
518 resolve::halign_meta(),
519 )
520 } else {
521 static_getter(
522 valign.map_or_else(resolve::valign_center, |v| v.resolved()),
523 resolve::valign_meta(),
524 )
525 };
526 let init = if vertical { resolve::lazy_vstack_init() } else { resolve::lazy_hstack_init() };
527
528 let pinned_meta = crate::type_by_name!(swift_type!(SwiftUI.PinnedScrollableViews).as_bytes());
531 assert!(!pinned_meta.is_null(), "PinnedScrollableViews metadata");
532 let mut pinned = vec![0u8; abi::type_bytes(pinned_meta)];
533
534 let mut result = vec![0u8; abi::type_bytes(stack_meta)];
535 core::arch::asm!("blr {f}", f = in(reg) init,
540 in("x0") align,
541 in("x1") 0u64,
542 in("x2") 1u64,
543 in("x3") pinned.as_mut_ptr(),
544 in("x4") abi::swift_closure_thunk as *const c_void,
545 in("x5") &mut ctx as *mut abi::ClosureCtx,
546 in("x6") content_meta,
547 in("x7") content_wt,
548 in("x8") result.as_mut_ptr(),
549 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
550 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
551 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
552 clobber_abi("C"),
553 );
554 wrap_owned(result, stack_meta, stack_wt)
555 }
556}
557
558pub fn lazy_vstack(children: &[ViewHandle]) -> ViewHandle {
560 lazy_stack_impl(children, true)
561}
562
563pub fn lazy_vstack_aligned(
565 children: &[ViewHandle],
566 alignment: super::HorizontalAlignment,
567) -> ViewHandle {
568 lazy_stack_aligned_impl(children, true, Some(alignment), None)
569}
570
571pub fn lazy_hstack(children: &[ViewHandle]) -> ViewHandle {
573 lazy_stack_impl(children, false)
574}
575
576pub fn lazy_hstack_aligned(
578 children: &[ViewHandle],
579 alignment: super::VerticalAlignment,
580) -> ViewHandle {
581 lazy_stack_aligned_impl(children, false, None, Some(alignment))
582}
583
584pub fn tuple_view(children: &[ViewHandle]) -> ViewHandle {
597 assert!(!children.is_empty(), "a TupleView needs at least one child");
598 if children.len() == 1 {
599 return children[0].clone();
600 }
601 unsafe {
602 let elements: Vec<*const c_void> = children.iter().map(|c| c.meta).collect();
603 let tuple_meta = abi::tuple_metadata(&elements);
604 assert!(!tuple_meta.is_null(), "tuple metadata instantiation failed");
605 let offsets = abi::tuple_element_offsets(tuple_meta, children.len());
606 let meta = abi::generic_metadata1(resolve::tupleview_ma(), tuple_meta);
607 assert!(!meta.is_null(), "TupleView metadata instantiation failed");
608 let wt = abi::get_view_wt(meta);
609 assert!(!wt.is_null(), "{} !: View", crate::diag::type_name(meta));
610
611 let kids: Vec<TupleChild> = children
612 .iter()
613 .zip(&offsets)
614 .map(|(c, &offset)| TupleChild { value: c.value_ptr(), meta: c.meta, offset })
615 .collect();
616 let payload = TuplePayload { children: kids.as_ptr(), count: kids.len() };
617 let mut out = vec![0u8; abi::type_bytes(meta)];
620 emit_tuple(out.as_mut_ptr(), &payload as *const TuplePayload as *mut c_void);
621 super::wrap_owned(out, meta, wt)
622 }
623}
624
625#[derive(Clone, Copy, Debug, PartialEq)]
632pub enum GridTrack {
633 Fixed(f64),
635}
636
637unsafe fn grid_item(track: GridTrack) -> Vec<u8> {
642 unsafe {
643 let size_meta = abi::metadata0(resolve::grid_item_size_ma());
644 assert!(!size_meta.is_null(), "GridItem.Size metadata");
645 let mut size = vec![0u8; abi::type_bytes(size_meta)];
646 let GridTrack::Fixed(points) = track;
647 size[..8].copy_from_slice(&points.to_le_bytes());
648 let tag = abi::enum_case_index(size_meta, "fixed")
653 .expect("GridItem.Size has a `fixed` case");
654 abi::inject_enum_tag(&mut size, size_meta, tag as u32);
655
656 let item_meta = abi::metadata0(resolve::grid_item_ma());
657 assert!(!item_meta.is_null(), "GridItem metadata");
658 let mut item = vec![0u8; abi::type_bytes(item_meta)];
659 core::arch::asm!("blr {f}", f = in(reg) resolve::grid_item_init(),
664 in("x0") size.as_mut_ptr(),
665 in("x1") 0u64, in("x2") 1u64,
666 in("x3") 0u64, in("x4") 0u64, in("x5") 1u64,
667 in("x8") item.as_mut_ptr(),
668 lateout("x6") _, lateout("x7") _,
669 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
670 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
671 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
672 clobber_abi("C"),
673 );
674 item
675 }
676}
677
678unsafe fn grid_item_array(tracks: &[GridTrack]) -> u64 {
683 unsafe {
684 let item_meta = abi::metadata0(resolve::grid_item_ma());
685 let stride = abi::type_bytes(item_meta);
686 let (array, buf): (u64, u64);
687 core::arch::asm!("blr {f}", f = in(reg) resolve::array_alloc_uninit(),
688 in("x0") tracks.len() as u64,
689 in("x1") item_meta,
690 lateout("x0") array, lateout("x1") buf,
691 lateout("x2") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
692 lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
693 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
694 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
695 lateout("lr") _, lateout("x20") _, lateout("x21") _, clobber_abi("C"),
696 );
697 for (i, t) in tracks.iter().enumerate() {
700 let item = grid_item(*t);
701 core::ptr::copy_nonoverlapping(
702 item.as_ptr(),
703 (buf as *mut u8).add(i * stride),
704 item.len(),
705 );
706 }
707 array
708 }
709}
710
711pub fn lazy_vgrid(tracks: &[GridTrack], children: &[ViewHandle]) -> ViewHandle {
713 unsafe { lazy_grid(tracks, children, true) }
714}
715
716pub fn lazy_hgrid(tracks: &[GridTrack], children: &[ViewHandle]) -> ViewHandle {
718 unsafe { lazy_grid(tracks, children, false) }
719}
720
721unsafe fn lazy_grid(tracks: &[GridTrack], children: &[ViewHandle], vertical: bool) -> ViewHandle {
727 unsafe {
728 let (content_meta, content_wt, offsets) = if children.len() == 1 {
732 (children[0].meta, children[0].wt, vec![0usize])
733 } else {
734 let elements: Vec<*const c_void> = children.iter().map(|c| c.meta).collect();
735 let tuple_meta = abi::tuple_metadata(&elements);
736 assert!(!tuple_meta.is_null(), "tuple metadata instantiation failed");
737 let offsets = abi::tuple_element_offsets(tuple_meta, children.len());
738 let m = abi::generic_metadata1(resolve::tupleview_ma(), tuple_meta);
739 assert!(!m.is_null(), "TupleView metadata instantiation failed");
740 let w = abi::get_view_wt(m);
741 assert!(!w.is_null(), "{} !: View", crate::diag::type_name(m));
742 (m, w, offsets)
743 };
744
745 let ma = if vertical { resolve::lazy_vgrid_ma() } else { resolve::lazy_hgrid_ma() };
746 let meta = abi::generic_metadata2(ma, content_meta, content_wt);
747 assert!(!meta.is_null(), "lazy grid metadata");
748 let wt = abi::get_view_wt(meta);
749 assert!(!wt.is_null(), "lazy grid !: View");
750
751 let array = grid_item_array(tracks);
752 let (align, _) = if vertical {
753 static_getter(resolve::halign_center(), resolve::halign_meta())
754 } else {
755 static_getter(resolve::valign_center(), resolve::valign_meta())
756 };
757
758 let kids: Vec<TupleChild> = children
761 .iter()
762 .zip(&offsets)
763 .map(|(c, &offset)| TupleChild { value: c.value_ptr(), meta: c.meta, offset })
764 .collect();
765 let payload = TuplePayload { children: kids.as_ptr(), count: kids.len() };
766 let mut ctx =
767 abi::ClosureCtx::new(emit_tuple, &payload as *const TuplePayload as *mut c_void);
768
769 let pinned_meta = crate::type_by_name!(swift_type!(SwiftUI.PinnedScrollableViews).as_bytes());
770 assert!(!pinned_meta.is_null(), "PinnedScrollableViews metadata");
771 let mut pinned = vec![0u8; abi::type_bytes(pinned_meta)];
772
773 let mut result = vec![0u8; abi::type_bytes(meta)];
774 core::arch::asm!(
781 "sub sp, sp, #16",
782 "str {vw}, [sp]",
783 "blr {f}",
784 "add sp, sp, #16",
785 f = in(reg) if vertical { resolve::lazy_vgrid_init() } else { resolve::lazy_hgrid_init() },
786 vw = in(reg) content_wt,
787 in("x0") array,
788 in("x1") align,
789 in("x2") 0u64, in("x3") 1u64,
790 in("x4") pinned.as_mut_ptr(),
791 in("x5") abi::swift_closure_thunk as *const c_void,
792 in("x6") &mut ctx as *mut abi::ClosureCtx,
793 in("x7") content_meta,
794 in("x8") result.as_mut_ptr(),
795 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
796 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
797 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
798 clobber_abi("C"),
799 );
800 wrap_owned(result, meta, wt)
801 }
802}