1use std::sync::{
28 Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard,
29 atomic::{AtomicPtr, Ordering},
30};
31
32use rustc_hash::FxHashMap as HashMap;
33
34use crate::{
35 space::MemorySpaceId,
36 value::{
37 FunctionId,
38 insn::{Binop, IntBinop},
39 },
40};
41
42#[derive(
51 Copy, Clone, Hash, Eq, PartialEq, Debug, Ord, PartialOrd, serde::Serialize, serde::Deserialize,
52)]
53pub struct TypeId(u32);
54
55#[derive(Clone, Debug, PartialEq, Eq, Hash)]
62pub enum TypeRequest {
63 Aggregate { fields: Vec<AggregateField> },
64 StructPointer { size: usize, pointee: TypeId },
65 Array { elem: TypeId, count: usize },
66 List { elem: TypeId, bound: Option<usize> },
67}
68
69impl TypeRequest {
70 pub fn aggregate(fields: Vec<AggregateField>) -> Self {
71 Self::Aggregate { fields }
72 }
73
74 pub const fn struct_pointer(size: usize, pointee: TypeId) -> Self {
75 Self::StructPointer { size, pointee }
76 }
77
78 pub const fn array(elem: TypeId, count: usize) -> Self {
79 Self::Array { elem, count }
80 }
81
82 pub const fn list(elem: TypeId, bound: Option<usize>) -> Self {
83 Self::List { elem, bound }
84 }
85}
86
87pub trait Type: Send + Sync {
92 fn size(&self) -> usize;
94
95 fn space(&self) -> Option<MemorySpaceId> {
97 None
98 }
99
100 fn fields(&self) -> Option<&[AggregateField]> {
103 None
104 }
105
106 fn struct_name(&self) -> Option<&str> {
108 None
109 }
110
111 fn function_return_owner(&self) -> Option<FunctionId> {
113 None
114 }
115
116 fn pointee(&self) -> Option<TypeId> {
118 None
119 }
120
121 fn array(&self) -> Option<(TypeId, usize)> {
125 None
126 }
127
128 fn list(&self) -> Option<(TypeId, Option<usize>)> {
136 None
137 }
138
139 fn clone_box(&self) -> Box<dyn Type>;
145
146 fn repr(&self) -> TypeRepr;
152}
153
154#[derive(Clone, serde::Serialize, serde::Deserialize)]
162pub enum TypeRepr {
163 Int {
164 size: usize,
165 },
166 Bool,
169 SpaceAddress {
170 size: usize,
171 space: MemorySpaceId,
172 },
173 Aggregate {
178 fields: Vec<AggregateField>,
179 },
180 Struct {
186 name: String,
187 size: usize,
188 fields: Vec<AggregateField>,
189 },
190 StructPointer {
193 size: usize,
194 pointee: TypeId,
195 },
196 Array {
207 elem: TypeId,
208 count: usize,
209 },
210 List {
220 elem: TypeId,
221 bound: Option<usize>,
222 },
223 FunctionReturn {
229 owner: FunctionId,
230 fields: Vec<AggregateField>,
231 },
232 CodePointer {
239 size: usize,
240 },
241}
242
243#[derive(Clone, Debug, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
250pub struct AggregateField {
251 pub name: String,
252 pub type_id: TypeId,
253 pub offset: usize,
255}
256
257impl AggregateField {
258 pub fn new(name: impl Into<String>, type_id: TypeId) -> Self {
261 Self::new_at(name, type_id, 0)
262 }
263
264 pub fn new_at(name: impl Into<String>, type_id: TypeId, offset: usize) -> Self {
266 Self {
267 name: name.into(),
268 type_id,
269 offset,
270 }
271 }
272}
273
274impl Clone for Box<dyn Type> {
275 fn clone(&self) -> Self {
276 self.clone_box()
277 }
278}
279
280#[derive(Clone)]
285struct IntType {
286 size: usize,
287}
288
289impl Type for IntType {
290 fn size(&self) -> usize {
291 self.size
292 }
293
294 fn clone_box(&self) -> Box<dyn Type> {
295 Box::new(self.clone())
296 }
297
298 fn repr(&self) -> TypeRepr {
299 TypeRepr::Int { size: self.size }
300 }
301}
302
303#[derive(Clone)]
307struct BoolType;
308
309impl Type for BoolType {
310 fn size(&self) -> usize {
311 1
312 }
313
314 fn clone_box(&self) -> Box<dyn Type> {
315 Box::new(self.clone())
316 }
317
318 fn repr(&self) -> TypeRepr {
319 TypeRepr::Bool
320 }
321}
322
323#[derive(Clone)]
332pub struct SpaceAddress {
333 size: usize,
334 space: MemorySpaceId,
335}
336
337impl Type for SpaceAddress {
338 fn size(&self) -> usize {
339 self.size
340 }
341
342 fn space(&self) -> Option<MemorySpaceId> {
343 Some(self.space)
344 }
345
346 fn clone_box(&self) -> Box<dyn Type> {
347 Box::new(self.clone())
348 }
349
350 fn repr(&self) -> TypeRepr {
351 TypeRepr::SpaceAddress {
352 size: self.size,
353 space: self.space,
354 }
355 }
356}
357
358#[derive(Clone)]
362struct AggregateType {
363 fields: Vec<AggregateField>,
364 size: usize,
365}
366
367#[derive(Clone)]
373struct FunctionReturnType {
374 owner: FunctionId,
375 fields: Vec<AggregateField>,
376 size: usize,
377}
378
379impl Type for FunctionReturnType {
380 fn size(&self) -> usize {
381 self.size
382 }
383
384 fn fields(&self) -> Option<&[AggregateField]> {
385 Some(&self.fields)
386 }
387
388 fn function_return_owner(&self) -> Option<FunctionId> {
389 Some(self.owner)
390 }
391
392 fn clone_box(&self) -> Box<dyn Type> {
393 Box::new(self.clone())
394 }
395
396 fn repr(&self) -> TypeRepr {
397 TypeRepr::FunctionReturn {
398 owner: self.owner,
399 fields: self.fields.clone(),
400 }
401 }
402}
403
404impl Type for AggregateType {
405 fn size(&self) -> usize {
406 self.size
407 }
408
409 fn fields(&self) -> Option<&[AggregateField]> {
410 Some(&self.fields)
411 }
412
413 fn clone_box(&self) -> Box<dyn Type> {
414 Box::new(self.clone())
415 }
416
417 fn repr(&self) -> TypeRepr {
418 TypeRepr::Aggregate {
419 fields: self.fields.clone(),
420 }
421 }
422}
423
424#[derive(Clone)]
433struct StructType {
434 name: String,
435 fields: Vec<AggregateField>,
436 size: usize,
437}
438
439impl Type for StructType {
440 fn size(&self) -> usize {
441 self.size
442 }
443
444 fn fields(&self) -> Option<&[AggregateField]> {
445 Some(&self.fields)
446 }
447
448 fn struct_name(&self) -> Option<&str> {
449 Some(&self.name)
450 }
451
452 fn clone_box(&self) -> Box<dyn Type> {
453 Box::new(self.clone())
454 }
455
456 fn repr(&self) -> TypeRepr {
457 TypeRepr::Struct {
458 name: self.name.clone(),
459 size: self.size,
460 fields: self.fields.clone(),
461 }
462 }
463}
464
465#[derive(Clone)]
469struct StructPointer {
470 size: usize,
471 pointee: TypeId,
472}
473
474impl Type for StructPointer {
475 fn size(&self) -> usize {
476 self.size
477 }
478
479 fn pointee(&self) -> Option<TypeId> {
480 Some(self.pointee)
481 }
482
483 fn clone_box(&self) -> Box<dyn Type> {
484 Box::new(self.clone())
485 }
486
487 fn repr(&self) -> TypeRepr {
488 TypeRepr::StructPointer {
489 size: self.size,
490 pointee: self.pointee,
491 }
492 }
493}
494
495#[derive(Clone)]
497struct CodePointerType {
498 size: usize,
499}
500
501impl Type for CodePointerType {
502 fn size(&self) -> usize {
503 self.size
504 }
505
506 fn clone_box(&self) -> Box<dyn Type> {
507 Box::new(self.clone())
508 }
509
510 fn repr(&self) -> TypeRepr {
511 TypeRepr::CodePointer { size: self.size }
512 }
513}
514
515#[derive(Clone)]
519struct ArrayType {
520 elem: TypeId,
521 count: usize,
522 size: usize,
523}
524
525impl Type for ArrayType {
526 fn size(&self) -> usize {
527 self.size
528 }
529
530 fn array(&self) -> Option<(TypeId, usize)> {
531 Some((self.elem, self.count))
532 }
533
534 fn clone_box(&self) -> Box<dyn Type> {
535 Box::new(self.clone())
536 }
537
538 fn repr(&self) -> TypeRepr {
539 TypeRepr::Array {
540 elem: self.elem,
541 count: self.count,
542 }
543 }
544}
545
546#[derive(Clone)]
552struct ListType {
553 elem: TypeId,
554 bound: Option<usize>,
555 size: usize,
556}
557
558impl Type for ListType {
559 fn size(&self) -> usize {
560 self.size
561 }
562
563 fn list(&self) -> Option<(TypeId, Option<usize>)> {
564 Some((self.elem, self.bound))
565 }
566
567 fn clone_box(&self) -> Box<dyn Type> {
568 Box::new(self.clone())
569 }
570
571 fn repr(&self) -> TypeRepr {
572 TypeRepr::List {
573 elem: self.elem,
574 bound: self.bound,
575 }
576 }
577}
578
579fn default_named_fields(fields: Vec<TypeId>) -> Vec<AggregateField> {
587 fields
588 .into_iter()
589 .enumerate()
590 .map(|(i, type_id)| AggregateField::new(format!("field{}", i + 1), type_id))
591 .collect()
592}
593
594fn validate_unique_fields(fields: &[AggregateField]) -> Result<(), String> {
595 for (i, field) in fields.iter().enumerate() {
596 if fields[..i]
597 .iter()
598 .any(|previous| previous.name == field.name)
599 {
600 return Err(format!(
601 "aggregate field names must be unique; duplicate `{}`",
602 field.name
603 ));
604 }
605 }
606 Ok(())
607}
608
609#[derive(Clone)]
616struct TypeManagerInner {
617 types: Vec<Box<dyn Type>>,
618 retired_types: Vec<Box<dyn Type>>,
621 int_by_size: HashMap<usize, TypeId>,
623 bool_id: Option<TypeId>,
625 space_address: HashMap<(usize, MemorySpaceId), TypeId>,
627 aggregate_by_fields: HashMap<Vec<AggregateField>, TypeId>,
629 function_return: HashMap<FunctionId, TypeId>,
631 struct_by_name: HashMap<String, TypeId>,
633 struct_pointer: HashMap<(usize, TypeId), TypeId>,
635 code_pointer: HashMap<usize, TypeId>,
637 array_by_elem_count: HashMap<(TypeId, usize), TypeId>,
639 list_by_elem_bound: HashMap<(TypeId, Option<usize>), TypeId>,
641}
642
643impl Default for TypeManagerInner {
644 fn default() -> Self {
645 Self::new()
646 }
647}
648
649impl TypeManagerInner {
650 fn new() -> Self {
651 Self {
652 types: Vec::new(),
653 retired_types: Vec::new(),
654 int_by_size: HashMap::default(),
655 bool_id: None,
656 space_address: HashMap::default(),
657 aggregate_by_fields: HashMap::default(),
658 function_return: HashMap::default(),
659 struct_by_name: HashMap::default(),
660 struct_pointer: HashMap::default(),
661 array_by_elem_count: HashMap::default(),
662 list_by_elem_bound: HashMap::default(),
663 code_pointer: HashMap::default(),
664 }
665 }
666
667 fn register(&mut self, ty: Box<dyn Type>) -> TypeId {
668 let id = TypeId(self.types.len() as u32);
669 self.types.push(ty);
670 id
671 }
672
673 pub fn get_or_make_int(&mut self, size: usize) -> TypeId {
676 if let Some(&id) = self.int_by_size.get(&size) {
677 return id;
678 }
679 let id = self.register(Box::new(IntType { size }));
680 self.int_by_size.insert(size, id);
681 id
682 }
683
684 pub fn get_or_make_code_pointer(&mut self, size: usize) -> TypeId {
688 if let Some(&id) = self.code_pointer.get(&size) {
689 return id;
690 }
691 let id = self.register(Box::new(CodePointerType { size }));
692 self.code_pointer.insert(size, id);
693 id
694 }
695
696 pub fn get_or_make_bool(&mut self) -> TypeId {
699 if let Some(id) = self.bool_id {
700 return id;
701 }
702 let id = self.register(Box::new(BoolType));
703 self.bool_id = Some(id);
704 id
705 }
706
707 pub fn bool_id(&self) -> Option<TypeId> {
709 self.bool_id
710 }
711
712 pub fn is_bool(&self, id: TypeId) -> bool {
714 matches!(self.get(id).repr(), TypeRepr::Bool)
715 }
716
717 pub fn get_or_make_space_address(&mut self, size: usize, space: MemorySpaceId) -> TypeId {
720 if let Some(&id) = self.space_address.get(&(size, space)) {
721 return id;
722 }
723 let id = self.register(Box::new(SpaceAddress { size, space }));
724 self.space_address.insert((size, space), id);
725 id
726 }
727
728 pub fn get_or_make_named_aggregate(&mut self, fields: Vec<AggregateField>) -> TypeId {
733 validate_unique_fields(&fields).expect("aggregate field names must be unique");
734 if let Some(&id) = self.aggregate_by_fields.get(&fields) {
735 return id;
736 }
737 let size = fields.iter().map(|f| self.size_of(f.type_id)).sum();
738 let id = self.register(Box::new(AggregateType {
739 fields: fields.clone(),
740 size,
741 }));
742 self.aggregate_by_fields.insert(fields, id);
743 id
744 }
745
746 fn create_function_return(
747 &mut self,
748 owner: FunctionId,
749 fields: Vec<AggregateField>,
750 ) -> Result<TypeId, String> {
751 validate_unique_fields(&fields)?;
752 if let Some(&existing) = self.function_return.get(&owner) {
753 return Err(format!(
754 "function {owner:?} already owns return type {existing:?}"
755 ));
756 }
757 let size = fields.iter().map(|field| self.size_of(field.type_id)).sum();
758 let id = self.register(Box::new(FunctionReturnType {
759 owner,
760 fields,
761 size,
762 }));
763 self.function_return.insert(owner, id);
764 Ok(id)
765 }
766
767 fn edit_function_return(
768 &mut self,
769 owner: FunctionId,
770 fields: Vec<AggregateField>,
771 ) -> Result<TypeId, String> {
772 validate_unique_fields(&fields)?;
773 let id = self
774 .function_return
775 .get(&owner)
776 .copied()
777 .ok_or_else(|| format!("function {owner:?} has no owned return type"))?;
778 let size = fields.iter().map(|field| self.size_of(field.type_id)).sum();
779 let replacement: Box<dyn Type> = Box::new(FunctionReturnType {
780 owner,
781 fields,
782 size,
783 });
784 let old = std::mem::replace(&mut self.types[id.0 as usize], replacement);
785 self.retired_types.push(old);
786 Ok(id)
787 }
788
789 pub fn get_or_make_struct(
793 &mut self,
794 name: impl Into<String>,
795 size: usize,
796 fields: Vec<AggregateField>,
797 ) -> TypeId {
798 let name = name.into();
799 if let Some(&id) = self.struct_by_name.get(&name) {
800 return id;
801 }
802 let id = self.register(Box::new(StructType {
803 name: name.clone(),
804 fields,
805 size,
806 }));
807 self.struct_by_name.insert(name, id);
808 id
809 }
810
811 pub fn struct_by_name(&self, name: &str) -> Option<TypeId> {
813 self.struct_by_name.get(name).copied()
814 }
815
816 pub fn get_or_make_struct_pointer(&mut self, size: usize, pointee: TypeId) -> TypeId {
819 if let Some(&id) = self.struct_pointer.get(&(size, pointee)) {
820 return id;
821 }
822 let id = self.register(Box::new(StructPointer { size, pointee }));
823 self.struct_pointer.insert((size, pointee), id);
824 id
825 }
826
827 pub fn get_or_make_array(&mut self, elem: TypeId, count: usize) -> TypeId {
831 if let Some(&id) = self.array_by_elem_count.get(&(elem, count)) {
832 return id;
833 }
834 let size = self.size_of(elem) * count;
835 let id = self.register(Box::new(ArrayType { elem, count, size }));
836 self.array_by_elem_count.insert((elem, count), id);
837 id
838 }
839
840 pub fn get_or_make_list(&mut self, elem: TypeId, bound: usize) -> TypeId {
847 self.get_or_make_list_opt(elem, Some(bound))
848 }
849
850 pub fn get_or_make_unbounded_list(&mut self, elem: TypeId) -> TypeId {
853 self.get_or_make_list_opt(elem, None)
854 }
855
856 fn get_or_make_list_opt(&mut self, elem: TypeId, bound: Option<usize>) -> TypeId {
858 if let Some(&id) = self.list_by_elem_bound.get(&(elem, bound)) {
859 return id;
860 }
861 let size = bound.map_or(0, |b| self.size_of(elem) * b);
864 let id = self.register(Box::new(ListType { elem, bound, size }));
865 self.list_by_elem_bound.insert((elem, bound), id);
866 id
867 }
868
869 pub fn get(&self, id: TypeId) -> &dyn Type {
871 &*self.types[id.0 as usize]
872 }
873
874 pub fn size_of(&self, id: TypeId) -> usize {
876 self.get(id).size()
877 }
878
879 pub fn binop_result(&mut self, lhs: TypeId, op: Binop, rhs: TypeId) -> TypeId {
886 if let Some(id) = self.binop_result_probe(lhs, op, rhs) {
888 id
889 } else {
890 self.get_or_make_bool()
891 }
892 }
893
894 fn binop_result_probe(&self, lhs: TypeId, op: Binop, _rhs: TypeId) -> Option<TypeId> {
898 match op {
899 Binop::Int(int_op) => match int_op {
900 IntBinop::Equal
901 | IntBinop::NotEqual
902 | IntBinop::Less
903 | IntBinop::LessEqual
904 | IntBinop::SLess
905 | IntBinop::SLessEqual => self.bool_id,
906 IntBinop::And | IntBinop::Or | IntBinop::Xor if self.is_bool(lhs) => Some(lhs),
909 _ => Some(lhs),
910 },
911 Binop::Float(float_op) => {
912 if float_op.is_comparison() {
913 self.bool_id
914 } else {
915 Some(lhs)
916 }
917 }
918 }
919 }
920}
921
922pub struct TypeManager {
929 inner: RwLock<TypeManagerInner>,
930 published: AtomicPtr<PublishedTypes>,
938 #[allow(clippy::vec_box)]
940 published_generations: Mutex<Vec<Box<PublishedTypes>>>,
941}
942
943struct PublishedTypes {
950 entries: Box<[*const dyn Type]>,
951}
952
953unsafe impl Send for PublishedTypes {}
957unsafe impl Sync for PublishedTypes {}
959
960impl PublishedTypes {
961 fn from_inner(inner: &TypeManagerInner) -> Self {
962 Self {
963 entries: inner
964 .types
965 .iter()
966 .map(|ty| &**ty as *const dyn Type)
967 .collect(),
968 }
969 }
970}
971
972impl Default for TypeManager {
973 fn default() -> Self {
974 Self::new()
975 }
976}
977
978impl Clone for TypeManager {
979 fn clone(&self) -> Self {
980 Self::from_inner(self.read().clone())
981 }
982}
983
984impl TypeManager {
985 pub fn new() -> Self {
986 Self::from_inner(TypeManagerInner::new())
987 }
988
989 fn from_inner(inner: TypeManagerInner) -> Self {
990 let generation = Box::new(PublishedTypes::from_inner(&inner));
991 let published = AtomicPtr::new((&*generation as *const PublishedTypes).cast_mut());
992 Self {
993 inner: RwLock::new(inner),
994 published,
995 published_generations: Mutex::new(vec![generation]),
996 }
997 }
998
999 fn read(&self) -> RwLockReadGuard<'_, TypeManagerInner> {
1000 self.inner.read().expect("type manager RwLock poisoned")
1001 }
1002
1003 fn write(&self) -> RwLockWriteGuard<'_, TypeManagerInner> {
1004 self.inner.write().expect("type manager RwLock poisoned")
1005 }
1006
1007 fn publish(&self, inner: &TypeManagerInner) {
1011 let generation = Box::new(PublishedTypes::from_inner(inner));
1012 let ptr = (&*generation as *const PublishedTypes).cast_mut();
1013 self.published_generations
1014 .lock()
1015 .expect("type publication generation lock poisoned")
1016 .push(generation);
1017 self.published.store(ptr, Ordering::Release);
1018 }
1019
1020 fn publish_exclusive(&mut self) {
1024 let generation = {
1025 let inner = self.inner.get_mut().expect("type manager RwLock poisoned");
1026 Box::new(PublishedTypes::from_inner(inner))
1027 };
1028 let ptr = (&*generation as *const PublishedTypes).cast_mut();
1029 self.published_generations
1030 .get_mut()
1031 .expect("type publication generation lock poisoned")
1032 .push(generation);
1033 self.published.store(ptr, Ordering::Release);
1034 }
1035
1036 fn published(&self) -> &PublishedTypes {
1037 let ptr = self.published.load(Ordering::Acquire);
1038 debug_assert!(!ptr.is_null(), "type publication pointer is null");
1039 unsafe { &*ptr }
1043 }
1044
1045 fn mint(&self, f: impl FnOnce(&mut TypeManagerInner) -> TypeId) -> TypeId {
1048 let mut inner = self.write();
1049 let old_len = inner.types.len();
1050 let id = f(&mut inner);
1051 if inner.types.len() != old_len {
1052 self.publish(&inner);
1053 }
1054 id
1055 }
1056
1057 pub fn get_or_make_int(&self, size: usize) -> TypeId {
1065 if let Some(&id) = self.read().int_by_size.get(&size) {
1066 return id;
1067 }
1068 self.mint(|inner| inner.get_or_make_int(size))
1069 }
1070 pub fn get_or_make_bool(&self) -> TypeId {
1071 if let Some(id) = self.read().bool_id {
1072 return id;
1073 }
1074 self.mint(TypeManagerInner::get_or_make_bool)
1075 }
1076 pub fn get_or_make_space_address(
1077 &self,
1078 size: usize,
1079 space: impl Into<MemorySpaceId>,
1080 ) -> TypeId {
1081 let space = space.into();
1082 if let Some(&id) = self.read().space_address.get(&(size, space)) {
1083 return id;
1084 }
1085 self.mint(|inner| inner.get_or_make_space_address(size, space))
1086 }
1087 pub fn get_or_make_aggregate(&self, fields: Vec<TypeId>) -> TypeId {
1090 self.get_or_make_named_aggregate(default_named_fields(fields))
1091 }
1092 pub fn get_or_make_named_aggregate(&self, fields: Vec<AggregateField>) -> TypeId {
1093 if let Some(&id) = self.read().aggregate_by_fields.get(&fields) {
1094 return id;
1095 }
1096 self.mint(|inner| inner.get_or_make_named_aggregate(fields))
1097 }
1098
1099 pub fn create_function_return(
1106 &mut self,
1107 owner: FunctionId,
1108 fields: Vec<AggregateField>,
1109 ) -> Result<TypeId, String> {
1110 let id = self
1111 .inner
1112 .get_mut()
1113 .expect("type manager RwLock poisoned")
1114 .create_function_return(owner, fields)?;
1115 self.publish_exclusive();
1116 Ok(id)
1117 }
1118
1119 pub fn edit_function_return(
1123 &mut self,
1124 owner: FunctionId,
1125 fields: Vec<AggregateField>,
1126 ) -> Result<TypeId, String> {
1127 let id = self
1128 .inner
1129 .get_mut()
1130 .expect("type manager RwLock poisoned")
1131 .edit_function_return(owner, fields)?;
1132 self.publish_exclusive();
1133 Ok(id)
1134 }
1135
1136 pub fn create_requested_types(&mut self, requests: &[TypeRequest]) -> Vec<TypeId> {
1140 if requests.is_empty() {
1141 return Vec::new();
1142 }
1143 let (ids, changed) = {
1144 let inner = self.inner.get_mut().expect("type manager RwLock poisoned");
1145 let before = inner.types.len();
1146 let ids = requests
1147 .iter()
1148 .map(|request| match *request {
1149 TypeRequest::Aggregate { ref fields } => {
1150 inner.get_or_make_named_aggregate(fields.clone())
1151 }
1152 TypeRequest::StructPointer { size, pointee } => {
1153 inner.get_or_make_struct_pointer(size, pointee)
1154 }
1155 TypeRequest::Array { elem, count } => inner.get_or_make_array(elem, count),
1156 TypeRequest::List { elem, bound } => inner.get_or_make_list_opt(elem, bound),
1157 })
1158 .collect();
1159 (ids, inner.types.len() != before)
1160 };
1161 if changed {
1162 self.publish_exclusive();
1163 }
1164 ids
1165 }
1166 pub fn get_or_make_struct(
1167 &self,
1168 name: impl Into<String>,
1169 size: usize,
1170 fields: Vec<AggregateField>,
1171 ) -> TypeId {
1172 let name = name.into();
1173 if let Some(&id) = self.read().struct_by_name.get(&name) {
1174 return id;
1175 }
1176 self.mint(|inner| inner.get_or_make_struct(name, size, fields))
1177 }
1178 pub fn get_or_make_struct_pointer(&self, size: usize, pointee: TypeId) -> TypeId {
1179 if let Some(&id) = self.read().struct_pointer.get(&(size, pointee)) {
1180 return id;
1181 }
1182 self.mint(|inner| inner.get_or_make_struct_pointer(size, pointee))
1183 }
1184 pub fn get_or_make_code_pointer(&self, size: usize) -> TypeId {
1185 if let Some(&id) = self.read().code_pointer.get(&size) {
1186 return id;
1187 }
1188 self.mint(|inner| inner.get_or_make_code_pointer(size))
1189 }
1190 pub fn get_struct_pointer(&self, size: usize, pointee: TypeId) -> Option<TypeId> {
1192 self.read().struct_pointer.get(&(size, pointee)).copied()
1193 }
1194
1195 pub fn get_named_aggregate(&self, fields: &[AggregateField]) -> Option<TypeId> {
1197 self.read().aggregate_by_fields.get(fields).copied()
1198 }
1199 pub fn get_or_make_array(&self, elem: TypeId, count: usize) -> TypeId {
1200 if let Some(&id) = self.read().array_by_elem_count.get(&(elem, count)) {
1201 return id;
1202 }
1203 self.mint(|inner| inner.get_or_make_array(elem, count))
1204 }
1205
1206 pub fn get_array(&self, elem: TypeId, count: usize) -> Option<TypeId> {
1208 self.read().array_by_elem_count.get(&(elem, count)).copied()
1209 }
1210 pub fn get_list(&self, elem: TypeId, bound: Option<usize>) -> Option<TypeId> {
1212 self.read().list_by_elem_bound.get(&(elem, bound)).copied()
1213 }
1214
1215 pub fn get_seq(&self, elem: TypeId, len: usize, is_list: bool) -> Option<TypeId> {
1217 if is_list {
1218 self.get_list(elem, Some(len))
1219 } else {
1220 self.get_array(elem, len)
1221 }
1222 }
1223 pub fn get_or_make_list(&self, elem: TypeId, bound: usize) -> TypeId {
1224 if let Some(&id) = self.read().list_by_elem_bound.get(&(elem, Some(bound))) {
1225 return id;
1226 }
1227 self.mint(|inner| inner.get_or_make_list(elem, bound))
1228 }
1229 pub fn get_or_make_unbounded_list(&self, elem: TypeId) -> TypeId {
1230 if let Some(&id) = self.read().list_by_elem_bound.get(&(elem, None)) {
1231 return id;
1232 }
1233 self.mint(|inner| inner.get_or_make_unbounded_list(elem))
1234 }
1235 pub fn get_or_make_seq(&self, elem: TypeId, len: usize, is_list: bool) -> TypeId {
1239 if is_list {
1240 self.get_or_make_list(elem, len)
1241 } else {
1242 self.get_or_make_array(elem, len)
1243 }
1244 }
1245 pub fn binop_result(&self, lhs: TypeId, op: Binop, rhs: TypeId) -> TypeId {
1246 if let Some(id) = self.read().binop_result_probe(lhs, op, rhs) {
1247 return id;
1248 }
1249 self.mint(|inner| inner.binop_result(lhs, op, rhs))
1250 }
1251
1252 pub fn bool_id(&self) -> Option<TypeId> {
1255 self.read().bool_id()
1256 }
1257 pub fn get_int(&self, size: usize) -> TypeId {
1262 self.read()
1263 .int_by_size
1264 .get(&size)
1265 .copied()
1266 .unwrap_or_else(|| panic!("canonical integer type i{} is not published", size * 8))
1267 }
1268 pub fn get_bool(&self) -> TypeId {
1270 self.bool_id()
1271 .expect("canonical bool type is not published")
1272 }
1273 pub fn struct_by_name(&self, name: &str) -> Option<TypeId> {
1274 self.read().struct_by_name(name)
1275 }
1276 pub fn function_return(&self, owner: FunctionId) -> Option<TypeId> {
1277 self.read().function_return.get(&owner).copied()
1278 }
1279
1280 pub fn is_bool(&self, id: TypeId) -> bool {
1283 matches!(self.get(id).repr(), TypeRepr::Bool)
1284 }
1285 pub fn function_return_owner(&self, id: TypeId) -> Option<FunctionId> {
1286 self.get(id).function_return_owner()
1287 }
1288 pub fn size_of(&self, id: TypeId) -> usize {
1289 self.get(id).size()
1290 }
1291 pub fn space_of(&self, id: TypeId) -> Option<MemorySpaceId> {
1292 self.get(id).space()
1293 }
1294 pub fn pointee_of(&self, id: TypeId) -> Option<TypeId> {
1295 self.get(id).pointee()
1296 }
1297 pub fn array_of(&self, id: TypeId) -> Option<(TypeId, usize)> {
1298 self.get(id).array()
1299 }
1300 pub fn list_of(&self, id: TypeId) -> Option<(TypeId, Option<usize>)> {
1301 self.get(id).list()
1302 }
1303 pub fn seq_of(&self, id: TypeId) -> Option<(TypeId, usize, bool)> {
1304 if let Some((elem, count)) = self.array_of(id) {
1305 return Some((elem, count, false));
1306 }
1307 self.list_of(id)
1308 .and_then(|(elem, bound)| bound.map(|bound| (elem, bound, true)))
1309 }
1310 pub fn seq_elem_of(&self, id: TypeId) -> Option<TypeId> {
1311 self.array_of(id)
1312 .map(|(elem, _)| elem)
1313 .or_else(|| self.list_of(id).map(|(elem, _)| elem))
1314 }
1315 pub fn type_name(&self, id: TypeId) -> String {
1316 match self.get(id).repr() {
1317 TypeRepr::Bool => "bool".to_string(),
1318 TypeRepr::Struct { name, .. } => name,
1319 TypeRepr::StructPointer { pointee, .. } => {
1320 format!("{}*", self.type_name(pointee))
1321 }
1322 TypeRepr::Array { elem, count } => {
1323 format!("[{};{}]", self.type_name(elem), count)
1324 }
1325 TypeRepr::List { elem, bound } => match bound {
1326 Some(bound) => format!("[{};<={}]", self.type_name(elem), bound),
1327 None => format!("[{};*]", self.type_name(elem)),
1328 },
1329 TypeRepr::CodePointer { size } => format!("code{}*", size * 8),
1330 _ => format!("i{}", self.size_of(id) * 8),
1331 }
1332 }
1333 pub fn field_type(&self, id: TypeId, index: usize) -> Option<TypeId> {
1334 self.aggregate_fields(id)?
1335 .get(index)
1336 .map(|field| field.type_id)
1337 }
1338 pub fn field_index(&self, id: TypeId, name: &str) -> Option<usize> {
1339 self.aggregate_fields(id)?
1340 .iter()
1341 .position(|field| field.name == name)
1342 }
1343
1344 pub fn published_len(&self) -> usize {
1352 self.published().entries.len()
1353 }
1354
1355 pub fn has_sequence_types(&self) -> bool {
1363 let inner = self.read();
1364 !inner.array_by_elem_count.is_empty() || !inner.list_by_elem_bound.is_empty()
1365 }
1366
1367 pub fn get(&self, id: TypeId) -> &dyn Type {
1375 let entries = &self.published().entries;
1376 let ptr = *entries.get(id.0 as usize).unwrap_or_else(|| {
1377 panic!(
1378 "missing published type {id:?}; published type count is {}",
1379 entries.len()
1380 )
1381 });
1382 unsafe { &*ptr }
1386 }
1387
1388 pub fn struct_name_of(&self, id: TypeId) -> Option<&str> {
1389 self.get(id).struct_name()
1390 }
1391 pub fn aggregate_fields(&self, id: TypeId) -> Option<&[AggregateField]> {
1392 self.get(id).fields()
1393 }
1394 pub fn field_by_offset(&self, id: TypeId, offset: usize) -> Option<(usize, &AggregateField)> {
1395 self.aggregate_fields(id)?
1396 .iter()
1397 .enumerate()
1398 .find(|(_, field)| field.offset == offset)
1399 }
1400 pub fn field_name(&self, id: TypeId, index: usize) -> Option<&str> {
1401 self.aggregate_fields(id)?
1402 .get(index)
1403 .map(|field| field.name.as_str())
1404 }
1405}
1406
1407impl serde::Serialize for TypeManager {
1419 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1420 let reprs: Vec<TypeRepr> = self
1421 .published()
1422 .entries
1423 .iter()
1424 .map(|&ptr| {
1425 unsafe { &*ptr }.repr()
1428 })
1429 .collect();
1430 reprs.serialize(serializer)
1431 }
1432}
1433
1434impl<'de> serde::Deserialize<'de> for TypeManager {
1435 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1436 let reprs = Vec::<TypeRepr>::deserialize(deserializer)?;
1437 let mut manager = TypeManager::new();
1438 let mut pending_returns: Vec<(FunctionId, Vec<AggregateField>)> = Vec::new();
1446 for repr in reprs {
1447 match repr {
1448 TypeRepr::Int { size } => {
1449 manager.get_or_make_int(size);
1450 }
1451 TypeRepr::Bool => {
1452 manager.get_or_make_bool();
1453 }
1454 TypeRepr::SpaceAddress { size, space } => {
1455 manager.get_or_make_space_address(size, space);
1456 }
1457 TypeRepr::Aggregate { fields } => {
1460 manager.get_or_make_named_aggregate(fields);
1461 }
1462 TypeRepr::FunctionReturn { owner, fields } => {
1463 manager
1464 .create_function_return(owner, Vec::new())
1465 .map_err(serde::de::Error::custom)?;
1466 pending_returns.push((owner, fields));
1467 }
1468 TypeRepr::Struct { name, size, fields } => {
1469 manager.get_or_make_struct(name, size, fields);
1470 }
1471 TypeRepr::StructPointer { size, pointee } => {
1474 manager.get_or_make_struct_pointer(size, pointee);
1475 }
1476 TypeRepr::Array { elem, count } => {
1479 manager.get_or_make_array(elem, count);
1480 }
1481 TypeRepr::List { elem, bound } => match bound {
1484 Some(b) => {
1485 manager.get_or_make_list(elem, b);
1486 }
1487 None => {
1488 manager.get_or_make_unbounded_list(elem);
1489 }
1490 },
1491 TypeRepr::CodePointer { size } => {
1492 manager.get_or_make_code_pointer(size);
1493 }
1494 }
1495 }
1496 for (owner, fields) in pending_returns {
1499 manager
1500 .edit_function_return(owner, fields)
1501 .map_err(serde::de::Error::custom)?;
1502 }
1503 Ok(manager)
1504 }
1505}
1506
1507#[cfg(test)]
1508mod tests {
1509 use super::*;
1510
1511 #[test]
1512 fn binop_result_bool_rules() {
1513 use crate::value::insn::{Binop, FloatBinop, IntBinop};
1514 let tm = TypeManager::new();
1515 let i32 = tm.get_or_make_int(4);
1516 let boolt = tm.get_or_make_bool();
1517
1518 assert_eq!(tm.binop_result(i32, Binop::Int(IntBinop::Less), i32), boolt);
1520 assert_eq!(
1521 tm.binop_result(i32, Binop::Int(IntBinop::Equal), i32),
1522 boolt
1523 );
1524 assert_eq!(
1526 tm.binop_result(i32, Binop::Float(FloatBinop::Less), i32),
1527 boolt
1528 );
1529 assert_eq!(
1531 tm.binop_result(boolt, Binop::Int(IntBinop::And), boolt),
1532 boolt
1533 );
1534 assert_eq!(
1535 tm.binop_result(boolt, Binop::Int(IntBinop::Or), boolt),
1536 boolt
1537 );
1538 assert_eq!(tm.binop_result(i32, Binop::Int(IntBinop::And), i32), i32);
1540 assert_eq!(tm.binop_result(i32, Binop::Int(IntBinop::Add), i32), i32);
1542 }
1543
1544 #[test]
1545 fn bool_is_byte_stored_and_interned() {
1546 let tm = TypeManager::new();
1547 let b = tm.get_or_make_bool();
1548 assert_eq!(tm.size_of(b), 1);
1549 assert!(tm.is_bool(b));
1550 assert_eq!(tm.get_or_make_bool(), b);
1551 assert_eq!(tm.type_name(b), "bool");
1552 let i8 = tm.get_or_make_int(1);
1553 assert!(!tm.is_bool(i8));
1554 }
1555
1556 #[test]
1557 fn bool_round_trips_through_serde() {
1558 let tm = TypeManager::new();
1559 let _i8 = tm.get_or_make_int(1);
1560 let b = tm.get_or_make_bool();
1561 let config = bincode::config::standard();
1562 let bytes = bincode::serde::encode_to_vec(&tm, config).unwrap();
1563 let (back, _): (TypeManager, _) =
1564 bincode::serde::decode_from_slice(&bytes, config).unwrap();
1565 assert!(back.is_bool(b));
1566 assert_eq!(back.size_of(b), 1);
1567 }
1568
1569 #[test]
1570 fn array_is_a_disguised_width_n_scalar() {
1571 let tm = TypeManager::new();
1572 let i8 = tm.get_or_make_int(1);
1573 let arr = tm.get_or_make_array(i8, 20);
1574
1575 assert_eq!(tm.size_of(arr), 20);
1577 assert!(tm.aggregate_fields(arr).is_none());
1579 assert_eq!(tm.array_of(arr), Some((i8, 20)));
1581 assert_eq!(tm.get_or_make_array(i8, 20), arr);
1583 assert_ne!(tm.get_or_make_array(i8, 21), arr);
1584 assert_eq!(tm.type_name(arr), "[i8;20]");
1586 }
1587
1588 #[test]
1589 fn array_round_trips_through_serde() {
1590 let tm = TypeManager::new();
1591 let i8 = tm.get_or_make_int(1);
1592 let arr = tm.get_or_make_array(i8, 20);
1593
1594 let config = bincode::config::standard();
1595 let bytes = bincode::serde::encode_to_vec(&tm, config).unwrap();
1596 let (back, _): (TypeManager, _) =
1597 bincode::serde::decode_from_slice(&bytes, config).unwrap();
1598 assert_eq!(back.array_of(arr), Some((i8, 20)));
1600 assert_eq!(back.size_of(arr), 20);
1601 }
1602
1603 #[test]
1604 fn list_round_trips_through_serde() {
1605 let tm = TypeManager::new();
1606 let i8 = tm.get_or_make_int(1);
1607 let list = tm.get_or_make_list(i8, 20);
1608
1609 let config = bincode::config::standard();
1610 let bytes = bincode::serde::encode_to_vec(&tm, config).unwrap();
1611 let (back, _): (TypeManager, _) =
1612 bincode::serde::decode_from_slice(&bytes, config).unwrap();
1613 assert_eq!(back.list_of(list), Some((i8, Some(20))));
1616 assert_eq!(back.array_of(list), None);
1617 assert_eq!(back.size_of(list), 20);
1618 }
1619
1620 #[test]
1621 fn unbounded_list_round_trips_and_has_no_footprint() {
1622 let tm = TypeManager::new();
1623 let i8 = tm.get_or_make_int(1);
1624 let list = tm.get_or_make_unbounded_list(i8);
1625 assert_eq!(tm.list_of(list), Some((i8, None)));
1627 assert_eq!(tm.size_of(list), 0);
1628 assert_ne!(list, tm.get_or_make_list(i8, 20));
1630
1631 let config = bincode::config::standard();
1632 let bytes = bincode::serde::encode_to_vec(&tm, config).unwrap();
1633 let (back, _): (TypeManager, _) =
1634 bincode::serde::decode_from_slice(&bytes, config).unwrap();
1635 assert_eq!(back.list_of(list), Some((i8, None)));
1636 assert_eq!(back.array_of(list), None);
1637 }
1638
1639 #[test]
1640 fn newly_minted_type_is_published_before_return() {
1641 let tm = TypeManager::new();
1642 let i16 = tm.get_or_make_int(2);
1643 let array = tm.get_or_make_array(i16, 7);
1644
1645 assert_eq!(tm.size_of(array), 14);
1646 assert_eq!(tm.array_of(array), Some((i16, 7)));
1647 }
1648
1649 #[test]
1650 fn concurrent_mint_and_published_reads_are_consistent() {
1651 let tm = TypeManager::new();
1652 let byte = tm.get_or_make_int(1);
1653
1654 std::thread::scope(|scope| {
1655 for _ in 0..8 {
1656 scope.spawn(|| {
1657 for count in 1..=128 {
1658 let array = tm.get_or_make_array(byte, count);
1659 assert_eq!(tm.size_of(array), count);
1660 assert_eq!(tm.array_of(array), Some((byte, count)));
1661 assert_eq!(tm.size_of(byte), 1);
1662 }
1663 });
1664 }
1665 });
1666 }
1667
1668 #[test]
1669 fn requested_types_are_created_and_published_as_one_barrier_batch() {
1670 let mut tm = TypeManager::new();
1671 let byte = tm.get_or_make_int(1);
1672 let requests = [
1673 TypeRequest::array(byte, 4),
1674 TypeRequest::array(byte, 8),
1675 TypeRequest::array(byte, 4),
1676 ];
1677 assert_eq!(tm.get_array(byte, 4), None);
1678
1679 let ids = tm.create_requested_types(&requests);
1680
1681 assert_eq!(ids[0], ids[2], "duplicate requests must intern once");
1682 assert_eq!(tm.get_array(byte, 4), Some(ids[0]));
1683 assert_eq!(tm.get_array(byte, 8), Some(ids[1]));
1684 assert_eq!(tm.array_of(ids[0]), Some((byte, 4)));
1685 assert_eq!(tm.array_of(ids[1]), Some((byte, 8)));
1686 }
1687
1688 #[test]
1689 fn function_return_types_are_unique_owned_and_editable() {
1690 let mut tm = TypeManager::new();
1691 let i32 = tm.get_or_make_int(4);
1692 let fields = vec![AggregateField::new("value", i32)];
1693 let first_owner = FunctionId::from(0usize);
1694 let second_owner = FunctionId::from(1usize);
1695
1696 let first = tm
1697 .create_function_return(first_owner, fields.clone())
1698 .unwrap();
1699 let second = tm
1700 .create_function_return(second_owner, fields.clone())
1701 .unwrap();
1702
1703 assert_ne!(first, second, "owned declarations must not deduplicate");
1704 assert_eq!(tm.function_return(first_owner), Some(first));
1705 assert_eq!(tm.function_return(second_owner), Some(second));
1706 assert_eq!(tm.function_return_owner(first), Some(first_owner));
1707 assert_eq!(tm.function_return_owner(second), Some(second_owner));
1708 assert!(
1709 tm.create_function_return(first_owner, fields.clone())
1710 .is_err(),
1711 "one function cannot acquire a second return identity"
1712 );
1713
1714 let edited = tm
1715 .edit_function_return(
1716 first_owner,
1717 vec![
1718 AggregateField::new("value", i32),
1719 AggregateField::new("status", i32),
1720 ],
1721 )
1722 .unwrap();
1723 assert_eq!(edited, first, "editing must preserve nominal identity");
1724 assert_eq!(tm.size_of(first), 8);
1725 assert_eq!(tm.aggregate_fields(first).unwrap().len(), 2);
1726 assert_eq!(tm.size_of(second), 4, "the other owner must not change");
1727 assert_eq!(tm.aggregate_fields(second).unwrap(), fields.as_slice());
1728 }
1729
1730 #[test]
1731 fn function_return_type_round_trips_with_owner_and_identity() {
1732 let mut tm = TypeManager::new();
1733 let i16 = tm.get_or_make_int(2);
1734 let owner = FunctionId::from(7usize);
1735 let return_type = tm
1736 .create_function_return(owner, vec![AggregateField::new("result", i16)])
1737 .unwrap();
1738
1739 let bytes = bincode::serde::encode_to_vec(&tm, bincode::config::standard()).unwrap();
1740 let (mut restored, _): (TypeManager, _) =
1741 bincode::serde::decode_from_slice(&bytes, bincode::config::standard()).unwrap();
1742
1743 assert_eq!(restored.function_return(owner), Some(return_type));
1744 assert_eq!(restored.function_return_owner(return_type), Some(owner));
1745 assert_eq!(restored.size_of(return_type), 2);
1746 assert_eq!(
1747 restored
1748 .edit_function_return(
1749 owner,
1750 vec![
1751 AggregateField::new("result", i16),
1752 AggregateField::new("carry", i16),
1753 ],
1754 )
1755 .unwrap(),
1756 return_type
1757 );
1758 assert_eq!(restored.size_of(return_type), 4);
1759 }
1760}