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}