Skip to main content

inkwell/types/
float_type.rs

1use llvm_sys::core::{LLVMConstReal, LLVMConstRealOfStringAndSize, LLVMGetTypeKind};
2use llvm_sys::execution_engine::LLVMCreateGenericValueOfFloat;
3use llvm_sys::prelude::LLVMTypeRef;
4
5use crate::context::ContextRef;
6use crate::support::LLVMString;
7use crate::types::enums::BasicMetadataTypeEnum;
8use crate::types::traits::AsTypeRef;
9#[llvm_versions(12..)]
10use crate::types::ScalableVectorType;
11use crate::types::{ArrayType, FunctionType, PointerType, Type, VectorType};
12use crate::values::{ArrayValue, FloatValue, GenericValue, IntValue};
13use crate::AddressSpace;
14
15use std::fmt::{self, Display};
16
17/// A `FloatType` is the type of a floating point constant or variable.
18#[derive(Debug, PartialEq, Eq, Clone, Copy)]
19pub struct FloatType<'ctx> {
20    float_type: Type<'ctx>,
21}
22
23impl<'ctx> FloatType<'ctx> {
24    /// Create `FloatType` from [`LLVMTypeRef`]
25    ///
26    /// # Safety
27    /// Undefined behavior, if referenced type isn't float type
28    pub unsafe fn new(float_type: LLVMTypeRef) -> Self {
29        assert!(!float_type.is_null());
30
31        FloatType {
32            float_type: Type::new(float_type),
33        }
34    }
35
36    /// Creates a `FunctionType` with this `FloatType` for its return type.
37    ///
38    /// # Example
39    ///
40    /// ```no_run
41    /// use inkwell::context::Context;
42    ///
43    /// let context = Context::create();
44    /// let f32_type = context.f32_type();
45    /// let fn_type = f32_type.fn_type(&[], false);
46    /// ```
47    pub fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
48        self.float_type.fn_type(param_types, is_var_args)
49    }
50
51    /// Creates an `ArrayType` with this `FloatType` for its element type.
52    ///
53    /// # Example
54    ///
55    /// ```no_run
56    /// use inkwell::context::Context;
57    ///
58    /// let context = Context::create();
59    /// let f32_type = context.f32_type();
60    /// let f32_array_type = f32_type.array_type(3);
61    ///
62    /// assert_eq!(f32_array_type.len(), 3);
63    /// assert_eq!(f32_array_type.get_element_type().into_float_type(), f32_type);
64    /// ```
65    pub fn array_type(self, size: u32) -> ArrayType<'ctx> {
66        self.float_type.array_type(size)
67    }
68
69    /// Creates a `VectorType` with this `FloatType` for its element type.
70    ///
71    /// # Example
72    ///
73    /// ```no_run
74    /// use inkwell::context::Context;
75    ///
76    /// let context = Context::create();
77    /// let f32_type = context.f32_type();
78    /// let f32_scalable_vector_type = f32_type.vec_type(3);
79    ///
80    /// assert_eq!(f32_scalable_vector_type.get_size(), 3);
81    /// assert_eq!(f32_scalable_vector_type.get_element_type().into_float_type(), f32_type);
82    /// ```
83    pub fn vec_type(self, size: u32) -> VectorType<'ctx> {
84        self.float_type.vec_type(size)
85    }
86
87    /// Creates a scalable `VectorType` with this `FloatType` for its element type.
88    ///
89    /// # Example
90    ///
91    /// ```no_run
92    /// use inkwell::context::Context;
93    ///
94    /// let context = Context::create();
95    /// let f32_type = context.f32_type();
96    /// let f32_vector_type = f32_type.scalable_vec_type(3);
97    ///
98    /// assert_eq!(f32_vector_type.get_size(), 3);
99    /// assert_eq!(f32_vector_type.get_element_type().into_float_type(), f32_type);
100    /// ```
101    #[llvm_versions(12..)]
102    pub fn scalable_vec_type(self, size: u32) -> ScalableVectorType<'ctx> {
103        self.float_type.scalable_vec_type(size)
104    }
105
106    /// Creates a `FloatValue` representing a constant value of this `FloatType`.
107    /// It will be automatically assigned this `FloatType`'s `Context`.
108    ///
109    /// # Example
110    /// ```no_run
111    /// use inkwell::context::Context;
112    ///
113    /// // Local Context
114    /// let context = Context::create();
115    /// let f32_type = context.f32_type();
116    /// let f32_value = f32_type.const_float(42.);
117    /// ```
118    pub fn const_float(self, value: f64) -> FloatValue<'ctx> {
119        unsafe { FloatValue::new(LLVMConstReal(self.float_type.ty, value)) }
120    }
121
122    // We could make this safe again by doing the validation for users.
123    /// Create a `FloatValue` from a string. This function is marked unsafe because LLVM
124    /// provides no error handling here, so this may produce undefined behavior if an invalid
125    /// string is used.
126    ///
127    /// # Example
128    ///
129    /// ```no_run
130    /// use inkwell::context::Context;
131    /// use inkwell::values::AnyValue;
132    ///
133    /// let context = Context::create();
134    /// let f64_type = context.f64_type();
135    /// let f64_val = unsafe { f64_type.const_float_from_string("3.6") };
136    ///
137    /// assert_eq!(f64_val.print_to_string().to_string(), "double 3.600000e+00");
138    ///
139    /// let f64_val = unsafe { f64_type.const_float_from_string("3.") };
140    ///
141    /// assert_eq!(f64_val.print_to_string().to_string(), "double 3.000000e+00");
142    ///
143    /// let f64_val = unsafe { f64_type.const_float_from_string("3") };
144    ///
145    /// assert_eq!(f64_val.print_to_string().to_string(), "double 3.000000e+00");
146    ///
147    /// let f64_val = unsafe { f64_type.const_float_from_string("3.asd") };
148    ///
149    /// assert_eq!(f64_val.print_to_string().to_string(), "double 0x7FF0000000000000");
150    /// ```
151    pub unsafe fn const_float_from_string(self, slice: &str) -> FloatValue<'ctx> {
152        assert!(!slice.is_empty());
153
154        unsafe {
155            FloatValue::new(LLVMConstRealOfStringAndSize(
156                self.as_type_ref(),
157                slice.as_ptr() as *const ::libc::c_char,
158                slice.len() as u32,
159            ))
160        }
161    }
162
163    /// Creates a constant zero value of this `FloatType`.
164    ///
165    /// # Example
166    ///
167    /// ```no_run
168    /// use inkwell::context::Context;
169    /// use inkwell::values::AnyValue;
170    ///
171    /// let context = Context::create();
172    /// let f32_type = context.f32_type();
173    /// let f32_zero = f32_type.const_zero();
174    ///
175    /// assert_eq!(f32_zero.print_to_string().to_string(), "float 0.000000e+00");
176    /// ```
177    pub fn const_zero(self) -> FloatValue<'ctx> {
178        unsafe { FloatValue::new(self.float_type.const_zero()) }
179    }
180
181    /// Gets the size of this `FloatType`. Value may vary depending on the target architecture.
182    ///
183    /// # Example
184    ///
185    /// ```no_run
186    /// use inkwell::context::Context;
187    ///
188    /// let context = Context::create();
189    /// let f32_type = context.f32_type();
190    /// let f32_type_size = f32_type.size_of();
191    /// ```
192    pub fn size_of(self) -> IntValue<'ctx> {
193        self.float_type.size_of().unwrap()
194    }
195
196    /// Gets a reference to the `Context` this `FloatType` was created in.
197    ///
198    /// # Example
199    ///
200    /// ```no_run
201    /// use inkwell::context::Context;
202    ///
203    /// let context = Context::create();
204    /// let f32_type = context.f32_type();
205    ///
206    /// assert_eq!(f32_type.get_context(), context);
207    /// ```
208    pub fn get_context(self) -> ContextRef<'ctx> {
209        self.float_type.get_context()
210    }
211
212    /// Creates a `PointerType` with this `FloatType` for its element type.
213    ///
214    /// # Example
215    ///
216    /// ```no_run
217    /// use inkwell::context::Context;
218    /// use inkwell::AddressSpace;
219    ///
220    /// let context = Context::create();
221    /// let f32_type = context.f32_type();
222    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
223    ///
224    /// #[cfg(feature = "typed-pointers")]
225    /// assert_eq!(f32_ptr_type.get_element_type().into_float_type(), f32_type);
226    /// ```
227    #[cfg_attr(
228        any(
229            all(feature = "llvm15-0", not(feature = "typed-pointers")),
230            all(feature = "llvm16-0", not(feature = "typed-pointers")),
231            feature = "llvm17-0",
232            feature = "llvm18-1",
233            feature = "llvm19-1",
234            feature = "llvm20-1",
235            feature = "llvm21-1",
236        ),
237        deprecated(
238            note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
239        )
240    )]
241    pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
242        self.float_type.ptr_type(address_space)
243    }
244
245    /// Gets the bit width of a `FloatType`.
246    ///
247    /// # Example
248    /// ```no_run
249    /// use inkwell::context::Context;
250    ///
251    /// let context = Context::create();
252    /// let f128_type = context.f128_type();
253    ///
254    /// assert_eq!(f128_type.get_bit_width(), 128);
255    /// ```
256    pub fn get_bit_width(self) -> u32 {
257        let type_kind = unsafe { LLVMGetTypeKind(self.as_type_ref()) };
258
259        match type_kind {
260            llvm_sys::LLVMTypeKind::LLVMHalfTypeKind => 16,
261            #[cfg(any(
262                feature = "llvm11-0",
263                feature = "llvm12-0",
264                feature = "llvm13-0",
265                feature = "llvm14-0",
266                feature = "llvm15-0",
267                feature = "llvm16-0",
268                feature = "llvm17-0",
269                feature = "llvm18-1",
270                feature = "llvm19-1",
271                feature = "llvm20-1",
272                feature = "llvm21-1",
273            ))]
274            llvm_sys::LLVMTypeKind::LLVMBFloatTypeKind => 16,
275            llvm_sys::LLVMTypeKind::LLVMFloatTypeKind => 32,
276            llvm_sys::LLVMTypeKind::LLVMDoubleTypeKind => 64,
277            llvm_sys::LLVMTypeKind::LLVMX86_FP80TypeKind => 80,
278            llvm_sys::LLVMTypeKind::LLVMFP128TypeKind | llvm_sys::LLVMTypeKind::LLVMPPC_FP128TypeKind => 128,
279            _ => unreachable!(),
280        }
281    }
282
283    /// Print the definition of a `FloatType` to `LLVMString`.
284    pub fn print_to_string(self) -> LLVMString {
285        self.float_type.print_to_string()
286    }
287
288    /// Creates an undefined instance of a `FloatType`.
289    ///
290    /// # Example
291    /// ```no_run
292    /// use inkwell::context::Context;
293    ///
294    /// let context = Context::create();
295    /// let f32_type = context.f32_type();
296    /// let f32_undef = f32_type.get_undef();
297    ///
298    /// assert!(f32_undef.is_undef());
299    /// ```
300    pub fn get_undef(&self) -> FloatValue<'ctx> {
301        unsafe { FloatValue::new(self.float_type.get_undef()) }
302    }
303
304    /// Creates a poison instance of a `FloatType`.
305    ///
306    /// # Example
307    /// ```no_run
308    /// use inkwell::context::Context;
309    /// use inkwell::values::AnyValue;
310    ///
311    /// let context = Context::create();
312    /// let f32_type = context.f32_type();
313    /// let f32_poison = f32_type.get_poison();
314    ///
315    /// assert!(f32_poison.is_poison());
316    /// ```
317    #[llvm_versions(12..)]
318    pub fn get_poison(&self) -> FloatValue<'ctx> {
319        unsafe { FloatValue::new(self.float_type.get_poison()) }
320    }
321
322    /// Creates a `GenericValue` for use with `ExecutionEngine`s.
323    pub fn create_generic_value(self, value: f64) -> GenericValue<'ctx> {
324        unsafe { GenericValue::new(LLVMCreateGenericValueOfFloat(self.as_type_ref(), value)) }
325    }
326
327    /// Creates a constant `ArrayValue`.
328    ///
329    /// # Example
330    /// ```no_run
331    /// use inkwell::context::Context;
332    ///
333    /// let context = Context::create();
334    /// let f32_type = context.f32_type();
335    /// let f32_val = f32_type.const_float(0.);
336    /// let f32_val2 = f32_type.const_float(2.);
337    /// let f32_array = f32_type.const_array(&[f32_val, f32_val2]);
338    ///
339    /// assert!(f32_array.is_const());
340    /// ```
341    pub fn const_array(self, values: &[FloatValue<'ctx>]) -> ArrayValue<'ctx> {
342        unsafe { ArrayValue::new_const_array(&self, values) }
343    }
344}
345
346unsafe impl AsTypeRef for FloatType<'_> {
347    fn as_type_ref(&self) -> LLVMTypeRef {
348        self.float_type.ty
349    }
350}
351
352impl Display for FloatType<'_> {
353    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354        write!(f, "{}", self.print_to_string())
355    }
356}