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}