Skip to main content

inkwell/values/
enums.rs

1use llvm_sys::core::{LLVMGetTypeKind, LLVMGetValueKind, LLVMIsAInstruction, LLVMTypeOf};
2use llvm_sys::prelude::LLVMValueRef;
3use llvm_sys::{LLVMTypeKind, LLVMValueKind};
4
5use crate::types::{AnyTypeEnum, BasicTypeEnum};
6use crate::values::traits::AsValueRef;
7use crate::values::{
8    ArrayValue, FloatValue, FunctionValue, InstructionValue, IntValue, MetadataValue, PhiValue, PointerValue,
9    ScalableVectorValue, StructValue, VectorValue,
10};
11
12use std::convert::TryFrom;
13use std::ffi::CStr;
14use std::fmt::{self, Display};
15
16use super::AnyValue;
17
18macro_rules! enum_value_set {
19    ($enum_name:ident: $($args:ident),*) => (
20        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21        pub enum $enum_name<'ctx> {
22            $(
23                $args($args<'ctx>),
24            )*
25        }
26
27        unsafe impl AsValueRef for $enum_name<'_> {
28            fn as_value_ref(&self) -> LLVMValueRef {
29                match *self {
30                    $(
31                        $enum_name::$args(ref t) => t.as_value_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> PartialEq<$args<'ctx>> for $enum_name<'ctx> {
45                fn eq(&self, other: &$args<'ctx>) -> bool {
46                    self.as_value_ref() == other.as_value_ref()
47                }
48            }
49
50            impl<'ctx> PartialEq<$enum_name<'ctx>> for $args<'ctx> {
51                fn eq(&self, other: &$enum_name<'ctx>) -> bool {
52                    self.as_value_ref() == other.as_value_ref()
53                }
54            }
55
56            impl<'ctx> TryFrom<$enum_name<'ctx>> for $args<'ctx> {
57                type Error = ();
58
59                fn try_from(value: $enum_name<'ctx>) -> Result<Self, Self::Error> {
60                    match value {
61                        $enum_name::$args(ty) => Ok(ty),
62                        _ => Err(()),
63                    }
64                }
65            }
66        )*
67    );
68}
69
70enum_value_set! {AggregateValueEnum: ArrayValue, StructValue}
71enum_value_set! {AnyValueEnum: ArrayValue, IntValue, FloatValue, PhiValue, FunctionValue, PointerValue, StructValue, VectorValue, ScalableVectorValue, InstructionValue, MetadataValue}
72enum_value_set! {BasicValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue, ScalableVectorValue}
73enum_value_set! {BasicMetadataValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue, ScalableVectorValue, MetadataValue}
74
75impl<'ctx> AnyValueEnum<'ctx> {
76    /// Get a value from an [LLVMValueRef].
77    ///
78    /// # Safety
79    ///
80    /// The ref must be valid and of supported enum type options ([LLVMTypeKind]).
81    pub unsafe fn new(value: LLVMValueRef) -> Self {
82        match LLVMGetTypeKind(LLVMTypeOf(value)) {
83            LLVMTypeKind::LLVMFloatTypeKind
84            | LLVMTypeKind::LLVMFP128TypeKind
85            | LLVMTypeKind::LLVMDoubleTypeKind
86            | LLVMTypeKind::LLVMHalfTypeKind
87            | LLVMTypeKind::LLVMX86_FP80TypeKind
88            | LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyValueEnum::FloatValue(FloatValue::new(value)),
89            #[cfg(any(
90                feature = "llvm11-0",
91                feature = "llvm12-0",
92                feature = "llvm13-0",
93                feature = "llvm14-0",
94                feature = "llvm15-0",
95                feature = "llvm16-0",
96                feature = "llvm17-0",
97                feature = "llvm18-1",
98                feature = "llvm19-1",
99                feature = "llvm20-1",
100                feature = "llvm21-1",
101            ))]
102            LLVMTypeKind::LLVMBFloatTypeKind => AnyValueEnum::FloatValue(FloatValue::new(value)),
103            LLVMTypeKind::LLVMIntegerTypeKind => AnyValueEnum::IntValue(IntValue::new(value)),
104            LLVMTypeKind::LLVMStructTypeKind => AnyValueEnum::StructValue(StructValue::new(value)),
105            LLVMTypeKind::LLVMPointerTypeKind => match LLVMGetValueKind(value) {
106                LLVMValueKind::LLVMFunctionValueKind => AnyValueEnum::FunctionValue(FunctionValue::new(value).unwrap()),
107                _ => AnyValueEnum::PointerValue(PointerValue::new(value)),
108            },
109            LLVMTypeKind::LLVMArrayTypeKind => AnyValueEnum::ArrayValue(ArrayValue::new(value)),
110            LLVMTypeKind::LLVMVectorTypeKind => AnyValueEnum::VectorValue(VectorValue::new(value)),
111            #[cfg(any(
112                feature = "llvm11-0",
113                feature = "llvm12-0",
114                feature = "llvm13-0",
115                feature = "llvm14-0",
116                feature = "llvm15-0",
117                feature = "llvm16-0",
118                feature = "llvm17-0",
119                feature = "llvm18-1",
120                feature = "llvm19-1",
121                feature = "llvm20-1",
122                feature = "llvm21-1",
123            ))]
124            LLVMTypeKind::LLVMScalableVectorTypeKind => {
125                AnyValueEnum::ScalableVectorValue(ScalableVectorValue::new(value))
126            },
127            LLVMTypeKind::LLVMFunctionTypeKind => AnyValueEnum::FunctionValue(FunctionValue::new(value).unwrap()),
128            LLVMTypeKind::LLVMVoidTypeKind => {
129                if LLVMIsAInstruction(value).is_null() {
130                    panic!("Void value isn't an instruction.");
131                }
132                AnyValueEnum::InstructionValue(InstructionValue::new(value))
133            },
134            LLVMTypeKind::LLVMMetadataTypeKind => panic!("Metadata values are not supported as AnyValue's."),
135            _ => panic!("The given type is not supported."),
136        }
137    }
138
139    pub fn get_type(&self) -> AnyTypeEnum<'ctx> {
140        unsafe { AnyTypeEnum::new(LLVMTypeOf(self.as_value_ref())) }
141    }
142
143    pub fn is_array_value(self) -> bool {
144        matches!(self, AnyValueEnum::ArrayValue(_))
145    }
146
147    pub fn is_int_value(self) -> bool {
148        matches!(self, AnyValueEnum::IntValue(_))
149    }
150
151    pub fn is_float_value(self) -> bool {
152        matches!(self, AnyValueEnum::FloatValue(_))
153    }
154
155    pub fn is_phi_value(self) -> bool {
156        matches!(self, AnyValueEnum::PhiValue(_))
157    }
158
159    pub fn is_function_value(self) -> bool {
160        matches!(self, AnyValueEnum::FunctionValue(_))
161    }
162
163    pub fn is_pointer_value(self) -> bool {
164        matches!(self, AnyValueEnum::PointerValue(_))
165    }
166
167    pub fn is_struct_value(self) -> bool {
168        matches!(self, AnyValueEnum::StructValue(_))
169    }
170
171    pub fn is_vector_value(self) -> bool {
172        matches!(self, AnyValueEnum::VectorValue(_))
173    }
174
175    pub fn is_scalable_vector_value(self) -> bool {
176        matches!(self, AnyValueEnum::ScalableVectorValue(_))
177    }
178
179    pub fn is_instruction_value(self) -> bool {
180        matches!(self, AnyValueEnum::InstructionValue(_))
181    }
182
183    #[track_caller]
184    pub fn into_array_value(self) -> ArrayValue<'ctx> {
185        if let AnyValueEnum::ArrayValue(v) = self {
186            v
187        } else {
188            panic!("Found {self:?} but expected the ArrayValue variant")
189        }
190    }
191
192    #[track_caller]
193    pub fn into_int_value(self) -> IntValue<'ctx> {
194        if let AnyValueEnum::IntValue(v) = self {
195            v
196        } else {
197            panic!("Found {self:?} but expected the IntValue variant")
198        }
199    }
200
201    #[track_caller]
202    pub fn into_float_value(self) -> FloatValue<'ctx> {
203        if let AnyValueEnum::FloatValue(v) = self {
204            v
205        } else {
206            panic!("Found {self:?} but expected the FloatValue variant")
207        }
208    }
209
210    #[track_caller]
211    pub fn into_phi_value(self) -> PhiValue<'ctx> {
212        if let AnyValueEnum::PhiValue(v) = self {
213            v
214        } else {
215            panic!("Found {self:?} but expected the PhiValue variant")
216        }
217    }
218
219    #[track_caller]
220    pub fn into_function_value(self) -> FunctionValue<'ctx> {
221        if let AnyValueEnum::FunctionValue(v) = self {
222            v
223        } else {
224            panic!("Found {self:?} but expected the FunctionValue variant")
225        }
226    }
227
228    #[track_caller]
229    pub fn into_pointer_value(self) -> PointerValue<'ctx> {
230        if let AnyValueEnum::PointerValue(v) = self {
231            v
232        } else {
233            panic!("Found {self:?} but expected the PointerValue variant")
234        }
235    }
236
237    #[track_caller]
238    pub fn into_struct_value(self) -> StructValue<'ctx> {
239        if let AnyValueEnum::StructValue(v) = self {
240            v
241        } else {
242            panic!("Found {self:?} but expected the StructValue variant")
243        }
244    }
245
246    #[track_caller]
247    pub fn into_vector_value(self) -> VectorValue<'ctx> {
248        if let AnyValueEnum::VectorValue(v) = self {
249            v
250        } else {
251            panic!("Found {self:?} but expected the VectorValue variant")
252        }
253    }
254
255    #[track_caller]
256    pub fn into_scalable_vector_value(self) -> ScalableVectorValue<'ctx> {
257        if let AnyValueEnum::ScalableVectorValue(v) = self {
258            v
259        } else {
260            panic!("Found {self:?} but expected the ScalableVectorValue variant")
261        }
262    }
263
264    #[track_caller]
265    pub fn into_instruction_value(self) -> InstructionValue<'ctx> {
266        if let AnyValueEnum::InstructionValue(v) = self {
267            v
268        } else {
269            panic!("Found {self:?} but expected the InstructionValue variant")
270        }
271    }
272}
273
274impl<'ctx> BasicValueEnum<'ctx> {
275    /// Get a value from an [LLVMValueRef].
276    ///
277    /// # Safety
278    ///
279    /// The ref must be valid and of supported enum type options ([LLVMTypeKind]).
280    pub unsafe fn new(value: LLVMValueRef) -> Self {
281        match LLVMGetTypeKind(LLVMTypeOf(value)) {
282            LLVMTypeKind::LLVMFloatTypeKind
283            | LLVMTypeKind::LLVMFP128TypeKind
284            | LLVMTypeKind::LLVMDoubleTypeKind
285            | LLVMTypeKind::LLVMHalfTypeKind
286            | LLVMTypeKind::LLVMX86_FP80TypeKind
287            | LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicValueEnum::FloatValue(FloatValue::new(value)),
288            #[cfg(any(
289                feature = "llvm11-0",
290                feature = "llvm12-0",
291                feature = "llvm13-0",
292                feature = "llvm14-0",
293                feature = "llvm15-0",
294                feature = "llvm16-0",
295                feature = "llvm17-0",
296                feature = "llvm18-1",
297                feature = "llvm19-1",
298                feature = "llvm20-1",
299                feature = "llvm21-1",
300            ))]
301            LLVMTypeKind::LLVMBFloatTypeKind => BasicValueEnum::FloatValue(FloatValue::new(value)),
302            LLVMTypeKind::LLVMIntegerTypeKind => BasicValueEnum::IntValue(IntValue::new(value)),
303            LLVMTypeKind::LLVMStructTypeKind => BasicValueEnum::StructValue(StructValue::new(value)),
304            LLVMTypeKind::LLVMPointerTypeKind => BasicValueEnum::PointerValue(PointerValue::new(value)),
305            LLVMTypeKind::LLVMArrayTypeKind => BasicValueEnum::ArrayValue(ArrayValue::new(value)),
306            LLVMTypeKind::LLVMVectorTypeKind => BasicValueEnum::VectorValue(VectorValue::new(value)),
307            #[cfg(any(
308                feature = "llvm11-0",
309                feature = "llvm12-0",
310                feature = "llvm13-0",
311                feature = "llvm14-0",
312                feature = "llvm15-0",
313                feature = "llvm16-0",
314                feature = "llvm17-0",
315                feature = "llvm18-1",
316                feature = "llvm19-1",
317                feature = "llvm20-1",
318                feature = "llvm21-1",
319            ))]
320            LLVMTypeKind::LLVMScalableVectorTypeKind => {
321                BasicValueEnum::ScalableVectorValue(ScalableVectorValue::new(value))
322            },
323            _ => unreachable!("The given type is not a basic type."),
324        }
325    }
326
327    /// Get the name of the `BasicValueEnum`.
328    pub fn get_name(&self) -> &CStr {
329        match self {
330            BasicValueEnum::ArrayValue(v) => v.get_name(),
331            BasicValueEnum::IntValue(v) => v.get_name(),
332            BasicValueEnum::FloatValue(v) => v.get_name(),
333            BasicValueEnum::PointerValue(v) => v.get_name(),
334            BasicValueEnum::StructValue(v) => v.get_name(),
335            BasicValueEnum::VectorValue(v) => v.get_name(),
336            BasicValueEnum::ScalableVectorValue(v) => v.get_name(),
337        }
338    }
339
340    /// Set name of the `BasicValueEnum`.
341    pub fn set_name(&self, name: &str) {
342        match self {
343            BasicValueEnum::ArrayValue(v) => v.set_name(name),
344            BasicValueEnum::IntValue(v) => v.set_name(name),
345            BasicValueEnum::FloatValue(v) => v.set_name(name),
346            BasicValueEnum::PointerValue(v) => v.set_name(name),
347            BasicValueEnum::StructValue(v) => v.set_name(name),
348            BasicValueEnum::VectorValue(v) => v.set_name(name),
349            BasicValueEnum::ScalableVectorValue(v) => v.set_name(name),
350        }
351    }
352
353    pub fn get_type(&self) -> BasicTypeEnum<'ctx> {
354        unsafe { BasicTypeEnum::new(LLVMTypeOf(self.as_value_ref())) }
355    }
356
357    pub fn is_array_value(self) -> bool {
358        matches!(self, BasicValueEnum::ArrayValue(_))
359    }
360
361    pub fn is_int_value(self) -> bool {
362        matches!(self, BasicValueEnum::IntValue(_))
363    }
364
365    pub fn is_float_value(self) -> bool {
366        matches!(self, BasicValueEnum::FloatValue(_))
367    }
368
369    pub fn is_pointer_value(self) -> bool {
370        matches!(self, BasicValueEnum::PointerValue(_))
371    }
372
373    pub fn is_struct_value(self) -> bool {
374        matches!(self, BasicValueEnum::StructValue(_))
375    }
376
377    pub fn is_vector_value(self) -> bool {
378        matches!(self, BasicValueEnum::VectorValue(_))
379    }
380
381    pub fn is_scalable_vector_value(self) -> bool {
382        matches!(self, BasicValueEnum::ScalableVectorValue(_))
383    }
384
385    #[track_caller]
386    pub fn into_array_value(self) -> ArrayValue<'ctx> {
387        if let BasicValueEnum::ArrayValue(v) = self {
388            v
389        } else {
390            panic!("Found {self:?} but expected the ArrayValue variant")
391        }
392    }
393
394    #[track_caller]
395    pub fn into_int_value(self) -> IntValue<'ctx> {
396        if let BasicValueEnum::IntValue(v) = self {
397            v
398        } else {
399            panic!("Found {self:?} but expected the IntValue variant")
400        }
401    }
402
403    #[track_caller]
404    pub fn into_float_value(self) -> FloatValue<'ctx> {
405        if let BasicValueEnum::FloatValue(v) = self {
406            v
407        } else {
408            panic!("Found {self:?} but expected the FloatValue variant")
409        }
410    }
411
412    #[track_caller]
413    pub fn into_pointer_value(self) -> PointerValue<'ctx> {
414        if let BasicValueEnum::PointerValue(v) = self {
415            v
416        } else {
417            panic!("Found {self:?} but expected PointerValue variant")
418        }
419    }
420
421    #[track_caller]
422    pub fn into_struct_value(self) -> StructValue<'ctx> {
423        if let BasicValueEnum::StructValue(v) = self {
424            v
425        } else {
426            panic!("Found {self:?} but expected the StructValue variant")
427        }
428    }
429
430    #[track_caller]
431    pub fn into_vector_value(self) -> VectorValue<'ctx> {
432        if let BasicValueEnum::VectorValue(v) = self {
433            v
434        } else {
435            panic!("Found {self:?} but expected the VectorValue variant")
436        }
437    }
438
439    #[track_caller]
440    pub fn into_scalable_vector_value(self) -> ScalableVectorValue<'ctx> {
441        if let BasicValueEnum::ScalableVectorValue(v) = self {
442            v
443        } else {
444            panic!("Found {self:?} but expected the ScalableVectorValue variant")
445        }
446    }
447}
448
449impl<'ctx> AggregateValueEnum<'ctx> {
450    /// Get a value from an [LLVMValueRef].
451    ///
452    /// # Safety
453    ///
454    /// The ref must be valid and of supported aggregate type enum options ([LLVMTypeKind]).
455    pub unsafe fn new(value: LLVMValueRef) -> Self {
456        match LLVMGetTypeKind(LLVMTypeOf(value)) {
457            LLVMTypeKind::LLVMArrayTypeKind => AggregateValueEnum::ArrayValue(ArrayValue::new(value)),
458            LLVMTypeKind::LLVMStructTypeKind => AggregateValueEnum::StructValue(StructValue::new(value)),
459            _ => unreachable!("The given type is not an aggregate type."),
460        }
461    }
462
463    pub fn is_array_value(self) -> bool {
464        matches!(self, AggregateValueEnum::ArrayValue(_))
465    }
466
467    pub fn is_struct_value(self) -> bool {
468        matches!(self, AggregateValueEnum::StructValue(_))
469    }
470
471    #[track_caller]
472    pub fn into_array_value(self) -> ArrayValue<'ctx> {
473        if let AggregateValueEnum::ArrayValue(v) = self {
474            v
475        } else {
476            panic!("Found {self:?} but expected the ArrayValue variant")
477        }
478    }
479
480    #[track_caller]
481    pub fn into_struct_value(self) -> StructValue<'ctx> {
482        if let AggregateValueEnum::StructValue(v) = self {
483            v
484        } else {
485            panic!("Found {self:?} but expected the StructValue variant")
486        }
487    }
488}
489
490impl<'ctx> BasicMetadataValueEnum<'ctx> {
491    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
492        match LLVMGetTypeKind(LLVMTypeOf(value)) {
493            LLVMTypeKind::LLVMFloatTypeKind
494            | LLVMTypeKind::LLVMFP128TypeKind
495            | LLVMTypeKind::LLVMDoubleTypeKind
496            | LLVMTypeKind::LLVMHalfTypeKind
497            | LLVMTypeKind::LLVMX86_FP80TypeKind
498            | LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicMetadataValueEnum::FloatValue(FloatValue::new(value)),
499            #[cfg(any(
500                feature = "llvm11-0",
501                feature = "llvm12-0",
502                feature = "llvm13-0",
503                feature = "llvm14-0",
504                feature = "llvm15-0",
505                feature = "llvm16-0",
506                feature = "llvm17-0",
507                feature = "llvm18-1",
508                feature = "llvm19-1",
509                feature = "llvm20-1",
510                feature = "llvm21-1",
511            ))]
512            LLVMTypeKind::LLVMBFloatTypeKind => BasicMetadataValueEnum::FloatValue(FloatValue::new(value)),
513            LLVMTypeKind::LLVMIntegerTypeKind => BasicMetadataValueEnum::IntValue(IntValue::new(value)),
514            LLVMTypeKind::LLVMStructTypeKind => BasicMetadataValueEnum::StructValue(StructValue::new(value)),
515            LLVMTypeKind::LLVMPointerTypeKind => BasicMetadataValueEnum::PointerValue(PointerValue::new(value)),
516            LLVMTypeKind::LLVMArrayTypeKind => BasicMetadataValueEnum::ArrayValue(ArrayValue::new(value)),
517            LLVMTypeKind::LLVMVectorTypeKind => BasicMetadataValueEnum::VectorValue(VectorValue::new(value)),
518            #[cfg(any(
519                feature = "llvm11-0",
520                feature = "llvm12-0",
521                feature = "llvm13-0",
522                feature = "llvm14-0",
523                feature = "llvm15-0",
524                feature = "llvm16-0",
525                feature = "llvm17-0",
526                feature = "llvm18-1",
527                feature = "llvm19-1",
528                feature = "llvm20-1",
529                feature = "llvm21-1",
530            ))]
531            LLVMTypeKind::LLVMScalableVectorTypeKind => {
532                BasicMetadataValueEnum::ScalableVectorValue(ScalableVectorValue::new(value))
533            },
534            LLVMTypeKind::LLVMMetadataTypeKind => BasicMetadataValueEnum::MetadataValue(MetadataValue::new(value)),
535            _ => unreachable!("Unsupported type"),
536        }
537    }
538
539    pub fn is_array_value(self) -> bool {
540        matches!(self, BasicMetadataValueEnum::ArrayValue(_))
541    }
542
543    pub fn is_int_value(self) -> bool {
544        matches!(self, BasicMetadataValueEnum::IntValue(_))
545    }
546
547    pub fn is_float_value(self) -> bool {
548        matches!(self, BasicMetadataValueEnum::FloatValue(_))
549    }
550
551    pub fn is_pointer_value(self) -> bool {
552        matches!(self, BasicMetadataValueEnum::PointerValue(_))
553    }
554
555    pub fn is_struct_value(self) -> bool {
556        matches!(self, BasicMetadataValueEnum::StructValue(_))
557    }
558
559    pub fn is_vector_value(self) -> bool {
560        matches!(self, BasicMetadataValueEnum::VectorValue(_))
561    }
562
563    pub fn is_scalable_vector_value(self) -> bool {
564        matches!(self, BasicMetadataValueEnum::ScalableVectorValue(_))
565    }
566
567    pub fn is_metadata_value(self) -> bool {
568        matches!(self, BasicMetadataValueEnum::MetadataValue(_))
569    }
570
571    #[track_caller]
572    pub fn into_array_value(self) -> ArrayValue<'ctx> {
573        if let BasicMetadataValueEnum::ArrayValue(v) = self {
574            v
575        } else {
576            panic!("Found {self:?} but expected the ArrayValue variant")
577        }
578    }
579
580    #[track_caller]
581    pub fn into_int_value(self) -> IntValue<'ctx> {
582        if let BasicMetadataValueEnum::IntValue(v) = self {
583            v
584        } else {
585            panic!("Found {self:?} but expected the IntValue variant")
586        }
587    }
588
589    #[track_caller]
590    pub fn into_float_value(self) -> FloatValue<'ctx> {
591        if let BasicMetadataValueEnum::FloatValue(v) = self {
592            v
593        } else {
594            panic!("Found {self:?} but expected FloatValue variant")
595        }
596    }
597
598    #[track_caller]
599    pub fn into_pointer_value(self) -> PointerValue<'ctx> {
600        if let BasicMetadataValueEnum::PointerValue(v) = self {
601            v
602        } else {
603            panic!("Found {self:?} but expected the PointerValue variant")
604        }
605    }
606
607    #[track_caller]
608    pub fn into_struct_value(self) -> StructValue<'ctx> {
609        if let BasicMetadataValueEnum::StructValue(v) = self {
610            v
611        } else {
612            panic!("Found {self:?} but expected the StructValue variant")
613        }
614    }
615
616    #[track_caller]
617    pub fn into_vector_value(self) -> VectorValue<'ctx> {
618        if let BasicMetadataValueEnum::VectorValue(v) = self {
619            v
620        } else {
621            panic!("Found {self:?} but expected the VectorValue variant")
622        }
623    }
624
625    #[track_caller]
626    pub fn into_scalable_vector_value(self) -> ScalableVectorValue<'ctx> {
627        if let BasicMetadataValueEnum::ScalableVectorValue(v) = self {
628            v
629        } else {
630            panic!("Found {self:?} but expected the ScalableVectorValue variant")
631        }
632    }
633
634    #[track_caller]
635    pub fn into_metadata_value(self) -> MetadataValue<'ctx> {
636        if let BasicMetadataValueEnum::MetadataValue(v) = self {
637            v
638        } else {
639            panic!("Found {self:?} but expected MetaData variant")
640        }
641    }
642}
643
644impl<'ctx> From<BasicValueEnum<'ctx>> for AnyValueEnum<'ctx> {
645    fn from(value: BasicValueEnum<'ctx>) -> Self {
646        unsafe { AnyValueEnum::new(value.as_value_ref()) }
647    }
648}
649
650impl<'ctx> From<BasicValueEnum<'ctx>> for BasicMetadataValueEnum<'ctx> {
651    fn from(value: BasicValueEnum<'ctx>) -> Self {
652        unsafe { BasicMetadataValueEnum::new(value.as_value_ref()) }
653    }
654}
655
656impl<'ctx> TryFrom<AnyValueEnum<'ctx>> for BasicValueEnum<'ctx> {
657    type Error = ();
658
659    fn try_from(value: AnyValueEnum<'ctx>) -> Result<Self, Self::Error> {
660        use AnyValueEnum::*;
661        Ok(match value {
662            ArrayValue(av) => av.into(),
663            IntValue(iv) => iv.into(),
664            FloatValue(fv) => fv.into(),
665            PointerValue(pv) => pv.into(),
666            StructValue(sv) => sv.into(),
667            VectorValue(vv) => vv.into(),
668            ScalableVectorValue(vv) => vv.into(),
669            MetadataValue(_) | PhiValue(_) | FunctionValue(_) | InstructionValue(_) => return Err(()),
670        })
671    }
672}
673
674impl<'ctx> TryFrom<AnyValueEnum<'ctx>> for BasicMetadataValueEnum<'ctx> {
675    type Error = ();
676
677    fn try_from(value: AnyValueEnum<'ctx>) -> Result<Self, Self::Error> {
678        use AnyValueEnum::*;
679        Ok(match value {
680            ArrayValue(av) => av.into(),
681            IntValue(iv) => iv.into(),
682            FloatValue(fv) => fv.into(),
683            PointerValue(pv) => pv.into(),
684            StructValue(sv) => sv.into(),
685            VectorValue(vv) => vv.into(),
686            ScalableVectorValue(vv) => vv.into(),
687            MetadataValue(mv) => mv.into(),
688            PhiValue(_) | FunctionValue(_) | InstructionValue(_) => return Err(()),
689        })
690    }
691}
692
693impl<'ctx> TryFrom<BasicMetadataValueEnum<'ctx>> for BasicValueEnum<'ctx> {
694    type Error = ();
695
696    fn try_from(value: BasicMetadataValueEnum<'ctx>) -> Result<Self, Self::Error> {
697        use BasicMetadataValueEnum::*;
698        Ok(match value {
699            ArrayValue(av) => av.into(),
700            IntValue(iv) => iv.into(),
701            FloatValue(fv) => fv.into(),
702            PointerValue(pv) => pv.into(),
703            StructValue(sv) => sv.into(),
704            VectorValue(vv) => vv.into(),
705            ScalableVectorValue(vv) => vv.into(),
706            MetadataValue(_) => return Err(()),
707        })
708    }
709}
710
711impl Display for AggregateValueEnum<'_> {
712    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
713        write!(f, "{}", self.print_to_string())
714    }
715}
716
717impl Display for AnyValueEnum<'_> {
718    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
719        write!(f, "{}", self.print_to_string())
720    }
721}
722
723impl Display for BasicValueEnum<'_> {
724    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
725        write!(f, "{}", self.print_to_string())
726    }
727}
728
729impl Display for BasicMetadataValueEnum<'_> {
730    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
731        write!(f, "{}", self.print_to_string())
732    }
733}