inkwell/values/
traits.rs

1use llvm_sys::prelude::LLVMValueRef;
2
3#[llvm_versions(12..)]
4use llvm_sys::core::LLVMIsPoison;
5
6use std::fmt::Debug;
7
8use crate::support::LLVMString;
9use crate::types::{
10    FloatMathType, FloatType, IntMathType, IntType, PointerMathType, PointerType, ScalableVectorType, VectorType,
11};
12use crate::values::{
13    AggregateValueEnum, AnyValueEnum, ArrayValue, BasicValueEnum, BasicValueUse, CallSiteValue, FloatValue,
14    FunctionValue, GlobalValue, InstructionValue, IntValue, PhiValue, PointerValue, ScalableVectorValue, StructValue,
15    Value, VectorValue,
16};
17
18use super::{BasicMetadataValueEnum, MetadataValue};
19
20// This is an ugly privacy hack so that Type can stay private to this module
21// and so that super traits using this trait will be not be implementable
22// outside this library
23pub unsafe trait AsValueRef {
24    fn as_value_ref(&self) -> LLVMValueRef;
25}
26
27macro_rules! trait_value_set {
28    ($trait_name:ident: $($args:ident),*) => (
29        $(
30            unsafe impl<'ctx> $trait_name<'ctx> for $args<'ctx> {}
31        )*
32
33        // REVIEW: Possible encompassing methods to implement:
34        // as_instruction, is_sized, ge/set metadata methods
35    );
36}
37
38macro_rules! math_trait_value_set {
39    ($trait_name:ident: $(($value_type:ident => $base_type:ident)),*) => (
40        $(
41            unsafe impl<'ctx> $trait_name<'ctx> for $value_type<'ctx> {
42                type BaseType = $base_type<'ctx>;
43                unsafe fn new(value: LLVMValueRef) -> $value_type<'ctx> {
44                    unsafe {
45                        $value_type::new(value)
46                    }
47                }
48            }
49        )*
50    )
51}
52
53macro_rules! base_trait_value_set {
54    ($trait_name:ident: $($value_type:ident),*) => (
55        $(
56            unsafe impl<'ctx> $trait_name<'ctx> for $value_type<'ctx> {
57                unsafe fn new(value: LLVMValueRef) -> $value_type<'ctx> {
58                    unsafe {
59                        $value_type::new(value)
60                    }
61                }
62            }
63        )*
64    )
65}
66
67/// Represents an aggregate value, built on top of other values.
68pub unsafe trait AggregateValue<'ctx>: BasicValue<'ctx> {
69    /// Returns an enum containing a typed version of the `AggregateValue`.
70    fn as_aggregate_value_enum(&self) -> AggregateValueEnum<'ctx> {
71        unsafe { AggregateValueEnum::new(self.as_value_ref()) }
72    }
73
74    // REVIEW: How does LLVM treat out of bound index? Maybe we should return an Option?
75    // or is that only in bounds GEP
76    // REVIEW: Should this be AggregatePointerValue?
77    #[llvm_versions(..=14)]
78    fn const_extract_value(&self, indexes: &mut [u32]) -> BasicValueEnum<'ctx> {
79        use llvm_sys::core::LLVMConstExtractValue;
80
81        unsafe {
82            BasicValueEnum::new(LLVMConstExtractValue(
83                self.as_value_ref(),
84                indexes.as_mut_ptr(),
85                indexes.len() as u32,
86            ))
87        }
88    }
89
90    // SubTypes: value should really be T in self: VectorValue<T> I think
91    #[llvm_versions(..=14)]
92    fn const_insert_value<BV: BasicValue<'ctx>>(&self, value: BV, indexes: &mut [u32]) -> BasicValueEnum<'ctx> {
93        use llvm_sys::core::LLVMConstInsertValue;
94
95        unsafe {
96            BasicValueEnum::new(LLVMConstInsertValue(
97                self.as_value_ref(),
98                value.as_value_ref(),
99                indexes.as_mut_ptr(),
100                indexes.len() as u32,
101            ))
102        }
103    }
104}
105
106/// Represents a basic value, which can be used both by itself, or in an `AggregateValue`.
107pub unsafe trait BasicValue<'ctx>: AnyValue<'ctx> {
108    /// Returns an enum containing a typed version of the `BasicValue`.
109    fn as_basic_value_enum(&self) -> BasicValueEnum<'ctx> {
110        unsafe { BasicValueEnum::new(self.as_value_ref()) }
111    }
112
113    /// Most `BasicValue`s are the byproduct of an instruction
114    /// and so are convertible into an `InstructionValue`
115    fn as_instruction_value(&self) -> Option<InstructionValue<'ctx>> {
116        let value = unsafe { Value::new(self.as_value_ref()) };
117
118        if !value.is_instruction() {
119            return None;
120        }
121
122        unsafe { Some(InstructionValue::new(self.as_value_ref())) }
123    }
124
125    fn get_first_use(&self) -> Option<BasicValueUse> {
126        unsafe { Value::new(self.as_value_ref()).get_first_use() }
127    }
128
129    /// Sets the name of a `BasicValue`. If the value is a constant, this is a noop.
130    fn set_name(&self, name: &str) {
131        unsafe { Value::new(self.as_value_ref()).set_name(name) }
132    }
133
134    // REVIEW: Possible encompassing methods to implement:
135    // get/set metadata
136}
137
138/// Represents a value which is permitted in integer math operations
139pub unsafe trait IntMathValue<'ctx>: BasicValue<'ctx> {
140    type BaseType: IntMathType<'ctx>;
141    unsafe fn new(value: LLVMValueRef) -> Self;
142}
143
144/// Represents a value which is permitted in floating point math operations
145pub unsafe trait FloatMathValue<'ctx>: BasicValue<'ctx> {
146    type BaseType: FloatMathType<'ctx>;
147    unsafe fn new(value: LLVMValueRef) -> Self;
148}
149
150pub unsafe trait PointerMathValue<'ctx>: BasicValue<'ctx> {
151    type BaseType: PointerMathType<'ctx>;
152    unsafe fn new(value: LLVMValueRef) -> Self;
153}
154
155/// Represents a value which is permitted in vector operations, either fixed or scalable
156pub unsafe trait VectorBaseValue<'ctx>: BasicValue<'ctx> {
157    unsafe fn new(value: LLVMValueRef) -> Self;
158}
159
160// REVIEW: print_to_string might be a good candidate to live here?
161/// Defines any struct wrapping an LLVM value.
162pub unsafe trait AnyValue<'ctx>: AsValueRef + Debug {
163    /// Returns an enum containing a typed version of `AnyValue`.
164    fn as_any_value_enum(&self) -> AnyValueEnum<'ctx> {
165        unsafe { AnyValueEnum::new(self.as_value_ref()) }
166    }
167
168    /// Prints a value to a `LLVMString`
169    fn print_to_string(&self) -> LLVMString {
170        unsafe { Value::new(self.as_value_ref()).print_to_string() }
171    }
172
173    /// Returns whether the value is `poison`
174    #[llvm_versions(12..)]
175    fn is_poison(&self) -> bool {
176        unsafe { LLVMIsPoison(self.as_value_ref()) == 1 }
177    }
178}
179
180trait_value_set! {AggregateValue: ArrayValue, AggregateValueEnum, StructValue}
181trait_value_set! {AnyValue: AnyValueEnum, BasicValueEnum, BasicMetadataValueEnum, AggregateValueEnum, ArrayValue, IntValue, FloatValue, GlobalValue, PhiValue, PointerValue, FunctionValue, StructValue, VectorValue, ScalableVectorValue, InstructionValue, CallSiteValue, MetadataValue}
182trait_value_set! {BasicValue: ArrayValue, BasicValueEnum, AggregateValueEnum, IntValue, FloatValue, GlobalValue, StructValue, PointerValue, VectorValue, ScalableVectorValue}
183math_trait_value_set! {IntMathValue: (IntValue => IntType), (VectorValue => VectorType), (ScalableVectorValue => ScalableVectorType), (PointerValue => IntType)}
184math_trait_value_set! {FloatMathValue: (FloatValue => FloatType), (VectorValue => VectorType), (ScalableVectorValue => ScalableVectorType)}
185math_trait_value_set! {PointerMathValue: (PointerValue => PointerType), (VectorValue => VectorType), (ScalableVectorValue => ScalableVectorType)}
186base_trait_value_set! {VectorBaseValue: VectorValue, ScalableVectorValue}