Skip to main content

inkwell/values/
call_site_value.rs

1use std::fmt::{self, Display};
2
3use llvm_sys::core::LLVMGetCalledFunctionType;
4use llvm_sys::core::{
5    LLVMGetCalledValue, LLVMGetInstructionCallConv, LLVMGetTypeKind, LLVMIsTailCall, LLVMSetInstrParamAlignment,
6    LLVMSetInstructionCallConv, LLVMSetTailCall, LLVMTypeOf,
7};
8#[llvm_versions(18..)]
9use llvm_sys::core::{LLVMGetTailCallKind, LLVMSetTailCallKind};
10use llvm_sys::prelude::LLVMValueRef;
11use llvm_sys::LLVMTypeKind;
12
13use crate::attributes::{Attribute, AttributeLoc};
14use crate::types::FunctionType;
15#[llvm_versions(18..)]
16use crate::values::operand_bundle::OperandBundleIter;
17use crate::values::{AsValueRef, BasicValueEnum, FunctionValue, InstructionValue, Value};
18
19use super::{AnyValue, InstructionOpcode};
20
21/// Either [BasicValueEnum] or [InstructionValue].
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub enum ValueKind<'ctx> {
24    /// Represents a [BasicValueEnum].
25    Basic(BasicValueEnum<'ctx>),
26    /// Represents an [InstructionValue].
27    Instruction(InstructionValue<'ctx>),
28}
29
30impl<'ctx> ValueKind<'ctx> {
31    /// Determines if the [ValueKind] is a [BasicValueEnum].
32    #[inline]
33    #[must_use]
34    pub fn is_basic(self) -> bool {
35        matches!(self, Self::Basic(_))
36    }
37
38    /// Determines if the [ValueKind] is an [InstructionValue].
39    #[inline]
40    #[must_use]
41    pub fn is_instruction(self) -> bool {
42        matches!(self, Self::Instruction(_))
43    }
44
45    /// If the [ValueKind] is a [BasicValueEnum], map it into [Option::Some].
46    #[inline]
47    #[must_use]
48    pub fn basic(self) -> Option<BasicValueEnum<'ctx>> {
49        match self {
50            Self::Basic(value) => Some(value),
51            _ => None,
52        }
53    }
54
55    /// If the [ValueKind] is an [InstructionValue], map it into [Option::Some].
56    #[inline]
57    #[must_use]
58    pub fn instruction(self) -> Option<InstructionValue<'ctx>> {
59        match self {
60            Self::Instruction(inst) => Some(inst),
61            _ => None,
62        }
63    }
64
65    /// Expect [BasicValueEnum], panic with the message if it is not.
66    #[inline]
67    #[must_use]
68    #[track_caller]
69    pub fn expect_basic(self, msg: &str) -> BasicValueEnum<'ctx> {
70        match self {
71            Self::Basic(value) => value,
72            _ => panic!("{msg}"),
73        }
74    }
75
76    /// Expect [InstructionValue], panic with the message if it is not.
77    #[inline]
78    #[must_use]
79    #[track_caller]
80    pub fn expect_instruction(self, msg: &str) -> InstructionValue<'ctx> {
81        match self {
82            Self::Instruction(inst) => inst,
83            _ => panic!("{msg}"),
84        }
85    }
86
87    /// Unwrap [BasicValueEnum]. Will panic if it is not.
88    #[inline]
89    #[must_use]
90    #[track_caller]
91    pub fn unwrap_basic(self) -> BasicValueEnum<'ctx> {
92        self.expect_basic("Called unwrap_basic() on ValueKind::Instruction.")
93    }
94
95    /// Unwrap [InstructionValue]. Will panic if it is not.
96    #[inline]
97    #[must_use]
98    #[track_caller]
99    pub fn unwrap_instruction(self) -> InstructionValue<'ctx> {
100        self.expect_instruction("Called unwrap_instruction() on ValueKind::Basic.")
101    }
102}
103
104/// A value resulting from a function call. It may have function attributes applied to it.
105///
106/// This struct may be removed in the future in favor of an `InstructionValue<CallSite>` type.
107#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
108pub struct CallSiteValue<'ctx>(Value<'ctx>);
109
110impl<'ctx> CallSiteValue<'ctx> {
111    /// Get a value from an [LLVMValueRef].
112    ///
113    /// # Safety
114    ///
115    /// The ref must be valid and of type call site.
116    pub unsafe fn new(value: LLVMValueRef) -> Self {
117        CallSiteValue(Value::new(value))
118    }
119
120    /// Sets whether or not this call is a tail call.
121    ///
122    /// # Example
123    ///
124    /// ```no_run
125    /// use inkwell::context::Context;
126    ///
127    /// let context = Context::create();
128    /// let builder = context.create_builder();
129    /// let module = context.create_module("my_mod");
130    /// let void_type = context.void_type();
131    /// let fn_type = void_type.fn_type(&[], false);
132    /// let fn_value = module.add_function("my_fn", fn_type, None);
133    /// let entry_bb = context.append_basic_block(fn_value, "entry");
134    ///
135    /// builder.position_at_end(entry_bb);
136    ///
137    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
138    ///
139    /// call_site_value.set_tail_call(true);
140    /// ```
141    pub fn set_tail_call(self, tail_call: bool) {
142        unsafe { LLVMSetTailCall(self.as_value_ref(), tail_call as i32) }
143    }
144
145    /// Determines whether or not this call is a tail call.
146    ///
147    /// # Example
148    ///
149    /// ```no_run
150    /// use inkwell::context::Context;
151    ///
152    /// let context = Context::create();
153    /// let builder = context.create_builder();
154    /// let module = context.create_module("my_mod");
155    /// let void_type = context.void_type();
156    /// let fn_type = void_type.fn_type(&[], false);
157    /// let fn_value = module.add_function("my_fn", fn_type, None);
158    /// let entry_bb = context.append_basic_block(fn_value, "entry");
159    ///
160    /// builder.position_at_end(entry_bb);
161    ///
162    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
163    ///
164    /// call_site_value.set_tail_call(true);
165    ///
166    /// assert!(call_site_value.is_tail_call());
167    /// ```
168    pub fn is_tail_call(self) -> bool {
169        unsafe { LLVMIsTailCall(self.as_value_ref()) == 1 }
170    }
171
172    /// Returns tail, musttail, and notail attributes.
173    ///
174    /// # Example
175    ///
176    /// ```no_run
177    /// use inkwell::values::LLVMTailCallKind::*;
178    ///
179    /// let context = inkwell::context::Context::create();
180    /// let builder = context.create_builder();
181    /// let module = context.create_module("my_mod");
182    /// let void_type = context.void_type();
183    /// let fn_type = void_type.fn_type(&[], false);
184    /// let fn_value = module.add_function("my_fn", fn_type, None);
185    /// let entry_bb = context.append_basic_block(fn_value, "entry");
186    ///
187    /// builder.position_at_end(entry_bb);
188    ///
189    /// let call_site = builder.build_call(fn_value, &[], "my_fn").unwrap();
190    ///
191    /// assert_eq!(call_site.get_tail_call_kind(), LLVMTailCallKindNone);
192    /// ```
193    #[llvm_versions(18..)]
194    pub fn get_tail_call_kind(self) -> super::LLVMTailCallKind {
195        unsafe { LLVMGetTailCallKind(self.as_value_ref()) }
196    }
197
198    /// Sets tail, musttail, and notail attributes.
199    ///
200    /// # Example
201    ///
202    /// ```no_run
203    /// use inkwell::values::LLVMTailCallKind::*;
204    ///
205    /// let context = inkwell::context::Context::create();
206    /// let builder = context.create_builder();
207    /// let module = context.create_module("my_mod");
208    /// let void_type = context.void_type();
209    /// let fn_type = void_type.fn_type(&[], false);
210    /// let fn_value = module.add_function("my_fn", fn_type, None);
211    /// let entry_bb = context.append_basic_block(fn_value, "entry");
212    ///
213    /// builder.position_at_end(entry_bb);
214    ///
215    /// let call_site = builder.build_call(fn_value, &[], "my_fn").unwrap();
216    ///
217    /// call_site.set_tail_call_kind(LLVMTailCallKindTail);
218    /// assert_eq!(call_site.get_tail_call_kind(), LLVMTailCallKindTail);
219    /// ```
220    #[llvm_versions(18..)]
221    pub fn set_tail_call_kind(self, kind: super::LLVMTailCallKind) {
222        unsafe { LLVMSetTailCallKind(self.as_value_ref(), kind) };
223    }
224
225    /// Try to convert this `CallSiteValue` to a `BasicValueEnum` if not a void return type.
226    ///
227    /// # Example
228    ///
229    /// ```no_run
230    /// use inkwell::context::Context;
231    ///
232    /// let context = Context::create();
233    /// let builder = context.create_builder();
234    /// let module = context.create_module("my_mod");
235    /// let void_type = context.void_type();
236    /// let fn_type = void_type.fn_type(&[], false);
237    /// let fn_value = module.add_function("my_fn", fn_type, None);
238    /// let entry_bb = context.append_basic_block(fn_value, "entry");
239    ///
240    /// builder.position_at_end(entry_bb);
241    ///
242    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
243    ///
244    /// assert!(call_site_value.try_as_basic_value().is_instruction());
245    /// ```
246    pub fn try_as_basic_value(self) -> ValueKind<'ctx> {
247        unsafe {
248            match LLVMGetTypeKind(LLVMTypeOf(self.as_value_ref())) {
249                LLVMTypeKind::LLVMVoidTypeKind => ValueKind::Instruction(InstructionValue::new(self.as_value_ref())),
250                _ => ValueKind::Basic(BasicValueEnum::new(self.as_value_ref())),
251            }
252        }
253    }
254
255    /// Adds an `Attribute` to this `CallSiteValue`.
256    ///
257    /// # Example
258    ///
259    /// ```no_run
260    /// use inkwell::attributes::AttributeLoc;
261    /// use inkwell::context::Context;
262    ///
263    /// let context = Context::create();
264    /// let builder = context.create_builder();
265    /// let module = context.create_module("my_mod");
266    /// let void_type = context.void_type();
267    /// let fn_type = void_type.fn_type(&[], false);
268    /// let fn_value = module.add_function("my_fn", fn_type, None);
269    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
270    /// // Enum attribute cannot have non-zero value
271    /// let enum_attribute = context.create_enum_attribute(1, 0);
272    /// let entry_bb = context.append_basic_block(fn_value, "entry");
273    ///
274    /// builder.position_at_end(entry_bb);
275    ///
276    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
277    ///
278    /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
279    /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
280    /// ```
281    pub fn add_attribute(self, loc: AttributeLoc, attribute: Attribute) {
282        use llvm_sys::core::LLVMAddCallSiteAttribute;
283
284        unsafe { LLVMAddCallSiteAttribute(self.as_value_ref(), loc.get_index(), attribute.attribute) }
285    }
286
287    /// Gets the `FunctionValue` this `CallSiteValue` is based on.
288    ///
289    /// Returns [`None`] if the call this value bases on is indirect or the retrieved function
290    /// value doesn't have the same type as the underlying call instruction.
291    ///
292    /// # Example
293    ///
294    /// ```
295    /// use inkwell::context::Context;
296    ///
297    /// let context = Context::create();
298    /// let builder = context.create_builder();
299    /// let module = context.create_module("my_mod");
300    /// let void_type = context.void_type();
301    /// let fn_type = void_type.fn_type(&[], false);
302    /// let fn_value = module.add_function("my_fn", fn_type, None);
303    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
304    /// // Enum attribute cannot have non-zero value
305    /// let enum_attribute = context.create_enum_attribute(1, 0);
306    /// let entry_bb = context.append_basic_block(fn_value, "entry");
307    ///
308    /// builder.position_at_end(entry_bb);
309    ///
310    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
311    ///
312    /// assert_eq!(call_site_value.get_called_fn_value(), Some(fn_value));
313    /// ```
314    pub fn get_called_fn_value(self) -> Option<FunctionValue<'ctx>> {
315        // SAFETY: the passed LLVMValueRef is of type CallSite
316        let called_value = unsafe { LLVMGetCalledValue(self.as_value_ref()) };
317
318        let fn_value = unsafe { FunctionValue::new(called_value) };
319
320        // Check that the retrieved function value has the same type as the callee.
321        // This matches the behavior of the C++ API `CallBase::getCalledFunction`.
322        // This is only possible on LLVM >=8, where the `LLVMGetCalledFunctionType` API exists.
323        self.get_called_fn_value_check_type_consistency(fn_value)
324    }
325
326    #[inline]
327    fn get_called_fn_value_check_type_consistency(
328        &self,
329        fn_value: Option<FunctionValue<'ctx>>,
330    ) -> Option<FunctionValue<'ctx>> {
331        fn_value.filter(|fn_value| fn_value.get_type() == self.get_called_fn_type())
332    }
333
334    /// Gets the type of the function called by the instruction this `CallSiteValue` is based on.
335    ///
336    /// # Example
337    ///
338    /// ```
339    /// use inkwell::context::Context;
340    ///
341    /// let context = Context::create();
342    /// let builder = context.create_builder();
343    /// let module = context.create_module("my_mod");
344    /// let i32_type = context.i32_type();
345    /// let fn_type = i32_type.fn_type(&[], false);
346    /// let fn_value = module.add_function("my_fn", fn_type, None);
347    ///
348    /// let entry_bb = context.append_basic_block(fn_value, "entry");
349    /// builder.position_at_end(entry_bb);
350    ///
351    /// // Recursive call.
352    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
353    ///
354    /// assert_eq!(call_site_value.get_called_fn_type(), fn_type);
355    /// ```
356    pub fn get_called_fn_type(self) -> FunctionType<'ctx> {
357        // SAFETY: the passed LLVMValueRef is of type CallSite
358        let fn_type_ref = unsafe { LLVMGetCalledFunctionType(self.as_value_ref()) };
359
360        // FIXME?: this assumes that fn_type_ref is not null.
361        // SAFETY: fn_type_ref is a function type reference.
362        unsafe { FunctionType::new(fn_type_ref) }
363    }
364
365    /// Counts the number of `Attribute`s on this `CallSiteValue` at an index.
366    ///
367    /// # Example
368    ///
369    /// ```no_run
370    /// use inkwell::attributes::AttributeLoc;
371    /// use inkwell::context::Context;
372    ///
373    /// let context = Context::create();
374    /// let builder = context.create_builder();
375    /// let module = context.create_module("my_mod");
376    /// let void_type = context.void_type();
377    /// let fn_type = void_type.fn_type(&[], false);
378    /// let fn_value = module.add_function("my_fn", fn_type, None);
379    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
380    /// // Enum attribute cannot have non-zero value
381    /// let enum_attribute = context.create_enum_attribute(1, 0);
382    /// let entry_bb = context.append_basic_block(fn_value, "entry");
383    ///
384    /// builder.position_at_end(entry_bb);
385    ///
386    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
387    ///
388    /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
389    /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
390    ///
391    /// assert_eq!(call_site_value.count_attributes(AttributeLoc::Return), 2);
392    /// ```
393    pub fn count_attributes(self, loc: AttributeLoc) -> u32 {
394        use llvm_sys::core::LLVMGetCallSiteAttributeCount;
395
396        unsafe { LLVMGetCallSiteAttributeCount(self.as_value_ref(), loc.get_index()) }
397    }
398
399    /// Get all `Attribute`s on this `CallSiteValue` at an index.
400    ///
401    /// # Example
402    ///
403    /// ```no_run
404    /// use inkwell::attributes::AttributeLoc;
405    /// use inkwell::context::Context;
406    ///
407    /// let context = Context::create();
408    /// let builder = context.create_builder();
409    /// let module = context.create_module("my_mod");
410    /// let void_type = context.void_type();
411    /// let fn_type = void_type.fn_type(&[], false);
412    /// let fn_value = module.add_function("my_fn", fn_type, None);
413    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
414    /// // Enum attribute cannot have non-zero value
415    /// let enum_attribute = context.create_enum_attribute(1, 0);
416    /// let entry_bb = context.append_basic_block(fn_value, "entry");
417    ///
418    /// builder.position_at_end(entry_bb);
419    ///
420    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
421    ///
422    /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
423    /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
424    ///
425    /// assert_eq!(call_site_value.attributes(AttributeLoc::Return), vec![ string_attribute, enum_attribute ]);
426    /// ```
427    pub fn attributes(self, loc: AttributeLoc) -> Vec<Attribute> {
428        use llvm_sys::core::LLVMGetCallSiteAttributes;
429        use std::mem::{ManuallyDrop, MaybeUninit};
430
431        let count = self.count_attributes(loc) as usize;
432
433        // initialize a vector, but leave each element uninitialized
434        let mut attribute_refs: Vec<MaybeUninit<Attribute>> = vec![MaybeUninit::uninit(); count];
435
436        // Safety: relies on `Attribute` having the same in-memory representation as `LLVMAttributeRef`
437        unsafe {
438            LLVMGetCallSiteAttributes(
439                self.as_value_ref(),
440                loc.get_index(),
441                attribute_refs.as_mut_ptr() as *mut _,
442            )
443        }
444
445        // Safety: all elements are initialized
446        unsafe {
447            // ensure the vector is not dropped
448            let mut attribute_refs = ManuallyDrop::new(attribute_refs);
449
450            Vec::from_raw_parts(
451                attribute_refs.as_mut_ptr() as *mut Attribute,
452                attribute_refs.len(),
453                attribute_refs.capacity(),
454            )
455        }
456    }
457
458    /// Gets an enum `Attribute` on this `CallSiteValue` at an index and kind id.
459    ///
460    /// # Example
461    ///
462    /// ```no_run
463    /// use inkwell::attributes::AttributeLoc;
464    /// use inkwell::context::Context;
465    ///
466    /// let context = Context::create();
467    /// let builder = context.create_builder();
468    /// let module = context.create_module("my_mod");
469    /// let void_type = context.void_type();
470    /// let fn_type = void_type.fn_type(&[], false);
471    /// let fn_value = module.add_function("my_fn", fn_type, None);
472    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
473    /// // Enum attribute cannot have non-zero value
474    /// let enum_attribute = context.create_enum_attribute(1, 0);
475    /// let entry_bb = context.append_basic_block(fn_value, "entry");
476    ///
477    /// builder.position_at_end(entry_bb);
478    ///
479    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
480    ///
481    /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
482    /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
483    ///
484    /// assert_eq!(call_site_value.get_enum_attribute(AttributeLoc::Return, 1).unwrap(), enum_attribute);
485    /// ```
486    // SubTypes: -> Attribute<Enum>
487    pub fn get_enum_attribute(self, loc: AttributeLoc, kind_id: u32) -> Option<Attribute> {
488        use llvm_sys::core::LLVMGetCallSiteEnumAttribute;
489
490        let ptr = unsafe { LLVMGetCallSiteEnumAttribute(self.as_value_ref(), loc.get_index(), kind_id) };
491
492        if ptr.is_null() {
493            return None;
494        }
495
496        unsafe { Some(Attribute::new(ptr)) }
497    }
498
499    /// Gets a string `Attribute` on this `CallSiteValue` at an index and key.
500    ///
501    /// # Example
502    ///
503    /// ```no_run
504    /// use inkwell::attributes::AttributeLoc;
505    /// use inkwell::context::Context;
506    ///
507    /// let context = Context::create();
508    /// let builder = context.create_builder();
509    /// let module = context.create_module("my_mod");
510    /// let void_type = context.void_type();
511    /// let fn_type = void_type.fn_type(&[], false);
512    /// let fn_value = module.add_function("my_fn", fn_type, None);
513    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
514    /// // Enum attribute cannot have non-zero value
515    /// let enum_attribute = context.create_enum_attribute(1, 0);
516    /// let entry_bb = context.append_basic_block(fn_value, "entry");
517    ///
518    /// builder.position_at_end(entry_bb);
519    ///
520    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
521    ///
522    /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
523    /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
524    ///
525    /// assert_eq!(call_site_value.get_string_attribute(AttributeLoc::Return, "my_key").unwrap(), string_attribute);
526    /// ```
527    // SubTypes: -> Attribute<String>
528    pub fn get_string_attribute(self, loc: AttributeLoc, key: &str) -> Option<Attribute> {
529        use llvm_sys::core::LLVMGetCallSiteStringAttribute;
530
531        let ptr = unsafe {
532            LLVMGetCallSiteStringAttribute(
533                self.as_value_ref(),
534                loc.get_index(),
535                key.as_ptr() as *const ::libc::c_char,
536                key.len() as u32,
537            )
538        };
539
540        if ptr.is_null() {
541            return None;
542        }
543
544        unsafe { Some(Attribute::new(ptr)) }
545    }
546
547    /// Removes an enum `Attribute` on this `CallSiteValue` at an index and kind id.
548    ///
549    /// # Example
550    ///
551    /// ```no_run
552    /// use inkwell::attributes::AttributeLoc;
553    /// use inkwell::context::Context;
554    ///
555    /// let context = Context::create();
556    /// let builder = context.create_builder();
557    /// let module = context.create_module("my_mod");
558    /// let void_type = context.void_type();
559    /// let fn_type = void_type.fn_type(&[], false);
560    /// let fn_value = module.add_function("my_fn", fn_type, None);
561    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
562    /// // Enum attribute cannot have non-zero value
563    /// let enum_attribute = context.create_enum_attribute(1, 0);
564    /// let entry_bb = context.append_basic_block(fn_value, "entry");
565    ///
566    /// builder.position_at_end(entry_bb);
567    ///
568    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
569    ///
570    /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
571    /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
572    /// call_site_value.remove_enum_attribute(AttributeLoc::Return, 1);
573    ///
574    /// assert_eq!(call_site_value.get_enum_attribute(AttributeLoc::Return, 1), None);
575    /// ```
576    pub fn remove_enum_attribute(self, loc: AttributeLoc, kind_id: u32) {
577        use llvm_sys::core::LLVMRemoveCallSiteEnumAttribute;
578
579        unsafe { LLVMRemoveCallSiteEnumAttribute(self.as_value_ref(), loc.get_index(), kind_id) }
580    }
581
582    /// Removes a string `Attribute` on this `CallSiteValue` at an index and key.
583    ///
584    /// # Example
585    ///
586    /// ```no_run
587    /// use inkwell::attributes::AttributeLoc;
588    /// use inkwell::context::Context;
589    ///
590    /// let context = Context::create();
591    /// let builder = context.create_builder();
592    /// let module = context.create_module("my_mod");
593    /// let void_type = context.void_type();
594    /// let fn_type = void_type.fn_type(&[], false);
595    /// let fn_value = module.add_function("my_fn", fn_type, None);
596    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
597    /// // Enum attribute cannot have non-zero value
598    /// let enum_attribute = context.create_enum_attribute(1, 0);
599    /// let entry_bb = context.append_basic_block(fn_value, "entry");
600    ///
601    /// builder.position_at_end(entry_bb);
602    ///
603    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
604    ///
605    /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
606    /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
607    /// call_site_value.remove_string_attribute(AttributeLoc::Return, "my_key");
608    ///
609    /// assert_eq!(call_site_value.get_string_attribute(AttributeLoc::Return, "my_key"), None);
610    /// ```
611    pub fn remove_string_attribute(self, loc: AttributeLoc, key: &str) {
612        use llvm_sys::core::LLVMRemoveCallSiteStringAttribute;
613
614        unsafe {
615            LLVMRemoveCallSiteStringAttribute(
616                self.as_value_ref(),
617                loc.get_index(),
618                key.as_ptr() as *const ::libc::c_char,
619                key.len() as u32,
620            )
621        }
622    }
623
624    /// Counts the number of arguments this `CallSiteValue` was called with.
625    ///
626    /// # Example
627    ///
628    /// ```no_run
629    /// use inkwell::attributes::AttributeLoc;
630    /// use inkwell::context::Context;
631    ///
632    /// let context = Context::create();
633    /// let builder = context.create_builder();
634    /// let module = context.create_module("my_mod");
635    /// let void_type = context.void_type();
636    /// let fn_type = void_type.fn_type(&[], false);
637    /// let fn_value = module.add_function("my_fn", fn_type, None);
638    /// let string_attribute = context.create_string_attribute("my_key", "my_val");
639    /// // Enum attribute cannot have non-zero value
640    /// let enum_attribute = context.create_enum_attribute(1, 0);
641    /// let entry_bb = context.append_basic_block(fn_value, "entry");
642    ///
643    /// builder.position_at_end(entry_bb);
644    ///
645    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
646    ///
647    /// assert_eq!(call_site_value.count_arguments(), 0);
648    /// ```
649    pub fn count_arguments(self) -> u32 {
650        use llvm_sys::core::LLVMGetNumArgOperands;
651
652        unsafe { LLVMGetNumArgOperands(self.as_value_ref()) }
653    }
654
655    /// Gets the calling convention for this `CallSiteValue`.
656    ///
657    /// # Example
658    ///
659    /// ```no_run
660    /// use inkwell::context::Context;
661    ///
662    /// let context = Context::create();
663    /// let builder = context.create_builder();
664    /// let module = context.create_module("my_mod");
665    /// let void_type = context.void_type();
666    /// let fn_type = void_type.fn_type(&[], false);
667    /// let fn_value = module.add_function("my_fn", fn_type, None);
668    /// let entry_bb = context.append_basic_block(fn_value, "entry");
669    ///
670    /// builder.position_at_end(entry_bb);
671    ///
672    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
673    ///
674    /// assert_eq!(call_site_value.get_call_convention(), 0);
675    /// ```
676    pub fn get_call_convention(self) -> u32 {
677        unsafe { LLVMGetInstructionCallConv(self.as_value_ref()) }
678    }
679
680    /// Sets the calling convention for this `CallSiteValue`.
681    ///
682    /// # Example
683    ///
684    /// ```no_run
685    /// use inkwell::context::Context;
686    ///
687    /// let context = Context::create();
688    /// let builder = context.create_builder();
689    /// let module = context.create_module("my_mod");
690    /// let void_type = context.void_type();
691    /// let fn_type = void_type.fn_type(&[], false);
692    /// let fn_value = module.add_function("my_fn", fn_type, None);
693    /// let entry_bb = context.append_basic_block(fn_value, "entry");
694    ///
695    /// builder.position_at_end(entry_bb);
696    ///
697    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
698    ///
699    /// call_site_value.set_call_convention(2);
700    ///
701    /// assert_eq!(call_site_value.get_call_convention(), 2);
702    /// ```
703    pub fn set_call_convention(self, conv: u32) {
704        unsafe { LLVMSetInstructionCallConv(self.as_value_ref(), conv) }
705    }
706
707    /// Shortcut for setting the alignment `Attribute` for this `CallSiteValue`.
708    ///
709    /// # Panics
710    ///
711    /// When the alignment is not a power of 2.
712    ///
713    /// # Example
714    ///
715    /// ```no_run
716    /// use inkwell::attributes::AttributeLoc;
717    /// use inkwell::context::Context;
718    ///
719    /// let context = Context::create();
720    /// let builder = context.create_builder();
721    /// let module = context.create_module("my_mod");
722    /// let void_type = context.void_type();
723    /// let fn_type = void_type.fn_type(&[], false);
724    /// let fn_value = module.add_function("my_fn", fn_type, None);
725    /// let entry_bb = context.append_basic_block(fn_value, "entry");
726    ///
727    /// builder.position_at_end(entry_bb);
728    ///
729    /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap();
730    ///
731    /// call_site_value.set_alignment_attribute(AttributeLoc::Param(0), 2);
732    /// ```
733    pub fn set_alignment_attribute(self, loc: AttributeLoc, alignment: u32) {
734        assert_eq!(alignment.count_ones(), 1, "Alignment must be a power of two.");
735
736        unsafe { LLVMSetInstrParamAlignment(self.as_value_ref(), loc.get_index(), alignment) }
737    }
738
739    /// Iterate over operand bundles.
740    ///
741    /// # Example
742    ///
743    /// ```
744    /// use inkwell::context::Context;
745    /// use inkwell::values::OperandBundle;
746    ///
747    /// let context = Context::create();
748    /// let module = context.create_module("op_bundles");
749    /// let builder = context.create_builder();
750    ///
751    /// let void_type = context.void_type();
752    /// let i32_type = context.i32_type();
753    /// let fn_type = void_type.fn_type(&[], false);
754    /// let fn_value = module.add_function("func", fn_type, None);
755    ///
756    /// let basic_block = context.append_basic_block(fn_value, "entry");
757    /// builder.position_at_end(basic_block);
758    ///
759    /// // Recursive call
760    /// let callinst = builder.build_direct_call_with_operand_bundles(
761    ///   fn_value,
762    ///   &[],
763    ///   &[OperandBundle::create("tag0", &[i32_type.const_zero().into()]), OperandBundle::create("tag1", &[])],
764    ///   "call"
765    /// ).unwrap();
766    ///
767    /// builder.build_return(None).unwrap();
768    /// # module.verify().unwrap();
769    ///
770    /// let mut op_bundles_iter = callinst.get_operand_bundles();
771    /// assert_eq!(op_bundles_iter.len(), 2);
772    /// let tags: Vec<String> = op_bundles_iter.map(|ob| ob.get_tag().unwrap().into()).collect();
773    /// assert_eq!(tags, vec!["tag0", "tag1"]);
774    /// ```
775    #[llvm_versions(18..)]
776    pub fn get_operand_bundles(&self) -> OperandBundleIter<'_, 'ctx> {
777        OperandBundleIter::new(self)
778    }
779}
780
781unsafe impl AsValueRef for CallSiteValue<'_> {
782    fn as_value_ref(&self) -> LLVMValueRef {
783        self.0.value
784    }
785}
786
787impl Display for CallSiteValue<'_> {
788    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
789        write!(f, "{}", self.print_to_string())
790    }
791}
792
793impl<'ctx> TryFrom<InstructionValue<'ctx>> for CallSiteValue<'ctx> {
794    type Error = ();
795
796    fn try_from(value: InstructionValue<'ctx>) -> Result<Self, Self::Error> {
797        if value.get_opcode() == InstructionOpcode::Call {
798            unsafe { Ok(CallSiteValue::new(value.as_value_ref())) }
799        } else {
800            Err(())
801        }
802    }
803}