inkwell::values

Struct BasicValueUse

source
pub struct BasicValueUse<'ctx>(/* private fields */);
Expand description

A usage of a BasicValue in another value.

Implementations§

source§

impl<'ctx> BasicValueUse<'ctx>

source

pub unsafe fn new(use_: LLVMUseRef) -> Self

Get a value from an LLVMUseRef.

§Safety

The ref must be valid and of type basic value.

source

pub fn get_next_use(self) -> Option<Self>

Gets the next use of a BasicBlock, InstructionValue or BasicValue if any.

The following example,

use inkwell::AddressSpace;
use inkwell::context::Context;
use inkwell::values::BasicValue;

let context = Context::create();
let module = context.create_module("ivs");
let builder = context.create_builder();
let void_type = context.void_type();
let f32_type = context.f32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let f32_ptr_type = context.ptr_type(AddressSpace::default());
let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);

let function = module.add_function("take_f32_ptr", fn_type, None);
let basic_block = context.append_basic_block(function, "entry");

builder.position_at_end(basic_block);

let arg1 = function.get_first_param().unwrap().into_pointer_value();
let f32_val = f32_type.const_float(std::f64::consts::PI);
let store_instruction = builder.build_store(arg1, f32_val).unwrap();
let free_instruction = builder.build_free(arg1).unwrap();
let return_instruction = builder.build_return(None).unwrap();

let arg1_first_use = arg1.get_first_use().unwrap();

assert!(arg1_first_use.get_next_use().is_some());

will generate LLVM IR roughly like (varying slightly across LLVM versions):

; ModuleID = 'ivs'
source_filename = "ivs"

define void @take_f32_ptr(float* %0) {
entry:
  store float 0x400921FB60000000, float* %0
  %1 = bitcast float* %0 to i8*
  tail call void @free(i8* %1)
  ret void
}

declare void @free(i8*)

which makes the arg1 (%0) uses clear:

  1. In the store instruction
  2. In the pointer bitcast
source

pub fn get_user(self) -> AnyValueEnum<'ctx>

Gets the user (an AnyValueEnum) of this use.

use inkwell::AddressSpace;
use inkwell::context::Context;
use inkwell::values::BasicValue;

let context = Context::create();
let module = context.create_module("ivs");
let builder = context.create_builder();
let void_type = context.void_type();
let f32_type = context.f32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let f32_ptr_type = context.ptr_type(AddressSpace::default());
let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);

let function = module.add_function("take_f32_ptr", fn_type, None);
let basic_block = context.append_basic_block(function, "entry");

builder.position_at_end(basic_block);

let arg1 = function.get_first_param().unwrap().into_pointer_value();
let f32_val = f32_type.const_float(std::f64::consts::PI);
let store_instruction = builder.build_store(arg1, f32_val).unwrap();
let free_instruction = builder.build_free(arg1).unwrap();
let return_instruction = builder.build_return(None).unwrap();

let store_operand_use0 = store_instruction.get_operand_use(0).unwrap();
let store_operand_use1 = store_instruction.get_operand_use(1).unwrap();

assert_eq!(store_operand_use0.get_user(), store_instruction);
assert_eq!(store_operand_use1.get_user(), store_instruction);
source

pub fn get_used_value(self) -> Either<BasicValueEnum<'ctx>, BasicBlock<'ctx>>

Gets the used value (a BasicValueEnum or BasicBlock) of this use.

use inkwell::AddressSpace;
use inkwell::context::Context;
use inkwell::values::BasicValue;

let context = Context::create();
let module = context.create_module("ivs");
let builder = context.create_builder();
let void_type = context.void_type();
let f32_type = context.f32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let f32_ptr_type = context.ptr_type(AddressSpace::default());
let fn_type = void_type.fn_type(&[f32_ptr_type.into()], false);

let function = module.add_function("take_f32_ptr", fn_type, None);
let basic_block = context.append_basic_block(function, "entry");

builder.position_at_end(basic_block);

let arg1 = function.get_first_param().unwrap().into_pointer_value();
let f32_val = f32_type.const_float(std::f64::consts::PI);
let store_instruction = builder.build_store(arg1, f32_val).unwrap();
let free_instruction = builder.build_free(arg1).unwrap();
let return_instruction = builder.build_return(None).unwrap();

let free_operand0 = free_instruction.get_operand(0).unwrap().left().unwrap();
let free_operand0_instruction = free_operand0.as_instruction_value().unwrap();
let bitcast_use_value = free_operand0_instruction
    .get_first_use()
    .unwrap()
    .get_used_value()
    .left()
    .unwrap();

assert_eq!(bitcast_use_value, free_operand0);

Trait Implementations§

source§

impl<'ctx> Clone for BasicValueUse<'ctx>

source§

fn clone(&self) -> BasicValueUse<'ctx>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<'ctx> Debug for BasicValueUse<'ctx>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'ctx> PartialEq for BasicValueUse<'ctx>

source§

fn eq(&self, other: &BasicValueUse<'ctx>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<'ctx> Copy for BasicValueUse<'ctx>

source§

impl<'ctx> Eq for BasicValueUse<'ctx>

source§

impl<'ctx> StructuralPartialEq for BasicValueUse<'ctx>

Auto Trait Implementations§

§

impl<'ctx> Freeze for BasicValueUse<'ctx>

§

impl<'ctx> RefUnwindSafe for BasicValueUse<'ctx>

§

impl<'ctx> !Send for BasicValueUse<'ctx>

§

impl<'ctx> !Sync for BasicValueUse<'ctx>

§

impl<'ctx> Unpin for BasicValueUse<'ctx>

§

impl<'ctx> UnwindSafe for BasicValueUse<'ctx>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.