From 15fd825d8cd35b9bcdb6155d38b8e7816984f1da Mon Sep 17 00:00:00 2001 From: Faouzi1406 <87236@glr.nl> Date: Thu, 4 May 2023 23:10:20 +0200 Subject: [PATCH 1/4] Get instruction with it's name --- src/basic_block.rs | 35 +++++++++++++++++++++++++++++++++ src/values/instruction_value.rs | 13 ++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/basic_block.rs b/src/basic_block.rs index 7bed19a3168..e0adc785c45 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -275,6 +275,41 @@ impl<'ctx> BasicBlock<'ctx> { unsafe { Some(InstructionValue::new(value)) } } + /// Obtains 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: impl AsRef) -> Option> { + 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 diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 47f44e91c86..9a5ff56d6fe 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -150,6 +150,19 @@ 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:impl AsRef) -> Option> { + let Some(ins_name) = self.get_name() else { + return self.get_next_instruction()?.get_instruction_with_name(name); + }; + if ins_name.to_str() == Ok(name.as_ref()) { + return Some(*self); + } + None + } + /// Set name of the `InstructionValue`. pub fn set_name(&self, name: &str) -> Result<(), &'static str> { if self.get_type().is_void_type() { From 4d02a89e880011bcff1f7f7ee9c6487a370b0d44 Mon Sep 17 00:00:00 2001 From: Faouzi1406 <87236@glr.nl> Date: Thu, 4 May 2023 23:40:38 +0200 Subject: [PATCH 2/4] fix mistake returning none instead of next if it doesn't equal --- src/values/instruction_value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 9a5ff56d6fe..bf807debef6 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -160,7 +160,7 @@ impl<'ctx> InstructionValue<'ctx> { if ins_name.to_str() == Ok(name.as_ref()) { return Some(*self); } - None + return self.get_next_instruction()?.get_instruction_with_name(name); } /// Set name of the `InstructionValue`. From bff277cc4703247e55f0c1d2b79487ee09a64097 Mon Sep 17 00:00:00 2001 From: Faouzi1406 <87236@glr.nl> Date: Fri, 5 May 2023 06:20:40 +0200 Subject: [PATCH 3/4] Add test && change let some to if let some --- src/basic_block.rs | 6 +++--- src/values/instruction_value.rs | 13 ++++++------- tests/all/test_instruction_values.rs | 29 ++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/basic_block.rs b/src/basic_block.rs index e0adc785c45..83ca8b6eb9f 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -275,7 +275,7 @@ impl<'ctx> BasicBlock<'ctx> { unsafe { Some(InstructionValue::new(value)) } } - /// Obtains a instruction based on the name + /// Performs a linear lookup to obtain a instruction based on the name /// /// # Example /// ```rust @@ -303,9 +303,9 @@ impl<'ctx> BasicBlock<'ctx> { /// 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")) + /// assert_eq!(some_number.unwrap().get_name().unwrap().to_str(), Ok("some_number")) /// ``` - pub fn get_instruction_with_name(self, name: impl AsRef) -> Option> { + pub fn get_instruction_with_name(self, name: &str) -> Option> { let instruction = self.get_first_instruction()?; instruction.get_instruction_with_name(name) } diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index bf807debef6..3a993e0abb9 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -150,15 +150,14 @@ impl<'ctx> InstructionValue<'ctx> { } } - /// Get a instruction with it's name - /// + /// Get a instruction with it's name /// Compares against all instructions after self, and self. - pub fn get_instruction_with_name(&self, name:impl AsRef) -> Option> { - let Some(ins_name) = self.get_name() else { + pub fn get_instruction_with_name(&self, name: &str) -> Option> { + 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); - }; - if ins_name.to_str() == Ok(name.as_ref()) { - return Some(*self); } return self.get_next_instruction()?.get_instruction_with_name(name); } diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index 6333fc29320..03c0e29f730 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -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")) +} From e4061e1edfbba609bd6304409739e66a23ec17d2 Mon Sep 17 00:00:00 2001 From: Faouzi1406 <87236@glr.nl> Date: Fri, 5 May 2023 12:24:43 +0200 Subject: [PATCH 4/4] remove unnecessary return --- src/values/instruction_value.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 3a993e0abb9..f1951e12faf 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -157,7 +157,6 @@ impl<'ctx> InstructionValue<'ctx> { if ins_name.to_str() == Ok(name) { return Some(*self); } - return self.get_next_instruction()?.get_instruction_with_name(name); } return self.get_next_instruction()?.get_instruction_with_name(name); }