1use crate::module::AddrSpace;
2use either::Either;
3use std::borrow::Borrow;
4use std::collections::HashMap;
5use std::fmt::{self, Display};
6use std::hash::Hash;
7use std::ops::Deref;
8use std::sync::Arc;
9
10#[derive(PartialEq, Eq, Clone, Debug, Hash)]
12#[allow(non_camel_case_types)]
13pub enum Type {
14 VoidType,
16 IntegerType { bits: u32 },
18 #[cfg(feature = "llvm-14-or-lower")]
20 PointerType {
21 pointee_type: TypeRef,
22 addr_space: AddrSpace,
23 },
24 #[cfg(feature = "llvm-15-or-greater")]
27 PointerType { addr_space: AddrSpace },
28 FPType(FPType),
30 FuncType {
32 result_type: TypeRef,
33 param_types: Vec<TypeRef>,
34 is_var_arg: bool,
35 },
36 VectorType {
40 element_type: TypeRef,
41 num_elements: usize,
42 #[cfg(feature = "llvm-11-or-greater")]
43 scalable: bool,
44 },
45 ArrayType {
49 element_type: TypeRef,
50 num_elements: usize,
51 },
52 StructType {
55 element_types: Vec<TypeRef>,
56 is_packed: bool,
57 },
58 NamedStructType {
62 name: String, },
65 X86_MMXType,
67 #[cfg(feature = "llvm-12-or-greater")]
70 X86_AMXType,
71 MetadataType,
73 LabelType,
76 TokenType,
78 #[cfg(feature = "llvm-16-or-greater")]
84 TargetExtType, }
86
87impl Display for Type {
88 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89 match self {
90 Type::VoidType => write!(f, "void"),
91 Type::IntegerType { bits } => write!(f, "i{}", bits),
92 #[cfg(feature = "llvm-14-or-lower")]
93 Type::PointerType { pointee_type, .. } => write!(f, "{}*", pointee_type),
94 #[cfg(feature = "llvm-15-or-greater")]
95 Type::PointerType { .. } => write!(f, "ptr"),
96 Type::FPType(fpt) => write!(f, "{}", fpt),
97 Type::FuncType {
98 result_type,
99 param_types,
100 is_var_arg,
101 } => {
102 write!(f, "{} (", result_type)?;
103 for (i, param_ty) in param_types.iter().enumerate() {
104 if i == param_types.len() - 1 {
105 write!(f, "{}", param_ty)?;
106 } else {
107 write!(f, "{}, ", param_ty)?;
108 }
109 }
110 if *is_var_arg {
111 write!(f, ", ...")?;
112 }
113 write!(f, ")")?;
114 Ok(())
115 },
116 Type::VectorType {
117 element_type,
118 num_elements,
119 #[cfg(feature = "llvm-11-or-greater")]
120 scalable,
121 } => {
122 #[cfg(feature = "llvm-11-or-greater")]
123 if *scalable {
124 write!(f, "<vscale x {} x {}>", num_elements, element_type)
125 } else {
126 write!(f, "<{} x {}>", num_elements, element_type)
127 }
128 #[cfg(feature = "llvm-10-or-lower")]
129 write!(f, "<{} x {}>", num_elements, element_type)
130 },
131 Type::ArrayType {
132 element_type,
133 num_elements,
134 } => write!(f, "[{} x {}]", num_elements, element_type),
135 Type::StructType {
136 element_types,
137 is_packed,
138 } => {
139 if *is_packed {
140 write!(f, "<")?;
141 }
142 write!(f, "{{ ")?;
143 for (i, element_ty) in element_types.iter().enumerate() {
144 if i == element_types.len() - 1 {
145 write!(f, "{}", element_ty)?;
146 } else {
147 write!(f, "{}, ", element_ty)?;
148 }
149 }
150 write!(f, " }}")?;
151 if *is_packed {
152 write!(f, ">")?;
153 }
154 Ok(())
155 },
156 Type::NamedStructType { name } => write!(f, "%{}", name),
157 Type::X86_MMXType => write!(f, "x86_mmx"),
158 #[cfg(feature = "llvm-12-or-greater")]
159 Type::X86_AMXType => write!(f, "x86_amx"),
160 Type::MetadataType => write!(f, "metadata"),
161 Type::LabelType => write!(f, "label"),
162 Type::TokenType => write!(f, "token"),
163 #[cfg(feature = "llvm-16-or-greater")]
164 Type::TargetExtType => write!(f, "target()"),
165 }
180 }
181}
182
183#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
185#[allow(non_camel_case_types)]
186pub enum FPType {
187 Half,
188 #[cfg(feature = "llvm-11-or-greater")]
189 BFloat,
190 Single,
191 Double,
192 FP128,
193 X86_FP80,
194 PPC_FP128,
195}
196
197impl From<FPType> for Type {
198 fn from(fpt: FPType) -> Type {
199 Type::FPType(fpt)
200 }
201}
202
203impl Display for FPType {
204 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
205 match self {
206 FPType::Half => write!(f, "half"),
207 #[cfg(feature = "llvm-11-or-greater")]
208 FPType::BFloat => write!(f, "bfloat"),
209 FPType::Single => write!(f, "float"),
210 FPType::Double => write!(f, "double"),
211 FPType::FP128 => write!(f, "fp128"),
212 FPType::X86_FP80 => write!(f, "x86_fp80"),
213 FPType::PPC_FP128 => write!(f, "ppc_fp128"),
214 }
215 }
216}
217
218#[derive(PartialEq, Eq, Clone, Debug, Hash)]
227pub struct TypeRef(Arc<Type>);
228
229impl AsRef<Type> for TypeRef {
230 fn as_ref(&self) -> &Type {
231 self.0.as_ref()
232 }
233}
234
235impl Deref for TypeRef {
236 type Target = Type;
237
238 fn deref(&self) -> &Type {
239 self.0.deref()
240 }
241}
242
243impl Display for TypeRef {
244 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
245 write!(f, "{}", &self.0)
246 }
247}
248
249impl TypeRef {
250 fn new(ty: Type) -> Self {
253 Self(Arc::new(ty))
254 }
255}
256
257pub trait Typed {
259 fn get_type(&self, types: &Types) -> TypeRef;
260}
261
262impl Typed for TypeRef {
263 fn get_type(&self, _types: &Types) -> TypeRef {
264 self.clone()
265 }
266}
267
268impl Typed for Type {
269 fn get_type(&self, types: &Types) -> TypeRef {
270 types.get_for_type(self)
271 }
272}
273
274impl Typed for FPType {
275 fn get_type(&self, types: &Types) -> TypeRef {
276 types.fp(*self)
277 }
278}
279
280impl<A, B> Typed for Either<A, B>
281where
282 A: Typed,
283 B: Typed,
284{
285 fn get_type(&self, types: &Types) -> TypeRef {
286 match self {
287 Either::Left(x) => types.type_of(x),
288 Either::Right(y) => types.type_of(y),
289 }
290 }
291}
292
293#[derive(Clone)]
296pub(crate) struct TypesBuilder {
297 void_type: TypeRef,
299 int_types: TypeCache<u32>,
301 #[cfg(feature = "llvm-14-or-lower")]
303 pointer_types: TypeCache<(TypeRef, AddrSpace)>,
304 #[cfg(feature = "llvm-15-or-greater")]
306 pointer_types: TypeCache<AddrSpace>,
307 fp_types: TypeCache<FPType>,
309 func_types: TypeCache<(TypeRef, Vec<TypeRef>, bool)>,
311 vec_types: TypeCache<(TypeRef, usize, bool)>,
313 arr_types: TypeCache<(TypeRef, usize)>,
315 struct_types: TypeCache<(Vec<TypeRef>, bool)>,
317 named_struct_types: TypeCache<String>,
319 named_struct_defs: HashMap<String, NamedStructDef>,
321 x86_mmx_type: TypeRef,
323 #[cfg(feature = "llvm-12-or-greater")]
325 x86_amx_type: TypeRef,
326 metadata_type: TypeRef,
328 label_type: TypeRef,
330 token_type: TypeRef,
332 #[cfg(feature = "llvm-16-or-greater")]
335 target_ext_type: TypeRef,
336 llvm_type_map: HashMap<LLVMTypeRef, TypeRef>,
339}
340
341impl TypesBuilder {
342 pub fn new() -> Self {
343 Self {
344 void_type: TypeRef::new(Type::VoidType),
345 int_types: TypeCache::new(),
346 pointer_types: TypeCache::new(),
347 fp_types: TypeCache::new(),
348 func_types: TypeCache::new(),
349 vec_types: TypeCache::new(),
350 arr_types: TypeCache::new(),
351 struct_types: TypeCache::new(),
352 named_struct_types: TypeCache::new(),
353 named_struct_defs: HashMap::new(),
354 x86_mmx_type: TypeRef::new(Type::X86_MMXType),
355 #[cfg(feature = "llvm-12-or-greater")]
356 x86_amx_type: TypeRef::new(Type::X86_AMXType),
357 metadata_type: TypeRef::new(Type::MetadataType),
358 label_type: TypeRef::new(Type::LabelType),
359 token_type: TypeRef::new(Type::TokenType),
360 #[cfg(feature = "llvm-16-or-greater")]
361 target_ext_type: TypeRef::new(Type::TargetExtType),
362 llvm_type_map: HashMap::new(),
363 }
364 }
365
366 pub fn build(self) -> Types {
370 Types {
371 void_type: self.void_type,
372 int_types: self.int_types,
373 pointer_types: self.pointer_types,
374 fp_types: self.fp_types,
375 func_types: self.func_types,
376 vec_types: self.vec_types,
377 arr_types: self.arr_types,
378 struct_types: self.struct_types,
379 named_struct_types: self.named_struct_types,
380 named_struct_defs: self.named_struct_defs,
381 x86_mmx_type: self.x86_mmx_type,
382 #[cfg(feature = "llvm-12-or-greater")]
383 x86_amx_type: self.x86_amx_type,
384 metadata_type: self.metadata_type,
385 label_type: self.label_type,
386 token_type: self.token_type,
387 #[cfg(feature = "llvm-16-or-greater")]
388 target_ext_type: self.target_ext_type,
389 }
390 }
391}
392
393#[allow(dead_code)]
395impl TypesBuilder {
396 pub fn void(&self) -> TypeRef {
398 self.void_type.clone()
399 }
400
401 pub fn int(&mut self, bits: u32) -> TypeRef {
403 self.int_types
404 .lookup_or_insert(bits, || Type::IntegerType { bits })
405 }
406
407 pub fn bool(&mut self) -> TypeRef {
409 self.int(1)
410 }
411
412 pub fn i8(&mut self) -> TypeRef {
414 self.int(8)
415 }
416
417 pub fn i16(&mut self) -> TypeRef {
419 self.int(16)
420 }
421
422 pub fn i32(&mut self) -> TypeRef {
424 self.int(32)
425 }
426
427 pub fn i64(&mut self) -> TypeRef {
429 self.int(64)
430 }
431
432 #[cfg(feature = "llvm-14-or-lower")]
434 pub fn pointer_to(&mut self, pointee_type: TypeRef) -> TypeRef {
435 self.pointer_in_addr_space(pointee_type, 0) }
437 #[cfg(feature = "llvm-15-or-greater")]
439 pub fn pointer(&mut self) -> TypeRef {
440 self.pointer_in_addr_space(0) }
442
443 #[cfg(feature = "llvm-14-or-lower")]
445 pub fn pointer_in_addr_space(
446 &mut self,
447 pointee_type: TypeRef,
448 addr_space: AddrSpace,
449 ) -> TypeRef {
450 self.pointer_types
451 .lookup_or_insert((pointee_type.clone(), addr_space), || Type::PointerType {
452 pointee_type,
453 addr_space,
454 })
455 }
456 #[cfg(feature = "llvm-15-or-greater")]
458 pub fn pointer_in_addr_space(&mut self, addr_space: AddrSpace) -> TypeRef {
459 self.pointer_types
460 .lookup_or_insert(addr_space, || Type::PointerType { addr_space })
461 }
462
463 pub fn fp(&mut self, fpt: FPType) -> TypeRef {
465 self.fp_types.lookup_or_insert(fpt, || Type::FPType(fpt))
466 }
467
468 pub fn single(&mut self) -> TypeRef {
470 self.fp(FPType::Single)
471 }
472
473 pub fn double(&mut self) -> TypeRef {
475 self.fp(FPType::Double)
476 }
477
478 pub fn func_type(
480 &mut self,
481 result_type: TypeRef,
482 param_types: Vec<TypeRef>,
483 is_var_arg: bool,
484 ) -> TypeRef {
485 self.func_types.lookup_or_insert(
486 (result_type.clone(), param_types.clone(), is_var_arg),
487 || Type::FuncType {
488 result_type,
489 param_types,
490 is_var_arg,
491 },
492 )
493 }
494
495 #[cfg(feature = "llvm-11-or-greater")]
497 pub fn vector_of(
498 &mut self,
499 element_type: TypeRef,
500 num_elements: usize,
501 scalable: bool,
502 ) -> TypeRef {
503 self.vec_types
504 .lookup_or_insert((element_type.clone(), num_elements, scalable), || {
505 Type::VectorType {
506 element_type,
507 num_elements,
508 scalable,
509 }
510 })
511 }
512 #[cfg(feature = "llvm-10-or-lower")]
514 pub fn vector_of(&mut self, element_type: TypeRef, num_elements: usize) -> TypeRef {
515 self.vec_types
516 .lookup_or_insert((element_type.clone(), num_elements, false), || {
517 Type::VectorType {
518 element_type,
519 num_elements,
520 }
521 })
522 }
523
524 pub fn array_of(&mut self, element_type: TypeRef, num_elements: usize) -> TypeRef {
526 self.arr_types
527 .lookup_or_insert((element_type.clone(), num_elements), || Type::ArrayType {
528 element_type,
529 num_elements,
530 })
531 }
532
533 pub fn struct_of(&mut self, element_types: Vec<TypeRef>, is_packed: bool) -> TypeRef {
535 self.struct_types
536 .lookup_or_insert((element_types.clone(), is_packed), || Type::StructType {
537 element_types,
538 is_packed,
539 })
540 }
541
542 pub fn named_struct(&mut self, name: String) -> TypeRef {
548 self.named_struct_types
549 .lookup_or_insert(name.clone(), || Type::NamedStructType { name })
550 }
551
552 pub fn named_struct_def(&self, name: &str) -> &NamedStructDef {
559 self.named_struct_defs
560 .get(name)
561 .expect("Named struct has not been defined")
562 }
563
564 pub fn add_named_struct_def(&mut self, name: String, def: NamedStructDef) {
568 match self.named_struct_defs.entry(name) {
569 Entry::Occupied(_) => {
570 panic!("Trying to redefine named struct");
571 },
572 Entry::Vacant(ventry) => {
573 ventry.insert(def);
574 },
575 }
576 }
577
578 pub fn x86_mmx(&self) -> TypeRef {
580 self.x86_mmx_type.clone()
581 }
582
583 #[cfg(feature = "llvm-12-or-greater")]
585 pub fn x86_amx(&self) -> TypeRef {
586 self.x86_amx_type.clone()
587 }
588
589 pub fn metadata_type(&self) -> TypeRef {
591 self.metadata_type.clone()
592 }
593
594 pub fn label_type(&self) -> TypeRef {
596 self.label_type.clone()
597 }
598
599 pub fn token_type(&self) -> TypeRef {
601 self.token_type.clone()
602 }
603
604 #[cfg(feature = "llvm-16-or-greater")]
606 pub fn target_ext_type(
607 &mut self,
608 ) -> TypeRef {
612 self.target_ext_type.clone()
613 }
614}
615
616#[derive(Clone, Debug, Hash)]
617pub enum NamedStructDef {
618 Opaque,
620 Defined(TypeRef),
622}
623
624#[derive(Clone)]
638pub struct Types {
639 void_type: TypeRef,
641 int_types: TypeCache<u32>,
643 #[cfg(feature = "llvm-14-or-lower")]
645 pointer_types: TypeCache<(TypeRef, AddrSpace)>,
646 #[cfg(feature = "llvm-15-or-greater")]
648 pointer_types: TypeCache<AddrSpace>,
649 fp_types: TypeCache<FPType>,
651 func_types: TypeCache<(TypeRef, Vec<TypeRef>, bool)>,
653 vec_types: TypeCache<(TypeRef, usize, bool)>,
656 arr_types: TypeCache<(TypeRef, usize)>,
658 struct_types: TypeCache<(Vec<TypeRef>, bool)>,
660 named_struct_types: TypeCache<String>,
662 named_struct_defs: HashMap<String, NamedStructDef>,
664 x86_mmx_type: TypeRef,
666 #[cfg(feature = "llvm-12-or-greater")]
668 x86_amx_type: TypeRef,
669 metadata_type: TypeRef,
671 label_type: TypeRef,
673 token_type: TypeRef,
675 #[cfg(feature = "llvm-16-or-greater")]
677 target_ext_type: TypeRef,
678}
679
680impl Types {
681 pub fn type_of<T: Typed + ?Sized>(&self, t: &T) -> TypeRef {
683 t.get_type(self)
684 }
685
686 pub fn void(&self) -> TypeRef {
688 self.void_type.clone()
689 }
690
691 pub fn int(&self, bits: u32) -> TypeRef {
693 self.int_types
694 .lookup(&bits)
695 .unwrap_or_else(|| TypeRef::new(Type::IntegerType { bits }))
696 }
697
698 pub fn bool(&self) -> TypeRef {
700 self.int(1)
701 }
702
703 pub fn i8(&self) -> TypeRef {
705 self.int(8)
706 }
707
708 pub fn i16(&self) -> TypeRef {
710 self.int(16)
711 }
712
713 pub fn i32(&self) -> TypeRef {
715 self.int(32)
716 }
717
718 pub fn i64(&self) -> TypeRef {
720 self.int(64)
721 }
722
723 #[cfg(feature = "llvm-14-or-lower")]
725 pub fn pointer_to(&self, pointee_type: TypeRef) -> TypeRef {
726 self.pointer_in_addr_space(pointee_type, 0)
727 }
728 #[cfg(feature = "llvm-15-or-greater")]
730 pub fn pointer(&self) -> TypeRef {
731 self.pointer_in_addr_space(0)
732 }
733
734 #[cfg(feature = "llvm-14-or-lower")]
736 pub fn pointer_in_addr_space(&self, pointee_type: TypeRef, addr_space: AddrSpace) -> TypeRef {
737 self.pointer_types
738 .lookup(&(pointee_type.clone(), addr_space))
739 .unwrap_or_else(|| {
740 TypeRef::new(Type::PointerType {
741 pointee_type,
742 addr_space,
743 })
744 })
745 }
746 #[cfg(feature = "llvm-15-or-greater")]
748 pub fn pointer_in_addr_space(&self, addr_space: AddrSpace) -> TypeRef {
749 self.pointer_types
750 .lookup(&addr_space)
751 .unwrap_or_else(|| TypeRef::new(Type::PointerType { addr_space }))
752 }
753
754 pub fn fp(&self, fpt: FPType) -> TypeRef {
756 self.fp_types
757 .lookup(&fpt)
758 .unwrap_or_else(|| TypeRef::new(Type::FPType(fpt)))
759 }
760
761 pub fn single(&self) -> TypeRef {
763 self.fp(FPType::Single)
764 }
765
766 pub fn double(&self) -> TypeRef {
768 self.fp(FPType::Double)
769 }
770
771 pub fn func_type(
773 &self,
774 result_type: TypeRef,
775 param_types: Vec<TypeRef>,
776 is_var_arg: bool,
777 ) -> TypeRef {
778 self.func_types
779 .lookup(&(result_type.clone(), param_types.clone(), is_var_arg))
780 .unwrap_or_else(|| {
781 TypeRef::new(Type::FuncType {
782 result_type,
783 param_types,
784 is_var_arg,
785 })
786 })
787 }
788
789 #[cfg(feature = "llvm-11-or-greater")]
791 pub fn vector_of(&self, element_type: TypeRef, num_elements: usize, scalable: bool) -> TypeRef {
792 self.vec_types
793 .lookup(&(element_type.clone(), num_elements, scalable))
794 .unwrap_or_else(|| {
795 TypeRef::new(Type::VectorType {
796 element_type,
797 num_elements,
798 scalable,
799 })
800 })
801 }
802 #[cfg(feature = "llvm-10-or-lower")]
803 pub fn vector_of(&self, element_type: TypeRef, num_elements: usize) -> TypeRef {
804 self.vec_types
805 .lookup(&(element_type.clone(), num_elements, false))
806 .unwrap_or_else(|| {
807 TypeRef::new(Type::VectorType {
808 element_type,
809 num_elements,
810 })
811 })
812 }
813
814 pub fn array_of(&self, element_type: TypeRef, num_elements: usize) -> TypeRef {
816 self.arr_types
817 .lookup(&(element_type.clone(), num_elements))
818 .unwrap_or_else(|| {
819 TypeRef::new(Type::ArrayType {
820 element_type,
821 num_elements,
822 })
823 })
824 }
825
826 pub fn struct_of(&self, element_types: Vec<TypeRef>, is_packed: bool) -> TypeRef {
828 self.struct_types
829 .lookup(&(element_types.clone(), is_packed))
830 .unwrap_or_else(|| {
831 TypeRef::new(Type::StructType {
832 element_types,
833 is_packed,
834 })
835 })
836 }
837
838 pub fn named_struct(&self, name: &str) -> TypeRef {
844 self.named_struct_types
845 .lookup(name)
846 .unwrap_or_else(|| TypeRef::new(Type::NamedStructType { name: name.into() }))
847 }
848
849 pub fn named_struct_def(&self, name: &str) -> Option<&NamedStructDef> {
855 self.named_struct_defs.get(name)
856 }
857
858 pub fn all_struct_names(&self) -> impl Iterator<Item = &String> {
860 self.named_struct_defs.keys()
861 }
862
863 pub fn add_named_struct_def(&mut self, name: String, def: NamedStructDef) {
867 match self.named_struct_defs.entry(name) {
868 Entry::Occupied(_) => {
869 panic!("Trying to redefine named struct");
870 },
871 Entry::Vacant(ventry) => {
872 ventry.insert(def);
873 },
874 }
875 }
876
877 pub fn remove_named_struct_def(&mut self, name: &str) -> bool {
882 self.named_struct_defs.remove(name).is_some()
883 }
884
885 pub fn x86_mmx(&self) -> TypeRef {
887 self.x86_mmx_type.clone()
888 }
889
890 #[cfg(feature = "llvm-12-or-greater")]
892 pub fn x86_amx(&self) -> TypeRef {
893 self.x86_amx_type.clone()
894 }
895
896 pub fn metadata_type(&self) -> TypeRef {
898 self.metadata_type.clone()
899 }
900
901 pub fn label_type(&self) -> TypeRef {
903 self.label_type.clone()
904 }
905
906 pub fn token_type(&self) -> TypeRef {
908 self.token_type.clone()
909 }
910
911 #[cfg(feature = "llvm-16-or-greater")]
914 pub fn target_ext_type(
915 &self,
916 ) -> TypeRef {
920 self.target_ext_type.clone()
921 }
922
923 #[rustfmt::skip] pub fn get_for_type(&self, ty: &Type) -> TypeRef {
926 match ty {
927 Type::VoidType => self.void(),
928 Type::IntegerType{ bits } => self.int(*bits),
929 #[cfg(feature = "llvm-14-or-lower")]
930 Type::PointerType { pointee_type, addr_space } => {
931 self.pointer_in_addr_space(pointee_type.clone(), *addr_space)
932 },
933 #[cfg(feature = "llvm-15-or-greater")]
934 Type::PointerType { addr_space } => {
935 self.pointer_in_addr_space(*addr_space)
936 },
937 Type::FPType(fpt) => self.fp(*fpt),
938 Type::FuncType { result_type, param_types, is_var_arg } => {
939 self.func_type(result_type.clone(), param_types.clone(), *is_var_arg)
940 },
941 #[cfg(feature="llvm-11-or-greater")]
942 Type::VectorType { element_type, num_elements, scalable } => {
943 self.vector_of(element_type.clone(), *num_elements, *scalable)
944 },
945 #[cfg(feature="llvm-10-or-lower")]
946 Type::VectorType { element_type, num_elements } => {
947 self.vector_of(element_type.clone(), *num_elements)
948 },
949 Type::ArrayType { element_type, num_elements } => {
950 self.array_of(element_type.clone(), *num_elements)
951 },
952 Type::StructType { element_types, is_packed } => {
953 self.struct_of(element_types.clone(), *is_packed)
954 },
955 Type::NamedStructType { name } => self.named_struct(name),
956 Type::X86_MMXType => self.x86_mmx(),
957 #[cfg(feature="llvm-12-or-greater")]
958 Type::X86_AMXType => self.x86_amx(),
959 Type::MetadataType => self.metadata_type(),
960 Type::LabelType => self.label_type(),
961 Type::TokenType => self.token_type(),
962 #[cfg(feature="llvm-16-or-greater")]
963 Type::TargetExtType => self.target_ext_type(),
964 }
965 }
966}
967
968impl Types {
969 pub fn blank_for_testing() -> Self {
973 TypesBuilder::new().build()
974 }
975}
976
977#[derive(Clone, Debug)]
978struct TypeCache<K: Eq + Hash + Clone> {
979 map: HashMap<K, TypeRef>,
980}
981
982#[allow(dead_code)]
983impl<K: Eq + Hash + Clone> TypeCache<K> {
984 fn new() -> Self {
985 Self {
986 map: HashMap::new(),
987 }
988 }
989
990 fn lookup<Q: ?Sized>(&self, key: &Q) -> Option<TypeRef>
993 where
994 K: Borrow<Q>,
995 Q: Hash + Eq,
996 {
997 self.map.get(key).cloned()
998 }
999
1000 fn lookup_or_insert(&mut self, key: K, if_missing: impl FnOnce() -> Type) -> TypeRef {
1004 self.map
1005 .entry(key)
1006 .or_insert_with(|| TypeRef::new(if_missing()))
1007 .clone()
1008 }
1009
1010 fn contains_key(&self, key: &K) -> bool {
1012 self.map.contains_key(key)
1013 }
1014}
1015
1016use crate::from_llvm::*;
1021use crate::llvm_sys::*;
1022use llvm_sys::LLVMTypeKind;
1023use std::collections::hash_map::Entry;
1024
1025impl TypesBuilder {
1026 pub(crate) fn type_from_llvm_ref(&mut self, ty: LLVMTypeRef) -> TypeRef {
1027 if let Some(typeref) = self.llvm_type_map.get(&ty) {
1028 return typeref.clone();
1029 }
1030 let typeref = self.parse_type_from_llvm_ref(ty);
1031 self.llvm_type_map.insert(ty, typeref.clone());
1032 typeref
1033 }
1034
1035 fn parse_type_from_llvm_ref(&mut self, ty: LLVMTypeRef) -> TypeRef {
1036 let kind = unsafe { LLVMGetTypeKind(ty) };
1037 match kind {
1038 LLVMTypeKind::LLVMVoidTypeKind => self.void(),
1039 LLVMTypeKind::LLVMIntegerTypeKind => self.int(unsafe { LLVMGetIntTypeWidth(ty) }),
1040 #[cfg(feature = "llvm-14-or-lower")]
1041 LLVMTypeKind::LLVMPointerTypeKind => {
1042 let pointee_type = self.type_from_llvm_ref(unsafe { LLVMGetElementType(ty) });
1043 self.pointer_in_addr_space(pointee_type, unsafe { LLVMGetPointerAddressSpace(ty) })
1044 },
1045 #[cfg(feature = "llvm-15-or-greater")]
1046 LLVMTypeKind::LLVMPointerTypeKind => {
1047 self.pointer_in_addr_space(unsafe { LLVMGetPointerAddressSpace(ty) })
1048 },
1049 LLVMTypeKind::LLVMArrayTypeKind => {
1050 let element_type = self.type_from_llvm_ref(unsafe { LLVMGetElementType(ty) });
1051
1052 #[cfg(feature = "llvm-16-or-lower")]
1056 let array_len = unsafe { LLVMGetArrayLength(ty) as usize };
1057 #[cfg(feature = "llvm-17-or-greater")]
1058 let array_len = unsafe { LLVMGetArrayLength2(ty) as usize };
1059
1060 self.array_of(element_type, array_len)
1061 },
1062 LLVMTypeKind::LLVMVectorTypeKind => {
1063 let element_type = self.type_from_llvm_ref(unsafe { LLVMGetElementType(ty) });
1064 #[cfg(feature = "llvm-11-or-greater")]
1065 let ret = self.vector_of(
1066 element_type,
1067 unsafe { LLVMGetVectorSize(ty) as usize },
1068 false,
1069 );
1070 #[cfg(feature = "llvm-10-or-lower")]
1071 let ret = self.vector_of(element_type, unsafe { LLVMGetVectorSize(ty) as usize });
1072 ret
1073 },
1074 #[cfg(feature = "llvm-11-or-greater")]
1075 LLVMTypeKind::LLVMScalableVectorTypeKind => {
1076 let element_type = self.type_from_llvm_ref(unsafe { LLVMGetElementType(ty) });
1077 self.vector_of(
1078 element_type,
1079 unsafe { LLVMGetVectorSize(ty) as usize },
1080 true,
1081 )
1082 },
1083 LLVMTypeKind::LLVMStructTypeKind => {
1084 let name = if unsafe { LLVMIsLiteralStruct(ty) } != 0 {
1085 None
1086 } else {
1087 unsafe { get_struct_name(ty) }
1088 };
1089
1090 match name {
1091 Some(s) if !s.is_empty() => {
1092 if self.named_struct_types.contains_key(&s) {
1093 self.named_struct(s)
1095 } else if unsafe { LLVMIsOpaqueStruct(ty) } != 0 {
1096 self.add_named_struct_def(s.clone(), NamedStructDef::Opaque);
1098 self.named_struct(s)
1100 } else {
1101 let named_struct_typeref = self.named_struct(s.clone());
1103 let actual_struct_type = self.struct_type_from_llvm_ref(ty);
1105 self.add_named_struct_def(
1107 s,
1108 NamedStructDef::Defined(actual_struct_type),
1109 );
1110 named_struct_typeref
1112 }
1113 },
1114 _ => self.struct_type_from_llvm_ref(ty),
1115 }
1116 },
1117 LLVMTypeKind::LLVMFunctionTypeKind => {
1118 let result_type = self.type_from_llvm_ref(unsafe { LLVMGetReturnType(ty) });
1119 let param_types = {
1120 let num_types = unsafe { LLVMCountParamTypes(ty) };
1121 let mut types: Vec<LLVMTypeRef> = Vec::with_capacity(num_types as usize);
1122 unsafe {
1123 LLVMGetParamTypes(ty, types.as_mut_ptr());
1124 types.set_len(num_types as usize);
1125 };
1126 types
1127 .into_iter()
1128 .map(|t| self.type_from_llvm_ref(t))
1129 .collect()
1130 };
1131 self.func_type(
1132 result_type,
1133 param_types,
1134 unsafe { LLVMIsFunctionVarArg(ty) } != 0,
1135 )
1136 },
1137 LLVMTypeKind::LLVMHalfTypeKind => self.fp(FPType::Half),
1138 #[cfg(feature = "llvm-11-or-greater")]
1139 LLVMTypeKind::LLVMBFloatTypeKind => self.fp(FPType::BFloat),
1140 LLVMTypeKind::LLVMFloatTypeKind => self.fp(FPType::Single),
1141 LLVMTypeKind::LLVMDoubleTypeKind => self.fp(FPType::Double),
1142 LLVMTypeKind::LLVMFP128TypeKind => self.fp(FPType::FP128),
1143 LLVMTypeKind::LLVMX86_FP80TypeKind => self.fp(FPType::X86_FP80),
1144 LLVMTypeKind::LLVMPPC_FP128TypeKind => self.fp(FPType::PPC_FP128),
1145 LLVMTypeKind::LLVMX86_MMXTypeKind => self.x86_mmx(),
1146 #[cfg(feature = "llvm-12-or-greater")]
1147 LLVMTypeKind::LLVMX86_AMXTypeKind => self.x86_amx(),
1148 LLVMTypeKind::LLVMMetadataTypeKind => self.metadata_type(),
1149 LLVMTypeKind::LLVMLabelTypeKind => self.label_type(),
1150 LLVMTypeKind::LLVMTokenTypeKind => self.token_type(),
1151 #[cfg(feature = "llvm-16-or-greater")]
1152 LLVMTypeKind::LLVMTargetExtTypeKind => self.target_ext_type(),
1153 }
1154 }
1155
1156 fn struct_type_from_llvm_ref(&mut self, ty: LLVMTypeRef) -> TypeRef {
1160 if unsafe { LLVMIsOpaqueStruct(ty) } != 0 {
1161 panic!(
1162 "struct_type_from_llvm_ref: shouldn't pass an opaque struct type to this function"
1163 );
1164 }
1165 let element_types = {
1166 let num_types = unsafe { LLVMCountStructElementTypes(ty) };
1167 let mut types: Vec<LLVMTypeRef> = Vec::with_capacity(num_types as usize);
1168 unsafe {
1169 LLVMGetStructElementTypes(ty, types.as_mut_ptr());
1170 types.set_len(num_types as usize);
1171 };
1172 types
1173 .into_iter()
1174 .map(|t| self.type_from_llvm_ref(t))
1175 .collect()
1176 };
1177 self.struct_of(element_types, unsafe { LLVMIsPackedStruct(ty) } != 0)
1178 }
1179}