Skip to main content

inkwell/types/
enums.rs

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