inkwell_llvm12/values/
enums.rs

1use llvm_sys::core::{LLVMGetTypeKind, LLVMIsAInstruction, LLVMTypeOf};
2use llvm_sys::prelude::LLVMValueRef;
3use llvm_sys::LLVMTypeKind;
4
5use crate::types::{AnyTypeEnum, BasicTypeEnum};
6use crate::values::traits::AsValueRef;
7use crate::values::{
8    ArrayValue, FloatValue, FunctionValue, InstructionValue, IntValue, MetadataValue, PhiValue,
9    PointerValue, StructValue, VectorValue,
10};
11
12use std::convert::TryFrom;
13use std::fmt::{self, Display};
14
15use super::AnyValue;
16
17macro_rules! enum_value_set {
18    ($enum_name:ident: $($args:ident),*) => (
19        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20        pub enum $enum_name<'ctx> {
21            $(
22                $args($args<'ctx>),
23            )*
24        }
25
26        impl AsValueRef for $enum_name<'_> {
27            fn as_value_ref(&self) -> LLVMValueRef {
28                match *self {
29                    $(
30                        $enum_name::$args(ref t) => t.as_value_ref(),
31                    )*
32                }
33            }
34        }
35
36        $(
37            impl<'ctx> From<$args<'ctx>> for $enum_name<'ctx> {
38                fn from(value: $args) -> $enum_name {
39                    $enum_name::$args(value)
40                }
41            }
42
43            impl<'ctx> PartialEq<$args<'ctx>> for $enum_name<'ctx> {
44                fn eq(&self, other: &$args<'ctx>) -> bool {
45                    self.as_value_ref() == other.as_value_ref()
46                }
47            }
48
49            impl<'ctx> PartialEq<$enum_name<'ctx>> for $args<'ctx> {
50                fn eq(&self, other: &$enum_name<'ctx>) -> bool {
51                    self.as_value_ref() == other.as_value_ref()
52                }
53            }
54
55            impl<'ctx> TryFrom<$enum_name<'ctx>> for $args<'ctx> {
56                type Error = ();
57
58                fn try_from(value: $enum_name<'ctx>) -> Result<Self, Self::Error> {
59                    match value {
60                        $enum_name::$args(ty) => Ok(ty),
61                        _ => Err(()),
62                    }
63                }
64            }
65        )*
66    );
67}
68
69enum_value_set! {AggregateValueEnum: ArrayValue, StructValue}
70enum_value_set! {AnyValueEnum: ArrayValue, IntValue, FloatValue, PhiValue, FunctionValue, PointerValue, StructValue, VectorValue, InstructionValue, MetadataValue}
71enum_value_set! {BasicValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue}
72enum_value_set! {BasicMetadataValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue, MetadataValue}
73
74impl<'ctx> AnyValueEnum<'ctx> {
75    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
76        match LLVMGetTypeKind(LLVMTypeOf(value)) {
77            LLVMTypeKind::LLVMFloatTypeKind
78            | LLVMTypeKind::LLVMFP128TypeKind
79            | LLVMTypeKind::LLVMDoubleTypeKind
80            | LLVMTypeKind::LLVMHalfTypeKind
81            | LLVMTypeKind::LLVMX86_FP80TypeKind
82            | LLVMTypeKind::LLVMPPC_FP128TypeKind => {
83                AnyValueEnum::FloatValue(FloatValue::new(value))
84            }
85            LLVMTypeKind::LLVMIntegerTypeKind => AnyValueEnum::IntValue(IntValue::new(value)),
86            LLVMTypeKind::LLVMStructTypeKind => AnyValueEnum::StructValue(StructValue::new(value)),
87            LLVMTypeKind::LLVMPointerTypeKind => {
88                AnyValueEnum::PointerValue(PointerValue::new(value))
89            }
90            LLVMTypeKind::LLVMArrayTypeKind => AnyValueEnum::ArrayValue(ArrayValue::new(value)),
91            LLVMTypeKind::LLVMVectorTypeKind => AnyValueEnum::VectorValue(VectorValue::new(value)),
92            LLVMTypeKind::LLVMFunctionTypeKind => {
93                AnyValueEnum::FunctionValue(FunctionValue::new(value).unwrap())
94            }
95            LLVMTypeKind::LLVMVoidTypeKind => {
96                if LLVMIsAInstruction(value).is_null() {
97                    panic!("Void value isn't an instruction.");
98                }
99                AnyValueEnum::InstructionValue(InstructionValue::new(value))
100            }
101            LLVMTypeKind::LLVMMetadataTypeKind => {
102                panic!("Metadata values are not supported as AnyValue's.")
103            }
104            _ => panic!("The given type is not supported."),
105        }
106    }
107
108    pub fn get_type(&self) -> AnyTypeEnum<'ctx> {
109        unsafe { AnyTypeEnum::new(LLVMTypeOf(self.as_value_ref())) }
110    }
111
112    pub fn is_array_value(self) -> bool {
113        matches!(self, AnyValueEnum::ArrayValue(_))
114    }
115
116    pub fn is_int_value(self) -> bool {
117        matches!(self, AnyValueEnum::IntValue(_))
118    }
119
120    pub fn is_float_value(self) -> bool {
121        matches!(self, AnyValueEnum::FloatValue(_))
122    }
123
124    pub fn is_phi_value(self) -> bool {
125        matches!(self, AnyValueEnum::PhiValue(_))
126    }
127
128    pub fn is_function_value(self) -> bool {
129        matches!(self, AnyValueEnum::FunctionValue(_))
130    }
131
132    pub fn is_pointer_value(self) -> bool {
133        matches!(self, AnyValueEnum::PointerValue(_))
134    }
135
136    pub fn is_struct_value(self) -> bool {
137        matches!(self, AnyValueEnum::StructValue(_))
138    }
139
140    pub fn is_vector_value(self) -> bool {
141        matches!(self, AnyValueEnum::VectorValue(_))
142    }
143
144    pub fn is_instruction_value(self) -> bool {
145        matches!(self, AnyValueEnum::InstructionValue(_))
146    }
147
148    pub fn into_array_value(self) -> ArrayValue<'ctx> {
149        if let AnyValueEnum::ArrayValue(v) = self {
150            v
151        } else {
152            panic!("Found {:?} but expected the ArrayValue variant", self)
153        }
154    }
155
156    pub fn into_int_value(self) -> IntValue<'ctx> {
157        if let AnyValueEnum::IntValue(v) = self {
158            v
159        } else {
160            panic!("Found {:?} but expected the IntValue variant", self)
161        }
162    }
163
164    pub fn into_float_value(self) -> FloatValue<'ctx> {
165        if let AnyValueEnum::FloatValue(v) = self {
166            v
167        } else {
168            panic!("Found {:?} but expected the FloatValue variant", self)
169        }
170    }
171
172    pub fn into_phi_value(self) -> PhiValue<'ctx> {
173        if let AnyValueEnum::PhiValue(v) = self {
174            v
175        } else {
176            panic!("Found {:?} but expected the PhiValue variant", self)
177        }
178    }
179
180    pub fn into_function_value(self) -> FunctionValue<'ctx> {
181        if let AnyValueEnum::FunctionValue(v) = self {
182            v
183        } else {
184            panic!("Found {:?} but expected the FunctionValue variant", self)
185        }
186    }
187
188    pub fn into_pointer_value(self) -> PointerValue<'ctx> {
189        if let AnyValueEnum::PointerValue(v) = self {
190            v
191        } else {
192            panic!("Found {:?} but expected the PointerValue variant", self)
193        }
194    }
195
196    pub fn into_struct_value(self) -> StructValue<'ctx> {
197        if let AnyValueEnum::StructValue(v) = self {
198            v
199        } else {
200            panic!("Found {:?} but expected the StructValue variant", self)
201        }
202    }
203
204    pub fn into_vector_value(self) -> VectorValue<'ctx> {
205        if let AnyValueEnum::VectorValue(v) = self {
206            v
207        } else {
208            panic!("Found {:?} but expected the VectorValue variant", self)
209        }
210    }
211
212    pub fn into_instruction_value(self) -> InstructionValue<'ctx> {
213        if let AnyValueEnum::InstructionValue(v) = self {
214            v
215        } else {
216            panic!("Found {:?} but expected the InstructionValue variant", self)
217        }
218    }
219}
220
221impl<'ctx> BasicValueEnum<'ctx> {
222    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
223        match LLVMGetTypeKind(LLVMTypeOf(value)) {
224            LLVMTypeKind::LLVMFloatTypeKind
225            | LLVMTypeKind::LLVMFP128TypeKind
226            | LLVMTypeKind::LLVMDoubleTypeKind
227            | LLVMTypeKind::LLVMHalfTypeKind
228            | LLVMTypeKind::LLVMX86_FP80TypeKind
229            | LLVMTypeKind::LLVMPPC_FP128TypeKind => {
230                BasicValueEnum::FloatValue(FloatValue::new(value))
231            }
232            LLVMTypeKind::LLVMIntegerTypeKind => BasicValueEnum::IntValue(IntValue::new(value)),
233            LLVMTypeKind::LLVMStructTypeKind => {
234                BasicValueEnum::StructValue(StructValue::new(value))
235            }
236            LLVMTypeKind::LLVMPointerTypeKind => {
237                BasicValueEnum::PointerValue(PointerValue::new(value))
238            }
239            LLVMTypeKind::LLVMArrayTypeKind => BasicValueEnum::ArrayValue(ArrayValue::new(value)),
240            LLVMTypeKind::LLVMVectorTypeKind => {
241                BasicValueEnum::VectorValue(VectorValue::new(value))
242            }
243            _ => unreachable!("The given type is not a basic type."),
244        }
245    }
246
247    pub fn get_type(&self) -> BasicTypeEnum<'ctx> {
248        unsafe { BasicTypeEnum::new(LLVMTypeOf(self.as_value_ref())) }
249    }
250
251    pub fn is_array_value(self) -> bool {
252        matches!(self, BasicValueEnum::ArrayValue(_))
253    }
254
255    pub fn is_int_value(self) -> bool {
256        matches!(self, BasicValueEnum::IntValue(_))
257    }
258
259    pub fn is_float_value(self) -> bool {
260        matches!(self, BasicValueEnum::FloatValue(_))
261    }
262
263    pub fn is_pointer_value(self) -> bool {
264        matches!(self, BasicValueEnum::PointerValue(_))
265    }
266
267    pub fn is_struct_value(self) -> bool {
268        matches!(self, BasicValueEnum::StructValue(_))
269    }
270
271    pub fn is_vector_value(self) -> bool {
272        matches!(self, BasicValueEnum::VectorValue(_))
273    }
274
275    pub fn into_array_value(self) -> ArrayValue<'ctx> {
276        if let BasicValueEnum::ArrayValue(v) = self {
277            v
278        } else {
279            panic!("Found {:?} but expected the ArrayValue variant", self)
280        }
281    }
282
283    pub fn into_int_value(self) -> IntValue<'ctx> {
284        if let BasicValueEnum::IntValue(v) = self {
285            v
286        } else {
287            panic!("Found {:?} but expected the IntValue variant", self)
288        }
289    }
290
291    pub fn into_float_value(self) -> FloatValue<'ctx> {
292        if let BasicValueEnum::FloatValue(v) = self {
293            v
294        } else {
295            panic!("Found {:?} but expected the FloatValue variant", self)
296        }
297    }
298
299    pub fn into_pointer_value(self) -> PointerValue<'ctx> {
300        if let BasicValueEnum::PointerValue(v) = self {
301            v
302        } else {
303            panic!("Found {:?} but expected PointerValue variant", self)
304        }
305    }
306
307    pub fn into_struct_value(self) -> StructValue<'ctx> {
308        if let BasicValueEnum::StructValue(v) = self {
309            v
310        } else {
311            panic!("Found {:?} but expected the StructValue variant", self)
312        }
313    }
314
315    pub fn into_vector_value(self) -> VectorValue<'ctx> {
316        if let BasicValueEnum::VectorValue(v) = self {
317            v
318        } else {
319            panic!("Found {:?} but expected the VectorValue variant", self)
320        }
321    }
322}
323
324impl<'ctx> AggregateValueEnum<'ctx> {
325    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
326        match LLVMGetTypeKind(LLVMTypeOf(value)) {
327            LLVMTypeKind::LLVMArrayTypeKind => {
328                AggregateValueEnum::ArrayValue(ArrayValue::new(value))
329            }
330            LLVMTypeKind::LLVMStructTypeKind => {
331                AggregateValueEnum::StructValue(StructValue::new(value))
332            }
333            _ => unreachable!("The given type is not an aggregate type."),
334        }
335    }
336
337    pub fn is_array_value(self) -> bool {
338        matches!(self, AggregateValueEnum::ArrayValue(_))
339    }
340
341    pub fn is_struct_value(self) -> bool {
342        matches!(self, AggregateValueEnum::StructValue(_))
343    }
344
345    pub fn into_array_value(self) -> ArrayValue<'ctx> {
346        if let AggregateValueEnum::ArrayValue(v) = self {
347            v
348        } else {
349            panic!("Found {:?} but expected the ArrayValue variant", self)
350        }
351    }
352
353    pub fn into_struct_value(self) -> StructValue<'ctx> {
354        if let AggregateValueEnum::StructValue(v) = self {
355            v
356        } else {
357            panic!("Found {:?} but expected the StructValue variant", self)
358        }
359    }
360}
361
362impl<'ctx> BasicMetadataValueEnum<'ctx> {
363    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
364        match LLVMGetTypeKind(LLVMTypeOf(value)) {
365            LLVMTypeKind::LLVMFloatTypeKind
366            | LLVMTypeKind::LLVMFP128TypeKind
367            | LLVMTypeKind::LLVMDoubleTypeKind
368            | LLVMTypeKind::LLVMHalfTypeKind
369            | LLVMTypeKind::LLVMX86_FP80TypeKind
370            | LLVMTypeKind::LLVMPPC_FP128TypeKind => {
371                BasicMetadataValueEnum::FloatValue(FloatValue::new(value))
372            }
373            LLVMTypeKind::LLVMIntegerTypeKind => {
374                BasicMetadataValueEnum::IntValue(IntValue::new(value))
375            }
376            LLVMTypeKind::LLVMStructTypeKind => {
377                BasicMetadataValueEnum::StructValue(StructValue::new(value))
378            }
379            LLVMTypeKind::LLVMPointerTypeKind => {
380                BasicMetadataValueEnum::PointerValue(PointerValue::new(value))
381            }
382            LLVMTypeKind::LLVMArrayTypeKind => {
383                BasicMetadataValueEnum::ArrayValue(ArrayValue::new(value))
384            }
385            LLVMTypeKind::LLVMVectorTypeKind => {
386                BasicMetadataValueEnum::VectorValue(VectorValue::new(value))
387            }
388            LLVMTypeKind::LLVMMetadataTypeKind => {
389                BasicMetadataValueEnum::MetadataValue(MetadataValue::new(value))
390            }
391            _ => unreachable!("Unsupported type"),
392        }
393    }
394
395    pub fn is_array_value(self) -> bool {
396        matches!(self, BasicMetadataValueEnum::ArrayValue(_))
397    }
398
399    pub fn is_int_value(self) -> bool {
400        matches!(self, BasicMetadataValueEnum::IntValue(_))
401    }
402
403    pub fn is_float_value(self) -> bool {
404        matches!(self, BasicMetadataValueEnum::FloatValue(_))
405    }
406
407    pub fn is_pointer_value(self) -> bool {
408        matches!(self, BasicMetadataValueEnum::PointerValue(_))
409    }
410
411    pub fn is_struct_value(self) -> bool {
412        matches!(self, BasicMetadataValueEnum::StructValue(_))
413    }
414
415    pub fn is_vector_value(self) -> bool {
416        matches!(self, BasicMetadataValueEnum::VectorValue(_))
417    }
418
419    pub fn is_metadata_value(self) -> bool {
420        matches!(self, BasicMetadataValueEnum::MetadataValue(_))
421    }
422
423    pub fn into_array_value(self) -> ArrayValue<'ctx> {
424        if let BasicMetadataValueEnum::ArrayValue(v) = self {
425            v
426        } else {
427            panic!("Found {:?} but expected the ArrayValue variant", self)
428        }
429    }
430
431    pub fn into_int_value(self) -> IntValue<'ctx> {
432        if let BasicMetadataValueEnum::IntValue(v) = self {
433            v
434        } else {
435            panic!("Found {:?} but expected the IntValue variant", self)
436        }
437    }
438
439    pub fn into_float_value(self) -> FloatValue<'ctx> {
440        if let BasicMetadataValueEnum::FloatValue(v) = self {
441            v
442        } else {
443            panic!("Found {:?} but expected FloatValue variant", self)
444        }
445    }
446
447    pub fn into_pointer_value(self) -> PointerValue<'ctx> {
448        if let BasicMetadataValueEnum::PointerValue(v) = self {
449            v
450        } else {
451            panic!("Found {:?} but expected the PointerValue variant", self)
452        }
453    }
454
455    pub fn into_struct_value(self) -> StructValue<'ctx> {
456        if let BasicMetadataValueEnum::StructValue(v) = self {
457            v
458        } else {
459            panic!("Found {:?} but expected the StructValue variant", self)
460        }
461    }
462
463    pub fn into_vector_value(self) -> VectorValue<'ctx> {
464        if let BasicMetadataValueEnum::VectorValue(v) = self {
465            v
466        } else {
467            panic!("Found {:?} but expected the VectorValue variant", self)
468        }
469    }
470
471    pub fn into_metadata_value(self) -> MetadataValue<'ctx> {
472        if let BasicMetadataValueEnum::MetadataValue(v) = self {
473            v
474        } else {
475            panic!("Found {:?} but expected MetaData variant", self)
476        }
477    }
478}
479
480impl<'ctx> From<BasicValueEnum<'ctx>> for AnyValueEnum<'ctx> {
481    fn from(value: BasicValueEnum<'ctx>) -> Self {
482        unsafe { AnyValueEnum::new(value.as_value_ref()) }
483    }
484}
485
486impl<'ctx> From<BasicValueEnum<'ctx>> for BasicMetadataValueEnum<'ctx> {
487    fn from(value: BasicValueEnum<'ctx>) -> Self {
488        unsafe { BasicMetadataValueEnum::new(value.as_value_ref()) }
489    }
490}
491
492impl<'ctx> TryFrom<AnyValueEnum<'ctx>> for BasicValueEnum<'ctx> {
493    type Error = ();
494
495    fn try_from(value: AnyValueEnum<'ctx>) -> Result<Self, Self::Error> {
496        Ok(match value {
497            AnyValueEnum::ArrayValue(av) => av.into(),
498            AnyValueEnum::IntValue(iv) => iv.into(),
499            AnyValueEnum::FloatValue(fv) => fv.into(),
500            AnyValueEnum::PointerValue(pv) => pv.into(),
501            AnyValueEnum::StructValue(sv) => sv.into(),
502            AnyValueEnum::VectorValue(vv) => vv.into(),
503            _ => return Err(()),
504        })
505    }
506}
507
508impl Display for AggregateValueEnum<'_> {
509    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
510        write!(f, "{}", self.print_to_string())
511    }
512}
513
514impl Display for AnyValueEnum<'_> {
515    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
516        write!(f, "{}", self.print_to_string())
517    }
518}
519
520impl Display for BasicValueEnum<'_> {
521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522        write!(f, "{}", self.print_to_string())
523    }
524}
525
526impl Display for BasicMetadataValueEnum<'_> {
527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528        write!(f, "{}", self.print_to_string())
529    }
530}