Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/values/int_value.rs
Line
Count
Source (jump to first uncovered line)
1
use 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
};
9
use llvm_sys::prelude::LLVMValueRef;
10
11
use std::convert::TryFrom;
12
use std::ffi::CStr;
13
use std::fmt::{self, Display};
14
15
use crate::types::{AsTypeRef, FloatType, IntType, PointerType};
16
use crate::values::traits::AsValueRef;
17
use crate::values::{BasicValue, BasicValueEnum, FloatValue, InstructionValue, PointerValue, Value};
18
use crate::IntPredicate;
19
20
use super::AnyValue;
21
22
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
23
pub struct IntValue<'ctx> {
24
    int_value: Value<'ctx>,
25
}
26
27
impl<'ctx> IntValue<'ctx> {
28
11.8M
    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
29
11.8M
        assert!(!value.is_null());
30
31
11.8M
        IntValue {
32
11.8M
            int_value: Value::new(value),
33
11.8M
        }
34
11.8M
    }
35
36
    /// Gets the name of an `IntValue`. If the value is a constant, this will
37
    /// return an empty string.
38
0
    pub fn get_name(&self) -> &CStr {
39
0
        self.int_value.get_name()
40
0
    }
41
42
    /// Set name of the `IntValue`.
43
0
    pub fn set_name(&self, name: &str) {
44
0
        self.int_value.set_name(name)
45
0
    }
46
47
12.5k
    pub fn get_type(self) -> IntType<'ctx> {
48
12.5k
        unsafe { IntType::new(self.int_value.get_type()) }
49
12.5k
    }
50
51
0
    pub fn is_null(self) -> bool {
52
0
        self.int_value.is_null()
53
0
    }
54
55
0
    pub fn is_undef(self) -> bool {
56
0
        self.int_value.is_undef()
57
0
    }
58
59
0
    pub fn print_to_stderr(self) {
60
0
        self.int_value.print_to_stderr()
61
0
    }
62
63
0
    pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
64
0
        self.int_value.as_instruction()
65
0
    }
66
67
0
    pub fn const_not(self) -> Self {
68
0
        unsafe { IntValue::new(LLVMConstNot(self.as_value_ref())) }
69
0
    }
70
71
    // REVIEW: What happens when not using a const value? This and other fns
72
0
    pub fn const_neg(self) -> Self {
73
0
        unsafe { IntValue::new(LLVMConstNeg(self.as_value_ref())) }
74
0
    }
75
76
0
    pub fn const_nsw_neg(self) -> Self {
77
0
        unsafe { IntValue::new(LLVMConstNSWNeg(self.as_value_ref())) }
78
0
    }
79
80
0
    pub fn const_nuw_neg(self) -> Self {
81
0
        unsafe { IntValue::new(LLVMConstNUWNeg(self.as_value_ref())) }
82
0
    }
83
84
0
    pub fn const_add(self, rhs: IntValue<'ctx>) -> Self {
85
0
        unsafe { IntValue::new(LLVMConstAdd(self.as_value_ref(), rhs.as_value_ref())) }
86
0
    }
87
88
0
    pub fn const_nsw_add(self, rhs: IntValue<'ctx>) -> Self {
89
0
        unsafe { IntValue::new(LLVMConstNSWAdd(self.as_value_ref(), rhs.as_value_ref())) }
90
0
    }
91
92
0
    pub fn const_nuw_add(self, rhs: IntValue<'ctx>) -> Self {
93
0
        unsafe { IntValue::new(LLVMConstNUWAdd(self.as_value_ref(), rhs.as_value_ref())) }
94
0
    }
95
96
0
    pub fn const_sub(self, rhs: IntValue<'ctx>) -> Self {
97
0
        unsafe { IntValue::new(LLVMConstSub(self.as_value_ref(), rhs.as_value_ref())) }
98
0
    }
99
100
0
    pub fn const_nsw_sub(self, rhs: IntValue<'ctx>) -> Self {
101
0
        unsafe { IntValue::new(LLVMConstNSWSub(self.as_value_ref(), rhs.as_value_ref())) }
102
0
    }
103
104
0
    pub fn const_nuw_sub(self, rhs: IntValue<'ctx>) -> Self {
105
0
        unsafe { IntValue::new(LLVMConstNUWSub(self.as_value_ref(), rhs.as_value_ref())) }
106
0
    }
107
108
0
    pub fn const_mul(self, rhs: IntValue<'ctx>) -> Self {
109
0
        unsafe { IntValue::new(LLVMConstMul(self.as_value_ref(), rhs.as_value_ref())) }
110
0
    }
111
112
0
    pub fn const_nsw_mul(self, rhs: IntValue<'ctx>) -> Self {
113
0
        unsafe { IntValue::new(LLVMConstNSWMul(self.as_value_ref(), rhs.as_value_ref())) }
114
0
    }
