|
1 | 1 | //! A `BasicBlock` is a container of instructions.
|
2 | 2 |
|
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}; |
4 | 4 | #[llvm_versions(3.9..=latest)]
|
5 | 5 | use llvm_sys::core::LLVMGetBasicBlockName;
|
6 | 6 | use llvm_sys::prelude::{LLVMValueRef, LLVMBasicBlockRef};
|
7 | 7 |
|
8 | 8 | use crate::context::ContextRef;
|
9 |
| -use crate::values::{BasicValueUse, FunctionValue, InstructionValue}; |
| 9 | +use crate::values::{AsValueRef, BasicValueUse, FunctionValue, InstructionValue, PointerValue}; |
10 | 10 |
|
11 | 11 | use std::fmt;
|
12 | 12 | use std::ffi::CStr;
|
@@ -514,6 +514,42 @@ impl<'ctx> BasicBlock<'ctx> {
|
514 | 514 | Some(BasicValueUse::new(use_))
|
515 | 515 | }
|
516 | 516 | }
|
| 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 | + } |
517 | 553 | }
|
518 | 554 |
|
519 | 555 | impl fmt::Debug for BasicBlock<'_> {
|
|
0 commit comments