Skip to content

Commit 2d715ed

Browse files
authored
Merge pull request rust-lang#262 from StackDoubleFlow/block-get-address
Add function to get the address of a basic block
2 parents 27a6444 + faec0be commit 2d715ed

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

src/basic_block.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! A `BasicBlock` is a container of instructions.
22
3-
use llvm_sys::core::{LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetNextBasicBlock, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMTypeOf, LLVMDeleteBasicBlock, LLVMGetPreviousBasicBlock, LLVMRemoveBasicBlockFromParent, LLVMGetFirstInstruction, LLVMGetLastInstruction, LLVMGetTypeContext, LLVMBasicBlockAsValue, LLVMReplaceAllUsesWith, LLVMGetFirstUse};
3+
use llvm_sys::core::{LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetNextBasicBlock, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMTypeOf, LLVMDeleteBasicBlock, LLVMGetPreviousBasicBlock, LLVMRemoveBasicBlockFromParent, LLVMGetFirstInstruction, LLVMGetLastInstruction, LLVMGetTypeContext, LLVMBasicBlockAsValue, LLVMReplaceAllUsesWith, LLVMGetFirstUse, LLVMBlockAddress};
44
#[llvm_versions(3.9..=latest)]
55
use llvm_sys::core::LLVMGetBasicBlockName;
66
use llvm_sys::prelude::{LLVMValueRef, LLVMBasicBlockRef};
77

88
use crate::context::ContextRef;
9-
use crate::values::{BasicValueUse, FunctionValue, InstructionValue};
9+
use crate::values::{AsValueRef, BasicValueUse, FunctionValue, InstructionValue, PointerValue};
1010

1111
use std::fmt;
1212
use std::ffi::CStr;
@@ -514,6 +514,42 @@ impl<'ctx> BasicBlock<'ctx> {
514514
Some(BasicValueUse::new(use_))
515515
}
516516
}
517+
518+
/// Gets the address of this `BasicBlock` if possible. Returns `None` if `self` is the entry block to a function.
519+
///
520+
/// # Safety
521+
///
522+
/// The returned PointerValue may only be used for `call` and `indirect_branch` instructions
523+
///
524+
/// # Example
525+
///
526+
/// ```no_run
527+
/// use inkwell::context::Context;
528+
/// let context = Context::create();
529+
/// let module = context.create_module("my_mod");
530+
/// let void_type = context.void_type();
531+
/// let fn_type = void_type.fn_type(&[], false);
532+
/// let fn_val = module.add_function("my_fn", fn_type, None);
533+
/// let entry_bb = context.append_basic_block(fn_val, "entry");
534+
/// let next_bb = context.append_basic_block(fn_val, "next");
535+
///
536+
/// assert!(unsafe { entry_bb.get_address() }.is_none());
537+
/// assert!(unsafe { next_bb.get_address() }.is_some());
538+
/// ```
539+
pub unsafe fn get_address(self) -> Option<PointerValue<'ctx>> {
540+
let parent = self.get_parent()?;
541+
542+
// Taking the address of the entry block is illegal.
543+
self.get_previous_basic_block()?;
544+
545+
let value = PointerValue::new(LLVMBlockAddress(parent.as_value_ref(), self.basic_block));
546+
547+
if value.is_null() {
548+
return None;
549+
}
550+
551+
Some(value)
552+
}
517553
}
518554

519555
impl fmt::Debug for BasicBlock<'_> {

tests/all/test_basic_block.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,17 @@ fn test_get_first_use() {
201201
assert_eq!(bb1.get_first_use().unwrap().get_user(), branch_inst);
202202
assert!(bb1.get_first_use().unwrap().get_next_use().is_none());
203203
}
204+
205+
#[test]
206+
fn test_get_address() {
207+
let context = Context::create();
208+
let module = context.create_module("my_mod");
209+
let void_type = context.void_type();
210+
let fn_type = void_type.fn_type(&[], false);
211+
let fn_val = module.add_function("my_fn", fn_type, None);
212+
let entry_bb = context.append_basic_block(fn_val, "entry");
213+
let next_bb = context.append_basic_block(fn_val, "next");
214+
215+
assert!(unsafe { entry_bb.get_address() }.is_none());
216+
assert!(unsafe { next_bb.get_address() }.is_some());
217+
}

0 commit comments

Comments
 (0)