1#[llvm_versions(..=16)]
2use llvm_sys::core::LLVMConstSelect;
3#[llvm_versions(..=17)]
4use llvm_sys::core::{
5 LLVMConstAShr, LLVMConstAnd, LLVMConstIntCast, LLVMConstLShr, LLVMConstOr, LLVMConstSExt, LLVMConstSExtOrBitCast,
6 LLVMConstSIToFP, LLVMConstUIToFP, LLVMConstZExt, LLVMConstZExtOrBitCast,
7};
8use llvm_sys::core::{
9 LLVMConstAdd, LLVMConstBitCast, LLVMConstICmp, LLVMConstIntGetSExtValue, LLVMConstIntGetZExtValue,
10 LLVMConstIntToPtr, LLVMConstMul, LLVMConstNSWAdd, LLVMConstNSWMul, LLVMConstNSWNeg, LLVMConstNSWSub,
11 LLVMConstNUWAdd, LLVMConstNUWMul, LLVMConstNUWNeg, LLVMConstNUWSub, LLVMConstNeg, LLVMConstNot, LLVMConstShl,
12 LLVMConstSub, LLVMConstTrunc, LLVMConstTruncOrBitCast, LLVMConstXor, LLVMIsAConstantInt,
13};
14use llvm_sys::prelude::LLVMValueRef;
15
16use std::convert::TryFrom;
17use std::ffi::CStr;
18use std::fmt::{self, Display};
19
20#[llvm_versions(..=17)]
21use crate::types::FloatType;
22use crate::types::{AsTypeRef, IntType, PointerType};
23use crate::values::traits::AsValueRef;
24#[llvm_versions(..=17)]
25use crate::values::FloatValue;
26#[llvm_versions(..=16)]
27use crate::values::{BasicValue, BasicValueEnum};
28use crate::values::{InstructionValue, PointerValue, Value};
29use crate::IntPredicate;
30
31use super::AnyValue;
32
33#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
34pub struct IntValue<'ctx> {
35 int_value: Value<'ctx>,
36}
37
38impl<'ctx> IntValue<'ctx> {
39 pub unsafe fn new(value: LLVMValueRef) -> Self {
45 assert!(!value.is_null());
46
47 IntValue {
48 int_value: Value::new(value),
49 }
50 }
51
52 pub fn get_name(&self) -> &CStr {
55 self.int_value.get_name()
56 }
57
58 pub fn set_name(&self, name: &str) {
60 self.int_value.set_name(name)
61 }
62
63 pub fn get_type(self) -> IntType<'ctx> {
64 unsafe { IntType::new(self.int_value.get_type()) }
65 }
66
67 pub fn is_null(self) -> bool {
68 self.int_value.is_null()
69 }
70
71 pub fn is_undef(self) -> bool {
72 self.int_value.is_undef()
73 }
74
75 pub fn print_to_stderr(self) {
76 self.int_value.print_to_stderr()
77 }
78
79 pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
80 self.int_value.as_instruction()
81 }
82
83 pub fn const_not(self) -> Self {
84 unsafe { IntValue::new(LLVMConstNot(self.as_value_ref())) }
85 }
86
87 pub fn const_neg(self) -> Self {
89 unsafe { IntValue::new(LLVMConstNeg(self.as_value_ref())) }
90 }
91
92 pub fn const_nsw_neg(self) -> Self {
93 unsafe { IntValue::new(LLVMConstNSWNeg(self.as_value_ref())) }
94 }
95
96 pub fn const_nuw_neg(self) -> Self {
97 unsafe { IntValue::new(LLVMConstNUWNeg(self.as_value_ref())) }
98 }
99
100 pub fn const_add(self, rhs: IntValue<'ctx>) -> Self {
101 unsafe { IntValue::new(LLVMConstAdd(self.as_value_ref(), rhs.as_value_ref())) }
102 }
103
104 pub fn const_nsw_add(self, rhs: IntValue<'ctx>) -> Self {
105 unsafe { IntValue::new(LLVMConstNSWAdd(self.as_value_ref(), rhs.as_value_ref())) }
106 }
107
108 pub fn const_nuw_add(self, rhs: IntValue<'ctx>) -> Self {
109 unsafe { IntValue::new(LLVMConstNUWAdd(self.as_value_ref(), rhs.as_value_ref())) }
110 }
111
112 pub fn const_sub(self, rhs: IntValue<'ctx>) -> Self {
113 unsafe { IntValue::new(LLVMConstSub(self.as_value_ref(), rhs.as_value_ref())) }
114 }
115
116 pub fn const_nsw_sub(self, rhs: IntValue<'ctx>) -> Self {
117 unsafe { IntValue::new(LLVMConstNSWSub(self.as_value_ref(), rhs.as_value_ref())) }
118 }
119
120 pub fn const_nuw_sub(self, rhs: IntValue<'ctx>) -> Self {
121 unsafe { IntValue::new(LLVMConstNUWSub(self.as_value_ref(), rhs.as_value_ref())) }
122 }
123
124 pub fn const_mul(self, rhs: IntValue<'ctx>) -> Self {
125 unsafe { IntValue::new(LLVMConstMul(self.as_value_ref(), rhs.as_value_ref())) }
126 }
127
128 pub fn const_nsw_mul(self, rhs: IntValue<'ctx>) -> Self {
129 unsafe { IntValue::new(LLVMConstNSWMul(self.as_value_ref(), rhs.as_value_ref())) }
130 }
131
132 pub fn const_nuw_mul(self, rhs: IntValue<'ctx>) -> Self {
133 unsafe { IntValue::new(LLVMConstNUWMul(self.as_value_ref(), rhs.as_value_ref())) }
134 }
135
136 #[llvm_versions(..=14)]
137 pub fn const_unsigned_div(self, rhs: IntValue<'ctx>) -> Self {
138 use llvm_sys::core::LLVMConstUDiv;
139
140 unsafe { IntValue::new(LLVMConstUDiv(self.as_value_ref(), rhs.as_value_ref())) }
141 }
142
143 #[llvm_versions(..=14)]
144 pub fn const_signed_div(self, rhs: IntValue<'ctx>) -> Self {
145 use llvm_sys::core::LLVMConstSDiv;
146
147 unsafe { IntValue::new(LLVMConstSDiv(self.as_value_ref(), rhs.as_value_ref())) }
148 }
149
150 #[llvm_versions(..=14)]
151 pub fn const_exact_signed_div(self, rhs: IntValue<'ctx>) -> Self {
152 use llvm_sys::core::LLVMConstExactSDiv;
153
154 unsafe { IntValue::new(LLVMConstExactSDiv(self.as_value_ref(), rhs.as_value_ref())) }
155 }
156
157 #[llvm_versions(..=14)]
158 pub fn const_exact_unsigned_div(self, rhs: IntValue<'ctx>) -> Self {
159 use llvm_sys::core::LLVMConstExactUDiv;
160
161 unsafe { IntValue::new(LLVMConstExactUDiv(self.as_value_ref(), rhs.as_value_ref())) }
162 }
163
164 #[llvm_versions(..=14)]
165 pub fn const_unsigned_remainder(self, rhs: IntValue<'ctx>) -> Self {
166 use llvm_sys::core::LLVMConstURem;
167
168 unsafe { IntValue::new(LLVMConstURem(self.as_value_ref(), rhs.as_value_ref())) }
169 }
170
171 #[llvm_versions(..=14)]
172 pub fn const_signed_remainder(self, rhs: IntValue<'ctx>) -> Self {
173 use llvm_sys::core::LLVMConstSRem;
174
175 unsafe { IntValue::new(LLVMConstSRem(self.as_value_ref(), rhs.as_value_ref())) }
176 }
177
178 #[llvm_versions(..=17)]
179 pub fn const_and(self, rhs: IntValue<'ctx>) -> Self {
180 unsafe { IntValue::new(LLVMConstAnd(self.as_value_ref(), rhs.as_value_ref())) }
181 }
182
183 #[llvm_versions(..=17)]
184 pub fn const_or(self, rhs: IntValue<'ctx>) -> Self {
185 unsafe { IntValue::new(LLVMConstOr(self.as_value_ref(), rhs.as_value_ref())) }
186 }
187
188 pub fn const_xor(self, rhs: IntValue<'ctx>) -> Self {
189 unsafe { IntValue::new(LLVMConstXor(self.as_value_ref(), rhs.as_value_ref())) }
190 }
191
192 #[llvm_versions(..=17)]
194 pub fn const_cast(self, int_type: IntType<'ctx>, is_signed: bool) -> Self {
195 unsafe {
196 IntValue::new(LLVMConstIntCast(
197 self.as_value_ref(),
198 int_type.as_type_ref(),
199 is_signed as i32,
200 ))
201 }
202 }
203
204 pub fn const_shl(self, rhs: IntValue<'ctx>) -> Self {
206 unsafe { IntValue::new(LLVMConstShl(self.as_value_ref(), rhs.as_value_ref())) }
207 }
208
209 #[llvm_versions(..=17)]
210 pub fn const_rshr(self, rhs: IntValue<'ctx>) -> Self {
211 unsafe { IntValue::new(LLVMConstLShr(self.as_value_ref(), rhs.as_value_ref())) }
212 }
213
214 #[llvm_versions(..=17)]
215 pub fn const_ashr(self, rhs: IntValue<'ctx>) -> Self {
216 unsafe { IntValue::new(LLVMConstAShr(self.as_value_ref(), rhs.as_value_ref())) }
217 }
218
219 #[llvm_versions(..=17)]
221 pub fn const_unsigned_to_float(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
222 unsafe { FloatValue::new(LLVMConstUIToFP(self.as_value_ref(), float_type.as_type_ref())) }
223 }
224
225 #[llvm_versions(..=17)]
227 pub fn const_signed_to_float(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
228 unsafe { FloatValue::new(LLVMConstSIToFP(self.as_value_ref(), float_type.as_type_ref())) }
229 }
230
231 pub fn const_to_pointer(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> {
232 unsafe { PointerValue::new(LLVMConstIntToPtr(self.as_value_ref(), ptr_type.as_type_ref())) }
233 }
234
235 pub fn const_truncate(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
236 unsafe { IntValue::new(LLVMConstTrunc(self.as_value_ref(), int_type.as_type_ref())) }
237 }
238
239 #[llvm_versions(..=17)]
241 pub fn const_s_extend(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
242 unsafe { IntValue::new(LLVMConstSExt(self.as_value_ref(), int_type.as_type_ref())) }
243 }
244
245 #[llvm_versions(..=17)]
247 pub fn const_z_ext(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
248 unsafe { IntValue::new(LLVMConstZExt(self.as_value_ref(), int_type.as_type_ref())) }
249 }
250
251 pub fn const_truncate_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
252 unsafe { IntValue::new(LLVMConstTruncOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
253 }
254
255 #[llvm_versions(..=17)]
257 pub fn const_s_extend_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
258 unsafe { IntValue::new(LLVMConstSExtOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
259 }
260
261 #[llvm_versions(..=17)]
263 pub fn const_z_ext_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
264 unsafe { IntValue::new(LLVMConstZExtOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
265 }
266
267 pub fn const_bit_cast(self, int_type: IntType) -> IntValue<'ctx> {
268 unsafe { IntValue::new(LLVMConstBitCast(self.as_value_ref(), int_type.as_type_ref())) }
269 }
270
271 pub fn const_int_compare(self, op: IntPredicate, rhs: IntValue<'ctx>) -> IntValue<'ctx> {
273 unsafe { IntValue::new(LLVMConstICmp(op.into(), self.as_value_ref(), rhs.as_value_ref())) }
274 }
275
276 #[llvm_versions(..=16)]
278 pub fn const_select<BV: BasicValue<'ctx>>(self, then: BV, else_: BV) -> BasicValueEnum<'ctx> {
279 unsafe {
280 BasicValueEnum::new(LLVMConstSelect(
281 self.as_value_ref(),
282 then.as_value_ref(),
283 else_.as_value_ref(),
284 ))
285 }
286 }
287
288 pub fn is_const(self) -> bool {
305 self.int_value.is_const()
306 }
307
308 pub fn is_constant_int(self) -> bool {
324 !unsafe { LLVMIsAConstantInt(self.as_value_ref()) }.is_null()
325 }
326
327 pub fn get_zero_extended_constant(self) -> Option<u64> {
341 if !self.is_constant_int() {
343 return None;
344 }
345 if self.get_type().get_bit_width() > 64 {
346 return None;
347 }
348
349 unsafe { Some(LLVMConstIntGetZExtValue(self.as_value_ref())) }
350 }
351
352 pub fn get_sign_extended_constant(self) -> Option<i64> {
366 if !self.is_constant_int() {
368 return None;
369 }
370 if self.get_type().get_bit_width() > 64 {
371 return None;
372 }
373
374 unsafe { Some(LLVMConstIntGetSExtValue(self.as_value_ref())) }
375 }
376
377 pub fn replace_all_uses_with(self, other: IntValue<'ctx>) {
378 self.int_value.replace_all_uses_with(other.as_value_ref())
379 }
380}
381
382unsafe impl AsValueRef for IntValue<'_> {
383 fn as_value_ref(&self) -> LLVMValueRef {
384 self.int_value.value
385 }
386}
387
388impl Display for IntValue<'_> {
389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390 write!(f, "{}", self.print_to_string())
391 }
392}
393
394impl<'ctx> TryFrom<InstructionValue<'ctx>> for IntValue<'ctx> {
395 type Error = ();
396
397 fn try_from(value: InstructionValue) -> Result<Self, Self::Error> {
398 if value.get_type().is_int_type() {
399 unsafe { Ok(IntValue::new(value.as_value_ref())) }
400 } else {
401 Err(())
402 }
403 }
404}