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}