Skip to content

Commit

Permalink
Merge pull request #416 from Faouzi1406/master
Browse files Browse the repository at this point in the history
Find a InstructionValue based on its name
  • Loading branch information
TheDan64 authored May 7, 2023
2 parents 04fac60 + e4061e1 commit 74f0f96
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/basic_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,41 @@ impl<'ctx> BasicBlock<'ctx> {
unsafe { Some(InstructionValue::new(value)) }
}

/// Performs a linear lookup to obtain a instruction based on the name
///
/// # Example
/// ```rust
/// use inkwell::context::Context;
/// use inkwell::AddressSpace;
///
/// let context = Context::create();
/// let module = context.create_module("ret");
/// let builder = context.create_builder();
///
/// let void_type = context.void_type();
/// let i32_type = context.i32_type();
/// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
///
/// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
/// let fn_value = module.add_function("ret", fn_type, None);
/// let entry = context.append_basic_block(fn_value, "entry");
/// builder.position_at_end(entry);
///
/// let var = builder.build_alloca(i32_type, "some_number");
/// builder.build_store(var, i32_type.const_int(1 as u64, false));
/// builder.build_return(None);
///
/// let block = fn_value.get_first_basic_block().unwrap();
/// let some_number = block.get_instruction_with_name("some_number");
///
/// assert!(some_number.is_some());
/// assert_eq!(some_number.unwrap().get_name().unwrap().to_str(), Ok("some_number"))
/// ```
pub fn get_instruction_with_name(self, name: &str) -> Option<InstructionValue<'ctx>> {
let instruction = self.get_first_instruction()?;
instruction.get_instruction_with_name(name)
}

/// Obtains the terminating `InstructionValue` in this `BasicBlock`, if any. A `BasicBlock` must have a terminating instruction to be valid.
///
/// # Example
Expand Down
11 changes: 11 additions & 0 deletions src/values/instruction_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,17 @@ impl<'ctx> InstructionValue<'ctx> {
}
}

/// Get a instruction with it's name
/// Compares against all instructions after self, and self.
pub fn get_instruction_with_name(&self, name: &str) -> Option<InstructionValue<'ctx>> {
if let Some(ins_name) = self.get_name() {
if ins_name.to_str() == Ok(name) {
return Some(*self);
}
}
return self.get_next_instruction()?.get_instruction_with_name(name);
}

/// Set name of the `InstructionValue`.
pub fn set_name(&self, name: &str) -> Result<(), &'static str> {
if self.get_type().is_void_type() {
Expand Down
29 changes: 29 additions & 0 deletions tests/all/test_instruction_values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,3 +589,32 @@ fn test_metadata_kinds() {
md_string.into(),
]);
}

#[test]
fn test_find_instruction_with_name() {
use inkwell::context::Context;
use inkwell::AddressSpace;

let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();

let void_type = context.void_type();
let i32_type = context.i32_type();
let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());

let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
builder.position_at_end(entry);

let var = builder.build_alloca(i32_type, "some_number");
builder.build_store(var, i32_type.const_int(1 as u64, false));
builder.build_return(None);

let block = fn_value.get_first_basic_block().unwrap();
let some_number = block.get_instruction_with_name("some_number");

assert!(some_number.is_some());
assert_eq!(some_number.unwrap().get_name().unwrap().to_str(), Ok("some_number"))
}

0 comments on commit 74f0f96

Please sign in to comment.