1use crate::spv::spec::ExtInstSetDesc;
4use rustc_hash::FxHashMap;
5use std::hash::Hash;
6use std::mem;
7use std::num::NonZeroU32;
8use std::ops::{Deref, DerefMut};
9
10#[derive(Default)]
24pub struct Context {
25 interners: Interners,
26 entity_allocs: EntityAllocs,
27
28 custom_spv_ext_inst_set_descs: elsa::FrozenBTreeMap<String, Box<ExtInstSetDesc>>,
29}
30
31impl Context {
32 pub fn register_custom_ext_inst_set(
35 &self,
36 ext_inst_set_name: &str,
37 ext_inst_set_desc: ExtInstSetDesc,
38 ) {
39 let lowercase_ext_inst_set_name = ext_inst_set_name.to_ascii_lowercase();
40 assert!(
41 self.get_custom_ext_inst_set_by_lowercase_name(&lowercase_ext_inst_set_name).is_none(),
42 "already registered {lowercase_ext_inst_set_name:?} \
43 (name before lowercasing: {ext_inst_set_name})"
44 );
45 self.custom_spv_ext_inst_set_descs
46 .insert(lowercase_ext_inst_set_name, Box::new(ext_inst_set_desc));
47 }
48
49 pub fn get_custom_ext_inst_set_by_lowercase_name(
53 &self,
54 lowercase_ext_inst_set_name: &str,
55 ) -> Option<&ExtInstSetDesc> {
56 self.custom_spv_ext_inst_set_descs.get(lowercase_ext_inst_set_name)
57 }
58}
59
60mod sealed {
63 use std::cell::Cell;
64 use std::num::NonZeroU32;
65
66 pub trait Interned: Sized + 'static {
67 type Def: ?Sized + Eq + std::hash::Hash;
68
69 fn preintern(_interner: &Interner<Self>) {}
70 fn from_u32(i: u32) -> Self;
71 fn to_u32(self) -> u32;
72 fn cx_interner(cx: &super::Context) -> &Interner<Self>;
73 }
74
75 pub struct Interner<I: Interned>(
79 elsa::FrozenIndexSet<Box<I::Def>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,
80 );
81
82 impl<I: Interned> Default for Interner<I> {
83 fn default() -> Self {
84 let interner = Self(Default::default());
85 I::preintern(&interner);
86 interner
87 }
88 }
89
90 impl<I: Interned> Interner<I> {
91 #[track_caller]
92 pub(super) fn intern(&self, value: impl AsRef<I::Def> + Into<Box<I::Def>>) -> I {
93 if let Some((i, _)) = self.0.get_full(value.as_ref()) {
94 return I::from_u32(i as u32);
95 }
96 let (i, _) = self.0.insert_full(value.into());
97 I::from_u32(i.try_into().expect("interner overflowed u32"))
98 }
99 }
100
101 impl<I: Interned> std::ops::Index<I> for Interner<I> {
102 type Output = I::Def;
103
104 fn index(&self, interned: I) -> &Self::Output {
105 &self.0[interned.to_u32() as usize]
106 }
107 }
108
109 pub trait Entity: Sized + Copy + Eq + std::hash::Hash + 'static {
117 type Def;
118
119 const CHUNK_SIZE: u32;
120 const CHUNK_MASK: u32 = {
121 assert!(Self::CHUNK_SIZE.is_power_of_two());
122 assert!(Self::CHUNK_SIZE as usize as u32 == Self::CHUNK_SIZE);
123 Self::CHUNK_SIZE - 1
124 };
125
126 fn from_non_zero_u32(i: NonZeroU32) -> Self;
127 fn to_non_zero_u32(self) -> NonZeroU32;
128 fn cx_entity_alloc(cx: &super::Context) -> &EntityAlloc<Self>;
129
130 #[inline(always)]
131 fn to_chunk_start_and_intra_chunk_idx(self) -> (Self, usize) {
132 let self_u32 = self.to_non_zero_u32().get();
133 (
134 Self::from_non_zero_u32(NonZeroU32::new(self_u32 & !Self::CHUNK_MASK).unwrap()),
135 (self_u32 & Self::CHUNK_MASK) as usize,
136 )
137 }
138 }
139
140 pub struct EntityAlloc<E: Entity>(Cell<E>);
141
142 impl<E: Entity> Default for EntityAlloc<E> {
143 fn default() -> Self {
144 Self(Cell::new(E::from_non_zero_u32(NonZeroU32::new(E::CHUNK_SIZE).unwrap())))
147 }
148 }
149
150 impl<E: Entity> EntityAlloc<E> {
151 #[track_caller]
152 pub(super) fn alloc_chunk(&self) -> E {
153 let chunk_start = self.0.get();
154 let next_chunk_start = E::from_non_zero_u32(
155 chunk_start
156 .to_non_zero_u32()
157 .checked_add(E::CHUNK_SIZE)
158 .expect("entity index overflowed u32"),
159 );
160 self.0.set(next_chunk_start);
161 chunk_start
162 }
163 }
164}
165use sealed::Entity as _;
166
167pub trait InternInCx<I> {
170 #[track_caller]
171 fn intern_in_cx(self, cx: &Context) -> I;
172}
173
174impl Context {
175 pub fn new() -> Self {
176 Self::default()
177 }
178
179 #[track_caller]
180 pub fn intern<T: InternInCx<I>, I>(&self, x: T) -> I {
181 x.intern_in_cx(self)
182 }
183}
184
185impl<I: sealed::Interned> std::ops::Index<I> for Context {
186 type Output = I::Def;
187
188 fn index(&self, interned: I) -> &Self::Output {
189 &I::cx_interner(self)[interned]
190 }
191}
192
193#[derive(Clone)]
201pub struct EntityDefs<E: sealed::Entity> {
202 complete_chunk_start_to_flattened_base: FxHashMap<E, usize>,
209
210 incomplete_chunk_start_and_flattened_base: Option<(E, usize)>,
215
216 flattened: Vec<E::Def>,
221}
222
223impl<E: sealed::Entity> Default for EntityDefs<E> {
224 fn default() -> Self {
225 Self {
226 complete_chunk_start_to_flattened_base: FxHashMap::default(),
227 incomplete_chunk_start_and_flattened_base: None,
228 flattened: vec![],
229 }
230 }
231}
232
233impl<E: sealed::Entity> EntityDefs<E> {
234 pub fn new() -> Self {
235 Self::default()
236 }
237
238 #[track_caller]
239 pub fn define(&mut self, cx: &Context, def: E::Def) -> E {
240 let entity = match self.incomplete_chunk_start_and_flattened_base {
241 Some((chunk_start, flattened_base)) => {
242 let chunk_len = self.flattened.len() - flattened_base;
243
244 if chunk_len == (E::CHUNK_SIZE - 1) as usize {
249 self.complete_chunk_start_to_flattened_base
250 .extend(self.incomplete_chunk_start_and_flattened_base.take());
251 }
252
253 E::from_non_zero_u32(
254 NonZeroU32::new(chunk_start.to_non_zero_u32().get() + chunk_len as u32)
255 .unwrap(),
256 )
257 }
258 None => {
259 let chunk_start = E::cx_entity_alloc(cx).alloc_chunk();
260
261 self.incomplete_chunk_start_and_flattened_base =
262 Some((chunk_start, self.flattened.len()));
263
264 chunk_start
265 }
266 };
267 self.flattened.push(def);
268 entity
269 }
270
271 fn entity_to_flattened(&self, entity: E) -> Option<usize> {
272 let (chunk_start, intra_chunk_idx) = entity.to_chunk_start_and_intra_chunk_idx();
273 let flattened_base = match self.incomplete_chunk_start_and_flattened_base {
274 Some((incomplete_chunk_start, incomplete_flattened_base))
275 if chunk_start == incomplete_chunk_start =>
276 {
277 incomplete_flattened_base
278 }
279 _ => *self.complete_chunk_start_to_flattened_base.get(&chunk_start)?,
280 };
281 Some(flattened_base + intra_chunk_idx)
282 }
283}
284
285impl<E: sealed::Entity> std::ops::Index<E> for EntityDefs<E> {
286 type Output = E::Def;
287
288 fn index(&self, entity: E) -> &Self::Output {
289 self.entity_to_flattened(entity).and_then(|i| self.flattened.get(i)).unwrap()
290 }
291}
292
293impl<E: sealed::Entity> std::ops::IndexMut<E> for EntityDefs<E> {
294 fn index_mut(&mut self, entity: E) -> &mut Self::Output {
295 self.entity_to_flattened(entity).and_then(|i| self.flattened.get_mut(i)).unwrap()
296 }
297}
298
299pub trait EntityOrientedMapKey<V>: Copy {
303 type Entity: sealed::Entity;
305 fn to_entity(key: Self) -> Self::Entity;
306
307 type DenseValueSlots: Default;
312 fn get_dense_value_slot(key: Self, slots: &Self::DenseValueSlots) -> &Option<V>;
313 fn get_dense_value_slot_mut(key: Self, slots: &mut Self::DenseValueSlots) -> &mut Option<V>;
314}
315
316impl<E: sealed::Entity, V> EntityOrientedMapKey<V> for E {
317 type Entity = E;
318 fn to_entity(key: E) -> E {
319 key
320 }
321
322 type DenseValueSlots = Option<V>;
323 fn get_dense_value_slot(_: Self, slot: &Option<V>) -> &Option<V> {
324 slot
325 }
326 fn get_dense_value_slot_mut(_: Self, slot: &mut Option<V>) -> &mut Option<V> {
327 slot
328 }
329}
330
331#[derive(Clone)]
341pub struct EntityOrientedDenseMap<K: EntityOrientedMapKey<V>, V> {
342 chunk_start_to_value_slots: SmallFxHashMap<K::Entity, Vec<K::DenseValueSlots>>,
345}
346
347#[derive(Clone)]
352enum SmallFxHashMap<K, V> {
353 Empty,
354 One(K, V),
355 More(FxHashMap<K, V>),
356}
357
358impl<K, V> Default for SmallFxHashMap<K, V> {
359 fn default() -> Self {
360 Self::Empty
361 }
362}
363
364impl<K: Copy + Eq + Hash, V: Default> SmallFxHashMap<K, V> {
365 fn get_mut_or_insert_default(&mut self, k: K) -> &mut V {
366 match *self {
369 Self::Empty => {
370 *self = Self::One(k, V::default());
371 }
372 Self::One(old_k, _) => {
373 if old_k != k {
374 let old = mem::replace(self, Self::More(Default::default()));
375 match (old, &mut *self) {
376 (Self::One(_, old_v), Self::More(map)) => {
377 map.insert(old_k, old_v);
378 }
379 _ => unreachable!(),
380 }
381 }
382 }
383 Self::More(_) => {}
384 }
385
386 match self {
388 Self::Empty => unreachable!(),
389 Self::One(_, v) => v,
390 Self::More(map) => map.entry(k).or_default(),
391 }
392 }
393
394 fn get(&self, k: K) -> Option<&V> {
395 #[allow(clippy::match_same_arms)]
396 match self {
397 Self::Empty => None,
398 Self::One(old_k, old_v) if *old_k == k => Some(old_v),
399 Self::One(..) => None,
400 Self::More(map) => map.get(&k),
401 }
402 }
403
404 fn get_mut(&mut self, k: K) -> Option<&mut V> {
405 #[allow(clippy::match_same_arms)]
406 match self {
407 Self::Empty => None,
408 Self::One(old_k, old_v) if *old_k == k => Some(old_v),
409 Self::One(..) => None,
410 Self::More(map) => map.get_mut(&k),
411 }
412 }
413}
414
415impl<K: EntityOrientedMapKey<V>, V> Default for EntityOrientedDenseMap<K, V> {
416 fn default() -> Self {
417 Self { chunk_start_to_value_slots: Default::default() }
418 }
419}
420
421impl<K: EntityOrientedMapKey<V>, V> EntityOrientedDenseMap<K, V> {
422 pub fn new() -> Self {
423 Self::default()
424 }
425
426 pub fn entry(&mut self, key: K) -> &mut Option<V> {
429 let entity = K::to_entity(key);
430 let (chunk_start, intra_chunk_idx) = entity.to_chunk_start_and_intra_chunk_idx();
431 let chunk_value_slots =
432 self.chunk_start_to_value_slots.get_mut_or_insert_default(chunk_start);
433
434 let needed_len = intra_chunk_idx + 1;
436 if chunk_value_slots.len() < needed_len {
437 chunk_value_slots.resize_with(needed_len, Default::default);
438 }
439
440 let value_slots = &mut chunk_value_slots[intra_chunk_idx];
441 K::get_dense_value_slot_mut(key, value_slots)
442 }
443
444 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
445 self.entry(key).replace(value)
446 }
447
448 pub fn get(&self, key: K) -> Option<&V> {
449 let entity = K::to_entity(key);
450 let (chunk_start, intra_chunk_idx) = entity.to_chunk_start_and_intra_chunk_idx();
451 let value_slots = self.chunk_start_to_value_slots.get(chunk_start)?.get(intra_chunk_idx)?;
452 K::get_dense_value_slot(key, value_slots).as_ref()
453 }
454
455 pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
456 self.get_slot_mut(key)?.as_mut()
457 }
458
459 pub fn remove(&mut self, key: K) -> Option<V> {
460 self.get_slot_mut(key)?.take()
461 }
462
463 fn get_slot_mut(&mut self, key: K) -> Option<&mut Option<V>> {
465 let entity = K::to_entity(key);
466 let (chunk_start, intra_chunk_idx) = entity.to_chunk_start_and_intra_chunk_idx();
467 let value_slots =
468 self.chunk_start_to_value_slots.get_mut(chunk_start)?.get_mut(intra_chunk_idx)?;
469 Some(K::get_dense_value_slot_mut(key, value_slots))
470 }
471}
472
473impl<K: EntityOrientedMapKey<V>, V> std::ops::Index<K> for EntityOrientedDenseMap<K, V> {
474 type Output = V;
475
476 fn index(&self, key: K) -> &V {
477 self.get(key).expect("no entry found for key")
478 }
479}
480
481impl<K: EntityOrientedMapKey<V>, V> std::ops::IndexMut<K> for EntityOrientedDenseMap<K, V> {
482 fn index_mut(&mut self, key: K) -> &mut V {
483 self.get_mut(key).expect("no entry found for key")
484 }
485}
486
487#[allow(rustdoc::private_intra_doc_links)]
488#[derive(Copy, Clone)]
493pub struct EntityList<E: sealed::Entity>(Option<FirstLast<E, E>>);
494
495#[derive(Copy, Clone)]
497struct FirstLast<F, L> {
498 first: F,
499 last: L,
500}
501
502impl<E: sealed::Entity> Default for EntityList<E> {
503 fn default() -> Self {
504 Self(None)
505 }
506}
507
508impl<E: sealed::Entity<Def = EntityListNode<E, D>>, D> EntityList<E> {
509 pub fn empty() -> Self {
510 Self::default()
511 }
512
513 pub fn is_empty(self) -> bool {
514 self.0.is_none()
515 }
516
517 pub fn iter(self) -> EntityListIter<E> {
518 EntityListIter { first: self.0.map(|list| list.first), last: self.0.map(|list| list.last) }
519 }
520
521 #[track_caller]
523 pub fn insert_first(&mut self, new_node: E, defs: &mut EntityDefs<E>) {
524 let new_node_def = &mut defs[new_node];
525 assert!(
526 new_node_def.prev.is_none() && new_node_def.next.is_none(),
527 "EntityList::insert_first: new node already linked into a (different?) list"
528 );
529
530 new_node_def.next = self.0.map(|this| this.first);
531 if let Some(old_first) = new_node_def.next {
532 let old_first_def = &mut defs[old_first];
533
534 assert!(old_first_def.prev.is_none(), "invalid EntityList: `first->prev != None`");
539
540 old_first_def.prev = Some(new_node);
541 }
542
543 self.0 =
544 Some(FirstLast { first: new_node, last: self.0.map_or(new_node, |this| this.last) });
545 }
546
547 #[track_caller]
549 pub fn insert_last(&mut self, new_node: E, defs: &mut EntityDefs<E>) {
550 let new_node_def = &mut defs[new_node];
551 assert!(
552 new_node_def.prev.is_none() && new_node_def.next.is_none(),
553 "EntityList::insert_last: new node already linked into a (different?) list"
554 );
555
556 new_node_def.prev = self.0.map(|this| this.last);
557 if let Some(old_last) = new_node_def.prev {
558 let old_last_def = &mut defs[old_last];
559
560 assert!(old_last_def.next.is_none(), "invalid EntityList: `last->next != None`");
565
566 old_last_def.next = Some(new_node);
567 }
568
569 self.0 =
570 Some(FirstLast { first: self.0.map_or(new_node, |this| this.first), last: new_node });
571 }
572
573 #[track_caller]
578 pub fn insert_before(&mut self, new_node: E, next: E, defs: &mut EntityDefs<E>) {
579 let prev = defs[next].prev.replace(new_node);
580
581 let new_node_def = &mut defs[new_node];
582 assert!(
583 new_node_def.prev.is_none() && new_node_def.next.is_none(),
584 "EntityList::insert_before: new node already linked into a (different?) list"
585 );
586
587 new_node_def.prev = prev;
588 new_node_def.next = Some(next);
589
590 match prev {
591 Some(prev) => {
592 let old_prev_next = defs[prev].next.replace(new_node);
593
594 assert!(
597 old_prev_next == Some(next),
598 "invalid EntityListNode: `node->prev->next != node`"
599 );
600 }
601 None => {
602 assert!(
607 self.0.map(|this| this.first) == Some(next),
608 "invalid EntityList: `node->prev == None` but `node != first`"
609 );
610
611 self.0.as_mut().unwrap().first = new_node;
612 }
613 }
614 }
615
616 #[track_caller]
618 pub fn prepend(&mut self, list_to_prepend: Self, defs: &mut EntityDefs<E>) {
619 *self = Self::concat(list_to_prepend, *self, defs);
620 }
621
622 #[track_caller]
624 pub fn append(&mut self, list_to_append: Self, defs: &mut EntityDefs<E>) {
625 *self = Self::concat(*self, list_to_append, defs);
626 }
627
628 #[track_caller]
630 fn concat(a: Self, b: Self, defs: &mut EntityDefs<E>) -> Self {
631 let (a, b) = match (a.0, b.0) {
632 (Some(a), Some(b)) => (a, b),
633 (a, b) => return Self(a.or(b)),
634 };
635
636 {
637 let a_last_def = &mut defs[a.last];
638
639 assert!(a_last_def.next.is_none(), "invalid EntityList: `last->next != None`");
644
645 a_last_def.next = Some(b.first);
646 }
647 {
648 let b_first_def = &mut defs[b.first];
649
650 assert!(b_first_def.prev.is_none(), "invalid EntityList: `first->prev != None`");
655
656 b_first_def.prev = Some(a.last);
657 }
658
659 Self(Some(FirstLast { first: a.first, last: b.last }))
660 }
661
662 #[track_caller]
664 pub fn remove(&mut self, node: E, defs: &mut EntityDefs<E>) {
665 let (prev, next) = {
667 let node_def = &mut defs[node];
668 (node_def.prev.take(), node_def.next.take())
669 };
670
671 match prev {
673 Some(prev) => {
674 let old_prev_next = mem::replace(&mut defs[prev].next, next);
675
676 assert!(
679 old_prev_next == Some(node),
680 "invalid EntityListNode: `node->prev->next != node`"
681 );
682 }
683 None => {
684 assert!(
689 self.0.map(|this| this.first) == Some(node),
690 "invalid EntityList: `node->prev == None` but `node != first`"
691 );
692 }
693 }
694
695 match next {
697 Some(next) => {
698 let old_next_prev = mem::replace(&mut defs[next].prev, prev);
699
700 assert!(
703 old_next_prev == Some(node),
704 "invalid EntityListNode: `node->next->prev != node`"
705 );
706 }
707 None => {
708 assert!(
713 self.0.map(|this| this.last) == Some(node),
714 "invalid EntityList: `node->next == None` but `node != last`"
715 );
716 }
717 }
718
719 match (prev, next) {
721 (Some(_), Some(_)) => {}
722 (None, Some(next)) => self.0.as_mut().unwrap().first = next,
723 (Some(prev), None) => self.0.as_mut().unwrap().last = prev,
724 (None, None) => self.0 = None,
725 }
726 }
727}
728
729#[derive(Copy, Clone)]
733pub struct EntityListIter<E: sealed::Entity> {
734 pub first: Option<E>,
735 pub last: Option<E>,
736}
737
738impl<E: sealed::Entity<Def = EntityListNode<E, D>>, D> EntityListIter<E> {
739 #[track_caller]
740 pub fn split_first(self, defs: &EntityDefs<E>) -> Option<(E, Self)> {
741 let Self { first, last } = self;
742 let current = first?;
743 let next = defs[current].next;
744 match next {
745 Some(next) => assert!(
748 defs[next].prev == Some(current),
749 "invalid EntityListNode: `node->next->prev != node`"
750 ),
751
752 None => assert!(
753 Some(current) == last,
754 "invalid EntityListIter: `first->next->...->next != last`"
755 ),
756 }
757 Some((current, Self { first: next, last }))
758 }
759
760 #[track_caller]
761 pub fn split_last(self, defs: &EntityDefs<E>) -> Option<(E, Self)> {
762 let Self { first, last } = self;
763 let current = last?;
764 let prev = defs[current].prev;
765 match prev {
766 Some(prev) => assert!(
769 defs[prev].next == Some(current),
770 "invalid EntityListNode: `node->prev->next != node`"
771 ),
772
773 None => assert!(
774 Some(current) == first,
775 "invalid EntityListIter: `last->prev->...->prev != first`"
776 ),
777 }
778 Some((current, Self { first, last: prev }))
779 }
780}
781
782#[derive(Clone)]
791pub struct EntityListNode<E: sealed::Entity<Def = Self>, D> {
792 prev: Option<E>,
793 next: Option<E>,
794
795 inner_def: D,
796}
797
798impl<E: sealed::Entity<Def = Self>, D> From<D> for EntityListNode<E, D> {
799 fn from(inner_def: D) -> Self {
800 Self { prev: None, next: None, inner_def }
801 }
802}
803
804impl<E: sealed::Entity<Def = Self>, D> EntityListNode<E, D> {
805 pub fn prev_in_list(&self) -> Option<E> {
806 self.prev
807 }
808 pub fn next_in_list(&self) -> Option<E> {
809 self.next
810 }
811}
812
813impl<E: sealed::Entity<Def = Self>, D> Deref for EntityListNode<E, D> {
814 type Target = D;
815 fn deref(&self) -> &D {
816 &self.inner_def
817 }
818}
819
820impl<E: sealed::Entity<Def = Self>, D> DerefMut for EntityListNode<E, D> {
821 fn deref_mut(&mut self) -> &mut D {
822 &mut self.inner_def
823 }
824}
825
826macro_rules! interners {
827 (
828 needs_as_ref { $($needs_as_ref_ty:ty),* $(,)? }
829 $($name:ident $(default($default:expr))? => $ty:ty),+ $(,)?
830 ) => {
831 $(impl AsRef<Self> for $needs_as_ref_ty {
832 fn as_ref(&self) -> &Self {
833 self
834 }
835 })*
836
837 #[allow(non_snake_case)]
838 #[derive(Default)]
839 struct Interners {
840 $($name: sealed::Interner<$name>),*
841 }
842
843 $(
844 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
847 pub struct $name(
848 #[doc(hidden)] u32,
851 );
852
853 $(impl Default for $name {
854 fn default() -> Self {
855 if false { let _ = $default; }
858
859 Self(0)
860 }
861 })?
862
863 impl sealed::Interned for $name {
864 type Def = $ty;
865
866 $(fn preintern(interner: &sealed::Interner<Self>) {
867 interner.intern($default);
868 })?
869 #[inline(always)]
870 fn from_u32(i: u32) -> Self {
871 Self(i)
872 }
873 #[inline(always)]
874 fn to_u32(self) -> u32 {
875 self.0
876 }
877 #[inline(always)]
878 fn cx_interner(cx: &Context) -> &sealed::Interner<Self> {
879 &cx.interners.$name
880 }
881 }
882 )*
883 };
884}
885
886interners! {
887 needs_as_ref {
888 crate::AttrSetDef,
889 crate::TypeDef,
890 crate::ConstDef,
891 crate::DataInstFormDef,
892 }
893
894 InternedStr => str,
897 AttrSet default(crate::AttrSetDef::default()) => crate::AttrSetDef,
898 Type => crate::TypeDef,
899 Const => crate::ConstDef,
900 DataInstForm => crate::DataInstFormDef,
901}
902
903impl<I: sealed::Interned> InternInCx<I> for I::Def
904where
905 I::Def: Sized + AsRef<I::Def>,
906{
907 fn intern_in_cx(self, cx: &Context) -> I {
908 I::cx_interner(cx).intern(self)
909 }
910}
911
912impl InternInCx<InternedStr> for &'_ str {
913 fn intern_in_cx(self, cx: &Context) -> InternedStr {
914 cx.interners.InternedStr.intern(self)
915 }
916}
917
918impl InternInCx<InternedStr> for String {
919 fn intern_in_cx(self, cx: &Context) -> InternedStr {
920 cx.interners.InternedStr.intern(self)
921 }
922}
923
924macro_rules! entities {
925 (
926 $($name:ident => chunk_size($chunk_size:literal) $def:ty),+ $(,)?
927 ) => {
928 #[allow(non_snake_case)]
929 #[derive(Default)]
930 struct EntityAllocs {
931 $($name: sealed::EntityAlloc<$name>),*
932 }
933
934 $(
935 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
938 pub struct $name(#[doc(hidden)] NonZeroU32);
939
940 impl sealed::Entity for $name {
941 type Def = $def;
942
943 const CHUNK_SIZE: u32 = $chunk_size;
944
945 #[inline(always)]
946 fn from_non_zero_u32(i: NonZeroU32) -> Self {
947 Self(i)
948 }
949 #[inline(always)]
950 fn to_non_zero_u32(self) -> NonZeroU32 {
951 self.0
952 }
953 #[inline(always)]
954 fn cx_entity_alloc(cx: &Context) -> &sealed::EntityAlloc<Self> {
955 &cx.entity_allocs.$name
956 }
957 }
958 )*
959 };
960}
961
962entities! {
963 GlobalVar => chunk_size(0x1_0000) crate::GlobalVarDecl,
964 Func => chunk_size(0x1_0000) crate::FuncDecl,
965 ControlRegion => chunk_size(0x1000) crate::ControlRegionDef,
966 ControlNode => chunk_size(0x1000) EntityListNode<ControlNode, crate::ControlNodeDef>,
967 DataInst => chunk_size(0x1000) EntityListNode<DataInst, crate::DataInstDef>,
968}