llvm_plugin_inkwell/
basic_block.rs

1//! A `BasicBlock` is a container of instructions.
2
3use llvm_sys::core::{
4    LLVMBasicBlockAsValue, LLVMBlockAddress, LLVMDeleteBasicBlock, LLVMGetBasicBlockName, LLVMGetBasicBlockParent,
5    LLVMGetBasicBlockTerminator, LLVMGetFirstInstruction, LLVMGetFirstUse, LLVMGetLastInstruction,
6    LLVMGetNextBasicBlock, LLVMGetPreviousBasicBlock, LLVMGetTypeContext, LLVMIsABasicBlock, LLVMIsConstant,
7    LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString,
8    LLVMRemoveBasicBlockFromParent, LLVMReplaceAllUsesWith, LLVMTypeOf,
9};
10use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef};
11
12use crate::context::ContextRef;
13use crate::support::to_c_str;
14use crate::values::{AsValueRef, BasicValueUse, FunctionValue, InstructionValue, PointerValue};
15
16use std::ffi::CStr;
17use std::fmt;
18use std::marker::PhantomData;
19
20/// A `BasicBlock` is a container of instructions.
21///
22/// `BasicBlock`s are values because they can be referenced by instructions (ie branching and switches).
23///
24/// A well formed `BasicBlock` is a list of non terminating instructions followed by a single terminating
25/// instruction. `BasicBlock`s are allowed to be malformed prior to running validation because it may be useful
26/// when constructing or modifying a program.
27#[derive(PartialEq, Eq, Clone, Copy, Hash)]
28pub struct BasicBlock<'ctx> {
29    pub(crate) basic_block: LLVMBasicBlockRef,
30    _marker: PhantomData<&'ctx ()>,
31}
32
33impl<'ctx> BasicBlock<'ctx> {
34    pub(crate) unsafe fn new(basic_block: LLVMBasicBlockRef) -> Option<Self> {
35        if basic_block.is_null() {
36            return None;
37        }
38
39        // NOTE: There is a LLVMBasicBlockAsValue but it might be the same as casting
40        assert!(!LLVMIsABasicBlock(basic_block as LLVMValueRef).is_null());
41
42        Some(BasicBlock {
43            basic_block,
44            _marker: PhantomData,
45        })
46    }
47
48    /// Acquires the underlying raw pointer belonging to this `BasicBlock` type.
49    pub fn as_mut_ptr(&self) -> LLVMBasicBlockRef {
50        self.basic_block
51    }
52
53    /// Obtains the `FunctionValue` that this `BasicBlock` belongs to, if any.
54    ///
55    /// # Example
56    /// ```no_run
57    /// use inkwell::context::Context;
58    /// use inkwell::module::Module;
59    /// use inkwell::builder::Builder;
60    ///
61    /// let context = Context::create();
62    /// let module = context.create_module("my_module");
63    /// let void_type = context.void_type();
64    /// let fn_type = void_type.fn_type(&[], false);
65    /// let function = module.add_function("do_nothing", fn_type, None);
66    ///
67    /// let basic_block = context.append_basic_block(function, "entry");
68    ///
69    /// assert_eq!(basic_block.get_parent().unwrap(), function);
70    ///
71    /// basic_block.remove_from_function();
72    ///
73    /// assert!(basic_block.get_parent().is_none());
74    /// ```
75    pub fn get_parent(self) -> Option<FunctionValue<'ctx>> {
76        unsafe { FunctionValue::new(LLVMGetBasicBlockParent(self.basic_block)) }
77    }
78
79    /// Gets the `BasicBlock` preceeding the current one, in its own scope, if any.
80    ///
81    /// # Example
82    /// ```no_run
83    /// use inkwell::context::Context;
84    /// use inkwell::module::Module;
85    /// use inkwell::builder::Builder;
86    ///
87    /// let context = Context::create();
88    /// let module = context.create_module("my_module");
89    /// let void_type = context.void_type();
90    /// let fn_type = void_type.fn_type(&[], false);
91    /// let function1 = module.add_function("do_nothing", fn_type, None);
92    ///
93    /// let basic_block1 = context.append_basic_block(function1, "entry");
94    ///
95    /// assert!(basic_block1.get_previous_basic_block().is_none());
96    ///
97    /// let function2 = module.add_function("do_nothing", fn_type, None);
98    ///
99    /// let basic_block2 = context.append_basic_block(function2, "entry");
100    /// let basic_block3 = context.append_basic_block(function2, "next");
101    ///
102    /// assert!(basic_block2.get_previous_basic_block().is_none());
103    /// assert_eq!(basic_block3.get_previous_basic_block().unwrap(), basic_block2);
104    /// ```
105    pub fn get_previous_basic_block(self) -> Option<BasicBlock<'ctx>> {
106        self.get_parent()?;
107
108        unsafe { BasicBlock::new(LLVMGetPreviousBasicBlock(self.basic_block)) }
109    }
110
111    /// Gets the `BasicBlock` succeeding the current one, in its own scope, if any.
112    ///
113    /// # Example
114    /// ```no_run
115    /// use inkwell::context::Context;
116    /// use inkwell::module::Module;
117    /// use inkwell::builder::Builder;
118    ///
119    /// let context = Context::create();
120    /// let module = context.create_module("my_module");
121    /// let void_type = context.void_type();
122    /// let fn_type = void_type.fn_type(&[], false);
123    /// let function1 = module.add_function("do_nothing", fn_type, None);
124    ///
125    /// let basic_block1 = context.append_basic_block(function1, "entry");
126    ///
127    /// assert!(basic_block1.get_next_basic_block().is_none());
128    ///
129    /// let function2 = module.add_function("do_nothing", fn_type, None);
130    ///
131    /// let basic_block2 = context.append_basic_block(function2, "entry");
132    /// let basic_block3 = context.append_basic_block(function2, "next");
133    ///
134    /// assert!(basic_block1.get_next_basic_block().is_none());
135    /// assert_eq!(basic_block2.get_next_basic_block().unwrap(), basic_block3);
136    /// assert!(basic_block3.get_next_basic_block().is_none());
137    /// ```
138    pub fn get_next_basic_block(self) -> Option<BasicBlock<'ctx>> {
139        self.get_parent()?;
140
141        unsafe { BasicBlock::new(LLVMGetNextBasicBlock(self.basic_block)) }
142    }
143
144    /// Prepends one `BasicBlock` before another.
145    /// It returns `Err(())` when either `BasicBlock` has no parent, as LLVM assumes they both have parents.
146    ///
147    /// # Example
148    /// ```no_run
149    /// use inkwell::context::Context;
150    /// use inkwell::module::Module;
151    /// use inkwell::builder::Builder;
152    ///
153    /// let context = Context::create();
154    /// let module = context.create_module("my_module");
155    /// let void_type = context.void_type();
156    /// let fn_type = void_type.fn_type(&[], false);
157    /// let function = module.add_function("do_nothing", fn_type, None);
158    ///
159    /// let basic_block1 = context.append_basic_block(function, "entry");
160    /// let basic_block2 = context.append_basic_block(function, "next");
161    ///
162    /// basic_block2.move_before(basic_block1);
163    ///
164    /// assert!(basic_block1.get_next_basic_block().is_none());
165    /// assert_eq!(basic_block2.get_next_basic_block().unwrap(), basic_block1);
166    /// ```
167    // REVIEW: What happens if blocks are from different scopes?
168    pub fn move_before(self, basic_block: BasicBlock<'ctx>) -> Result<(), ()> {
169        // This method is UB if the parent no longer exists, so we must check for parent (or encode into type system)
170        if self.get_parent().is_none() || basic_block.get_parent().is_none() {
171            return Err(());
172        }
173
174        unsafe { LLVMMoveBasicBlockBefore(self.basic_block, basic_block.basic_block) }
175
176        Ok(())
177    }
178
179    /// Appends one `BasicBlock` after another.
180    /// It returns `Err(())` when either `BasicBlock` has no parent, as LLVM assumes they both have parents.
181    ///
182    /// # Example
183    /// ```no_run
184    /// use inkwell::context::Context;
185    /// use inkwell::module::Module;
186    /// use inkwell::builder::Builder;
187    ///
188    /// let context = Context::create();
189    /// let module = context.create_module("my_module");
190    /// let void_type = context.void_type();
191    /// let fn_type = void_type.fn_type(&[], false);
192    /// let function = module.add_function("do_nothing", fn_type, None);
193    ///
194    /// let basic_block1 = context.append_basic_block(function, "entry");
195    /// let basic_block2 = context.append_basic_block(function, "next");
196    ///
197    /// basic_block1.move_after(basic_block2);
198    ///
199    /// assert!(basic_block1.get_next_basic_block().is_none());
200    /// assert_eq!(basic_block2.get_next_basic_block().unwrap(), basic_block1);
201    /// ```
202    // REVIEW: What happens if blocks are from different scopes?
203    pub fn move_after(self, basic_block: BasicBlock<'ctx>) -> Result<(), ()> {
204        // This method is UB if the parent no longer exists, so we must check for parent (or encode into type system)
205        if self.get_parent().is_none() || basic_block.get_parent().is_none() {
206            return Err(());
207        }
208
209        unsafe { LLVMMoveBasicBlockAfter(self.basic_block, basic_block.basic_block) }
210
211        Ok(())
212    }
213
214    /// Obtains the first `InstructionValue` in this `BasicBlock`, if any.
215    ///
216    /// # Example
217    /// ```no_run
218    /// use inkwell::context::Context;
219    /// use inkwell::module::Module;
220    /// use inkwell::builder::Builder;
221    /// use inkwell::values::InstructionOpcode;
222    ///
223    /// let context = Context::create();
224    /// let builder = context.create_builder();
225    /// let module = context.create_module("my_module");
226    /// let void_type = context.void_type();
227    /// let fn_type = void_type.fn_type(&[], false);
228    /// let function = module.add_function("do_nothing", fn_type, None);
229    /// let basic_block = context.append_basic_block(function, "entry");
230    ///
231    /// builder.position_at_end(basic_block);
232    /// builder.build_return(None);
233    ///
234    /// assert_eq!(basic_block.get_first_instruction().unwrap().get_opcode(), InstructionOpcode::Return);
235    /// ```
236    pub fn get_first_instruction(self) -> Option<InstructionValue<'ctx>> {
237        let value = unsafe { LLVMGetFirstInstruction(self.basic_block) };
238
239        if value.is_null() {
240            return None;
241        }
242
243        unsafe { Some(InstructionValue::new(value)) }
244    }
245
246    /// Obtains the last `InstructionValue` in this `BasicBlock`, if any. A `BasicBlock` must have a last instruction to be valid.
247    ///
248    /// # Example
249    /// ```no_run
250    /// use inkwell::context::Context;
251    /// use inkwell::module::Module;
252    /// use inkwell::builder::Builder;
253    /// use inkwell::values::InstructionOpcode;
254    ///
255    /// let context = Context::create();
256    /// let builder = context.create_builder();
257    /// let module = context.create_module("my_module");
258    /// let void_type = context.void_type();
259    /// let fn_type = void_type.fn_type(&[], false);
260    /// let function = module.add_function("do_nothing", fn_type, None);
261    /// let basic_block = context.append_basic_block(function, "entry");
262    ///
263    /// builder.position_at_end(basic_block);
264    /// builder.build_return(None);
265    ///
266    /// assert_eq!(basic_block.get_last_instruction().unwrap().get_opcode(), InstructionOpcode::Return);
267    /// ```
268    pub fn get_last_instruction(self) -> Option<InstructionValue<'ctx>> {
269        let value = unsafe { LLVMGetLastInstruction(self.basic_block) };
270
271        if value.is_null() {
272            return None;
273        }
274
275        unsafe { Some(InstructionValue::new(value)) }
276    }
277
278    /// Obtains the terminating `InstructionValue` in this `BasicBlock`, if any. A `BasicBlock` must have a terminating instruction to be valid.
279    ///
280    /// # Example
281    /// ```no_run
282    /// use inkwell::context::Context;
283    /// use inkwell::module::Module;
284    /// use inkwell::builder::Builder;
285    /// use inkwell::values::InstructionOpcode;
286    ///
287    /// let context = Context::create();
288    /// let builder = context.create_builder();
289    /// let module = context.create_module("my_module");
290    /// let void_type = context.void_type();
291    /// let fn_type = void_type.fn_type(&[], false);
292    /// let function = module.add_function("do_nothing", fn_type, None);
293    /// let basic_block = context.append_basic_block(function, "entry");
294    ///
295    /// builder.position_at_end(basic_block);
296    /// builder.build_return(None);
297    ///
298    /// assert_eq!(basic_block.get_terminator().unwrap().get_opcode(), InstructionOpcode::Return);
299    /// ```
300    // REVIEW: If we wanted the return type could be Option<Either<BasicValueEnum, InstructionValue>>
301    // if getting a value over an instruction is preferable
302    // TODOC: Every BB must have a terminating instruction or else it is invalid
303    // REVIEW: Unclear how this differs from get_last_instruction
304    pub fn get_terminator(self) -> Option<InstructionValue<'ctx>> {
305        let value = unsafe { LLVMGetBasicBlockTerminator(self.basic_block) };
306
307        if value.is_null() {
308            return None;
309        }
310
311        unsafe { Some(InstructionValue::new(value)) }
312    }
313
314    /// Removes this `BasicBlock` from its parent `FunctionValue`.
315    /// It returns `Err(())` when it has no parent to remove from.
316    ///
317    /// # Example
318    /// ```no_run
319    /// use inkwell::context::Context;
320    /// use inkwell::module::Module;
321    /// use inkwell::builder::Builder;
322    ///
323    /// let context = Context::create();
324    /// let module = context.create_module("my_module");
325    /// let void_type = context.void_type();
326    /// let fn_type = void_type.fn_type(&[], false);
327    /// let function = module.add_function("do_nothing", fn_type, None);
328    /// let basic_block = context.append_basic_block(function, "entry");
329    ///
330    /// assert_eq!(basic_block.get_parent().unwrap(), function);
331    ///
332    /// basic_block.remove_from_function();
333    ///
334    /// assert!(basic_block.get_parent().is_none());
335    /// ```
336    // SubTypes: Don't need to call get_parent for a BasicBlock<HasParent> and would return BasicBlock<Orphan>
337    // by taking ownership of self (though BasicBlock's are not uniquely obtained...)
338    // might have to make some methods do something like -> Result<..., BasicBlock<Orphan>> for BasicBlock<HasParent>
339    // and would move_before/after make it no longer orphaned? etc..
340    pub fn remove_from_function(self) -> Result<(), ()> {
341        // This method is UB if the parent no longer exists, so we must check for parent (or encode into type system)
342        if self.get_parent().is_none() {
343            return Err(());
344        }
345
346        unsafe { LLVMRemoveBasicBlockFromParent(self.basic_block) }
347
348        Ok(())
349    }
350
351    /// Removes this `BasicBlock` completely from memory. This is unsafe because you could easily have other references to the same `BasicBlock`.
352    /// It returns `Err(())` when it has no parent to delete from, as LLVM assumes it has a parent.
353    ///
354    /// # Example
355    /// ```no_run
356    /// use inkwell::context::Context;
357    /// use inkwell::module::Module;
358    /// use inkwell::builder::Builder;
359    ///
360    /// let context = Context::create();
361    /// let module = context.create_module("my_module");
362    /// let void_type = context.void_type();
363    /// let fn_type = void_type.fn_type(&[], false);
364    /// let function = module.add_function("do_nothing", fn_type, None);
365    /// let basic_block = context.append_basic_block(function, "entry");
366    ///
367    /// unsafe {
368    ///     basic_block.delete();
369    /// }
370    /// assert!(function.get_basic_blocks().is_empty());
371    /// ```
372    pub unsafe fn delete(self) -> Result<(), ()> {
373        // This method is UB if the parent no longer exists, so we must check for parent (or encode into type system)
374        if self.get_parent().is_none() {
375            return Err(());
376        }
377
378        LLVMDeleteBasicBlock(self.basic_block);
379
380        Ok(())
381    }
382
383    /// Obtains the `ContextRef` this `BasicBlock` belongs to.
384    ///
385    /// # Example
386    /// ```no_run
387    /// use inkwell::context::Context;
388    /// use inkwell::module::Module;
389    /// use inkwell::builder::Builder;
390    ///
391    /// let context = Context::create();
392    /// let module = context.create_module("my_module");
393    /// let void_type = context.void_type();
394    /// let fn_type = void_type.fn_type(&[], false);
395    /// let function = module.add_function("do_nothing", fn_type, None);
396    /// let basic_block = context.append_basic_block(function, "entry");
397    ///
398    /// assert_eq!(context, basic_block.get_context());
399    /// ```
400    pub fn get_context(self) -> ContextRef<'ctx> {
401        unsafe { ContextRef::new(LLVMGetTypeContext(LLVMTypeOf(LLVMBasicBlockAsValue(self.basic_block)))) }
402    }
403
404    /// Gets the name of a `BasicBlock`.
405    ///
406    /// # Example
407    ///
408    /// ```no_run
409    /// use inkwell::context::Context;
410    ///
411    /// let context = Context::create();
412    /// let builder = context.create_builder();
413    /// let module = context.create_module("my_mod");
414    /// let void_type = context.void_type();
415    /// let fn_type = void_type.fn_type(&[], false);
416    /// let fn_val = module.add_function("my_fn", fn_type, None);
417    /// let bb = context.append_basic_block(fn_val, "entry");
418    ///
419    /// assert_eq!(bb.get_name().to_str(), Ok("entry"));
420    /// ```
421    pub fn get_name(&self) -> &CStr {
422        let ptr = unsafe { LLVMGetBasicBlockName(self.basic_block) };
423
424        unsafe { CStr::from_ptr(ptr) }
425    }
426
427    /// Set name of the `BasicBlock`.
428    pub fn set_name(&self, name: &str) {
429        let c_string = to_c_str(name);
430
431        #[cfg(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))]
432        {
433            use llvm_sys::core::LLVMSetValueName;
434
435            unsafe { LLVMSetValueName(LLVMBasicBlockAsValue(self.basic_block), c_string.as_ptr()) };
436        }
437        #[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
438        {
439            use llvm_sys::core::LLVMSetValueName2;
440
441            unsafe { LLVMSetValueName2(LLVMBasicBlockAsValue(self.basic_block), c_string.as_ptr(), name.len()) };
442        }
443    }
444
445    /// Replaces all uses of this basic block with another.
446    ///
447    /// # Example
448    ///
449    /// ```
450    /// use inkwell::context::Context;
451    ///
452    /// let context = Context::create();
453    /// let builder = context.create_builder();
454    /// let module = context.create_module("my_mod");
455    /// let void_type = context.void_type();
456    /// let fn_type = void_type.fn_type(&[], false);
457    /// let fn_val = module.add_function("my_fn", fn_type, None);
458    /// let entry = context.append_basic_block(fn_val, "entry");
459    /// let bb1 = context.append_basic_block(fn_val, "bb1");
460    /// let bb2 = context.append_basic_block(fn_val, "bb2");
461    /// builder.position_at_end(entry);
462    /// let branch_inst = builder.build_unconditional_branch(bb1);
463    ///
464    /// bb1.replace_all_uses_with(&bb2);
465    ///
466    /// assert_eq!(branch_inst.get_operand(0).unwrap().right().unwrap(), bb2);
467    /// ```
468    pub fn replace_all_uses_with(self, other: &BasicBlock<'ctx>) {
469        let value = unsafe { LLVMBasicBlockAsValue(self.basic_block) };
470        let other = unsafe { LLVMBasicBlockAsValue(other.basic_block) };
471
472        // LLVM may infinite-loop when they aren't distinct, which is UB in C++.
473        if value != other {
474            unsafe {
475                LLVMReplaceAllUsesWith(value, other);
476            }
477        }
478    }
479
480    /// Gets the first use of this `BasicBlock` if any.
481    ///
482    /// The following example,
483    ///
484    /// ```no_run
485    /// use inkwell::AddressSpace;
486    /// use inkwell::context::Context;
487    /// use inkwell::values::BasicValue;
488    ///
489    /// let context = Context::create();
490    /// let module = context.create_module("ivs");
491    /// let builder = context.create_builder();
492    /// let void_type = context.void_type();
493    /// let fn_type = void_type.fn_type(&[], false);
494    /// let fn_val = module.add_function("my_fn", fn_type, None);
495    /// let entry = context.append_basic_block(fn_val, "entry");
496    /// let bb1 = context.append_basic_block(fn_val, "bb1");
497    /// let bb2 = context.append_basic_block(fn_val, "bb2");
498    /// builder.position_at_end(entry);
499    /// let branch_inst = builder.build_unconditional_branch(bb1);
500    ///
501    /// assert!(bb2.get_first_use().is_none());
502    /// assert!(bb1.get_first_use().is_some());
503    /// ```
504    pub fn get_first_use(self) -> Option<BasicValueUse<'ctx>> {
505        let use_ = unsafe { LLVMGetFirstUse(LLVMBasicBlockAsValue(self.basic_block)) };
506
507        if use_.is_null() {
508            return None;
509        }
510
511        unsafe { Some(BasicValueUse::new(use_)) }
512    }
513
514    /// Gets the address of this `BasicBlock` if possible. Returns `None` if `self` is the entry block to a function.
515    ///
516    /// # Safety
517    ///
518    /// The returned PointerValue may only be used for `call` and `indirect_branch` instructions
519    ///
520    /// # Example
521    ///
522    /// ```no_run
523    /// use inkwell::context::Context;
524    /// let context = Context::create();
525    /// let module = context.create_module("my_mod");
526    /// let void_type = context.void_type();
527    /// let fn_type = void_type.fn_type(&[], false);
528    /// let fn_val = module.add_function("my_fn", fn_type, None);
529    /// let entry_bb = context.append_basic_block(fn_val, "entry");
530    /// let next_bb = context.append_basic_block(fn_val, "next");
531    ///
532    /// assert!(unsafe { entry_bb.get_address() }.is_none());
533    /// assert!(unsafe { next_bb.get_address() }.is_some());
534    /// ```
535    pub unsafe fn get_address(self) -> Option<PointerValue<'ctx>> {
536        let parent = self.get_parent()?;
537
538        // Taking the address of the entry block is illegal.
539        self.get_previous_basic_block()?;
540
541        let value = PointerValue::new(LLVMBlockAddress(parent.as_value_ref(), self.basic_block));
542
543        if value.is_null() {
544            return None;
545        }
546
547        Some(value)
548    }
549}
550
551impl fmt::Debug for BasicBlock<'_> {
552    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
553        let llvm_value = unsafe { CStr::from_ptr(LLVMPrintValueToString(self.basic_block as LLVMValueRef)) };
554        let llvm_type = unsafe { CStr::from_ptr(LLVMPrintTypeToString(LLVMTypeOf(self.basic_block as LLVMValueRef))) };
555        let is_const = unsafe { LLVMIsConstant(self.basic_block as LLVMValueRef) == 1 };
556
557        f.debug_struct("BasicBlock")
558            .field("address", &self.basic_block)
559            .field("is_const", &is_const)
560            .field("llvm_value", &llvm_value)
561            .field("llvm_type", &llvm_type)
562            .finish()
563    }
564}