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