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}