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}