115
116
0
    pub fn const_nuw_mul(self, rhs: IntValue<'ctx>) -> Self {
117
0
        unsafe { IntValue::new(LLVMConstNUWMul(self.as_value_ref(), rhs.as_value_ref())) }
118
0
    }
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
0
    pub fn const_and(self, rhs: IntValue<'ctx>) -> Self {
163
0
        unsafe { IntValue::new(LLVMConstAnd(self.as_value_ref(), rhs.as_value_ref())) }
164
0
    }
165
166
0
    pub fn const_or(self, rhs: IntValue<'ctx>) -> Self {
167
0
        unsafe { IntValue::new(LLVMConstOr(self.as_value_ref(), rhs.as_value_ref())) }
168
0
    }
169
170
0
    pub fn const_xor(self, rhs: IntValue<'ctx>) -> Self {
171
0
        unsafe { IntValue::new(LLVMConstXor(self.as_value_ref(), rhs.as_value_ref())) }
172
0
    }
173
174
    // TODO: Could infer is_signed from type (one day)?
175
0
    pub fn const_cast(self, int_type: IntType<'ctx>, is_signed: bool) -> Self {
176
0
        unsafe {
177
0
            IntValue::new(LLVMConstIntCast(
178
0
                self.as_value_ref(),
179
0
                int_type.as_type_ref(),
180
0
                is_signed as i32,
181
0
            ))
182
0
        }
183
0
    }
184
185
    // TODO: Give shift methods more descriptive names
186
0
    pub fn const_shl(self, rhs: IntValue<'ctx>) -> Self {
187
0
        unsafe { IntValue::new(LLVMConstShl(self.as_value_ref(), rhs.as_value_ref())) }
188
0
    }
189
190
0
    pub fn const_rshr(self, rhs: IntValue<'ctx>) -> Self {
191
0
        unsafe { IntValue::new(LLVMConstLShr(self.as_value_ref(), rhs.as_value_ref())) }
192
0
    }
193
194
0
    pub fn const_ashr(self, rhs: IntValue<'ctx>) -> Self {
195
0
        unsafe { IntValue::new(LLVMConstAShr(self.as_value_ref(), rhs.as_value_ref())) }
196
0
    }
197
198
    // SubType: const_to_float impl only for unsigned types
199
0
    pub fn const_unsigned_to_float(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
200
0
        unsafe { FloatValue::new(LLVMConstUIToFP(self.as_value_ref(), float_type.as_type_ref())) }
201
0
    }
202
203
    // SubType: const_to_float impl only for signed types
204
0
    pub fn const_signed_to_float(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
205
0
        unsafe { FloatValue::new(LLVMConstSIToFP(self.as_value_ref(), float_type.as_type_ref())) }
206
0
    }
