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