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 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}