207
208
0
    pub fn const_to_pointer(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> {
209
0
        unsafe { PointerValue::new(LLVMConstIntToPtr(self.as_value_ref(), ptr_type.as_type_ref())) }
210
0
    }
211
212
0
    pub fn const_truncate(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
213
0
        unsafe { IntValue::new(LLVMConstTrunc(self.as_value_ref(), int_type.as_type_ref())) }
214
0
    }
215
216
    // TODO: More descriptive name
217
0
    pub fn const_s_extend(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
218
0
        unsafe { IntValue::new(LLVMConstSExt(self.as_value_ref(), int_type.as_type_ref())) }
219
0
    }
220
221
    // TODO: More descriptive name
222
0
    pub fn const_z_ext(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
223
0
        unsafe { IntValue::new(LLVMConstZExt(self.as_value_ref(), int_type.as_type_ref())) }
224
0
    }
225
226
0
    pub fn const_truncate_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
227
0
        unsafe { IntValue::new(LLVMConstTruncOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
228
0
    }
229
230
    // TODO: More descriptive name
231
0
    pub fn const_s_extend_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
232
0
        unsafe { IntValue::new(LLVMConstSExtOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
233
0
    }
234
235
    // TODO: More descriptive name
236
0
    pub fn const_z_ext_or_bit_cast(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
237
0
        unsafe { IntValue::new(LLVMConstZExtOrBitCast(self.as_value_ref(), int_type.as_type_ref())) }
238
0
    }
239
240
0
    pub fn const_bit_cast(self, int_type: IntType) -> IntValue<'ctx> {
241
0
        unsafe { IntValue::new(LLVMConstBitCast(self.as_value_ref(), int_type.as_type_ref())) }
242
0
    }
243
244
    // SubType: rhs same as lhs; return IntValue<bool>
245
0
    pub fn const_int_compare(self, op: IntPredicate, rhs: IntValue<'ctx>) -> IntValue<'ctx> {
246
0
        unsafe { IntValue::new(LLVMConstICmp(op.into(), self.as_value_ref(), rhs.as_value_ref())) }
247
0
    }
248
249
    // SubTypes: self can only be IntValue<bool>
250
0
    pub fn const_select<BV: BasicValue<'ctx>>(self, then: BV, else_: BV) -> BasicValueEnum<'ctx> {
251
0
        unsafe {
252
0
            BasicValueEnum::new(LLVMConstSelect(
253
0
                self.as_value_ref(),
254
0
                then.as_value_ref(),
255
0
                else_.as_value_ref(),
256
0
            ))
257
0
        }
258
0
    }
259
260
    /// Determines whether or not an `IntValue` is an `llvm::Constant`.
261
    ///
262
    /// Constants includes values that are not known at compile time, for
263
    /// example the address of a function casted to an integer.
264
    ///
265
    /// # Example
266
    ///
267
    /// ```no_run
268
    /// use inkwell::context::Context;
269
    ///
270
    /// let context = Context::create();
271
    /// let i64_type = context.i64_type();
272
    /// let i64_val = i64_type.const_int(12, false);
273
    ///
274
    /// assert!(i64_val.is_const());
275
    /// ```
276
0
    pub fn is_const(self) -> bool {
277
0
        self.int_value.is_const()
278
0
    }
279
280
    /// Determines whether or not an `IntValue` is an `llvm::ConstantInt`.
281
    ///
282
    /// ConstantInt only includes values that are known at compile time.
283
    ///
284
    /// # Example
285
    ///
286
    /// ```no_run
287
    /// use inkwell::context::Context;
288
    ///
289
    /// let context = Context::create();
290
    /// let i64_type = context.i64_type();
291
    /// let i64_val = i64_type.const_int(12, false);
292
    ///
293
    /// assert!(i64_val.is_constant_int());
294
    /// ```
295
0
    pub fn is_constant_int(self) -> bool {
296
0
        !unsafe { LLVMIsAConstantInt(self.as_value_ref()) }.is_null()
297
0
    }
298
299
    /// Obtains a constant `IntValue`'s zero extended value.
300
    ///
301
    /// # Example
302
    ///
303
    /// ```no_run
304
    /// use inkwell::context::Context;
305
    ///
306
    /// let context = Context::create();
307
    /// let i8_type = context.i8_type();
308
    /// let i8_all_ones = i8_type.const_all_ones();
309
    ///
310
    /// assert_eq!(i8_all_ones.get_zero_extended_constant(), Some(255));
311
    /// ```
312
0
    pub fn get_zero_extended_constant(self) -> Option<u64> {
313
0
        // Garbage values are produced on non constant values
314
0
        if !self.is_constant_int() {
315
0
            return None;
316
0
        }
317
0
        if self.get_type().get_bit_width() > 64 {
318
0
            return None;
319
0
        }
320
0
321
0
        unsafe { Some(LLVMConstIntGetZExtValue(self.as_value_ref())) }
322
0
    }
323
324
    /// Obtains a constant `IntValue`'s sign extended value.
325
    ///
326
    /// # Example
327
    ///
328
    /// ```no_run
329
    /// use inkwell::context::Context;
330
    ///
331
    /// let context = Context::create();
332
    /// let i8_type = context.i8_type();
333
    /// let i8_all_ones = i8_type.const_all_ones();
334
    ///
335
    /// assert_eq!(i8_all_ones.get_sign_extended_constant(), Some(-1));
336
    /// ```
337
0
    pub fn get_sign_extended_constant(self) -> Option<i64> {
338
0
        // Garbage values are produced on non constant values
339
0
        if !self.is_constant_int() {
340
0
            return None;
341
0
        }
342
0
        if self.get_type().get_bit_width() > 64 {
343
0
            return None;
344
0
        }
345
0
346
0
        unsafe { Some(LLVMConstIntGetSExtValue(self.as_value_ref())) }
347
0
    }
348
349
0
    pub fn replace_all_uses_with(self, other: IntValue<'ctx>) {
350
0
        self.int_value.replace_all_uses_with(other.as_value_ref())
351
0
    }
352
}
353
354
unsafe impl AsValueRef for IntValue<'_> {
355
7.66M
    fn as_value_ref(&self) -> LLVMValueRef {
356
7.66M
        self.int_value.value
357
7.66M
    }
<inkwell::values::int_value::IntValue as inkwell::values::traits::AsValueRef>::as_value_ref
Line
Count
Source
355
5.95M
    fn as_value_ref(&self) -> LLVMValueRef {
356
5.95M
        self.int_value.value
357
5.95M
    }
<inkwell::values::int_value::IntValue as inkwell::values::traits::AsValueRef>::as_value_ref
Line
Count
Source
355
1.70M
    fn as_value_ref(&self) -> LLVMValueRef {
356
1.70M
        self.int_value.value
357
1.70M
    }
358
}
359
360
impl Display for IntValue<'_> {
361
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362
0
        write!(f, "{}", self.print_to_string())
363
0
    }
364
}
365
366
impl<'ctx> TryFrom<InstructionValue<'ctx>> for IntValue<'ctx> {
367
    type Error = ();
368
369
0
    fn try_from(value: InstructionValue) -> Result<Self, Self::Error> {
370
0
        if value.get_type().is_int_type() {
371
0
            unsafe { Ok(IntValue::new(value.as_value_ref())) }
372
        } else {
373
0
            Err(())
374
        }
375
0
    }
376
}