Skip to main content

inkwell/values/
fn_value.rs

1use llvm_sys::LLVMValue;
2use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction, LLVMViewFunctionCFG, LLVMViewFunctionCFGOnly};
3use llvm_sys::core::LLVMAppendExistingBasicBlock;
4use llvm_sys::core::{
5    LLVMAddAttributeAtIndex, LLVMGetAttributeCountAtIndex, LLVMGetEnumAttributeAtIndex, LLVMGetStringAttributeAtIndex,
6    LLVMRemoveEnumAttributeAtIndex, LLVMRemoveStringAttributeAtIndex,
7};
8use llvm_sys::core::{
9    LLVMCountBasicBlocks, LLVMCountParams, LLVMDeleteFunction, LLVMGetBasicBlocks, LLVMGetFirstBasicBlock,
10    LLVMGetFirstParam, LLVMGetFunctionCallConv, LLVMGetGC, LLVMGetIntrinsicID, LLVMGetLastBasicBlock, LLVMGetLastParam,
11    LLVMGetLinkage, LLVMGetNextFunction, LLVMGetNextParam, LLVMGetParam, LLVMGetParams, LLVMGetPreviousFunction,
12    LLVMIsAFunction, LLVMIsConstant, LLVMSetFunctionCallConv, LLVMSetGC, LLVMSetLinkage, LLVMSetParamAlignment,
13};
14use llvm_sys::core::{LLVMGetPersonalityFn, LLVMSetPersonalityFn};
15use llvm_sys::debuginfo::{LLVMGetSubprogram, LLVMSetSubprogram};
16#[llvm_versions(20..)]
17use llvm_sys::error::LLVMGetErrorMessage;
18use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef};
19#[llvm_versions(20..)]
20use llvm_sys::transforms::pass_builder::LLVMRunPassesOnFunction;
21
22use std::ffi::CStr;
23use std::fmt::{self, Display};
24use std::marker::PhantomData;
25use std::mem::forget;
26use std::ptr::NonNull;
27
28use crate::attributes::{Attribute, AttributeLoc};
29use crate::basic_block::BasicBlock;
30use crate::debug_info::DISubprogram;
31use crate::module::Linkage;
32#[llvm_versions(20..)]
33use crate::passes::PassBuilderOptions;
34#[llvm_versions(20..)]
35use crate::support::LLVMString;
36use crate::support::{assert_niche, to_c_str};
37#[llvm_versions(20..)]
38use crate::targets::TargetMachine;
39use crate::types::FunctionType;
40use crate::values::traits::{AnyValue, AsValueRef};
41use crate::values::{BasicValueEnum, GlobalValue, Value};
42
43#[repr(transparent)]
44#[derive(PartialEq, Eq, Clone, Copy, Hash)]
45pub struct FunctionValue<'ctx> {
46    fn_value: Value<'ctx>,
47}
48const _: () = assert_niche::<FunctionValue>();
49
50impl<'ctx> FunctionValue<'ctx> {
51    /// Get a value from an [LLVMValueRef].
52    ///
53    /// # Safety
54    ///
55    /// The ref must be valid and of type function.
56    pub unsafe fn new(value: LLVMValueRef) -> Option<Self> {
57        unsafe {
58            if value.is_null() || LLVMIsAFunction(value).is_null() {
59                return None;
60            }
61
62            Some(FunctionValue {
63                fn_value: Value::new(value),
64            })
65        }
66    }
67
68    pub fn get_linkage(self) -> Linkage {
69        unsafe { LLVMGetLinkage(self.as_value_ref()).into() }
70    }
71
72    pub fn set_linkage(self, linkage: Linkage) {
73        unsafe { LLVMSetLinkage(self.as_value_ref(), linkage.into()) }
74    }
75
76    pub fn is_null(self) -> bool {
77        self.fn_value.is_null()
78    }
79
80    pub fn is_undef(self) -> bool {
81        self.fn_value.is_undef()
82    }
83
84    pub fn print_to_stderr(self) {
85        self.fn_value.print_to_stderr()
86    }
87
88    // FIXME: Better error returns, code 1 is error
89    pub fn verify(self, print: bool) -> bool {
90        let action = if print {
91            LLVMVerifierFailureAction::LLVMPrintMessageAction
92        } else {
93            LLVMVerifierFailureAction::LLVMReturnStatusAction
94        };
95
96        let code = unsafe { LLVMVerifyFunction(self.fn_value.as_mut_ptr(), action) };
97
98        code != 1
99    }
100
101    // REVIEW: If there's a demand, could easily create a module.get_functions() -> Iterator
102    pub fn get_next_function(self) -> Option<Self> {
103        unsafe { FunctionValue::new(LLVMGetNextFunction(self.as_value_ref())) }
104    }
105
106    pub fn get_previous_function(self) -> Option<Self> {
107        unsafe { FunctionValue::new(LLVMGetPreviousFunction(self.as_value_ref())) }
108    }
109
110    pub fn get_first_param(self) -> Option<BasicValueEnum<'ctx>> {
111        let param = unsafe { LLVMGetFirstParam(self.as_value_ref()) };
112
113        if param.is_null() {
114            return None;
115        }
116
117        unsafe { Some(BasicValueEnum::new(param)) }
118    }
119
120    pub fn get_last_param(self) -> Option<BasicValueEnum<'ctx>> {
121        let param = unsafe { LLVMGetLastParam(self.as_value_ref()) };
122
123        if param.is_null() {
124            return None;
125        }
126
127        unsafe { Some(BasicValueEnum::new(param)) }
128    }
129
130    pub fn get_first_basic_block(self) -> Option<BasicBlock<'ctx>> {
131        unsafe { BasicBlock::new(LLVMGetFirstBasicBlock(self.as_value_ref())) }
132    }
133
134    pub fn get_nth_param(self, nth: u32) -> Option<BasicValueEnum<'ctx>> {
135        let count = self.count_params();
136
137        if nth + 1 > count {
138            return None;
139        }
140
141        unsafe { Some(BasicValueEnum::new(LLVMGetParam(self.as_value_ref(), nth))) }
142    }
143
144    pub fn count_params(self) -> u32 {
145        unsafe { LLVMCountParams(self.fn_value.as_mut_ptr()) }
146    }
147
148    pub fn count_basic_blocks(self) -> u32 {
149        unsafe { LLVMCountBasicBlocks(self.as_value_ref()) }
150    }
151
152    pub fn get_basic_block_iter(self) -> BasicBlockIter<'ctx> {
153        BasicBlockIter(self.get_first_basic_block())
154    }
155
156    pub fn get_basic_blocks(self) -> Vec<BasicBlock<'ctx>> {
157        let count = self.count_basic_blocks();
158        let mut raw_vec: Vec<LLVMBasicBlockRef> = Vec::with_capacity(count as usize);
159        let ptr = raw_vec.as_mut_ptr();
160
161        forget(raw_vec);
162
163        let raw_vec = unsafe {
164            LLVMGetBasicBlocks(self.as_value_ref(), ptr);
165
166            Vec::from_raw_parts(ptr, count as usize, count as usize)
167        };
168
169        raw_vec
170            .iter()
171            .map(|val| unsafe { BasicBlock::new(*val).unwrap() })
172            .collect()
173    }
174
175    pub fn get_param_iter(self) -> ParamValueIter<'ctx> {
176        ParamValueIter {
177            param_iter_value: self.fn_value.value,
178            start: true,
179            _marker: PhantomData,
180        }
181    }
182
183    pub fn get_params(self) -> Vec<BasicValueEnum<'ctx>> {
184        let count = self.count_params();
185        let mut raw_vec: Vec<LLVMValueRef> = Vec::with_capacity(count as usize);
186        let ptr = raw_vec.as_mut_ptr();
187
188        forget(raw_vec);
189
190        let raw_vec = unsafe {
191            LLVMGetParams(self.as_value_ref(), ptr);
192
193            Vec::from_raw_parts(ptr, count as usize, count as usize)
194        };
195
196        raw_vec.iter().map(|val| unsafe { BasicValueEnum::new(*val) }).collect()
197    }
198
199    pub fn get_last_basic_block(self) -> Option<BasicBlock<'ctx>> {
200        unsafe { BasicBlock::new(LLVMGetLastBasicBlock(self.fn_value.as_mut_ptr())) }
201    }
202
203    /// Gets the name of a `FunctionValue`.
204    pub fn get_name(&self) -> &CStr {
205        self.fn_value.get_name()
206    }
207
208    /// View the control flow graph and produce a .dot file
209    pub fn view_function_cfg(self) {
210        unsafe { LLVMViewFunctionCFG(self.as_value_ref()) }
211    }
212
213    /// Only view the control flow graph
214    pub fn view_function_cfg_only(self) {
215        unsafe { LLVMViewFunctionCFGOnly(self.as_value_ref()) }
216    }
217
218    // TODO: Look for ways to prevent use after delete but maybe not possible
219    pub unsafe fn delete(self) {
220        unsafe { LLVMDeleteFunction(self.as_value_ref()) }
221    }
222
223    pub fn get_type(self) -> FunctionType<'ctx> {
224        unsafe { FunctionType::new(llvm_sys::core::LLVMGlobalGetValueType(self.as_value_ref())) }
225    }
226
227    // TODOC: How this works as an exception handler
228    pub fn has_personality_function(self) -> bool {
229        use llvm_sys::core::LLVMHasPersonalityFn;
230
231        unsafe { LLVMHasPersonalityFn(self.as_value_ref()) == 1 }
232    }
233
234    pub fn get_personality_function(self) -> Option<FunctionValue<'ctx>> {
235        // This prevents a segfault when not having a pfn
236        if !self.has_personality_function() {
237            return None;
238        }
239
240        unsafe { FunctionValue::new(LLVMGetPersonalityFn(self.as_value_ref())) }
241    }
242
243    pub fn set_personality_function(self, personality_fn: FunctionValue<'ctx>) {
244        unsafe { LLVMSetPersonalityFn(self.as_value_ref(), personality_fn.as_value_ref()) }
245    }
246
247    pub fn get_intrinsic_id(self) -> u32 {
248        unsafe { LLVMGetIntrinsicID(self.as_value_ref()) }
249    }
250
251    pub fn get_call_conventions(self) -> u32 {
252        unsafe { LLVMGetFunctionCallConv(self.as_value_ref()) }
253    }
254
255    pub fn set_call_conventions(self, call_conventions: u32) {
256        unsafe { LLVMSetFunctionCallConv(self.as_value_ref(), call_conventions) }
257    }
258
259    pub fn get_gc(&self) -> &CStr {
260        unsafe { CStr::from_ptr(LLVMGetGC(self.as_value_ref())) }
261    }
262
263    pub fn set_gc(self, gc: &str) {
264        let c_string = to_c_str(gc);
265
266        unsafe { LLVMSetGC(self.as_value_ref(), c_string.as_ptr()) }
267    }
268
269    pub fn replace_all_uses_with(self, other: FunctionValue<'ctx>) {
270        self.fn_value.replace_all_uses_with(other.as_value_ref())
271    }
272
273    /// Adds an `Attribute` to a particular location in this `FunctionValue`.
274    ///
275    /// # Example
276    ///
277    /// ```no_run
278    /// use inkwell::attributes::AttributeLoc;
279    /// use inkwell::context::Context;
280    ///
281    /// let context = Context::create();
282    /// let module = context.create_module("my_mod");
283    /// let void_type = context.void_type();
284    /// let fn_type = void_type.fn_type(&[], false);
285    /// let fn_value = module.add_function("my_fn", fn_type, None);
286    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
287    /// let enum_attribute = context.create_enum_attribute(1, 1);
288    ///
289    /// fn_value.add_attribute(AttributeLoc::Return, string_attribute);
290    /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute);
291    /// ```
292    pub fn add_attribute(self, loc: AttributeLoc, attribute: Attribute) {
293        unsafe { LLVMAddAttributeAtIndex(self.as_value_ref(), loc.get_index(), attribute.as_mut_ptr()) }
294    }
295
296    /// Counts the number of `Attribute`s belonging to the specified location in this `FunctionValue`.
297    ///
298    /// # Example
299    ///
300    /// ```no_run
301    /// use inkwell::attributes::AttributeLoc;
302    /// use inkwell::context::Context;
303    ///
304    /// let context = Context::create();
305    /// let module = context.create_module("my_mod");
306    /// let void_type = context.void_type();
307    /// let fn_type = void_type.fn_type(&[], false);
308    /// let fn_value = module.add_function("my_fn", fn_type, None);
309    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
310    /// let enum_attribute = context.create_enum_attribute(1, 1);
311    ///
312    /// fn_value.add_attribute(AttributeLoc::Return, string_attribute);
313    /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute);
314    ///
315    /// assert_eq!(fn_value.count_attributes(AttributeLoc::Return), 2);
316    /// ```
317    pub fn count_attributes(self, loc: AttributeLoc) -> u32 {
318        unsafe { LLVMGetAttributeCountAtIndex(self.as_value_ref(), loc.get_index()) }
319    }
320
321    /// Get all `Attribute`s belonging to the specified location in this `FunctionValue`.
322    ///
323    /// # Example
324    ///
325    /// ```no_run
326    /// use inkwell::attributes::AttributeLoc;
327    /// use inkwell::context::Context;
328    ///
329    /// let context = Context::create();
330    /// let module = context.create_module("my_mod");
331    /// let void_type = context.void_type();
332    /// let fn_type = void_type.fn_type(&[], false);
333    /// let fn_value = module.add_function("my_fn", fn_type, None);
334    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
335    /// let enum_attribute = context.create_enum_attribute(1, 1);
336    ///
337    /// fn_value.add_attribute(AttributeLoc::Return, string_attribute);
338    /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute);
339    ///
340    /// assert_eq!(fn_value.attributes(AttributeLoc::Return), vec![string_attribute, enum_attribute]);
341    /// ```
342    pub fn attributes(self, loc: AttributeLoc) -> Vec<Attribute> {
343        use llvm_sys::core::LLVMGetAttributesAtIndex;
344        use std::mem::{ManuallyDrop, MaybeUninit};
345
346        let count = self.count_attributes(loc) as usize;
347
348        // initialize a vector, but leave each element uninitialized
349        let mut attribute_refs: Vec<MaybeUninit<Attribute>> = vec![MaybeUninit::uninit(); count];
350
351        // Safety: relies on `Attribute` having the same in-memory representation as `LLVMAttributeRef`
352        unsafe {
353            LLVMGetAttributesAtIndex(
354                self.as_value_ref(),
355                loc.get_index(),
356                attribute_refs.as_mut_ptr() as *mut _,
357            )
358        }
359
360        // Safety: all elements are initialized
361        unsafe {
362            // ensure the vector is not dropped
363            let mut attribute_refs = ManuallyDrop::new(attribute_refs);
364
365            Vec::from_raw_parts(
366                attribute_refs.as_mut_ptr() as *mut Attribute,
367                attribute_refs.len(),
368                attribute_refs.capacity(),
369            )
370        }
371    }
372
373    /// Removes a string `Attribute` belonging to the specified location in this `FunctionValue`.
374    ///
375    /// # Example
376    ///
377    /// ```no_run
378    /// use inkwell::attributes::AttributeLoc;
379    /// use inkwell::context::Context;
380    ///
381    /// let context = Context::create();
382    /// let module = context.create_module("my_mod");
383    /// let void_type = context.void_type();
384    /// let fn_type = void_type.fn_type(&[], false);
385    /// let fn_value = module.add_function("my_fn", fn_type, None);
386    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
387    ///
388    /// fn_value.add_attribute(AttributeLoc::Return, string_attribute);
389    /// fn_value.remove_string_attribute(AttributeLoc::Return, "my_key");
390    /// ```
391    pub fn remove_string_attribute(self, loc: AttributeLoc, key: &str) {
392        unsafe {
393            LLVMRemoveStringAttributeAtIndex(
394                self.as_value_ref(),
395                loc.get_index(),
396                key.as_ptr() as *const ::libc::c_char,
397                key.len() as u32,
398            )
399        }
400    }
401
402    /// Removes an enum `Attribute` belonging to the specified location in this `FunctionValue`.
403    ///
404    /// # Example
405    ///
406    /// ```no_run
407    /// use inkwell::attributes::AttributeLoc;
408    /// use inkwell::context::Context;
409    ///
410    /// let context = Context::create();
411    /// let module = context.create_module("my_mod");
412    /// let void_type = context.void_type();
413    /// let fn_type = void_type.fn_type(&[], false);
414    /// let fn_value = module.add_function("my_fn", fn_type, None);
415    /// let enum_attribute = context.create_enum_attribute(1, 1);
416    ///
417    /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute);
418    /// fn_value.remove_enum_attribute(AttributeLoc::Return, 1);
419    /// ```
420    pub fn remove_enum_attribute(self, loc: AttributeLoc, kind_id: u32) {
421        unsafe { LLVMRemoveEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) }
422    }
423
424    /// Gets an enum `Attribute` belonging to the specified location in this `FunctionValue`.
425    ///
426    /// # Example
427    ///
428    /// ```no_run
429    /// use inkwell::attributes::AttributeLoc;
430    /// use inkwell::context::Context;
431    ///
432    /// let context = Context::create();
433    /// let module = context.create_module("my_mod");
434    /// let void_type = context.void_type();
435    /// let fn_type = void_type.fn_type(&[], false);
436    /// let fn_value = module.add_function("my_fn", fn_type, None);
437    /// let enum_attribute = context.create_enum_attribute(1, 1);
438    ///
439    /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute);
440    ///
441    /// assert_eq!(fn_value.get_enum_attribute(AttributeLoc::Return, 1), Some(enum_attribute));
442    /// ```
443    // SubTypes: -> Option<Attribute<Enum>>
444    pub fn get_enum_attribute(self, loc: AttributeLoc, kind_id: u32) -> Option<Attribute> {
445        let ptr = unsafe { LLVMGetEnumAttributeAtIndex(self.as_value_ref(), loc.get_index(), kind_id) };
446
447        if ptr.is_null() {
448            return None;
449        }
450
451        unsafe { Some(Attribute::new(ptr)) }
452    }
453
454    /// Gets a string `Attribute` belonging to the specified location in this `FunctionValue`.
455    ///
456    /// # Example
457    ///
458    /// ```no_run
459    /// use inkwell::attributes::AttributeLoc;
460    /// use inkwell::context::Context;
461    ///
462    /// let context = Context::create();
463    /// let module = context.create_module("my_mod");
464    /// let void_type = context.void_type();
465    /// let fn_type = void_type.fn_type(&[], false);
466    /// let fn_value = module.add_function("my_fn", fn_type, None);
467    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
468    ///
469    /// fn_value.add_attribute(AttributeLoc::Return, string_attribute);
470    ///
471    /// assert_eq!(fn_value.get_string_attribute(AttributeLoc::Return, "my_key"), Some(string_attribute));
472    /// ```
473    // SubTypes: -> Option<Attribute<String>>
474    pub fn get_string_attribute(self, loc: AttributeLoc, key: &str) -> Option<Attribute> {
475        let ptr = unsafe {
476            LLVMGetStringAttributeAtIndex(
477                self.as_value_ref(),
478                loc.get_index(),
479                key.as_ptr() as *const ::libc::c_char,
480                key.len() as u32,
481            )
482        };
483
484        if ptr.is_null() {
485            return None;
486        }
487
488        unsafe { Some(Attribute::new(ptr)) }
489    }
490
491    pub fn set_param_alignment(self, param_index: u32, alignment: u32) {
492        if let Some(param) = self.get_nth_param(param_index) {
493            unsafe { LLVMSetParamAlignment(param.as_value_ref(), alignment) }
494        }
495    }
496
497    /// Gets the `GlobalValue` version of this `FunctionValue`. This allows
498    /// you to further inspect its global properties or even convert it to
499    /// a `PointerValue`.
500    pub fn as_global_value(self) -> GlobalValue<'ctx> {
501        unsafe { GlobalValue::new(self.as_value_ref()) }
502    }
503
504    /// Set the debug info descriptor
505    pub fn set_subprogram(self, subprogram: DISubprogram<'ctx>) {
506        unsafe { LLVMSetSubprogram(self.as_value_ref(), subprogram.as_mut_ptr()) }
507    }
508
509    /// Get the debug info descriptor
510    pub fn get_subprogram(self) -> Option<DISubprogram<'ctx>> {
511        let metadata_ref = unsafe { LLVMGetSubprogram(self.as_value_ref()) };
512
513        Some(DISubprogram {
514            metadata_ref: NonNull::new(metadata_ref)?,
515            _marker: PhantomData,
516        })
517    }
518
519    /// Get the section to which this function belongs
520    pub fn get_section(&self) -> Option<&CStr> {
521        self.fn_value.get_section()
522    }
523
524    /// Set the section to which this function should belong
525    pub fn set_section(self, section: Option<&str>) {
526        self.fn_value.set_section(section)
527    }
528
529    pub fn append_existing_basic_block(&self, basic_block: BasicBlock<'ctx>) {
530        unsafe {
531            LLVMAppendExistingBasicBlock(self.as_value_ref(), basic_block.as_mut_ptr());
532        }
533    }
534
535    /// Construct and run a set of passes over a function.
536    ///
537    /// Behaves the same as [`Module::run_passes`](crate::module::Module::run_passes), but
538    /// operates on a single function instead of an entire module.
539    ///
540    /// See [`Module::run_passes`](crate::module::Module::run_passes) for details on
541    /// the passes format.
542    #[llvm_versions(20..)]
543    pub fn run_passes(
544        &self,
545        passes: &str,
546        machine: &TargetMachine,
547        options: PassBuilderOptions,
548    ) -> Result<(), LLVMString> {
549        unsafe {
550            let error = LLVMRunPassesOnFunction(
551                self.as_value_ref(),
552                to_c_str(passes).as_ptr(),
553                machine.target_machine.as_ptr(),
554                options.options_ref,
555            );
556            if error.is_null() {
557                Ok(())
558            } else {
559                let message = LLVMGetErrorMessage(error);
560                Err(LLVMString::new(message as *const libc::c_char))
561            }
562        }
563    }
564}
565
566unsafe impl AsValueRef for FunctionValue<'_> {
567    fn as_value_ref(&self) -> LLVMValueRef {
568        self.fn_value.as_mut_ptr()
569    }
570}
571
572impl Display for FunctionValue<'_> {
573    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
574        write!(f, "{}", self.print_to_string())
575    }
576}
577
578impl fmt::Debug for FunctionValue<'_> {
579    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
580        let llvm_value = self.print_to_string();
581        let llvm_type = self.get_type();
582        let name = self.get_name();
583        let is_const = unsafe { LLVMIsConstant(self.fn_value.as_mut_ptr()) == 1 };
584        let is_null = self.is_null();
585
586        f.debug_struct("FunctionValue")
587            .field("name", &name)
588            .field("address", &self.as_value_ref())
589            .field("is_const", &is_const)
590            .field("is_null", &is_null)
591            .field("llvm_value", &llvm_value)
592            .field("llvm_type", &llvm_type.print_to_string())
593            .finish()
594    }
595}
596
597/// Iterate over all `BasicBlock`s in a function.
598#[repr(transparent)]
599#[derive(Debug)]
600pub struct BasicBlockIter<'ctx>(Option<BasicBlock<'ctx>>);
601
602impl<'ctx> Iterator for BasicBlockIter<'ctx> {
603    type Item = BasicBlock<'ctx>;
604
605    fn next(&mut self) -> Option<Self::Item> {
606        if let Some(bb) = self.0 {
607            self.0 = bb.get_next_basic_block();
608            Some(bb)
609        } else {
610            None
611        }
612    }
613}
614
615#[derive(Debug)]
616pub struct ParamValueIter<'ctx> {
617    param_iter_value: NonNull<LLVMValue>,
618    start: bool,
619    _marker: PhantomData<&'ctx ()>,
620}
621const _: () = assert_niche::<ParamValueIter>();
622
623impl<'ctx> Iterator for ParamValueIter<'ctx> {
624    type Item = BasicValueEnum<'ctx>;
625
626    fn next(&mut self) -> Option<Self::Item> {
627        if self.start {
628            let first_value = unsafe { LLVMGetFirstParam(self.param_iter_value.as_ptr()) };
629
630            if first_value.is_null() {
631                return None;
632            }
633
634            self.start = false;
635
636            self.param_iter_value = unsafe { NonNull::new_unchecked(first_value) };
637
638            return unsafe { Some(Self::Item::new(first_value)) };
639        }
640
641        let next_value = unsafe { LLVMGetNextParam(self.param_iter_value.as_ptr()) };
642
643        if next_value.is_null() {
644            return None;
645        }
646
647        self.param_iter_value = unsafe { NonNull::new_unchecked(next_value) };
648
649        unsafe { Some(Self::Item::new(next_value)) }
650    }
651}