1use llvm_sys::core::{LLVMIsConstant, LLVMIsPoison};
2use llvm_sys::prelude::LLVMValueRef;
3
4use std::fmt::Debug;
5
6use crate::support::LLVMString;
7use crate::types::{
8 FloatMathType, FloatType, IntMathType, IntType, PointerMathType, PointerType, ScalableVectorType, VectorType,
9};
10use crate::values::{
11 AggregateValueEnum, AnyValueEnum, ArrayValue, BasicValueEnum, BasicValueUse, CallSiteValue, FloatValue,
12 FunctionValue, GlobalValue, InstructionValue, IntValue, PhiValue, PointerValue, ScalableVectorValue, StructValue,
13 Value, VectorValue,
14};
15
16use super::{BasicMetadataValueEnum, MetadataValue};
17
18pub unsafe trait AsValueRef {
22 fn as_value_ref(&self) -> LLVMValueRef;
23}
24
25macro_rules! trait_value_set {
26 ($trait_name:ident: $($args:ident),*) => (
27 $(
28 unsafe impl<'ctx> $trait_name<'ctx> for $args<'ctx> {}
29 )*
30
31 );
34}
35
36macro_rules! math_trait_value_set {
37 ($trait_name:ident: $(($value_type:ident => $base_type:ident)),*) => (
38 $(
39 unsafe impl<'ctx> $trait_name<'ctx> for $value_type<'ctx> {
40 type BaseType = $base_type<'ctx>;
41 unsafe fn new(value: LLVMValueRef) -> $value_type<'ctx> {
42 unsafe {
43 $value_type::new(value)
44 }
45 }
46 }
47 )*
48 )
49}
50
51macro_rules! base_trait_value_set {
52 ($trait_name:ident: $($value_type:ident),*) => (
53 $(
54 unsafe impl<'ctx> $trait_name<'ctx> for $value_type<'ctx> {
55 unsafe fn new(value: LLVMValueRef) -> $value_type<'ctx> {
56 unsafe {
57 $value_type::new(value)
58 }
59 }
60 }
61 )*
62 )
63}
64
65pub unsafe trait AggregateValue<'ctx>: BasicValue<'ctx> {
67 fn as_aggregate_value_enum(&self) -> AggregateValueEnum<'ctx> {
69 unsafe { AggregateValueEnum::new(self.as_value_ref()) }
70 }
71
72 #[llvm_versions(..=14)]
76 fn const_extract_value(&self, indexes: &mut [u32]) -> BasicValueEnum<'ctx> {
77 use llvm_sys::core::LLVMConstExtractValue;
78
79 unsafe {
80 BasicValueEnum::new(LLVMConstExtractValue(
81 self.as_value_ref(),
82 indexes.as_mut_ptr(),
83 indexes.len() as u32,
84 ))
85 }
86 }
87
88 #[llvm_versions(..=14)]
90 fn const_insert_value<BV: BasicValue<'ctx>>(&self, value: BV, indexes: &mut [u32]) -> BasicValueEnum<'ctx> {
91 use llvm_sys::core::LLVMConstInsertValue;
92
93 unsafe {
94 BasicValueEnum::new(LLVMConstInsertValue(
95 self.as_value_ref(),
96 value.as_value_ref(),
97 indexes.as_mut_ptr(),
98 indexes.len() as u32,
99 ))
100 }
101 }
102}
103
104pub unsafe trait BasicValue<'ctx>: AnyValue<'ctx> {
106 fn as_basic_value_enum(&self) -> BasicValueEnum<'ctx> {
108 unsafe { BasicValueEnum::new(self.as_value_ref()) }
109 }
110
111 fn as_instruction_value(&self) -> Option<InstructionValue<'ctx>> {
114 let value = unsafe { Value::new(self.as_value_ref()) };
115
116 if !value.is_instruction() {
117 return None;
118 }
119
120 unsafe { Some(InstructionValue::new(self.as_value_ref())) }
121 }
122
123 fn get_first_use(&self) -> Option<BasicValueUse<'ctx>> {
124 unsafe { Value::new(self.as_value_ref()).get_first_use() }
125 }
126
127 fn set_name(&self, name: &str) {
129 unsafe { Value::new(self.as_value_ref()).set_name(name) }
130 }
131
132 fn is_const(&self) -> bool {
134 unsafe { LLVMIsConstant(self.as_value_ref()) == 1 }
135 }
136
137 }
140
141pub unsafe trait IntMathValue<'ctx>: BasicValue<'ctx> {
143 type BaseType: IntMathType<'ctx>;
144 unsafe fn new(value: LLVMValueRef) -> Self;
145}
146
147pub unsafe trait FloatMathValue<'ctx>: BasicValue<'ctx> {
149 type BaseType: FloatMathType<'ctx>;
150 unsafe fn new(value: LLVMValueRef) -> Self;
151}
152
153pub unsafe trait PointerMathValue<'ctx>: BasicValue<'ctx> {
154 type BaseType: PointerMathType<'ctx>;
155 unsafe fn new(value: LLVMValueRef) -> Self;
156}
157
158pub unsafe trait VectorBaseValue<'ctx>: BasicValue<'ctx> {
160 unsafe fn new(value: LLVMValueRef) -> Self;
161}
162
163pub unsafe trait AnyValue<'ctx>: AsValueRef + Debug {
166 fn as_any_value_enum(&self) -> AnyValueEnum<'ctx> {
168 unsafe { AnyValueEnum::new(self.as_value_ref()) }
169 }
170
171 fn print_to_string(&self) -> LLVMString {
173 unsafe { Value::new(self.as_value_ref()).print_to_string() }
174 }
175
176 fn is_poison(&self) -> bool {
178 unsafe { LLVMIsPoison(self.as_value_ref()) == 1 }
179 }
180}
181
182trait_value_set! {AggregateValue: ArrayValue, AggregateValueEnum, StructValue}
183trait_value_set! {AnyValue: AnyValueEnum, BasicValueEnum, BasicMetadataValueEnum, AggregateValueEnum, ArrayValue, IntValue, FloatValue, GlobalValue, PhiValue, PointerValue, FunctionValue, StructValue, VectorValue, ScalableVectorValue, InstructionValue, CallSiteValue, MetadataValue}
184trait_value_set! {BasicValue: ArrayValue, BasicValueEnum, AggregateValueEnum, IntValue, FloatValue, GlobalValue, StructValue, PointerValue, VectorValue, ScalableVectorValue}
185math_trait_value_set! {IntMathValue: (IntValue => IntType), (VectorValue => VectorType), (ScalableVectorValue => ScalableVectorType), (PointerValue => IntType)}
186math_trait_value_set! {FloatMathValue: (FloatValue => FloatType), (VectorValue => VectorType), (ScalableVectorValue => ScalableVectorType)}
187math_trait_value_set! {PointerMathValue: (PointerValue => PointerType), (VectorValue => VectorType), (ScalableVectorValue => ScalableVectorType)}
188base_trait_value_set! {VectorBaseValue: VectorValue, ScalableVectorValue}