Skip to main content

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    pub unsafe fn new(type_: LLVMTypeRef) -> Self {
124        match LLVMGetTypeKind(type_) {
125            LLVMTypeKind::LLVMMetadataTypeKind => Self::MetadataType(MetadataType::new(type_)),
126            _ => BasicTypeEnum::new(type_).into(),
127        }
128    }
129
130    pub fn into_array_type(self) -> ArrayType<'ctx> {
131        if let BasicMetadataTypeEnum::ArrayType(t) = self {
132            t
133        } else {
134            panic!("Found {self:?} but expected another variant");
135        }
136    }
137
138    pub fn into_float_type(self) -> FloatType<'ctx> {
139        if let BasicMetadataTypeEnum::FloatType(t) = self {
140            t
141        } else {
142            panic!("Found {self:?} but expected another variant");
143        }
144    }
145
146    pub fn into_int_type(self) -> IntType<'ctx> {
147        if let BasicMetadataTypeEnum::IntType(t) = self {
148            t
149        } else {
150            panic!("Found {self:?} but expected another variant");
151        }
152    }
153
154    pub fn into_pointer_type(self) -> PointerType<'ctx> {
155        if let BasicMetadataTypeEnum::PointerType(t) = self {
156            t
157        } else {
158            panic!("Found {self:?} but expected another variant");
159        }
160    }
161
162    pub fn into_struct_type(self) -> StructType<'ctx> {
163        if let BasicMetadataTypeEnum::StructType(t) = self {
164            t
165        } else {
166            panic!("Found {self:?} but expected another variant");
167        }
168    }
169
170    pub fn into_vector_type(self) -> VectorType<'ctx> {
171        if let BasicMetadataTypeEnum::VectorType(t) = self {
172            t
173        } else {
174            panic!("Found {self:?} but expected another variant");
175        }
176    }
177
178    pub fn into_scalable_vector_type(self) -> ScalableVectorType<'ctx> {
179        if let BasicMetadataTypeEnum::ScalableVectorType(t) = self {
180            t
181        } else {
182            panic!("Found {self:?} but expected another variant");
183        }
184    }
185
186    pub fn into_metadata_type(self) -> MetadataType<'ctx> {
187        if let BasicMetadataTypeEnum::MetadataType(t) = self {
188            t
189        } else {
190            panic!("Found {self:?} but expected another variant");
191        }
192    }
193
194    pub fn is_array_type(self) -> bool {
195        matches!(self, BasicMetadataTypeEnum::ArrayType(_))
196    }
197
198    pub fn is_float_type(self) -> bool {
199        matches!(self, BasicMetadataTypeEnum::FloatType(_))
200    }
201
202    pub fn is_int_type(self) -> bool {
203        matches!(self, BasicMetadataTypeEnum::IntType(_))
204    }
205
206    pub fn is_metadata_type(self) -> bool {
207        matches!(self, BasicMetadataTypeEnum::MetadataType(_))
208    }
209
210    pub fn is_pointer_type(self) -> bool {
211        matches!(self, BasicMetadataTypeEnum::PointerType(_))
212    }
213
214    pub fn is_struct_type(self) -> bool {
215        matches!(self, BasicMetadataTypeEnum::StructType(_))
216    }
217
218    pub fn is_vector_type(self) -> bool {
219        matches!(self, BasicMetadataTypeEnum::VectorType(_))
220    }
221
222    pub fn is_scalable_vector_type(self) -> bool {
223        matches!(self, BasicMetadataTypeEnum::ScalableVectorType(_))
224    }
225
226    /// Print the definition of a `BasicMetadataTypeEnum` to `LLVMString`.
227    pub fn print_to_string(self) -> LLVMString {
228        match self {
229            BasicMetadataTypeEnum::ArrayType(t) => t.print_to_string(),
230            BasicMetadataTypeEnum::IntType(t) => t.print_to_string(),
231            BasicMetadataTypeEnum::FloatType(t) => t.print_to_string(),
232            BasicMetadataTypeEnum::PointerType(t) => t.print_to_string(),
233            BasicMetadataTypeEnum::StructType(t) => t.print_to_string(),
234            BasicMetadataTypeEnum::VectorType(t) => t.print_to_string(),
235            BasicMetadataTypeEnum::ScalableVectorType(t) => t.print_to_string(),
236            BasicMetadataTypeEnum::MetadataType(t) => t.print_to_string(),
237        }
238    }
239}
240
241impl<'ctx> AnyTypeEnum<'ctx> {
242    /// Create `AnyTypeEnum` from [`LLVMTypeRef`]
243    ///
244    /// # Safety
245    /// Undefined behavior, if referenced type isn't part of `AnyTypeEnum`
246    pub unsafe fn new(type_: LLVMTypeRef) -> Self {
247        match LLVMGetTypeKind(type_) {
248            LLVMTypeKind::LLVMVoidTypeKind => AnyTypeEnum::VoidType(VoidType::new(type_)),
249            LLVMTypeKind::LLVMHalfTypeKind
250            | LLVMTypeKind::LLVMFloatTypeKind
251            | LLVMTypeKind::LLVMDoubleTypeKind
252            | LLVMTypeKind::LLVMX86_FP80TypeKind
253            | LLVMTypeKind::LLVMFP128TypeKind
254            | LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
255            #[cfg(any(
256                feature = "llvm11-0",
257                feature = "llvm12-0",
258                feature = "llvm13-0",
259                feature = "llvm14-0",
260                feature = "llvm15-0",
261                feature = "llvm16-0",
262                feature = "llvm17-0",
263                feature = "llvm18-1",
264                feature = "llvm19-1",
265                feature = "llvm20-1",
266                feature = "llvm21-1",
267            ))]
268            LLVMTypeKind::LLVMBFloatTypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
269            LLVMTypeKind::LLVMLabelTypeKind => panic!("FIXME: Unsupported type: Label"),
270            LLVMTypeKind::LLVMIntegerTypeKind => AnyTypeEnum::IntType(IntType::new(type_)),
271            LLVMTypeKind::LLVMFunctionTypeKind => AnyTypeEnum::FunctionType(FunctionType::new(type_)),
272            LLVMTypeKind::LLVMStructTypeKind => AnyTypeEnum::StructType(StructType::new(type_)),
273            LLVMTypeKind::LLVMArrayTypeKind => AnyTypeEnum::ArrayType(ArrayType::new(type_)),
274            LLVMTypeKind::LLVMPointerTypeKind => AnyTypeEnum::PointerType(PointerType::new(type_)),
275            LLVMTypeKind::LLVMVectorTypeKind => AnyTypeEnum::VectorType(VectorType::new(type_)),
276            #[cfg(any(
277                feature = "llvm11-0",
278                feature = "llvm12-0",
279                feature = "llvm13-0",
280                feature = "llvm14-0",
281                feature = "llvm15-0",
282                feature = "llvm16-0",
283                feature = "llvm17-0",
284                feature = "llvm18-1",
285                feature = "llvm19-1",
286                feature = "llvm20-1",
287                feature = "llvm21-1",
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
293            #[cfg(not(any(feature = "llvm20-1", feature = "llvm21-1")))]
294            LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("FIXME: Unsupported type: MMX"),
295            #[cfg(any(
296                feature = "llvm12-0",
297                feature = "llvm13-0",
298                feature = "llvm14-0",
299                feature = "llvm15-0",
300                feature = "llvm16-0",
301                feature = "llvm17-0",
302                feature = "llvm18-1",
303                feature = "llvm19-1",
304                feature = "llvm20-1",
305                feature = "llvm21-1",
306            ))]
307            LLVMTypeKind::LLVMX86_AMXTypeKind => panic!("FIXME: Unsupported type: AMX"),
308            LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"),
309            #[cfg(any(
310                feature = "llvm16-0",
311                feature = "llvm17-0",
312                feature = "llvm18-1",
313                feature = "llvm19-1",
314                feature = "llvm20-1",
315                feature = "llvm21-1",
316            ))]
317            LLVMTypeKind::LLVMTargetExtTypeKind => panic!("FIXME: Unsupported type: TargetExt"),
318        }
319    }
320
321    /// This will panic if type is a void or function type.
322    pub(crate) fn as_basic_type_enum(&self) -> BasicTypeEnum<'ctx> {
323        unsafe { BasicTypeEnum::new(self.as_type_ref()) }
324    }
325
326    pub fn into_array_type(self) -> ArrayType<'ctx> {
327        if let AnyTypeEnum::ArrayType(t) = self {
328            t
329        } else {
330            panic!("Found {self:?} but expected the ArrayType variant");
331        }
332    }
333
334    pub fn into_float_type(self) -> FloatType<'ctx> {
335        if let AnyTypeEnum::FloatType(t) = self {
336            t
337        } else {
338            panic!("Found {self:?} but expected the FloatType variant");
339        }
340    }
341
342    pub fn into_function_type(self) -> FunctionType<'ctx> {
343        if let AnyTypeEnum::FunctionType(t) = self {
344            t
345        } else {
346            panic!("Found {self:?} but expected the FunctionType variant");
347        }
348    }
349
350    pub fn into_int_type(self) -> IntType<'ctx> {
351        if let AnyTypeEnum::IntType(t) = self {
352            t
353        } else {
354            panic!("Found {self:?} but expected the IntType variant");
355        }
356    }
357
358    pub fn into_pointer_type(self) -> PointerType<'ctx> {
359        if let AnyTypeEnum::PointerType(t) = self {
360            t
361        } else {
362            panic!("Found {self:?} but expected the PointerType variant");
363        }
364    }
365
366    pub fn into_struct_type(self) -> StructType<'ctx> {
367        if let AnyTypeEnum::StructType(t) = self {
368            t
369        } else {
370            panic!("Found {self:?} but expected the StructType variant");
371        }
372    }
373
374    pub fn into_vector_type(self) -> VectorType<'ctx> {
375        if let AnyTypeEnum::VectorType(t) = self {
376            t
377        } else {
378            panic!("Found {self:?} but expected the VectorType variant");
379        }
380    }
381
382    pub fn into_scalable_vector_type(self) -> ScalableVectorType<'ctx> {
383        if let AnyTypeEnum::ScalableVectorType(t) = self {
384            t
385        } else {
386            panic!("Found {self:?} but expected the ScalableVectorType variant");
387        }
388    }
389
390    pub fn into_void_type(self) -> VoidType<'ctx> {
391        if let AnyTypeEnum::VoidType(t) = self {
392            t
393        } else {
394            panic!("Found {self:?} but expected the VoidType variant");
395        }
396    }
397
398    pub fn is_array_type(self) -> bool {
399        matches!(self, AnyTypeEnum::ArrayType(_))
400    }
401
402    pub fn is_float_type(self) -> bool {
403        matches!(self, AnyTypeEnum::FloatType(_))
404    }
405
406    pub fn is_function_type(self) -> bool {
407        matches!(self, AnyTypeEnum::FunctionType(_))
408    }
409
410    pub fn is_int_type(self) -> bool {
411        matches!(self, AnyTypeEnum::IntType(_))
412    }
413
414    pub fn is_pointer_type(self) -> bool {
415        matches!(self, AnyTypeEnum::PointerType(_))
416    }
417
418    pub fn is_struct_type(self) -> bool {
419        matches!(self, AnyTypeEnum::StructType(_))
420    }
421
422    pub fn is_vector_type(self) -> bool {
423        matches!(self, AnyTypeEnum::VectorType(_))
424    }
425
426    pub fn is_void_type(self) -> bool {
427        matches!(self, AnyTypeEnum::VoidType(_))
428    }
429
430    pub fn size_of(&self) -> Option<IntValue<'ctx>> {
431        match self {
432            AnyTypeEnum::ArrayType(t) => t.size_of(),
433            AnyTypeEnum::FloatType(t) => Some(t.size_of()),
434            AnyTypeEnum::IntType(t) => Some(t.size_of()),
435            AnyTypeEnum::PointerType(t) => Some(t.size_of()),
436            AnyTypeEnum::StructType(t) => t.size_of(),
437            AnyTypeEnum::VectorType(t) => t.size_of(),
438            AnyTypeEnum::ScalableVectorType(t) => t.size_of(),
439            AnyTypeEnum::VoidType(_) => None,
440            AnyTypeEnum::FunctionType(_) => None,
441        }
442    }
443
444    /// Print the definition of a `AnyTypeEnum` to `LLVMString`.
445    pub fn print_to_string(self) -> LLVMString {
446        match self {
447            AnyTypeEnum::ArrayType(t) => t.print_to_string(),
448            AnyTypeEnum::FloatType(t) => t.print_to_string(),
449            AnyTypeEnum::IntType(t) => t.print_to_string(),
450            AnyTypeEnum::PointerType(t) => t.print_to_string(),
451            AnyTypeEnum::StructType(t) => t.print_to_string(),
452            AnyTypeEnum::VectorType(t) => t.print_to_string(),
453            AnyTypeEnum::ScalableVectorType(t) => t.print_to_string(),
454            AnyTypeEnum::VoidType(t) => t.print_to_string(),
455            AnyTypeEnum::FunctionType(t) => t.print_to_string(),
456        }
457    }
458}
459
460impl<'ctx> BasicTypeEnum<'ctx> {
461    /// Create `BasicTypeEnum` from [`LLVMTypeRef`]
462    ///
463    /// # Safety
464    /// Undefined behavior, if referenced type isn't part of basic type enum.
465    pub unsafe fn new(type_: LLVMTypeRef) -> Self {
466        match LLVMGetTypeKind(type_) {
467            LLVMTypeKind::LLVMHalfTypeKind
468            | LLVMTypeKind::LLVMFloatTypeKind
469            | LLVMTypeKind::LLVMDoubleTypeKind
470            | LLVMTypeKind::LLVMX86_FP80TypeKind
471            | LLVMTypeKind::LLVMFP128TypeKind
472            | LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
473            #[cfg(any(
474                feature = "llvm11-0",
475                feature = "llvm12-0",
476                feature = "llvm13-0",
477                feature = "llvm14-0",
478                feature = "llvm15-0",
479                feature = "llvm16-0",
480                feature = "llvm17-0",
481                feature = "llvm18-1",
482                feature = "llvm19-1",
483                feature = "llvm20-1",
484                feature = "llvm21-1",
485            ))]
486            LLVMTypeKind::LLVMBFloatTypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
487            LLVMTypeKind::LLVMIntegerTypeKind => BasicTypeEnum::IntType(IntType::new(type_)),
488            LLVMTypeKind::LLVMStructTypeKind => BasicTypeEnum::StructType(StructType::new(type_)),
489            LLVMTypeKind::LLVMPointerTypeKind => BasicTypeEnum::PointerType(PointerType::new(type_)),
490            LLVMTypeKind::LLVMArrayTypeKind => BasicTypeEnum::ArrayType(ArrayType::new(type_)),
491            LLVMTypeKind::LLVMVectorTypeKind => BasicTypeEnum::VectorType(VectorType::new(type_)),
492            #[cfg(any(
493                feature = "llvm11-0",
494                feature = "llvm12-0",
495                feature = "llvm13-0",
496                feature = "llvm14-0",
497                feature = "llvm15-0",
498                feature = "llvm16-0",
499                feature = "llvm17-0",
500                feature = "llvm18-1",
501                feature = "llvm19-1",
502                feature = "llvm20-1",
503                feature = "llvm21-1",
504            ))]
505            LLVMTypeKind::LLVMScalableVectorTypeKind => {
506                BasicTypeEnum::ScalableVectorType(ScalableVectorType::new(type_))
507            },
508            LLVMTypeKind::LLVMMetadataTypeKind => panic!("Unsupported basic type: Metadata"),
509            // see https://llvm.org/docs/LangRef.html#x86-mmx-type
510            #[cfg(not(any(feature = "llvm20-1", feature = "llvm21-1")))]
511            LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("Unsupported basic type: MMX"),
512            // see https://llvm.org/docs/LangRef.html#x86-amx-type
513            #[cfg(any(
514                feature = "llvm12-0",
515                feature = "llvm13-0",
516                feature = "llvm14-0",
517                feature = "llvm15-0",
518                feature = "llvm16-0",
519                feature = "llvm17-0",
520                feature = "llvm18-1",
521                feature = "llvm19-1",
522                feature = "llvm20-1",
523                feature = "llvm21-1",
524            ))]
525            LLVMTypeKind::LLVMX86_AMXTypeKind => unreachable!("Unsupported basic type: AMX"),
526            LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported basic type: Label"),
527            LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported basic type: VoidType"),
528            LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported basic type: FunctionType"),
529            LLVMTypeKind::LLVMTokenTypeKind => unreachable!("Unsupported basic type: Token"),
530            #[cfg(any(
531                feature = "llvm16-0",
532                feature = "llvm17-0",
533                feature = "llvm18-1",
534                feature = "llvm19-1",
535                feature = "llvm20-1",
536                feature = "llvm21-1",
537            ))]
538            LLVMTypeKind::LLVMTargetExtTypeKind => unreachable!("Unsupported basic type: TargetExt"),
539        }
540    }
541
542    pub fn into_array_type(self) -> ArrayType<'ctx> {
543        if let BasicTypeEnum::ArrayType(t) = self {
544            t
545        } else {
546            panic!("Found {self:?} but expected the ArrayType variant");
547        }
548    }
549
550    pub fn into_float_type(self) -> FloatType<'ctx> {
551        if let BasicTypeEnum::FloatType(t) = self {
552            t
553        } else {
554            panic!("Found {self:?} but expected the FloatType variant");
555        }
556    }
557
558    pub fn into_int_type(self) -> IntType<'ctx> {
559        if let BasicTypeEnum::IntType(t) = self {
560            t
561        } else {
562            panic!("Found {self:?} but expected the IntType variant");
563        }
564    }
565
566    pub fn into_pointer_type(self) -> PointerType<'ctx> {
567        if let BasicTypeEnum::PointerType(t) = self {
568            t
569        } else {
570            panic!("Found {self:?} but expected the PointerType variant");
571        }
572    }
573
574    pub fn into_struct_type(self) -> StructType<'ctx> {
575        if let BasicTypeEnum::StructType(t) = self {
576            t
577        } else {
578            panic!("Found {self:?} but expected the StructType variant");
579        }
580    }
581
582    pub fn into_vector_type(self) -> VectorType<'ctx> {
583        if let BasicTypeEnum::VectorType(t) = self {
584            t
585        } else {
586            panic!("Found {self:?} but expected the VectorType variant");
587        }
588    }
589
590    pub fn into_scalable_vector_type(self) -> ScalableVectorType<'ctx> {
591        if let BasicTypeEnum::ScalableVectorType(t) = self {
592            t
593        } else {
594            panic!("Found {self:?} but expected the ScalableVectorType variant");
595        }
596    }
597
598    pub fn is_array_type(self) -> bool {
599        matches!(self, BasicTypeEnum::ArrayType(_))
600    }
601
602    pub fn is_float_type(self) -> bool {
603        matches!(self, BasicTypeEnum::FloatType(_))
604    }
605
606    pub fn is_int_type(self) -> bool {
607        matches!(self, BasicTypeEnum::IntType(_))
608    }
609
610    pub fn is_pointer_type(self) -> bool {
611        matches!(self, BasicTypeEnum::PointerType(_))
612    }
613
614    pub fn is_struct_type(self) -> bool {
615        matches!(self, BasicTypeEnum::StructType(_))
616    }
617
618    pub fn is_vector_type(self) -> bool {
619        matches!(self, BasicTypeEnum::VectorType(_))
620    }
621
622    pub fn is_scalable_vector_type(self) -> bool {
623        matches!(self, BasicTypeEnum::ScalableVectorType(_))
624    }
625
626    /// Creates a constant `BasicValueZero`.
627    ///
628    /// # Example
629    /// ```
630    /// use inkwell::context::Context;
631    /// use crate::inkwell::types::BasicType;
632    ///
633    /// let context = Context::create();
634    /// let f32_type = context.f32_type().as_basic_type_enum();
635    /// let f32_zero = f32_type.const_zero();
636    /// ```
637    pub fn const_zero(self) -> BasicValueEnum<'ctx> {
638        match self {
639            BasicTypeEnum::ArrayType(ty) => ty.const_zero().as_basic_value_enum(),
640            BasicTypeEnum::FloatType(ty) => ty.const_zero().as_basic_value_enum(),
641            BasicTypeEnum::IntType(ty) => ty.const_zero().as_basic_value_enum(),
642            BasicTypeEnum::PointerType(ty) => ty.const_zero().as_basic_value_enum(),
643            BasicTypeEnum::StructType(ty) => ty.const_zero().as_basic_value_enum(),
644            BasicTypeEnum::VectorType(ty) => ty.const_zero().as_basic_value_enum(),
645            BasicTypeEnum::ScalableVectorType(ty) => ty.const_zero().as_basic_value_enum(),
646        }
647    }
648
649    /// Print the definition of a `BasicTypeEnum` to `LLVMString`.
650    pub fn print_to_string(self) -> LLVMString {
651        match self {
652            BasicTypeEnum::ArrayType(t) => t.print_to_string(),
653            BasicTypeEnum::FloatType(t) => t.print_to_string(),
654            BasicTypeEnum::IntType(t) => t.print_to_string(),
655            BasicTypeEnum::PointerType(t) => t.print_to_string(),
656            BasicTypeEnum::StructType(t) => t.print_to_string(),
657            BasicTypeEnum::VectorType(t) => t.print_to_string(),
658            BasicTypeEnum::ScalableVectorType(t) => t.print_to_string(),
659        }
660    }
661}
662
663impl<'ctx> TryFrom<AnyTypeEnum<'ctx>> for BasicTypeEnum<'ctx> {
664    type Error = ();
665
666    fn try_from(value: AnyTypeEnum<'ctx>) -> Result<Self, Self::Error> {
667        use AnyTypeEnum::*;
668        Ok(match value {
669            ArrayType(at) => at.into(),
670            FloatType(ft) => ft.into(),
671            IntType(it) => it.into(),
672            PointerType(pt) => pt.into(),
673            StructType(st) => st.into(),
674            VectorType(vt) => vt.into(),
675            ScalableVectorType(vt) => vt.into(),
676            VoidType(_) | FunctionType(_) => return Err(()),
677        })
678    }
679}
680
681impl<'ctx> TryFrom<AnyTypeEnum<'ctx>> for BasicMetadataTypeEnum<'ctx> {
682    type Error = ();
683
684    fn try_from(value: AnyTypeEnum<'ctx>) -> Result<Self, Self::Error> {
685        use AnyTypeEnum::*;
686        Ok(match value {
687            ArrayType(at) => at.into(),
688            FloatType(ft) => ft.into(),
689            IntType(it) => it.into(),
690            PointerType(pt) => pt.into(),
691            StructType(st) => st.into(),
692            VectorType(vt) => vt.into(),
693            ScalableVectorType(vt) => vt.into(),
694            VoidType(_) | FunctionType(_) => return Err(()),
695        })
696    }
697}
698
699impl<'ctx> TryFrom<BasicMetadataTypeEnum<'ctx>> for BasicTypeEnum<'ctx> {
700    type Error = ();
701
702    fn try_from(value: BasicMetadataTypeEnum<'ctx>) -> Result<Self, Self::Error> {
703        use BasicMetadataTypeEnum::*;
704        Ok(match value {
705            ArrayType(at) => at.into(),
706            FloatType(ft) => ft.into(),
707            IntType(it) => it.into(),
708            PointerType(pt) => pt.into(),
709            StructType(st) => st.into(),
710            VectorType(vt) => vt.into(),
711            ScalableVectorType(vt) => vt.into(),
712            MetadataType(_) => return Err(()),
713        })
714    }
715}
716
717impl<'ctx> From<BasicTypeEnum<'ctx>> for BasicMetadataTypeEnum<'ctx> {
718    fn from(value: BasicTypeEnum<'ctx>) -> Self {
719        use BasicTypeEnum::*;
720        match value {
721            ArrayType(at) => at.into(),
722            FloatType(ft) => ft.into(),
723            IntType(it) => it.into(),
724            PointerType(pt) => pt.into(),
725            StructType(st) => st.into(),
726            VectorType(vt) => vt.into(),
727            ScalableVectorType(vt) => vt.into(),
728        }
729    }
730}
731
732impl Display for AnyTypeEnum<'_> {
733    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
734        write!(f, "{}", self.print_to_string())
735    }
736}
737
738impl Display for BasicTypeEnum<'_> {
739    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
740        write!(f, "{}", self.print_to_string())
741    }
742}
743
744impl Display for BasicMetadataTypeEnum<'_> {
745    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
746        write!(f, "{}", self.print_to_string())
747    }
748}