inkwell/types/
enums.rs

1use llvm_sys::core::LLVMGetTypeKind;
2use llvm_sys::prelude::LLVMTypeRef;
3use llvm_sys::LLVMTypeKind;
4
5use crate::support::LLVMString;
6use crate::types::traits::AsTypeRef;
7use crate::types::MetadataType;
8use crate::types::{
9    ArrayType, FloatType, FunctionType, IntType, PointerType, ScalableVectorType, StructType, VectorType, VoidType,
10};
11use crate::values::{BasicValue, BasicValueEnum, IntValue};
12
13use std::convert::TryFrom;
14use std::fmt::{self, Display};
15
16macro_rules! enum_type_set {
17    ($(#[$enum_attrs:meta])* $enum_name:ident: { $($(#[$variant_attrs:meta])* $args:ident,)+ }) => (
18        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
19        $(#[$enum_attrs])*
20        pub enum $enum_name<'ctx> {
21            $(
22                $(#[$variant_attrs])*
23                $args($args<'ctx>),
24            )*
25        }
26
27        unsafe impl AsTypeRef for $enum_name<'_> {
28            fn as_type_ref(&self) -> LLVMTypeRef {
29                match *self {
30                    $(
31                        $enum_name::$args(ref t) => t.as_type_ref(),
32                    )*
33                }
34            }
35        }
36
37        $(
38            impl<'ctx> From<$args<'ctx>> for $enum_name<'ctx> {
39                fn from(value: $args) -> $enum_name {
40                    $enum_name::$args(value)
41                }
42            }
43
44            impl<'ctx> TryFrom<$enum_name<'ctx>> for $args<'ctx> {
45                type Error = ();
46
47                fn try_from(value: $enum_name<'ctx>) -> Result<Self, Self::Error> {
48                    match value {
49                        $enum_name::$args(ty) => Ok(ty),
50                        _ => Err(()),
51                    }
52                }
53            }
54        )*
55    );
56}
57
58enum_type_set! {
59    /// A wrapper for any `BasicType`, `VoidType`, or `FunctionType`.
60    AnyTypeEnum: {
61        /// A contiguous homogeneous container type.
62        ArrayType,
63        /// A floating point type.
64        FloatType,
65        /// A function return and parameter definition.
66        FunctionType,
67        /// An integer type.
68        IntType,
69        /// A pointer type.
70        PointerType,
71        /// A contiguous heterogeneous container type.
72        StructType,
73        /// A contiguous homogeneous "SIMD" container type.
74        VectorType,
75        /// A contiguous homogeneous scalable "SIMD" container type.
76        ScalableVectorType,
77        /// A valueless type.
78        VoidType,
79    }
80}
81enum_type_set! {
82    /// A wrapper for any `BasicType`.
83    BasicTypeEnum: {
84        /// A contiguous homogeneous container type.
85        ArrayType,
86        /// A floating point type.
87        FloatType,
88        /// An integer type.
89        IntType,
90        /// A pointer type.
91        PointerType,
92        /// A contiguous heterogeneous container type.
93        StructType,
94        /// A contiguous homogeneous "SIMD" container type.
95        VectorType,
96        /// A contiguous homogeneous scalable "SIMD" container type.
97        ScalableVectorType,
98    }
99}
100enum_type_set! {
101    BasicMetadataTypeEnum: {
102        ArrayType,
103        FloatType,
104        IntType,
105        PointerType,
106        StructType,
107        VectorType,
108        ScalableVectorType,
109        MetadataType,
110    }
111}
112
113impl<'ctx> BasicMetadataTypeEnum<'ctx> {
114    /// Create [`BasicMetadataTypeEnum`] from [`LLVMTypeRef`].
115    ///
116    /// # Safety
117    ///
118    /// Undefined behavior if the referenced type cannot be represented as [`BasicMetadataTypeEnum`],
119    /// or the underlying pointer is null.
120    ///
121    /// Before LLVM 6, [`BasicMetadataTypeEnum::MetadataType`] variants cannot be created
122    /// with this function. Attempting to do results in undefined behavior.
123    #[llvm_versions(6..)]
124    pub unsafe fn new(type_: LLVMTypeRef) -> Self {
125        match LLVMGetTypeKind(type_) {
126            LLVMTypeKind::LLVMMetadataTypeKind => Self::MetadataType(MetadataType::new(type_)),
127            _ => BasicTypeEnum::new(type_).into(),
128        }
129    }
130
131    #[llvm_versions(..6)]
132    pub unsafe fn new(type_: LLVMTypeRef) -> Self {
133        BasicTypeEnum::new(type_).into()
134    }
135
136    pub fn into_array_type(self) -> ArrayType<'ctx> {
137        if let BasicMetadataTypeEnum::ArrayType(t) = self {
138            t
139        } else {
140            panic!("Found {:?} but expected another variant", self);
141        }
142    }
143
144    pub fn into_float_type(self) -> FloatType<'ctx> {
145        if let BasicMetadataTypeEnum::FloatType(t) = self {
146            t
147        } else {
148            panic!("Found {:?} but expected another variant", self);
149        }
150    }
151
152    pub fn into_int_type(self) -> IntType<'ctx> {
153        if let BasicMetadataTypeEnum::IntType(t) = self {
154            t
155        } else {
156            panic!("Found {:?} but expected another variant", self);
157        }
158    }
159
160    pub fn into_pointer_type(self) -> PointerType<'ctx> {
161        if let BasicMetadataTypeEnum::PointerType(t) = self {
162            t
163        } else {
164            panic!("Found {:?} but expected another variant", self);
165        }
166    }
167
168    pub fn into_struct_type(self) -> StructType<'ctx> {
169        if let BasicMetadataTypeEnum::StructType(t) = self {
170            t
171        } else {
172            panic!("Found {:?} but expected another variant", self);
173        }
174    }
175
176    pub fn into_vector_type(self) -> VectorType<'ctx> {
177        if let BasicMetadataTypeEnum::VectorType(t) = self {
178            t
179        } else {
180            panic!("Found {:?} but expected another variant", self);
181        }
182    }
183
184    pub fn into_scalable_vector_type(self) -> ScalableVectorType<'ctx> {
185        if let BasicMetadataTypeEnum::ScalableVectorType(t) = self {
186            t
187        } else {
188            panic!("Found {:?} but expected another variant", self);
189        }
190    }
191
192    pub fn into_metadata_type(self) -> MetadataType<'ctx> {
193        if let BasicMetadataTypeEnum::MetadataType(t) = self {
194            t
195        } else {
196            panic!("Found {:?} but expected another variant", self);
197        }
198    }
199
200    pub fn is_array_type(self) -> bool {
201        matches!(self, BasicMetadataTypeEnum::ArrayType(_))
202    }
203
204    pub fn is_float_type(self) -> bool {
205        matches!(self, BasicMetadataTypeEnum::FloatType(_))
206    }
207
208    pub fn is_int_type(self) -> bool {
209        matches!(self, BasicMetadataTypeEnum::IntType(_))
210    }
211
212    pub fn is_metadata_type(self) -> bool {
213        matches!(self, BasicMetadataTypeEnum::MetadataType(_))
214    }
215
216    pub fn is_pointer_type(self) -> bool {
217        matches!(self, BasicMetadataTypeEnum::PointerType(_))
218    }
219
220    pub fn is_struct_type(self) -> bool {
221        matches!(self, BasicMetadataTypeEnum::StructType(_))
222    }
223
224    pub fn is_vector_type(self) -> bool {
225        matches!(self, BasicMetadataTypeEnum::VectorType(_))
226    }
227
228    pub fn is_scalable_vector_type(self) -> bool {
229        matches!(self, BasicMetadataTypeEnum::ScalableVectorType(_))
230    }
231
232    /// Print the definition of a `BasicMetadataTypeEnum` to `LLVMString`.
233    pub fn print_to_string(self) -> LLVMString {
234        match self {
235            BasicMetadataTypeEnum::ArrayType(t) => t.print_to_string(),
236            BasicMetadataTypeEnum::IntType(t) => t.print_to_string(),
237            BasicMetadataTypeEnum::FloatType(t) => t.print_to_string(),
238            BasicMetadataTypeEnum::PointerType(t) => t.print_to_string(),
239            BasicMetadataTypeEnum::StructType(t) => t.print_to_string(),
240            BasicMetadataTypeEnum::VectorType(t) => t.print_to_string(),
241            BasicMetadataTypeEnum::ScalableVectorType(t) => t.print_to_string(),
242            BasicMetadataTypeEnum::MetadataType(t) => t.print_to_string(),
243        }
244    }
245}
246
247impl<'ctx> AnyTypeEnum<'ctx> {
248    /// Create `AnyTypeEnum` from [`LLVMTypeRef`]
249    ///
250    /// # Safety
251    /// Undefined behavior, if referenced type isn't part of `AnyTypeEnum`
252    pub unsafe fn new(type_: LLVMTypeRef) -> Self {
253        match LLVMGetTypeKind(type_) {
254            LLVMTypeKind::LLVMVoidTypeKind => AnyTypeEnum::VoidType(VoidType::new(type_)),
255            LLVMTypeKind::LLVMHalfTypeKind
256            | LLVMTypeKind::LLVMFloatTypeKind
257            | LLVMTypeKind::LLVMDoubleTypeKind
258            | LLVMTypeKind::LLVMX86_FP80TypeKind
259            | LLVMTypeKind::LLVMFP128TypeKind
260            | LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
261            #[cfg(any(
262                feature = "llvm11-0",
263                feature = "llvm12-0",
264                feature = "llvm13-0",
265                feature = "llvm14-0",
266                feature = "llvm15-0",
267                feature = "llvm16-0",
268                feature = "llvm17-0",
269                feature = "llvm18-0"
270            ))]
271            LLVMTypeKind::LLVMBFloatTypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
272            LLVMTypeKind::LLVMLabelTypeKind => panic!("FIXME: Unsupported type: Label"),
273            LLVMTypeKind::LLVMIntegerTypeKind => AnyTypeEnum::IntType(IntType::new(type_)),
274            LLVMTypeKind::LLVMFunctionTypeKind => AnyTypeEnum::FunctionType(FunctionType::new(type_)),
275            LLVMTypeKind::LLVMStructTypeKind => AnyTypeEnum::StructType(StructType::new(type_)),
276            LLVMTypeKind::LLVMArrayTypeKind => AnyTypeEnum::ArrayType(ArrayType::new(type_)),
277            LLVMTypeKind::LLVMPointerTypeKind => AnyTypeEnum::PointerType(PointerType::new(type_)),
278            LLVMTypeKind::LLVMVectorTypeKind => AnyTypeEnum::VectorType(VectorType::new(type_)),
279            #[cfg(any(
280                feature = "llvm11-0",
281                feature = "llvm12-0",
282                feature = "llvm13-0",
283                feature = "llvm14-0",
284                feature = "llvm15-0",
285                feature = "llvm16-0",
286                feature = "llvm17-0",
287                feature = "llvm18-0"
288            ))]
289            LLVMTypeKind::LLVMScalableVectorTypeKind => AnyTypeEnum::ScalableVectorType(ScalableVectorType::new(type_)),
290            // FIXME: should inkwell support metadata as AnyType?
291            LLVMTypeKind::LLVMMetadataTypeKind => panic!("Metadata type is not supported as AnyType."),
292            LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("FIXME: Unsupported type: MMX"),
293            #[cfg(any(
294                feature = "llvm12-0",
295                feature = "llvm13-0",
296                feature = "llvm14-0",
297                feature = "llvm15-0",
298                feature = "llvm16-0",
299                feature = "llvm17-0",
300                feature = "llvm18-0"
301            ))]
302            LLVMTypeKind::LLVMX86_AMXTypeKind => panic!("FIXME: Unsupported type: AMX"),
303            LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"),
304            #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
305            LLVMTypeKind::LLVMTargetExtTypeKind => panic!("FIXME: Unsupported type: TargetExt"),
306        }
307    }
308
309    /// This will panic if type is a void or function type.
310    pub(crate) fn as_basic_type_enum(&self) -> BasicTypeEnum<'ctx> {
311        unsafe { BasicTypeEnum::new(self.as_type_ref()) }
312    }
313
314    pub fn into_array_type(self) -> ArrayType<'ctx> {
315        if let AnyTypeEnum::ArrayType(t) = self {
316            t
317        } else {
318            panic!("Found {:?} but expected the ArrayType variant", self);
319        }
320    }
321
322    pub fn into_float_type(self) -> FloatType<'ctx> {
323        if let AnyTypeEnum::FloatType(t) = self {
324            t
325        } else {
326            panic!("Found {:?} but expected the FloatType variant", self);
327        }
328    }
329
330    pub fn into_function_type(self) -> FunctionType<'ctx> {
331        if let AnyTypeEnum::FunctionType(t) = self {
332            t
333        } else {
334            panic!("Found {:?} but expected the FunctionType variant", self);
335        }
336    }
337
338    pub fn into_int_type(self) -> IntType<'ctx> {
339        if let AnyTypeEnum::IntType(t) = self {
340            t
341        } else {
342            panic!("Found {:?} but expected the IntType variant", self);
343        }
344    }
345
346    pub fn into_pointer_type(self) -> PointerType<'ctx> {
347        if let AnyTypeEnum::PointerType(t) = self {
348            t
349        } else {
350            panic!("Found {:?} but expected the PointerType variant", self);
351        }
352    }
353
354    pub fn into_struct_type(self) -> StructType<'ctx> {
355        if let AnyTypeEnum::StructType(t) = self {
356            t
357        } else {
358            panic!("Found {:?} but expected the StructType variant", self);
359        }
360    }
361
362    pub fn into_vector_type(self) -> VectorType<'ctx> {
363        if let AnyTypeEnum::VectorType(t) = self {
364            t
365        } else {
366            panic!("Found {:?} but expected the VectorType variant", self);
367        }
368    }
369
370    pub fn into_scalable_vector_type(self) -> ScalableVectorType<'ctx> {
371        if let AnyTypeEnum::ScalableVectorType(t) = self {
372            t
373        } else {
374            panic!("Found {:?} but expected the ScalableVectorType variant", self);
375        }
376    }
377
378    pub fn into_void_type(self) -> VoidType<'ctx> {
379        if let AnyTypeEnum::VoidType(t) = self {
380            t
381        } else {
382            panic!("Found {:?} but expected the VoidType variant", self);
383        }
384    }
385
386    pub fn is_array_type(self) -> bool {
387        matches!(self, AnyTypeEnum::ArrayType(_))
388    }
389
390    pub fn is_float_type(self) -> bool {
391        matches!(self, AnyTypeEnum::FloatType(_))
392    }
393
394    pub fn is_function_type(self) -> bool {
395        matches!(self, AnyTypeEnum::FunctionType(_))
396    }
397
398    pub fn is_int_type(self) -> bool {
399        matches!(self, AnyTypeEnum::IntType(_))
400    }
401
402    pub fn is_pointer_type(self) -> bool {
403        matches!(self, AnyTypeEnum::PointerType(_))
404    }
405
406    pub fn is_struct_type(self) -> bool {
407        matches!(self, AnyTypeEnum::StructType(_))
408    }
409
410    pub fn is_vector_type(self) -> bool {
411        matches!(self, AnyTypeEnum::VectorType(_))
412    }
413
414    pub fn is_void_type(self) -> bool {
415        matches!(self, AnyTypeEnum::VoidType(_))
416    }
417
418    pub fn size_of(&self) -> Option<IntValue<'ctx>> {
419        match self {
420            AnyTypeEnum::ArrayType(t) => t.size_of(),
421            AnyTypeEnum::FloatType(t) => Some(t.size_of()),
422            AnyTypeEnum::IntType(t) => Some(t.size_of()),
423            AnyTypeEnum::PointerType(t) => Some(t.size_of()),
424            AnyTypeEnum::StructType(t) => t.size_of(),
425            AnyTypeEnum::VectorType(t) => t.size_of(),
426            AnyTypeEnum::ScalableVectorType(t) => t.size_of(),
427            AnyTypeEnum::VoidType(_) => None,
428            AnyTypeEnum::FunctionType(_) => None,
429        }
430    }
431
432    /// Print the definition of a `AnyTypeEnum` to `LLVMString`.
433    pub fn print_to_string(self) -> LLVMString {
434        match self {
435            AnyTypeEnum::ArrayType(t) => t.print_to_string(),
436            AnyTypeEnum::FloatType(t) => t.print_to_string(),
437            AnyTypeEnum::IntType(t) => t.print_to_string(),
438            AnyTypeEnum::PointerType(t) => t.print_to_string(),
439            AnyTypeEnum::StructType(t) => t.print_to_string(),
440            AnyTypeEnum::VectorType(t) => t.print_to_string(),
441            AnyTypeEnum::ScalableVectorType(t) => t.print_to_string(),
442            AnyTypeEnum::VoidType(t) => t.print_to_string(),
443            AnyTypeEnum::FunctionType(t) => t.print_to_string(),
444        }
445    }
446}
447
448impl<'ctx> BasicTypeEnum<'ctx> {
449    /// Create `BasicTypeEnum` from [`LLVMTypeRef`]
450    ///
451    /// # Safety
452    /// Undefined behavior, if referenced type isn't part of basic type enum.
453    pub unsafe fn new(type_: LLVMTypeRef) -> Self {
454        match LLVMGetTypeKind(type_) {
455            LLVMTypeKind::LLVMHalfTypeKind
456            | LLVMTypeKind::LLVMFloatTypeKind
457            | LLVMTypeKind::LLVMDoubleTypeKind
458            | LLVMTypeKind::LLVMX86_FP80TypeKind
459            | LLVMTypeKind::LLVMFP128TypeKind
460            | LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
461            #[cfg(any(
462                feature = "llvm11-0",
463                feature = "llvm12-0",
464                feature = "llvm13-0",
465                feature = "llvm14-0",
466                feature = "llvm15-0",
467                feature = "llvm16-0",
468                feature = "llvm17-0",
469                feature = "llvm18-0"
470            ))]
471            LLVMTypeKind::LLVMBFloatTypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
472            LLVMTypeKind::LLVMIntegerTypeKind => BasicTypeEnum::IntType(IntType::new(type_)),
473            LLVMTypeKind::LLVMStructTypeKind => BasicTypeEnum::StructType(StructType::new(type_)),
474            LLVMTypeKind::LLVMPointerTypeKind => BasicTypeEnum::PointerType(PointerType::new(type_)),
475            LLVMTypeKind::LLVMArrayTypeKind => BasicTypeEnum::ArrayType(ArrayType::new(type_)),
476            LLVMTypeKind::LLVMVectorTypeKind => BasicTypeEnum::VectorType(VectorType::new(type_)),
477            #[cfg(any(
478                feature = "llvm11-0",
479                feature = "llvm12-0",
480                feature = "llvm13-0",
481                feature = "llvm14-0",
482                feature = "llvm15-0",
483                feature = "llvm16-0",
484                feature = "llvm17-0",
485                feature = "llvm18-0"
486            ))]
487            LLVMTypeKind::LLVMScalableVectorTypeKind => {
488                BasicTypeEnum::ScalableVectorType(ScalableVectorType::new(type_))
489            },
490            LLVMTypeKind::LLVMMetadataTypeKind => panic!("Unsupported basic type: Metadata"),
491            // see https://llvm.org/docs/LangRef.html#x86-mmx-type
492            LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("Unsupported basic type: MMX"),
493            // see https://llvm.org/docs/LangRef.html#x86-amx-type
494            #[cfg(any(
495                feature = "llvm12-0",
496                feature = "llvm13-0",
497                feature = "llvm14-0",
498                feature = "llvm15-0",
499                feature = "llvm16-0",
500                feature = "llvm17-0",
501                feature = "llvm18-0"
502            ))]
503            LLVMTypeKind::LLVMX86_AMXTypeKind => unreachable!("Unsupported basic type: AMX"),
504            LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported basic type: Label"),
505            LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported basic type: VoidType"),
506            LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported basic type: FunctionType"),
507            LLVMTypeKind::LLVMTokenTypeKind => unreachable!("Unsupported basic type: Token"),
508            #[cfg(any(feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
509            LLVMTypeKind::LLVMTargetExtTypeKind => unreachable!("Unsupported basic type: TargetExt"),
510        }
511    }
512
513    pub fn into_array_type(self) -> ArrayType<'ctx> {
514        if let BasicTypeEnum::ArrayType(t) = self {
515            t
516        } else {
517            panic!("Found {:?} but expected the ArrayType variant", self);
518        }
519    }
520
521    pub fn into_float_type(self) -> FloatType<'ctx> {
522        if let BasicTypeEnum::FloatType(t) = self {
523            t
524        } else {
525            panic!("Found {:?} but expected the FloatType variant", self);
526        }
527    }
528
529    pub fn into_int_type(self) -> IntType<'ctx> {
530        if let BasicTypeEnum::IntType(t) = self {
531            t
532        } else {
533            panic!("Found {:?} but expected the IntType variant", self);
534        }
535    }
536
537    pub fn into_pointer_type(self) -> PointerType<'ctx> {
538        if let BasicTypeEnum::PointerType(t) = self {
539            t
540        } else {
541            panic!("Found {:?} but expected the PointerType variant", self);
542        }
543    }
544
545    pub fn into_struct_type(self) -> StructType<'ctx> {
546        if let BasicTypeEnum::StructType(t) = self {
547            t
548        } else {
549            panic!("Found {:?} but expected the StructType variant", self);
550        }
551    }
552
553    pub fn into_vector_type(self) -> VectorType<'ctx> {
554        if let BasicTypeEnum::VectorType(t) = self {
555            t
556        } else {
557            panic!("Found {:?} but expected the VectorType variant", self);
558        }
559    }
560
561    pub fn into_scalable_vector_type(self) -> ScalableVectorType<'ctx> {
562        if let BasicTypeEnum::ScalableVectorType(t) = self {
563            t
564        } else {
565            panic!("Found {:?} but expected the ScalableVectorType variant", self);
566        }
567    }
568
569    pub fn is_array_type(self) -> bool {
570        matches!(self, BasicTypeEnum::ArrayType(_))
571    }
572
573    pub fn is_float_type(self) -> bool {
574        matches!(self, BasicTypeEnum::FloatType(_))
575    }
576
577    pub fn is_int_type(self) -> bool {
578        matches!(self, BasicTypeEnum::IntType(_))
579    }
580
581    pub fn is_pointer_type(self) -> bool {
582        matches!(self, BasicTypeEnum::PointerType(_))
583    }
584
585    pub fn is_struct_type(self) -> bool {
586        matches!(self, BasicTypeEnum::StructType(_))
587    }
588
589    pub fn is_vector_type(self) -> bool {
590        matches!(self, BasicTypeEnum::VectorType(_))
591    }
592
593    pub fn is_scalable_vector_type(self) -> bool {
594        matches!(self, BasicTypeEnum::ScalableVectorType(_))
595    }
596
597    /// Creates a constant `BasicValueZero`.
598    ///
599    /// # Example
600    /// ```
601    /// use inkwell::context::Context;
602    /// use crate::inkwell::types::BasicType;
603    ///
604    /// let context = Context::create();
605    /// let f32_type = context.f32_type().as_basic_type_enum();
606    /// let f32_zero = f32_type.const_zero();
607    /// ```
608    pub fn const_zero(self) -> BasicValueEnum<'ctx> {
609        match self {
610            BasicTypeEnum::ArrayType(ty) => ty.const_zero().as_basic_value_enum(),
611            BasicTypeEnum::FloatType(ty) => ty.const_zero().as_basic_value_enum(),
612            BasicTypeEnum::IntType(ty) => ty.const_zero().as_basic_value_enum(),
613            BasicTypeEnum::PointerType(ty) => ty.const_zero().as_basic_value_enum(),
614            BasicTypeEnum::StructType(ty) => ty.const_zero().as_basic_value_enum(),
615            BasicTypeEnum::VectorType(ty) => ty.const_zero().as_basic_value_enum(),
616            BasicTypeEnum::ScalableVectorType(ty) => ty.const_zero().as_basic_value_enum(),
617        }
618    }
619
620    /// Print the definition of a `BasicTypeEnum` to `LLVMString`.
621    pub fn print_to_string(self) -> LLVMString {
622        match self {
623            BasicTypeEnum::ArrayType(t) => t.print_to_string(),
624            BasicTypeEnum::FloatType(t) => t.print_to_string(),
625            BasicTypeEnum::IntType(t) => t.print_to_string(),
626            BasicTypeEnum::PointerType(t) => t.print_to_string(),
627            BasicTypeEnum::StructType(t) => t.print_to_string(),
628            BasicTypeEnum::VectorType(t) => t.print_to_string(),
629            BasicTypeEnum::ScalableVectorType(t) => t.print_to_string(),
630        }
631    }
632}
633
634impl<'ctx> TryFrom<AnyTypeEnum<'ctx>> for BasicTypeEnum<'ctx> {
635    type Error = ();
636
637    fn try_from(value: AnyTypeEnum<'ctx>) -> Result<Self, Self::Error> {
638        use AnyTypeEnum::*;
639        Ok(match value {
640            ArrayType(at) => at.into(),
641            FloatType(ft) => ft.into(),
642            IntType(it) => it.into(),
643            PointerType(pt) => pt.into(),
644            StructType(st) => st.into(),
645            VectorType(vt) => vt.into(),
646            ScalableVectorType(vt) => vt.into(),
647            VoidType(_) | FunctionType(_) => return Err(()),
648        })
649    }
650}
651
652impl<'ctx> TryFrom<AnyTypeEnum<'ctx>> for BasicMetadataTypeEnum<'ctx> {
653    type Error = ();
654
655    fn try_from(value: AnyTypeEnum<'ctx>) -> Result<Self, Self::Error> {
656        use AnyTypeEnum::*;
657        Ok(match value {
658            ArrayType(at) => at.into(),
659            FloatType(ft) => ft.into(),
660            IntType(it) => it.into(),
661            PointerType(pt) => pt.into(),
662            StructType(st) => st.into(),
663            VectorType(vt) => vt.into(),
664            ScalableVectorType(vt) => vt.into(),
665            VoidType(_) | FunctionType(_) => return Err(()),
666        })
667    }
668}
669
670impl<'ctx> TryFrom<BasicMetadataTypeEnum<'ctx>> for BasicTypeEnum<'ctx> {
671    type Error = ();
672
673    fn try_from(value: BasicMetadataTypeEnum<'ctx>) -> Result<Self, Self::Error> {
674        use BasicMetadataTypeEnum::*;
675        Ok(match value {
676            ArrayType(at) => at.into(),
677            FloatType(ft) => ft.into(),
678            IntType(it) => it.into(),
679            PointerType(pt) => pt.into(),
680            StructType(st) => st.into(),
681            VectorType(vt) => vt.into(),
682            ScalableVectorType(vt) => vt.into(),
683            MetadataType(_) => return Err(()),
684        })
685    }
686}
687
688impl<'ctx> From<BasicTypeEnum<'ctx>> for BasicMetadataTypeEnum<'ctx> {
689    fn from(value: BasicTypeEnum<'ctx>) -> Self {
690        use BasicTypeEnum::*;
691        match value {
692            ArrayType(at) => at.into(),
693            FloatType(ft) => ft.into(),
694            IntType(it) => it.into(),
695            PointerType(pt) => pt.into(),
696            StructType(st) => st.into(),
697            VectorType(vt) => vt.into(),
698            ScalableVectorType(vt) => vt.into(),
699        }
700    }
701}
702
703impl Display for AnyTypeEnum<'_> {
704    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705        write!(f, "{}", self.print_to_string())
706    }
707}
708
709impl Display for BasicTypeEnum<'_> {
710    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
711        write!(f, "{}", self.print_to_string())
712    }
713}
714
715impl Display for BasicMetadataTypeEnum<'_> {
716    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
717        write!(f, "{}", self.print_to_string())
718    }
719}