llvm_plugin_inkwell/values/
int_value.rs1use llvm_sys::core::{
2 LLVMConstAShr, LLVMConstAdd, LLVMConstAnd, LLVMConstBitCast, LLVMConstICmp, LLVMConstIntCast,
3 LLVMConstIntGetSExtValue, LLVMConstIntGetZExtValue, LLVMConstIntToPtr, LLVMConstLShr, LLVMConstMul,
4 LLVMConstNSWAdd, LLVMConstNSWMul, LLVMConstNSWNeg, LLVMConstNSWSub, LLVMConstNUWAdd, LLVMConstNUWMul,
5 LLVMConstNUWNeg, LLVMConstNUWSub, LLVMConstNeg, LLVMConstNot, LLVMConstOr, LLVMConstSExt, LLVMConstSExtOrBitCast,
6 LLVMConstSIToFP, LLVMConstSelect, LLVMConstShl, LLVMConstSub, LLVMConstTrunc, LLVMConstTruncOrBitCast,
7 LLVMConstUIToFP, LLVMConstXor, LLVMConstZExt, LLVMConstZExtOrBitCast, LLVMIsAConstantInt,
8};
9use llvm_sys::prelude::LLVMValueRef;
10
11use std::convert::TryFrom;
12use std::ffi::CStr;
13use std::fmt::{self, Display};
14
15use crate::types::{AsTypeRef, FloatType, IntType, PointerType};
16use crate::values::traits::AsValueRef;
17use crate::values::{BasicValue, BasicValueEnum, FloatValue, InstructionValue, PointerValue, Value};
18use crate::IntPredicate;
19
20use super::AnyValue;
21
22#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
23pub struct IntValue<'ctx> {
24 int_value: Value<'ctx>,
25}
26
27impl<'ctx> IntValue<'ctx> {
28 pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
29 assert!(!value.is_null());
30
31 IntValue {
32 int_value: Value::new(value),
33 }
34 }
35
36 pub fn get_name(&self) -> &CStr {
39 self.int_value.get_name()
40 }
41
42 pub fn set_name(&self, name: &str) {
44 self.int_value.set_name(name)
45 }
46
47 pub fn get_type(self) -> IntType<'ctx> {
48 unsafe { IntType::new(self.int_value.get_type()) }
49 }
50
51 pub fn is_null(self) -> bool {
52 self.int_value.is_null()
53 }
54
55 pub fn is_undef(self) -> bool {
56 self.int_value.is_undef()
57 }
58
59 pub fn print_to_stderr(self) {
60 self.int_value.print_to_stderr()
61 }
62
63 pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
64 self.int_value.as_instruction()
65 }
66
67 pub fn const_not(self) -> Self {
68 unsafe { IntValue::new(LLVMConstNot(self.as_value_ref())) }
69 }
70
71 pub fn const_neg(self) -> Self {
73 unsafe { IntValue::new(LLVMConstNeg(self.as_value_ref())) }
74 }
75
76 pub fn const_nsw_neg(self) -> Self {
77 unsafe { IntValue::new(LLVMConstNSWNeg(self.as_value_ref())) }
78 }
79
80 pub fn const_nuw_neg(self) -> Self {
81 unsafe { IntValue::new(LLVMConstNUWNeg(self.as_value_ref())) }
82 }
83
84 pub fn const_add(self, rhs: IntValue<'ctx>) -> Self {
85 unsafe { IntValue::new(LLVMConstAdd(self.as_value_ref(), rhs.as_value_ref())) }
86 }
87
88 pub fn const_nsw_add(self, rhs: IntValue<'ctx>) -> Self {
89 unsafe { IntValue::new(LLVMConstNSWAdd(self.as_value_ref(), rhs.as_value_ref())) }
90 }
91
92 pub fn const_nuw_add(self, rhs: IntValue<'ctx>) -> Self {
93 unsafe { IntValue::new(LLVMConstNUWAdd(self.as_value_ref(), rhs.as_value_ref())) }
94 }
95
96 pub fn const_sub(self, rhs: IntValue<'ctx>) -> Self {
97 unsafe { IntValue::new(LLVMConstSub(self.as_value_ref(), rhs.as_value_ref())) }
98 }
99
100 pub fn const_nsw_sub(self, rhs: IntValue<'ctx>) -> Self {
101 unsafe { IntValue::new(LLVMConstNSWSub(self.as_value_ref(), rhs.as_value_ref())) }
102 }
103
104 pub fn const_nuw_sub(self, rhs: IntValue<'ctx>) -> Self {
105 unsafe { IntValue::new(LLVMConstNUWSub(self.as_value_ref(), rhs.as_value_ref())) }
106 }
107
108 pub fn const_mul(self, rhs: IntValue<'ctx>) -> Self {
109 unsafe { IntValue::new(LLVMConstMul(self.as_value_ref(), rhs.as_value_ref())) }
110 }
111
112 pub fn const_nsw_mul(self, rhs: IntValue<'ctx>) -> Self {
113 unsafe { IntValue::new(LLVMConstNSWMul(self.as_value_ref(), rhs.as_value_ref())) }
114 }
115
116 pub fn const_nuw_mul(self, rhs: IntValue<'ctx>) -> Self {
117 unsafe { IntValue::new(LLVMConstNUWMul(self.as_value_ref(), rhs.as_value_ref())) }
118 }
119
120 #[llvm_versions(4.0..=14.0)]
121 pub fn const_unsigned_div(self, rhs: IntValue<'ctx>) -> Self {
122 use llvm_sys::core::LLVMConstUDiv;
123
124 unsafe { IntValue::new(LLVMConstUDiv(self.as_value_ref(), rhs.as_value_ref())) }
125 }
126
127 #[llvm_versions(4.0..=14.0)]
128 pub fn const_signed_div(self, rhs: IntValue<'ctx>) -> Self {
129 use llvm_sys::core::LLVMConstSDiv;
130
131 unsafe { IntValue::new(LLVMConstSDiv(self.as_value_ref(), rhs.as_value_ref())) }
132 }
133
134 #[llvm_versions(4.0..=14.0)]
135 pub fn const_exact_signed_div(self, rhs: IntValue<'ctx>) -> Self {
136 use llvm_sys::core::LLVMConstExactSDiv;
137
138 unsafe { IntValue::new(LLVMConstExactSDiv(self.as_value_ref(), rhs.as_value_ref())) }
139 }
140
141 #[llvm_versions(4.0..=14.0)]
142 pub fn const_exact_unsigned_div(self, rhs: IntValue<'ctx>) -> Self {
143 use llvm_sys::core::LLVMConstExactUDiv;
144
145 unsafe { IntValue::new(LLVMConstExactUDiv(self.as_value_ref(), rhs.as_value_ref())) }
146 }
147
148 #[llvm_versions(4.0..=14.0)]
149 pub fn const_unsigned_remainder(self, rhs: IntValue<'ctx>) -> Self {
150 use llvm_sys::core::LLVMConstURem;
151
152 unsafe { IntValue::new(LLVMConstURem(self.as_value_ref(), rhs.as_value_ref())) }
153 }
154
155 #[llvm_versions(4.0..=14.0)]
156 pub fn const_signed_remainder(self, rhs: IntValue<'ctx>) -> Self {
157 use llvm_sys::core::LLVMConstSRem;
158
159 unsafe { IntValue::new(LLVMConstSRem(self.as_value_ref(), rhs.as_value_ref())) }
160 }
161
162 pub fn const_and(self, rhs: IntValue<'ctx>) -> Self {
163 unsafe { IntValue::new(LLVMConstAnd(self.as_value_ref(), rhs.as_value_ref())) }
164 }
165
166 pub fn const_or(self, rhs: IntValue<'ctx>) -> Self {
167 unsafe { IntValue::new(LLVMConstOr(self.as_value_ref(), rhs.as_value_ref())) }
168 }
169
170 pub fn const_xor(self, rhs: IntValue<'ctx>) -> Self {
171 unsafe { IntValue::new(LLVMConstXor(self.as_value_ref(), rhs.as_value_ref())) }
172 }
173
174 pub fn const_cast(self, int_type: IntType<'ctx>, is_signed: bool) -> Self {
176 unsafe {
177 IntValue::new(LLVMConstIntCast(
178 self.as_value_ref(),
179 int_type.as_type_ref(),
180 is_signed as i32,
181 ))
182 }
183 }
184
185 pub fn const_shl(self, rhs: IntValue<'ctx>) -> Self {
187 unsafe { IntValue::new(LLVMConstShl(self.as_value_ref(), rhs.as_value_ref())) }
188 }
189
190 pub fn const_rshr(self, rhs: IntValue<'ctx>) -> Self {
191 unsafe { IntValue::new(LLVMConstLShr(self.as_value_ref(), rhs.as_value_ref())) }
192 }
193
194 pub fn const_ashr(self, rhs: IntValue<'ctx>) -> Self {
195 unsafe { IntValue::new(LLVMConstAShr(self.as_value_ref(), rhs.as_value_ref())) }
196 }
197
198 pub fn const_unsigned_to_float(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
200 unsafe { FloatValue::new(LLVMConstUIToFP(self.as_value_ref(), float_type.as_type_ref())) }
201 }
202
203 pub fn const_signed_to_float(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
205 unsafe { FloatValue::new(LLVMConstSIToFP(self.as_value_ref(), float_type.as_type_ref())) }
206 }
207
208 pub fn const_to_pointer(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> {
209 unsafe { PointerValue::new(LLVMConstIntToPtr(self.as_value_ref(), ptr_type.as_type_ref())) }
210 }
211
212 pub fn const_truncate(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
213 unsafe { IntValue::new(LLVMConstTrunc(self.as_value_ref(), int_type.as_type_ref())) }
214 }
215
216 pub fn const_s_extend(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
218 unsafe { IntValue::new(LLVMConstSExt(self.as_value_ref(), int_type.as_type_ref())) }
219 }
220
221 pub fn const_z_ext(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
223 unsafe { IntValue::new(LLVMConstZExt(self.as_value_ref(), int_type.as_type_ref())) }
224 }
225
226 pub fn const_truncate_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
227 unsafe { IntValue::new(LLVMConstTruncOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
228 }
229
230 pub fn const_s_extend_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
232 unsafe { IntValue::new(LLVMConstSExtOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
233 }
234
235 pub fn const_z_ext_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
237 unsafe { IntValue::new(LLVMConstZExtOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
238 }
239
240 pub fn const_bit_cast(self, int_type: IntType) -> IntValue<'ctx> {
241 unsafe { IntValue::new(LLVMConstBitCast(self.as_value_ref(), int_type.as_type_ref())) }
242 }
243
244 pub fn const_int_compare(self, op: IntPredicate, rhs: IntValue<'ctx>) -> IntValue<'ctx> {
246 unsafe { IntValue::new(LLVMConstICmp(op.into(), self.as_value_ref(), rhs.as_value_ref())) }
247 }
248
249 pub fn const_select<BV: BasicValue<'ctx>>(self, then: BV, else_: BV) -> BasicValueEnum<'ctx> {
251 unsafe {
252 BasicValueEnum::new(LLVMConstSelect(
253 self.as_value_ref(),
254 then.as_value_ref(),
255 else_.as_value_ref(),
256 ))
257 }
258 }
259
260 pub fn is_const(self) -> bool {
277 self.int_value.is_const()
278 }
279
280 pub fn is_constant_int(self) -> bool {
296 !unsafe { LLVMIsAConstantInt(self.as_value_ref()) }.is_null()
297 }
298
299 pub fn get_zero_extended_constant(self) -> Option<u64> {
313 if !self.is_constant_int() {
315 return None;
316 }
317 if self.get_type().get_bit_width() > 64 {
318 return None;
319 }
320
321 unsafe { Some(LLVMConstIntGetZExtValue(self.as_value_ref())) }
322 }
323
324 pub fn get_sign_extended_constant(self) -> Option<i64> {
338 if !self.is_constant_int() {
340 return None;
341 }
342 if self.get_type().get_bit_width() > 64 {
343 return None;
344 }
345
346 unsafe { Some(LLVMConstIntGetSExtValue(self.as_value_ref())) }
347 }
348
349 pub fn replace_all_uses_with(self, other: IntValue<'ctx>) {
350 self.int_value.replace_all_uses_with(other.as_value_ref())
351 }
352}
353
354unsafe impl AsValueRef for IntValue<'_> {
355 fn as_value_ref(&self) -> LLVMValueRef {
356 self.int_value.value
357 }
358}
359
360impl Display for IntValue<'_> {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 write!(f, "{}", self.print_to_string())
363 }
364}
365
366impl<'ctx> TryFrom<InstructionValue<'ctx>> for IntValue<'ctx> {
367 type Error = ();
368
369 fn try_from(value: InstructionValue) -> Result<Self, Self::Error> {
370 if value.get_type().is_int_type() {
371 unsafe { Ok(IntValue::new(value.as_value_ref())) }
372 } else {
373 Err(())
374 }
375 }
376}