Skip to main content

inkwell/values/
instruction_value.rs

1#[llvm_versions(14..)]
2use llvm_sys::core::LLVMGetGEPSourceElementType;
3use llvm_sys::core::{
4    LLVMGetAlignment, LLVMGetAllocatedType, LLVMGetFCmpPredicate, LLVMGetICmpPredicate, LLVMGetIndices,
5    LLVMGetInstructionOpcode, LLVMGetInstructionParent, LLVMGetMetadata, LLVMGetNextInstruction, LLVMGetNumIndices,
6    LLVMGetNumOperands, LLVMGetOperand, LLVMGetOperandUse, LLVMGetPreviousInstruction, LLVMGetVolatile,
7    LLVMHasMetadata, LLVMInstructionClone, LLVMInstructionEraseFromParent, LLVMInstructionRemoveFromParent,
8    LLVMIsAAllocaInst, LLVMIsABasicBlock, LLVMIsAGetElementPtrInst, LLVMIsALoadInst, LLVMIsAStoreInst,
9    LLVMIsATerminatorInst, LLVMIsConditional, LLVMIsTailCall, LLVMSetAlignment, LLVMSetMetadata, LLVMSetOperand,
10    LLVMSetVolatile, LLVMValueAsBasicBlock,
11};
12use llvm_sys::core::{LLVMGetAtomicRMWBinOp, LLVMIsAAtomicCmpXchgInst, LLVMIsAAtomicRMWInst};
13use llvm_sys::core::{LLVMGetOrdering, LLVMSetOrdering};
14use llvm_sys::prelude::LLVMValueRef;
15use llvm_sys::LLVMOpcode;
16
17use std::{ffi::CStr, fmt, fmt::Display};
18
19use crate::debug_info::DILocation;
20use crate::values::{BasicValue, BasicValueEnum, BasicValueUse, MetadataValue, Value};
21use crate::AtomicRMWBinOp;
22use crate::{basic_block::BasicBlock, types::AnyTypeEnum};
23use crate::{error::AlignmentError, values::basic_value_use::Operand};
24use crate::{types::BasicTypeEnum, values::traits::AsValueRef};
25use crate::{AtomicOrdering, FloatPredicate, IntPredicate};
26
27use super::AnyValue;
28
29/// Errors for atomic operations on load/store instructions.
30#[derive(Debug, thiserror::Error, PartialEq, Eq)]
31pub enum AtomicError {
32    #[error("The release ordering is not valid on load instructions.")]
33    ReleaseOnLoad,
34    #[error("The acq_rel ordering is not valid on load or store instructions.")]
35    AcquireRelease,
36    #[error("The acquire ordering is not valid on store instructions.")]
37    AcquireOnStore,
38}
39
40/// Errors for InstructionValue.
41#[derive(Debug, thiserror::Error, PartialEq, Eq)]
42pub enum InstructionValueError {
43    #[error("Cannot set name of a void-type instruction.")]
44    CannotNameVoidTypeInst,
45    #[error("Value is not a load, store, atomicrmw or cmpxchg instruction.")]
46    NotMemoryAccessInst,
47    #[error("Value is not a load or store instruction.")]
48    NotLoadOrStoreInst,
49    #[error("Value is not an alloca instruction.")]
50    NotAllocaInst,
51    #[error("Alignment Error: {0}")]
52    AlignmentError(AlignmentError),
53    #[error("Not a GEP instruction.")]
54    NotGEPInst,
55    #[error("Atomic Error: {0}")]
56    AtomicError(AtomicError),
57    #[error("Metadata is expected to be a node.")]
58    ExpectedNode,
59}
60
61// REVIEW: Split up into structs for SubTypes on InstructionValues?
62// REVIEW: This should maybe be split up into InstructionOpcode and ConstOpcode?
63// see LLVMGetConstOpcode
64#[llvm_enum(LLVMOpcode)]
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
66pub enum InstructionOpcode {
67    // Actual Instructions:
68    Add,
69    AddrSpaceCast,
70    Alloca,
71    And,
72    AShr,
73    AtomicCmpXchg,
74    AtomicRMW,
75    BitCast,
76    Br,
77    Call,
78    CallBr,
79    CatchPad,
80    CatchRet,
81    CatchSwitch,
82    CleanupPad,
83    CleanupRet,
84    ExtractElement,
85    ExtractValue,
86    FNeg,
87    FAdd,
88    FCmp,
89    FDiv,
90    Fence,
91    FMul,
92    FPExt,
93    FPToSI,
94    FPToUI,
95    FPTrunc,
96    Freeze,
97    FRem,
98    FSub,
99    GetElementPtr,
100    ICmp,
101    IndirectBr,
102    InsertElement,
103    InsertValue,
104    IntToPtr,
105    Invoke,
106    LandingPad,
107    Load,
108    LShr,
109    Mul,
110    Or,
111    #[llvm_variant(LLVMPHI)]
112    Phi,
113    PtrToInt,
114    Resume,
115    #[llvm_variant(LLVMRet)]
116    Return,
117    SDiv,
118    Select,
119    SExt,
120    Shl,
121    ShuffleVector,
122    SIToFP,
123    SRem,
124    Store,
125    Sub,
126    Switch,
127    Trunc,
128    UDiv,
129    UIToFP,
130    Unreachable,
131    URem,
132    UserOp1,
133    UserOp2,
134    VAArg,
135    Xor,
136    ZExt,
137}
138
139#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
140pub struct InstructionValue<'ctx> {
141    instruction_value: Value<'ctx>,
142}
143
144impl<'ctx> InstructionValue<'ctx> {
145    fn is_a_load_inst(self) -> bool {
146        !unsafe { LLVMIsALoadInst(self.as_value_ref()) }.is_null()
147    }
148
149    fn is_a_store_inst(self) -> bool {
150        !unsafe { LLVMIsAStoreInst(self.as_value_ref()) }.is_null()
151    }
152
153    fn is_a_alloca_inst(self) -> bool {
154        !unsafe { LLVMIsAAllocaInst(self.as_value_ref()) }.is_null()
155    }
156
157    #[allow(dead_code)]
158    fn is_a_getelementptr_inst(self) -> bool {
159        !unsafe { LLVMIsAGetElementPtrInst(self.as_value_ref()) }.is_null()
160    }
161
162    fn is_a_atomicrmw_inst(self) -> bool {
163        !unsafe { LLVMIsAAtomicRMWInst(self.as_value_ref()) }.is_null()
164    }
165
166    fn is_a_cmpxchg_inst(self) -> bool {
167        !unsafe { LLVMIsAAtomicCmpXchgInst(self.as_value_ref()) }.is_null()
168    }
169
170    /// Get a value from an [LLVMValueRef].
171    ///
172    /// # Safety
173    ///
174    /// The ref must be valid and of type instruction.
175    pub unsafe fn new(instruction_value: LLVMValueRef) -> Self {
176        debug_assert!(!instruction_value.is_null());
177
178        let value = Value::new(instruction_value);
179
180        debug_assert!(value.is_instruction());
181
182        InstructionValue {
183            instruction_value: value,
184        }
185    }
186
187    /// Creates a clone of this `InstructionValue`, and returns it.
188    /// The clone will have no parent, and no name.
189    pub fn explicit_clone(&self) -> Self {
190        unsafe { Self::new(LLVMInstructionClone(self.as_value_ref())) }
191    }
192
193    /// Get name of the `InstructionValue`.
194    pub fn get_name(&self) -> Option<&CStr> {
195        if self.get_type().is_void_type() {
196            None
197        } else {
198            Some(self.instruction_value.get_name())
199        }
200    }
201
202    /// Get a instruction with it's name
203    /// Compares against all instructions after self, and self.
204    pub fn get_instruction_with_name(&self, name: &str) -> Option<InstructionValue<'ctx>> {
205        if let Some(ins_name) = self.get_name() {
206            if ins_name.to_str() == Ok(name) {
207                return Some(*self);
208            }
209        }
210        self.get_next_instruction()?.get_instruction_with_name(name)
211    }
212
213    /// Set name of the `InstructionValue`.
214    pub fn set_name(&self, name: &str) -> Result<(), InstructionValueError> {
215        if self.get_type().is_void_type() {
216            Err(InstructionValueError::CannotNameVoidTypeInst)
217        } else {
218            self.instruction_value.set_name(name);
219            Ok(())
220        }
221    }
222
223    /// Get type of the current InstructionValue
224    pub fn get_type(self) -> AnyTypeEnum<'ctx> {
225        unsafe { AnyTypeEnum::new(self.instruction_value.get_type()) }
226    }
227
228    pub fn get_opcode(self) -> InstructionOpcode {
229        let opcode = unsafe { LLVMGetInstructionOpcode(self.as_value_ref()) };
230
231        InstructionOpcode::new(opcode)
232    }
233
234    pub fn get_previous_instruction(self) -> Option<Self> {
235        let value = unsafe { LLVMGetPreviousInstruction(self.as_value_ref()) };
236
237        if value.is_null() {
238            return None;
239        }
240
241        unsafe { Some(InstructionValue::new(value)) }
242    }
243
244    pub fn get_next_instruction(self) -> Option<Self> {
245        let value = unsafe { LLVMGetNextInstruction(self.as_value_ref()) };
246
247        if value.is_null() {
248            return None;
249        }
250
251        unsafe { Some(InstructionValue::new(value)) }
252    }
253
254    // REVIEW: Potentially unsafe if parent BB or grandparent fn were removed?
255    pub fn erase_from_basic_block(self) {
256        unsafe { LLVMInstructionEraseFromParent(self.as_value_ref()) }
257    }
258
259    // REVIEW: Potentially unsafe if parent BB or grandparent fn were removed?
260    pub fn remove_from_basic_block(self) {
261        unsafe { LLVMInstructionRemoveFromParent(self.as_value_ref()) }
262    }
263
264    // REVIEW: Potentially unsafe is parent BB or grandparent fn was deleted
265    // REVIEW: Should this *not* be an option? Parent should always exist,
266    // but I doubt LLVM returns null if the parent BB (or grandparent FN)
267    // was deleted... Invalid memory is more likely. Cloned IV will have no
268    // parent?
269    pub fn get_parent(self) -> Option<BasicBlock<'ctx>> {
270        unsafe { BasicBlock::new(LLVMGetInstructionParent(self.as_value_ref())) }
271    }
272
273    /// Returns if the instruction is a terminator
274    pub fn is_terminator(self) -> bool {
275        unsafe { !LLVMIsATerminatorInst(self.as_value_ref()).is_null() }
276    }
277
278    // SubTypes: Only apply to terminators
279    /// Returns if a terminator is conditional or not
280    pub fn is_conditional(self) -> bool {
281        if self.get_opcode() == InstructionOpcode::Br {
282            unsafe { LLVMIsConditional(self.as_value_ref()) == 1 }
283        } else {
284            false
285        }
286    }
287
288    pub fn is_tail_call(self) -> bool {
289        // LLVMIsTailCall has UB if the value is not an llvm::CallInst*.
290        if self.get_opcode() == InstructionOpcode::Call {
291            unsafe { LLVMIsTailCall(self.as_value_ref()) == 1 }
292        } else {
293            false
294        }
295    }
296
297    /// Returns the tail call kind on call instructions.
298    ///
299    /// Other instructions return `None`.
300    #[llvm_versions(18..)]
301    pub fn get_tail_call_kind(self) -> Option<super::LLVMTailCallKind> {
302        if self.get_opcode() == InstructionOpcode::Call {
303            unsafe { llvm_sys::core::LLVMGetTailCallKind(self.as_value_ref()) }.into()
304        } else {
305            None
306        }
307    }
308
309    /// Check whether this instructions supports [fast math flags][0].
310    ///
311    /// [0]: https://llvm.org/docs/LangRef.html#fast-math-flags
312    #[llvm_versions(18..)]
313    pub fn can_use_fast_math_flags(self) -> bool {
314        unsafe { llvm_sys::core::LLVMCanValueUseFastMathFlags(self.as_value_ref()) == 1 }
315    }
316
317    /// Get [fast math flags][0] of supported instructions.
318    ///
319    /// Calling this on unsupported instructions is safe and returns `None`.
320    ///
321    /// [0]: https://llvm.org/docs/LangRef.html#fast-math-flags
322    #[llvm_versions(18..)]
323    pub fn get_fast_math_flags(self) -> Option<u32> {
324        self.can_use_fast_math_flags()
325            .then(|| unsafe { llvm_sys::core::LLVMGetFastMathFlags(self.as_value_ref()) } as u32)
326    }
327
328    /// Set [fast math flags][0] on supported instructions.
329    ///
330    /// Calling this on unsupported instructions is safe and results in a no-op.
331    ///
332    /// [0]: https://llvm.org/docs/LangRef.html#fast-math-flags
333    #[llvm_versions(18..)]
334    pub fn set_fast_math_flags(self, flags: u32) {
335        if self.can_use_fast_math_flags() {
336            unsafe { llvm_sys::core::LLVMSetFastMathFlags(self.as_value_ref(), flags) };
337        }
338    }
339
340    /// Check if a `zext` instruction has the non-negative flag set.
341    ///
342    /// Calling this function on other instructions is safe and returns `None`.
343    #[llvm_versions(18..)]
344    pub fn get_non_negative_flag(self) -> Option<bool> {
345        (self.get_opcode() == InstructionOpcode::ZExt)
346            .then(|| unsafe { llvm_sys::core::LLVMGetNNeg(self.as_value_ref()) == 1 })
347    }
348
349    /// Set the non-negative flag on `zext` instructions.
350    ///
351    /// Calling this function on other instructions is safe and results in a no-op.
352    #[llvm_versions(18..)]
353    pub fn set_non_negative_flag(self, flag: bool) {
354        if self.get_opcode() == InstructionOpcode::ZExt {
355            unsafe { llvm_sys::core::LLVMSetNNeg(self.as_value_ref(), flag as i32) };
356        }
357    }
358
359    /// Checks if an `or` instruction has the `disjoint` flag set.
360    ///
361    /// Calling this function on other instructions is safe and returns `None`.
362    #[llvm_versions(18..)]
363    pub fn get_disjoint_flag(self) -> Option<bool> {
364        (self.get_opcode() == InstructionOpcode::Or)
365            .then(|| unsafe { llvm_sys::core::LLVMGetIsDisjoint(self.as_value_ref()) == 1 })
366    }
367
368    /// Set the `disjoint` flag on `or` instructions.
369    ///
370    /// Calling this function on other instructions is safe and results in a no-op.
371    #[llvm_versions(18..)]
372    pub fn set_disjoint_flag(self, flag: bool) {
373        if self.get_opcode() == InstructionOpcode::Or {
374            unsafe { llvm_sys::core::LLVMSetIsDisjoint(self.as_value_ref(), flag as i32) };
375        }
376    }
377
378    pub fn replace_all_uses_with(self, other: &InstructionValue<'ctx>) {
379        self.instruction_value.replace_all_uses_with(other.as_value_ref())
380    }
381
382    // SubTypes: Only apply to memory access instructions
383    /// Returns whether or not a memory access instruction is volatile.
384    pub fn get_volatile(self) -> Result<bool, InstructionValueError> {
385        if !self.is_a_load_inst() && !self.is_a_store_inst() && !self.is_a_atomicrmw_inst() && !self.is_a_cmpxchg_inst()
386        {
387            return Err(InstructionValueError::NotMemoryAccessInst);
388        }
389        Ok(unsafe { LLVMGetVolatile(self.as_value_ref()) } == 1)
390    }
391
392    // SubTypes: Only apply to memory access instructions
393    /// Sets whether or not a memory access instruction is volatile.
394    pub fn set_volatile(self, volatile: bool) -> Result<(), InstructionValueError> {
395        if !self.is_a_load_inst() && !self.is_a_store_inst() && !self.is_a_atomicrmw_inst() && !self.is_a_cmpxchg_inst()
396        {
397            return Err(InstructionValueError::NotMemoryAccessInst);
398        }
399        unsafe { LLVMSetVolatile(self.as_value_ref(), volatile as i32) };
400        Ok(())
401    }
402
403    // SubTypes: Only apply to alloca instruction
404    /// Returns the type that is allocated by the alloca instruction.
405    pub fn get_allocated_type(self) -> Result<BasicTypeEnum<'ctx>, InstructionValueError> {
406        if !self.is_a_alloca_inst() {
407            return Err(InstructionValueError::NotAllocaInst);
408        }
409        Ok(unsafe { BasicTypeEnum::new(LLVMGetAllocatedType(self.as_value_ref())) })
410    }
411
412    // SubTypes: Only apply to GetElementPtr instruction
413    /// Returns the source element type of the given GEP.
414    #[llvm_versions(14..)]
415    pub fn get_gep_source_element_type(self) -> Result<BasicTypeEnum<'ctx>, InstructionValueError> {
416        if !self.is_a_getelementptr_inst() {
417            return Err(InstructionValueError::NotGEPInst);
418        }
419        Ok(unsafe { BasicTypeEnum::new(LLVMGetGEPSourceElementType(self.as_value_ref())) })
420    }
421
422    // SubTypes: Only apply to memory access and alloca instructions
423    /// Returns alignment on a memory access instruction or alloca.
424    pub fn get_alignment(self) -> Result<u32, InstructionValueError> {
425        if !self.is_a_alloca_inst() && !self.is_a_load_inst() && !self.is_a_store_inst() {
426            return Err(InstructionValueError::AlignmentError(
427                AlignmentError::UnalignedInstruction,
428            ));
429        }
430        Ok(unsafe { LLVMGetAlignment(self.as_value_ref()) })
431    }
432
433    // SubTypes: Only apply to memory access and alloca instructions
434    /// Sets alignment on a memory access instruction or alloca.
435    pub fn set_alignment(self, alignment: u32) -> Result<(), InstructionValueError> {
436        // Zero check is unnecessary as 0 is not a power of two.
437        if !alignment.is_power_of_two() {
438            return Err(InstructionValueError::AlignmentError(AlignmentError::NonPowerOfTwo(
439                alignment,
440            )));
441        }
442        if !self.is_a_alloca_inst() && !self.is_a_load_inst() && !self.is_a_store_inst() {
443            return Err(InstructionValueError::AlignmentError(
444                AlignmentError::UnalignedInstruction,
445            ));
446        }
447        unsafe { LLVMSetAlignment(self.as_value_ref(), alignment) };
448        Ok(())
449    }
450
451    // SubTypes: Only apply to memory access instructions
452    /// Returns atomic ordering on a memory access instruction.
453    pub fn get_atomic_ordering(self) -> Result<AtomicOrdering, InstructionValueError> {
454        if !self.is_a_load_inst() && !self.is_a_store_inst() {
455            return Err(InstructionValueError::NotLoadOrStoreInst);
456        }
457        Ok(unsafe { LLVMGetOrdering(self.as_value_ref()) }.into())
458    }
459
460    // SubTypes: Only apply to memory access instructions
461    /// Sets atomic ordering on a memory access instruction.
462    pub fn set_atomic_ordering(self, ordering: AtomicOrdering) -> Result<(), InstructionValueError> {
463        // Although fence and atomicrmw both have an ordering, the LLVM C API
464        // does not support them. The cmpxchg instruction has two orderings and
465        // does not work with this API.
466        if !self.is_a_load_inst() && !self.is_a_store_inst() {
467            return Err(InstructionValueError::NotLoadOrStoreInst);
468        }
469        match ordering {
470            AtomicOrdering::Release if self.is_a_load_inst() => {
471                return Err(InstructionValueError::AtomicError(AtomicError::ReleaseOnLoad))
472            },
473            AtomicOrdering::AcquireRelease => {
474                return Err(InstructionValueError::AtomicError(AtomicError::AcquireRelease))
475            },
476            AtomicOrdering::Acquire if self.is_a_store_inst() => {
477                return Err(InstructionValueError::AtomicError(AtomicError::AcquireOnStore))
478            },
479            _ => {},
480        };
481        unsafe { LLVMSetOrdering(self.as_value_ref(), ordering.into()) };
482        Ok(())
483    }
484
485    /// Obtains the number of operands an `InstructionValue` has.
486    /// An operand is a `BasicValue` used in an IR instruction.
487    ///
488    /// The following example,
489    ///
490    /// ```no_run
491    /// use inkwell::AddressSpace;
492    /// use inkwell::context::Context;
493    ///
494    /// let context = Context::create();
495    /// let module = context.create_module("ivs");
496    /// let builder = context.create_builder();
497    /// let void_type = context.void_type();
498    /// let f32_type = context.f32_type();
499    /// #[cfg(feature = "typed-pointers")]
500    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
501    /// #[cfg(not(feature = "typed-pointers"))]
502    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
503    /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);
504    ///
505    /// let function = module.add_function("take_f32_ptr", fn_type, None);
506    /// let basic_block = context.append_basic_block(function, "entry");
507    ///
508    /// builder.position_at_end(basic_block);
509    ///
510    /// let arg1 = function.get_first_param().unwrap().into_pointer_value();
511    /// let f32_val = f32_type.const_float(std::f64::consts::PI);
512    /// let store_instruction = builder.build_store(arg1, f32_val).unwrap();
513    /// let free_instruction = builder.build_free(arg1).unwrap();
514    /// let return_instruction = builder.build_return(None).unwrap();
515    ///
516    /// assert_eq!(store_instruction.get_num_operands(), 2);
517    /// assert_eq!(free_instruction.get_num_operands(), 2);
518    /// assert_eq!(return_instruction.get_num_operands(), 0);
519    /// ```
520    ///
521    /// will generate LLVM IR roughly like (varying slightly across LLVM versions):
522    ///
523    /// ```ir
524    /// ; ModuleID = 'ivs'
525    /// source_filename = "ivs"
526    ///
527    /// define void @take_f32_ptr(float* %0) {
528    /// entry:
529    ///   store float 0x400921FB60000000, float* %0
530    ///   %1 = bitcast float* %0 to i8*
531    ///   tail call void @free(i8* %1)
532    ///   ret void
533    /// }
534    ///
535    /// declare void @free(i8*)
536    /// ```
537    ///
538    /// which makes the number of instruction operands clear:
539    /// 1) Store has two: a const float and a variable float pointer %0
540    /// 2) Bitcast has one: a variable float pointer %0
541    /// 3) Function call has two: i8 pointer %1 argument, and the free function itself
542    /// 4) Void return has zero: void is not a value and does not count as an operand
543    ///    even though the return instruction can take values.
544    pub fn get_num_operands(self) -> u32 {
545        unsafe { LLVMGetNumOperands(self.as_value_ref()) as u32 }
546    }
547
548    /// Obtains the operand an `InstructionValue` has at a given index if any.
549    /// An operand is a `BasicValue` used in an IR instruction.
550    ///
551    /// The following example,
552    ///
553    /// ```no_run
554    /// use inkwell::AddressSpace;
555    /// use inkwell::context::Context;
556    ///
557    /// let context = Context::create();
558    /// let module = context.create_module("ivs");
559    /// let builder = context.create_builder();
560    /// let void_type = context.void_type();
561    /// let f32_type = context.f32_type();
562    /// #[cfg(feature = "typed-pointers")]
563    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
564    /// #[cfg(not(feature = "typed-pointers"))]
565    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
566    /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);
567    ///
568    /// let function = module.add_function("take_f32_ptr", fn_type, None);
569    /// let basic_block = context.append_basic_block(function, "entry");
570    ///
571    /// builder.position_at_end(basic_block);
572    ///
573    /// let arg1 = function.get_first_param().unwrap().into_pointer_value();
574    /// let f32_val = f32_type.const_float(std::f64::consts::PI);
575    /// let store_instruction = builder.build_store(arg1, f32_val).unwrap();
576    /// let free_instruction = builder.build_free(arg1).unwrap();
577    /// let return_instruction = builder.build_return(None).unwrap();
578    ///
579    /// assert!(store_instruction.get_operand(0).is_some());
580    /// assert!(store_instruction.get_operand(1).is_some());
581    /// assert!(store_instruction.get_operand(2).is_none());
582    /// assert!(free_instruction.get_operand(0).is_some());
583    /// assert!(free_instruction.get_operand(1).is_some());
584    /// assert!(free_instruction.get_operand(2).is_none());
585    /// assert!(return_instruction.get_operand(0).is_none());
586    /// assert!(return_instruction.get_operand(1).is_none());
587    /// ```
588    ///
589    /// will generate LLVM IR roughly like (varying slightly across LLVM versions):
590    ///
591    /// ```ir
592    /// ; ModuleID = 'ivs'
593    /// source_filename = "ivs"
594    ///
595    /// define void @take_f32_ptr(float* %0) {
596    /// entry:
597    ///   store float 0x400921FB60000000, float* %0
598    ///   %1 = bitcast float* %0 to i8*
599    ///   tail call void @free(i8* %1)
600    ///   ret void
601    /// }
602    ///
603    /// declare void @free(i8*)
604    /// ```
605    ///
606    /// which makes the instruction operands clear:
607    /// 1) Store has two: a const float and a variable float pointer %0
608    /// 2) Bitcast has one: a variable float pointer %0
609    /// 3) Function call has two: i8 pointer %1 argument, and the free function itself
610    /// 4) Void return has zero: void is not a value and does not count as an operand
611    ///    even though the return instruction can take values.
612    pub fn get_operand(self, index: u32) -> Option<Operand<'ctx>> {
613        let num_operands = self.get_num_operands();
614
615        if index >= num_operands {
616            return None;
617        }
618
619        unsafe { self.get_operand_unchecked(index) }
620    }
621
622    /// Get the operand of an `InstructionValue`.
623    ///
624    /// # Safety
625    ///
626    /// The index must be less than [InstructionValue::get_num_operands].
627    pub unsafe fn get_operand_unchecked(self, index: u32) -> Option<Operand<'ctx>> {
628        let operand = unsafe { LLVMGetOperand(self.as_value_ref(), index) };
629
630        if operand.is_null() {
631            return None;
632        }
633
634        let is_basic_block = unsafe { !LLVMIsABasicBlock(operand).is_null() };
635
636        if is_basic_block {
637            let bb = unsafe { BasicBlock::new(LLVMValueAsBasicBlock(operand)) };
638
639            Some(Operand::Block(bb.expect("BasicBlock should always be valid")))
640        } else {
641            Some(Operand::Value(unsafe { BasicValueEnum::new(operand) }))
642        }
643    }
644
645    /// Get an instruction value operand iterator.
646    pub fn get_operands(self) -> OperandIter<'ctx> {
647        OperandIter {
648            iv: self,
649            i: 0,
650            count: self.get_num_operands(),
651        }
652    }
653
654    /// Sets the operand an `InstructionValue` has at a given index if possible.
655    /// An operand is a `BasicValue` used in an IR instruction.
656    ///
657    /// ```no_run
658    /// use inkwell::AddressSpace;
659    /// use inkwell::context::Context;
660    ///
661    /// let context = Context::create();
662    /// let module = context.create_module("ivs");
663    /// let builder = context.create_builder();
664    /// let void_type = context.void_type();
665    /// let f32_type = context.f32_type();
666    /// #[cfg(feature = "typed-pointers")]
667    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
668    /// #[cfg(not(feature = "typed-pointers"))]
669    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
670    /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);
671    ///
672    /// let function = module.add_function("take_f32_ptr", fn_type, None);
673    /// let basic_block = context.append_basic_block(function, "entry");
674    ///
675    /// builder.position_at_end(basic_block);
676    ///
677    /// let arg1 = function.get_first_param().unwrap().into_pointer_value();
678    /// let f32_val = f32_type.const_float(std::f64::consts::PI);
679    /// let store_instruction = builder.build_store(arg1, f32_val).unwrap();
680    /// let free_instruction = builder.build_free(arg1).unwrap();
681    /// let return_instruction = builder.build_return(None).unwrap();
682    ///
683    /// // This will produce invalid IR:
684    /// free_instruction.set_operand(0, f32_val);
685    ///
686    /// assert_eq!(free_instruction.get_operand(0).unwrap().unwrap_value(), f32_val);
687    /// ```
688    pub fn set_operand<BV: BasicValue<'ctx>>(self, index: u32, val: BV) -> bool {
689        let num_operands = self.get_num_operands();
690
691        if index >= num_operands {
692            return false;
693        }
694
695        unsafe { LLVMSetOperand(self.as_value_ref(), index, val.as_value_ref()) }
696
697        true
698    }
699
700    /// Gets the use of an operand(`BasicValue`), if any.
701    ///
702    /// ```no_run
703    /// use inkwell::AddressSpace;
704    /// use inkwell::context::Context;
705    /// use inkwell::values::BasicValue;
706    ///
707    /// let context = Context::create();
708    /// let module = context.create_module("ivs");
709    /// let builder = context.create_builder();
710    /// let void_type = context.void_type();
711    /// let f32_type = context.f32_type();
712    /// #[cfg(feature = "typed-pointers")]
713    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
714    /// #[cfg(not(feature = "typed-pointers"))]
715    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
716    /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);
717    ///
718    /// let function = module.add_function("take_f32_ptr", fn_type, None);
719    /// let basic_block = context.append_basic_block(function, "entry");
720    ///
721    /// builder.position_at_end(basic_block);
722    ///
723    /// let arg1 = function.get_first_param().unwrap().into_pointer_value();
724    /// let f32_val = f32_type.const_float(std::f64::consts::PI);
725    /// let store_instruction = builder.build_store(arg1, f32_val).unwrap();
726    /// let free_instruction = builder.build_free(arg1).unwrap();
727    /// let return_instruction = builder.build_return(None).unwrap();
728    ///
729    /// assert_eq!(store_instruction.get_operand_use(1), arg1.get_first_use());
730    /// ```
731    pub fn get_operand_use(self, index: u32) -> Option<BasicValueUse<'ctx>> {
732        let num_operands = self.get_num_operands();
733
734        if index >= num_operands {
735            return None;
736        }
737
738        unsafe { self.get_operand_use_unchecked(index) }
739    }
740
741    /// Gets the use of an operand(`BasicValue`), if any.
742    ///
743    /// # Safety
744    ///
745    /// The index must be smaller than [InstructionValue::get_num_operands].
746    pub unsafe fn get_operand_use_unchecked(self, index: u32) -> Option<BasicValueUse<'ctx>> {
747        let use_ = unsafe { LLVMGetOperandUse(self.as_value_ref(), index) };
748
749        if use_.is_null() {
750            return None;
751        }
752
753        unsafe { Some(BasicValueUse::new(use_)) }
754    }
755
756    /// Get an instruction value operand use iterator.
757    pub fn get_operand_uses(self) -> OperandUseIter<'ctx> {
758        OperandUseIter {
759            iv: self,
760            i: 0,
761            count: self.get_num_operands(),
762        }
763    }
764
765    /// Obtains the number of indices an `InstructionValue` has.
766    /// An index is used in `ExtractValue` and `InsertValue` instructions to specify
767    /// which field or element to access in an aggregate type (struct or array).
768    ///
769    /// Returns 0 for instructions that are not `ExtractValue` or `InsertValue`.
770    ///
771    /// The following example,
772    ///
773    /// ```no_run
774    /// use inkwell::context::Context;
775    /// use inkwell::values::BasicValue;
776    ///
777    /// let context = Context::create();
778    /// let module = context.create_module("ivs");
779    /// let builder = context.create_builder();
780    /// let void_type = context.void_type();
781    /// let i32_type = context.i32_type();
782    /// let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false);
783    /// let fn_type = void_type.fn_type(&[], false);
784    ///
785    /// let function = module.add_function("test", fn_type, None);
786    /// let basic_block = context.append_basic_block(function, "entry");
787    ///
788    /// builder.position_at_end(basic_block);
789    ///
790    /// let struct_val = struct_type.get_undef();
791    /// let extract_instruction = builder.build_extract_value(struct_val, 0, "extract").unwrap()
792    ///     .as_instruction_value().unwrap();
793    ///
794    /// assert_eq!(extract_instruction.get_num_indices(), 1);
795    /// ```
796    pub fn get_num_indices(self) -> u32 {
797        let opcode = self.get_opcode();
798        if opcode != InstructionOpcode::ExtractValue && opcode != InstructionOpcode::InsertValue {
799            return 0;
800        }
801        unsafe { LLVMGetNumIndices(self.as_value_ref()) }
802    }
803
804    /// Obtains the indices an `InstructionValue` has as a vector.
805    /// An index is used in `ExtractValue` and `InsertValue` instructions to specify
806    /// which field or element to access in an aggregate type (struct or array).
807    ///
808    /// Returns an empty vector for instructions that are not `ExtractValue` or `InsertValue`.
809    ///
810    /// The following example,
811    ///
812    /// ```no_run
813    /// use inkwell::context::Context;
814    /// use inkwell::values::BasicValue;
815    ///
816    /// let context = Context::create();
817    /// let module = context.create_module("ivs");
818    /// let builder = context.create_builder();
819    /// let void_type = context.void_type();
820    /// let i32_type = context.i32_type();
821    /// let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false);
822    /// let fn_type = void_type.fn_type(&[], false);
823    ///
824    /// let function = module.add_function("test", fn_type, None);
825    /// let basic_block = context.append_basic_block(function, "entry");
826    ///
827    /// builder.position_at_end(basic_block);
828    ///
829    /// let struct_val = struct_type.get_undef();
830    /// let extract_instruction = builder.build_extract_value(struct_val, 0, "extract").unwrap()
831    ///     .as_instruction_value().unwrap();
832    ///
833    /// assert_eq!(extract_instruction.get_indices(), vec![0]);
834    /// ```
835    pub fn get_indices(self) -> Vec<u32> {
836        let num_indices = self.get_num_indices();
837        if num_indices == 0 {
838            return Vec::new();
839        }
840
841        unsafe {
842            let indices_ptr = LLVMGetIndices(self.as_value_ref());
843            std::slice::from_raw_parts(indices_ptr, num_indices as usize).to_vec()
844        }
845    }
846
847    /// Gets the first use of an `InstructionValue` if any.
848    ///
849    /// The following example,
850    ///
851    /// ```no_run
852    /// use inkwell::AddressSpace;
853    /// use inkwell::context::Context;
854    /// use inkwell::values::BasicValue;
855    ///
856    /// let context = Context::create();
857    /// let module = context.create_module("ivs");
858    /// let builder = context.create_builder();
859    /// let void_type = context.void_type();
860    /// let f32_type = context.f32_type();
861    /// #[cfg(feature = "typed-pointers")]
862    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
863    /// #[cfg(not(feature = "typed-pointers"))]
864    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
865    /// let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);
866    ///
867    /// let function = module.add_function("take_f32_ptr", fn_type, None);
868    /// let basic_block = context.append_basic_block(function, "entry");
869    ///
870    /// builder.position_at_end(basic_block);
871    ///
872    /// let arg1 = function.get_first_param().unwrap().into_pointer_value();
873    /// let f32_val = f32_type.const_float(std::f64::consts::PI);
874    /// let store_instruction = builder.build_store(arg1, f32_val).unwrap();
875    /// let free_instruction = builder.build_free(arg1).unwrap();
876    /// let return_instruction = builder.build_return(None).unwrap();
877    ///
878    /// assert!(arg1.get_first_use().is_some());
879    /// ```
880    pub fn get_first_use(self) -> Option<BasicValueUse<'ctx>> {
881        self.instruction_value.get_first_use()
882    }
883
884    /// Gets the predicate of an `ICmp` `InstructionValue`.
885    /// For instance, in the LLVM instruction
886    /// `%3 = icmp slt i32 %0, %1`
887    /// this gives the `slt`.
888    ///
889    /// If the instruction is not an `ICmp`, this returns None.
890    pub fn get_icmp_predicate(self) -> Option<IntPredicate> {
891        // REVIEW: this call to get_opcode() can be inefficient;
892        // what happens if we don't perform this check, and just call
893        // LLVMGetICmpPredicate() regardless?
894        if self.get_opcode() == InstructionOpcode::ICmp {
895            let pred = unsafe { LLVMGetICmpPredicate(self.as_value_ref()) };
896            Some(IntPredicate::new(pred))
897        } else {
898            None
899        }
900    }
901
902    /// Gets the predicate of an `FCmp` `InstructionValue`.
903    /// For instance, in the LLVM instruction
904    /// `%3 = fcmp olt float %0, %1`
905    /// this gives the `olt`.
906    ///
907    /// If the instruction is not an `FCmp`, this returns None.
908    pub fn get_fcmp_predicate(self) -> Option<FloatPredicate> {
909        // REVIEW: this call to get_opcode() can be inefficient;
910        // what happens if we don't perform this check, and just call
911        // LLVMGetFCmpPredicate() regardless?
912        if self.get_opcode() == InstructionOpcode::FCmp {
913            let pred = unsafe { LLVMGetFCmpPredicate(self.as_value_ref()) };
914            Some(FloatPredicate::new(pred))
915        } else {
916            None
917        }
918    }
919
920    /// Gets the binary operation of an `AtomicRMW` `InstructionValue`.
921    /// For instance, in the LLVM instruction
922    /// `%3 = atomicrmw add i32* %ptr, i32 %val monotonic`
923    /// this gives the `add`.
924    ///
925    /// If the instruction is not an `AtomicRMW`, this returns None.
926    pub fn get_atomic_rmw_bin_op(self) -> Option<AtomicRMWBinOp> {
927        if self.get_opcode() == InstructionOpcode::AtomicRMW {
928            let bin_op = unsafe { LLVMGetAtomicRMWBinOp(self.as_value_ref()) };
929            Some(AtomicRMWBinOp::new(bin_op))
930        } else {
931            None
932        }
933    }
934
935    /// Determines whether or not this `Instruction` has any associated metadata.
936    pub fn has_metadata(self) -> bool {
937        unsafe { LLVMHasMetadata(self.instruction_value.value) == 1 }
938    }
939
940    /// Gets the `MetadataValue` associated with this `Instruction` at a specific
941    /// `kind_id`.
942    pub fn get_metadata(self, kind_id: u32) -> Option<MetadataValue<'ctx>> {
943        let metadata_value = unsafe { LLVMGetMetadata(self.instruction_value.value, kind_id) };
944
945        if metadata_value.is_null() {
946            return None;
947        }
948
949        unsafe { Some(MetadataValue::new(metadata_value)) }
950    }
951
952    /// Determines whether or not this `Instruction` has any associated metadata
953    /// `kind_id`.
954    pub fn set_metadata(self, metadata: MetadataValue<'ctx>, kind_id: u32) -> Result<(), InstructionValueError> {
955        if !metadata.is_node() {
956            return Err(InstructionValueError::ExpectedNode);
957        }
958
959        unsafe {
960            LLVMSetMetadata(self.instruction_value.value, kind_id, metadata.as_value_ref());
961        }
962
963        Ok(())
964    }
965
966    /// Get the debug location for this instruction.
967    pub fn get_debug_location(self) -> Option<DILocation<'ctx>> {
968        // https://github.com/llvm/llvm-project/blob/e83cc896e7c2378914a391f942c188d454b517d2/llvm/include/llvm/IR/Instruction.h#L513
969        let metadata_ref = unsafe { llvm_sys::debuginfo::LLVMInstructionGetDebugLoc(self.as_value_ref()) };
970        if metadata_ref.is_null() {
971            None
972        } else {
973            Some(DILocation {
974                metadata_ref,
975                _marker: std::marker::PhantomData,
976            })
977        }
978    }
979
980    /// Set the debug location for this instruction.
981    pub fn set_debug_location(self, location: Option<DILocation<'_>>) {
982        // https://github.com/llvm/llvm-project/blob/e83cc896e7c2378914a391f942c188d454b517d2/llvm/include/llvm/IR/Instruction.h#L510
983        let metadata_ref = location.map_or(std::ptr::null_mut(), |loc| loc.metadata_ref);
984        unsafe {
985            llvm_sys::debuginfo::LLVMInstructionSetDebugLoc(self.as_value_ref(), metadata_ref);
986        }
987    }
988}
989
990unsafe impl AsValueRef for InstructionValue<'_> {
991    fn as_value_ref(&self) -> LLVMValueRef {
992        self.instruction_value.value
993    }
994}
995
996impl Display for InstructionValue<'_> {
997    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
998        write!(f, "{}", self.print_to_string())
999    }
1000}
1001
1002/// Iterate over all the operands of an instruction value.
1003#[derive(Debug)]
1004pub struct OperandIter<'ctx> {
1005    iv: InstructionValue<'ctx>,
1006    i: u32,
1007    count: u32,
1008}
1009
1010impl<'ctx> Iterator for OperandIter<'ctx> {
1011    type Item = Option<Operand<'ctx>>;
1012
1013    fn next(&mut self) -> Option<Self::Item> {
1014        if self.i < self.count {
1015            let result = unsafe { self.iv.get_operand_unchecked(self.i) };
1016            self.i += 1;
1017            Some(result)
1018        } else {
1019            None
1020        }
1021    }
1022}
1023
1024/// Iterate over all the operands of an instruction value.
1025#[derive(Debug)]
1026pub struct OperandUseIter<'ctx> {
1027    iv: InstructionValue<'ctx>,
1028    i: u32,
1029    count: u32,
1030}
1031
1032impl<'ctx> Iterator for OperandUseIter<'ctx> {
1033    type Item = Option<BasicValueUse<'ctx>>;
1034
1035    fn next(&mut self) -> Option<Self::Item> {
1036        if self.i < self.count {
1037            let result = unsafe { self.iv.get_operand_use_unchecked(self.i) };
1038            self.i += 1;
1039            Some(result)
1040        } else {
1041            None
1042        }
1043    }
1044}