Skip to main content

inkwell/
builder.rs

1//! A `Builder` enables you to build instructions.
2
3#[llvm_versions(18..)]
4use llvm_sys::core::LLVMBuildCallWithOperandBundles;
5use llvm_sys::core::{
6    LLVMAddCase, LLVMAddClause, LLVMAddDestination, LLVMBuildAShr, LLVMBuildAdd, LLVMBuildAddrSpaceCast,
7    LLVMBuildAggregateRet, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildArrayMalloc,
8    LLVMBuildAtomicCmpXchg, LLVMBuildAtomicRMW, LLVMBuildBinOp, LLVMBuildBitCast, LLVMBuildBr, LLVMBuildCast,
9    LLVMBuildCondBr, LLVMBuildExactSDiv, LLVMBuildExtractElement, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp,
10    LLVMBuildFDiv, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFPCast, LLVMBuildFPExt, LLVMBuildFPToSI, LLVMBuildFPToUI,
11    LLVMBuildFPTrunc, LLVMBuildFRem, LLVMBuildFSub, LLVMBuildFence, LLVMBuildFree, LLVMBuildGlobalString,
12    LLVMBuildICmp, LLVMBuildIndirectBr, LLVMBuildInsertElement, LLVMBuildInsertValue, LLVMBuildIntCast,
13    LLVMBuildIntToPtr, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLShr, LLVMBuildLandingPad, LLVMBuildMalloc,
14    LLVMBuildMul, LLVMBuildNSWAdd, LLVMBuildNSWMul, LLVMBuildNSWNeg, LLVMBuildNSWSub, LLVMBuildNUWAdd, LLVMBuildNUWMul,
15    LLVMBuildNUWSub, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, LLVMBuildPointerCast, LLVMBuildPtrToInt,
16    LLVMBuildResume, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildSDiv, LLVMBuildSExt, LLVMBuildSExtOrBitCast,
17    LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect, LLVMBuildShl, LLVMBuildShuffleVector, LLVMBuildStore,
18    LLVMBuildSub, LLVMBuildSwitch, LLVMBuildTrunc, LLVMBuildTruncOrBitCast, LLVMBuildUDiv, LLVMBuildUIToFP,
19    LLVMBuildURem, LLVMBuildUnreachable, LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt, LLVMBuildZExtOrBitCast,
20    LLVMClearInsertionPosition, LLVMDisposeBuilder, LLVMGetInsertBlock, LLVMInsertIntoBuilder,
21    LLVMInsertIntoBuilderWithName, LLVMPositionBuilder, LLVMPositionBuilderAtEnd, LLVMPositionBuilderBefore,
22    LLVMSetCleanup,
23};
24
25#[llvm_versions(..20)]
26use llvm_sys::core::LLVMBuildGlobalStringPtr;
27
28#[llvm_versions(20..)]
29use llvm_sys::core::LLVMBuildGlobalString as LLVMBuildGlobalStringPtr;
30
31#[llvm_versions(..17)]
32use llvm_sys::core::LLVMBuildNUWNeg;
33
34#[llvm_versions(17..)]
35use llvm_sys::core::LLVMSetNUW;
36
37#[llvm_versions(..=14)]
38#[allow(deprecated)]
39use llvm_sys::core::{LLVMBuildCall, LLVMBuildInvoke};
40#[llvm_versions(15..)]
41use llvm_sys::core::{LLVMBuildCall2, LLVMBuildInvoke2};
42#[cfg(all(feature = "typed-pointers", not(feature = "llvm16-0")))]
43#[allow(deprecated)]
44use llvm_sys::core::{LLVMBuildGEP, LLVMBuildInBoundsGEP, LLVMBuildLoad, LLVMBuildPtrDiff, LLVMBuildStructGEP};
45#[cfg(any(not(feature = "typed-pointers"), feature = "llvm16-0"))]
46use llvm_sys::core::{LLVMBuildGEP2, LLVMBuildInBoundsGEP2, LLVMBuildLoad2, LLVMBuildPtrDiff2, LLVMBuildStructGEP2};
47use llvm_sys::core::{LLVMBuildIntCast2, LLVMBuildMemCpy, LLVMBuildMemMove, LLVMBuildMemSet};
48use llvm_sys::prelude::{LLVMBuilderRef, LLVMValueRef};
49use thiserror::Error;
50
51use crate::basic_block::BasicBlock;
52use crate::debug_info::DILocation;
53use crate::support::to_c_str;
54#[llvm_versions(15..)]
55use crate::types::FunctionType;
56use crate::types::{AsTypeRef, BasicType, FloatMathType, IntMathType, PointerMathType, PointerType};
57#[llvm_versions(..=14)]
58use crate::values::CallableValue;
59#[llvm_versions(18..)]
60use crate::values::operand_bundle::OperandBundle;
61use crate::values::{
62    AggregateValue, AggregateValueEnum, AsValueRef, AtomicError, BasicMetadataValueEnum, BasicValue, BasicValueEnum,
63    CallSiteValue, FloatMathValue, FunctionValue, GlobalValue, InstructionOpcode, InstructionValue, IntMathValue,
64    IntValue, PhiValue, PointerMathValue, PointerValue, StructValue, VectorBaseValue,
65};
66
67use crate::error::AlignmentError;
68use crate::{AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate};
69
70use std::cell::Cell;
71use std::marker::PhantomData;
72
73#[derive(Debug, PartialEq, Clone, Copy)]
74enum PositionState {
75    NotSet,
76    Set,
77}
78
79#[derive(Error, Debug, PartialEq, Eq)]
80pub enum CmpxchgOrderingError {
81    #[error("Both success and failure orderings must be monotonic or stronger.")]
82    WeakerThanMonotic,
83    #[error("The failure ordering may not be stronger than the success ordering.")]
84    WeakerSuccessOrdering,
85    #[error("The failure ordering may not be release or acquire release.")]
86    ReleaseOrAcqRel,
87}
88
89/// Errors that can be generated by the Builder. All `build_*` methods return a `Result<_, BuilderError>`, which must be handled.
90#[derive(Error, Debug, PartialEq, Eq)]
91pub enum BuilderError {
92    #[error("Builder position is not set")]
93    UnsetPosition,
94    #[error("Alignment error")]
95    AlignmentError(#[from] crate::error::AlignmentError),
96    #[error("Aggregate extract index out of range")]
97    ExtractOutOfRange,
98    #[error("The bitwidth of value must be a power of 2 and greater than or equal to 8.")]
99    BitwidthError,
100    #[error("Pointee type does not match the value's type")]
101    PointeeTypeMismatch,
102    #[error("Values must have the same type")]
103    NotSameType,
104    #[error("Values must have pointer or integer type")]
105    NotPointerOrInteger,
106    #[error("Cmpxchg ordering error or mismatch")]
107    CmpxchgOrdering(CmpxchgOrderingError),
108    #[error("Atomic ordering error")]
109    AtomicOrdering(AtomicError),
110    #[error("GEP pointee is not a struct")]
111    GEPPointee,
112    #[error("GEP index out of range")]
113    GEPIndex,
114}
115
116#[derive(Debug)]
117/// All `build_*` methods return a `Result<_, BuilderError>` type containing either the returned value or some error.
118/// Those methods all may return `BuilderError::UnsetPosition` if a `position_*` method has not yet been called, in addition
119/// to any other possibility.
120pub struct Builder<'ctx> {
121    builder: LLVMBuilderRef,
122    positioned: Cell<PositionState>,
123    _marker: PhantomData<&'ctx ()>,
124}
125
126#[allow(unused)] // only used in documentation
127use crate::context::Context;
128
129impl<'ctx> Builder<'ctx> {
130    pub unsafe fn new(builder: LLVMBuilderRef) -> Self {
131        debug_assert!(!builder.is_null());
132
133        Builder {
134            positioned: Cell::from(PositionState::NotSet),
135            builder,
136            _marker: PhantomData,
137        }
138    }
139
140    /// Acquires the underlying raw pointer belonging to this `Builder` type.
141    pub fn as_mut_ptr(&self) -> LLVMBuilderRef {
142        self.builder
143    }
144
145    // REVIEW: Would probably make this API a bit simpler by taking Into<Option<&BasicValue>>
146    // So that you could just do build_return(&value) or build_return(None). Is that frowned upon?
147    /// Builds a function return instruction. It should be provided with `None` if the return type
148    /// is void otherwise `Some(&value)` should be provided.
149    ///
150    /// # Example
151    ///
152    /// ```no_run
153    /// use inkwell::context::Context;
154    ///
155    /// // A simple function which returns its argument:
156    /// let context = Context::create();
157    /// let module = context.create_module("ret");
158    /// let builder = context.create_builder();
159    /// let i32_type = context.i32_type();
160    /// let arg_types = [i32_type.into()];
161    /// let fn_type = i32_type.fn_type(&arg_types, false);
162    /// let fn_value = module.add_function("ret", fn_type, None);
163    /// let entry = context.append_basic_block(fn_value, "entry");
164    /// let i32_arg = fn_value.get_first_param().unwrap();
165    ///
166    /// builder.position_at_end(entry);
167    /// builder.build_return(Some(&i32_arg)).unwrap();
168    /// ```
169    pub fn build_return(&self, value: Option<&dyn BasicValue<'ctx>>) -> Result<InstructionValue<'ctx>, BuilderError> {
170        if self.positioned.get() != PositionState::Set {
171            return Err(BuilderError::UnsetPosition);
172        }
173        let value = unsafe {
174            value.map_or_else(
175                || LLVMBuildRetVoid(self.builder),
176                |value| LLVMBuildRet(self.builder, value.as_value_ref()),
177            )
178        };
179
180        unsafe { Ok(InstructionValue::new(value)) }
181    }
182
183    /// Builds a function return instruction for a return type which is an aggregate type (ie structs and arrays).
184    /// It is not necessary to use this over `build_return` but may be more convenient to use.
185    ///
186    /// # Example
187    ///
188    /// ```no_run
189    /// use inkwell::context::Context;
190    ///
191    /// // This builds a simple function which returns a struct (tuple) of two ints.
192    /// let context = Context::create();
193    /// let module = context.create_module("ret");
194    /// let builder = context.create_builder();
195    /// let i32_type = context.i32_type();
196    /// let i32_three = i32_type.const_int(3, false);
197    /// let i32_seven = i32_type.const_int(7, false);
198    /// let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false);
199    /// let fn_type = struct_type.fn_type(&[], false);
200    /// let fn_value = module.add_function("ret", fn_type, None);
201    /// let entry = context.append_basic_block(fn_value, "entry");
202    ///
203    /// builder.position_at_end(entry);
204    /// builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]).unwrap();
205    /// ```
206    pub fn build_aggregate_return(
207        &self,
208        values: &[BasicValueEnum<'ctx>],
209    ) -> Result<InstructionValue<'ctx>, BuilderError> {
210        if self.positioned.get() != PositionState::Set {
211            return Err(BuilderError::UnsetPosition);
212        }
213        let mut args: Vec<LLVMValueRef> = values.iter().map(|val| val.as_value_ref()).collect();
214        let value = unsafe { LLVMBuildAggregateRet(self.builder, args.as_mut_ptr(), args.len() as u32) };
215
216        unsafe { Ok(InstructionValue::new(value)) }
217    }
218
219    /// Builds a function call instruction.
220    /// [`FunctionValue`]s can be implicitly converted into a [`CallableValue`].
221    /// See [`CallableValue`] for details on calling a [`PointerValue`] that points to a function.
222    ///
223    /// [`FunctionValue`]: crate::values::FunctionValue
224    ///
225    /// # Example
226    ///
227    /// ```no_run
228    /// use inkwell::context::Context;
229    ///
230    /// // A simple function which calls itself:
231    /// let context = Context::create();
232    /// let module = context.create_module("ret");
233    /// let builder = context.create_builder();
234    /// let i32_type = context.i32_type();
235    /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
236    /// let fn_value = module.add_function("ret", fn_type, None);
237    /// let entry = context.append_basic_block(fn_value, "entry");
238    /// let i32_arg = fn_value.get_first_param().unwrap();
239    /// let md_string = context.metadata_string("a metadata");
240    ///
241    /// builder.position_at_end(entry);
242    ///
243    /// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call").unwrap()
244    ///     .try_as_basic_value()
245    ///     .unwrap_basic();
246    ///
247    /// builder.build_return(Some(&ret_val)).unwrap();
248    /// ```
249    #[llvm_versions(..=14)]
250    pub fn build_call<F>(
251        &self,
252        function: F,
253        args: &[BasicMetadataValueEnum<'ctx>],
254        name: &str,
255    ) -> Result<CallSiteValue<'ctx>, BuilderError>
256    where
257        F: Into<CallableValue<'ctx>>,
258    {
259        if self.positioned.get() != PositionState::Set {
260            return Err(BuilderError::UnsetPosition);
261        }
262        let callable_value = function.into();
263        let fn_val_ref = callable_value.as_value_ref();
264
265        // LLVM gets upset when void return calls are named because they don't return anything
266        let name = if callable_value.returns_void() { "" } else { name };
267
268        let c_string = to_c_str(name);
269        let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
270
271        #[allow(deprecated)]
272        let value = unsafe {
273            LLVMBuildCall(
274                self.builder,
275                fn_val_ref,
276                args.as_mut_ptr(),
277                args.len() as u32,
278                c_string.as_ptr(),
279            )
280        };
281
282        unsafe { Ok(CallSiteValue::new(value)) }
283    }
284
285    /// Builds a function call instruction. Alias for [Builder::build_direct_call].
286    #[llvm_versions(15..)]
287    pub fn build_call(
288        &self,
289        function: FunctionValue<'ctx>,
290        args: &[BasicMetadataValueEnum<'ctx>],
291        name: &str,
292    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
293        if self.positioned.get() != PositionState::Set {
294            return Err(BuilderError::UnsetPosition);
295        }
296        self.build_direct_call(function, args, name)
297    }
298
299    /// Builds a function call instruction. The function being called is known at compile time. If
300    /// you want to call a function pointer, see [Builder::build_indirect_call].
301    ///
302    /// # Example
303    ///
304    /// ```no_run
305    /// use inkwell::context::Context;
306    ///
307    /// // A simple function which calls itself:
308    /// let context = Context::create();
309    /// let module = context.create_module("ret");
310    /// let builder = context.create_builder();
311    /// let i32_type = context.i32_type();
312    /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
313    /// let fn_value = module.add_function("ret", fn_type, None);
314    /// let entry = context.append_basic_block(fn_value, "entry");
315    /// let i32_arg = fn_value.get_first_param().unwrap();
316    /// let md_string = context.metadata_string("a metadata");
317    ///
318    /// builder.position_at_end(entry);
319    ///
320    /// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call").unwrap()
321    ///     .try_as_basic_value()
322    ///     .unwrap_basic();
323    ///
324    /// builder.build_return(Some(&ret_val)).unwrap();
325    /// ```
326    #[llvm_versions(15..)]
327    pub fn build_direct_call(
328        &self,
329        function: FunctionValue<'ctx>,
330        args: &[BasicMetadataValueEnum<'ctx>],
331        name: &str,
332    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
333        if self.positioned.get() != PositionState::Set {
334            return Err(BuilderError::UnsetPosition);
335        }
336        self.build_call_help(function.get_type(), function.as_value_ref(), args, name)
337    }
338
339    /// Build a function call instruction, with attached operand bundles.
340    ///
341    /// # Example
342    ///
343    /// ```
344    /// use inkwell::context::Context;
345    /// use inkwell::values::OperandBundle;
346    ///
347    /// let context = Context::create();
348    /// let module = context.create_module("call_with_op_bundles");
349    /// let builder = context.create_builder();
350    /// let i32_type = context.i32_type();
351    ///
352    /// // declare i32 @func(i32)
353    /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
354    /// let fn_value = module.add_function("func", fn_type, None);
355    ///
356    /// let basic_block = context.append_basic_block(fn_value, "entry");
357    /// builder.position_at_end(basic_block);
358    ///
359    /// // %func_ret = call i32 @func(i32 0) [ "tag"(i32 0) ]
360    /// let ret_val = builder.build_direct_call_with_operand_bundles(
361    ///     fn_value,
362    ///     &[i32_type.const_zero().into()],
363    ///     &[OperandBundle::create("tag", &[i32_type.const_zero().into()])],
364    ///     "func_ret"
365    /// )
366    ///     .unwrap()
367    ///     .try_as_basic_value()
368    ///     .unwrap_basic();
369    /// builder.build_return(Some(&ret_val)).unwrap();
370    ///
371    /// # module.verify().unwrap();
372    /// ```
373    #[llvm_versions(18..)]
374    pub fn build_direct_call_with_operand_bundles(
375        &self,
376        function: FunctionValue<'ctx>,
377        args: &[BasicMetadataValueEnum<'ctx>],
378        operand_bundles: &[OperandBundle<'ctx>],
379        name: &str,
380    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
381        self.build_call_with_operand_bundles_help(
382            function.get_type(),
383            function.as_value_ref(),
384            args,
385            operand_bundles,
386            name,
387        )
388    }
389
390    /// Call a function pointer. Because a pointer does not carry a type, the type of the function
391    /// must be specified explicitly.
392    ///
393    /// See [Context::create_inline_asm] for a practical example. Basic usage looks like this:
394    ///
395    /// ```no_run
396    /// use inkwell::context::Context;
397    ///
398    /// // A simple function which calls itself:
399    /// let context = Context::create();
400    /// let module = context.create_module("ret");
401    /// let builder = context.create_builder();
402    /// let i32_type = context.i32_type();
403    /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
404    /// let fn_value = module.add_function("ret", fn_type, None);
405    /// let entry = context.append_basic_block(fn_value, "entry");
406    /// let i32_arg = fn_value.get_first_param().unwrap();
407    /// let md_string = context.metadata_string("a metadata");
408    ///
409    /// builder.position_at_end(entry);
410    ///
411    /// let function_pointer = fn_value.as_global_value().as_pointer_value();
412    /// let ret_val = builder.build_indirect_call(fn_value.get_type(), function_pointer, &[i32_arg.into(), md_string.into()], "call").unwrap()
413    ///     .try_as_basic_value()
414    ///     .unwrap_basic();
415    ///
416    /// builder.build_return(Some(&ret_val)).unwrap();
417    /// ```
418    ///
419    #[llvm_versions(15..)]
420    pub fn build_indirect_call(
421        &self,
422        function_type: FunctionType<'ctx>,
423        function_pointer: PointerValue<'ctx>,
424        args: &[BasicMetadataValueEnum<'ctx>],
425        name: &str,
426    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
427        if self.positioned.get() != PositionState::Set {
428            return Err(BuilderError::UnsetPosition);
429        }
430        self.build_call_help(function_type, function_pointer.as_value_ref(), args, name)
431    }
432
433    /// Build a call instruction to a function pointer, with attached operand bundles.
434    ///
435    /// See [Builder::build_direct_call_with_operand_bundles] for a usage example
436    /// with operand bundles.
437    #[llvm_versions(18..)]
438    pub fn build_indirect_call_with_operand_bundles(
439        &self,
440        function_type: FunctionType<'ctx>,
441        function_pointer: PointerValue<'ctx>,
442        args: &[BasicMetadataValueEnum<'ctx>],
443        operand_bundles: &[OperandBundle<'ctx>],
444        name: &str,
445    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
446        self.build_call_with_operand_bundles_help(
447            function_type,
448            function_pointer.as_value_ref(),
449            args,
450            operand_bundles,
451            name,
452        )
453    }
454
455    #[llvm_versions(15..)]
456    fn build_call_help(
457        &self,
458        function_type: FunctionType<'ctx>,
459        fn_val_ref: LLVMValueRef,
460        args: &[BasicMetadataValueEnum<'ctx>],
461        name: &str,
462    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
463        if self.positioned.get() != PositionState::Set {
464            return Err(BuilderError::UnsetPosition);
465        }
466        // LLVM gets upset when void return calls are named because they don't return anything
467        let name = match function_type.get_return_type() {
468            None => "",
469            Some(_) => name,
470        };
471
472        let fn_ty_ref = function_type.as_type_ref();
473
474        let c_string = to_c_str(name);
475        let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
476
477        let value = unsafe {
478            LLVMBuildCall2(
479                self.builder,
480                fn_ty_ref,
481                fn_val_ref,
482                args.as_mut_ptr(),
483                args.len() as u32,
484                c_string.as_ptr(),
485            )
486        };
487
488        unsafe { Ok(CallSiteValue::new(value)) }
489    }
490
491    #[llvm_versions(18..)]
492    fn build_call_with_operand_bundles_help(
493        &self,
494        function_type: FunctionType<'ctx>,
495        fn_val_ref: LLVMValueRef,
496        args: &[BasicMetadataValueEnum<'ctx>],
497        operand_bundles: &[OperandBundle<'ctx>],
498        name: &str,
499    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
500        use llvm_sys::prelude::LLVMOperandBundleRef;
501
502        if self.positioned.get() != PositionState::Set {
503            return Err(BuilderError::UnsetPosition);
504        }
505        // LLVM gets upset when void return calls are named because they don't return anything
506        let name = match function_type.get_return_type() {
507            None => "",
508            Some(_) => name,
509        };
510
511        let fn_ty_ref = function_type.as_type_ref();
512
513        let c_string = to_c_str(name);
514        let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
515        let mut operand_bundles: Vec<LLVMOperandBundleRef> =
516            operand_bundles.iter().map(|val| val.as_mut_ptr()).collect();
517
518        let value = unsafe {
519            LLVMBuildCallWithOperandBundles(
520                self.builder,
521                fn_ty_ref,
522                fn_val_ref,
523                args.as_mut_ptr(),
524                args.len() as u32,
525                operand_bundles.as_mut_ptr(),
526                operand_bundles.len() as u32,
527                c_string.as_ptr(),
528            )
529        };
530
531        unsafe { Ok(CallSiteValue::new(value)) }
532    }
533
534    /// An invoke is similar to a normal function call, but used to
535    /// call functions that may throw an exception, and then respond to the exception.
536    ///
537    /// When the called function returns normally, the `then` block is evaluated next. If instead
538    /// the function threw an exception, the `catch` block is entered. The first non-phi
539    /// instruction of the catch block must be a `landingpad` instruction. See also
540    /// [`Builder::build_landing_pad`].
541    ///
542    /// The [`add_prune_eh_pass`] turns an invoke into a call when the called function is
543    /// guaranteed to never throw an exception.
544    ///
545    /// [`add_prune_eh_pass`]: crate::passes::PassManager::add_prune_eh_pass
546    ///
547    /// This example catches C++ exceptions of type `int`, and returns `0` if an exceptions is thrown.
548    /// For usage of a cleanup landing pad and the `resume` instruction, see [`Builder::build_resume`]
549    /// ```no_run
550    /// use inkwell::context::Context;
551    /// use inkwell::AddressSpace;
552    /// use inkwell::module::Linkage;
553    ///
554    /// let context = Context::create();
555    /// let module = context.create_module("sum");
556    /// let builder = context.create_builder();
557    ///
558    /// let f32_type = context.f32_type();
559    /// let fn_type = f32_type.fn_type(&[], false);
560    ///
561    /// // we will pretend this function can throw an exception
562    /// let function = module.add_function("bomb", fn_type, None);
563    /// let basic_block = context.append_basic_block(function, "entry");
564    ///
565    /// builder.position_at_end(basic_block);
566    ///
567    /// let pi = f32_type.const_float(std::f64::consts::PI);
568    ///
569    /// builder.build_return(Some(&pi)).unwrap();
570    ///
571    /// let function2 = module.add_function("wrapper", fn_type, None);
572    /// let basic_block2 = context.append_basic_block(function2, "entry");
573    ///
574    /// builder.position_at_end(basic_block2);
575    ///
576    /// let then_block = context.append_basic_block(function2, "then_block");
577    /// let catch_block = context.append_basic_block(function2, "catch_block");
578    ///
579    /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();
580    ///
581    /// {
582    ///     builder.position_at_end(then_block);
583    ///
584    ///     // in the then_block, the `call_site` value is defined and can be used
585    ///     let result = call_site.try_as_basic_value().unwrap_basic();
586    ///
587    ///     builder.build_return(Some(&result)).unwrap();
588    /// }
589    ///
590    /// {
591    ///     builder.position_at_end(catch_block);
592    ///
593    ///     // the personality function used by C++
594    ///     let personality_function = {
595    ///         let name = "__gxx_personality_v0";
596    ///         let linkage = Some(Linkage::External);
597    ///
598    ///         module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
599    ///     };
600    ///
601    ///     // type of an exception in C++
602    ///     #[cfg(feature = "typed-pointers")]
603    ///     let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default());
604    ///     #[cfg(not(feature = "typed-pointers"))]
605    ///     let i32_ptr_ty = context.ptr_type(AddressSpace::default());
606    ///     let i32_type = context.i32_type();
607    ///     let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
608    ///
609    ///     let null = i8_ptr_type.const_zero();
610    ///     let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
611    ///
612    ///     // we handle the exception by returning a default value
613    ///     builder.build_return(Some(&f32_type.const_zero())).unwrap();
614    /// }
615    /// ```
616    #[llvm_versions(..=14)]
617    pub fn build_invoke<F>(
618        &self,
619        function: F,
620        args: &[BasicValueEnum<'ctx>],
621        then_block: BasicBlock<'ctx>,
622        catch_block: BasicBlock<'ctx>,
623        name: &str,
624    ) -> Result<CallSiteValue<'ctx>, BuilderError>
625    where
626        F: Into<CallableValue<'ctx>>,
627    {
628        if self.positioned.get() != PositionState::Set {
629            return Err(BuilderError::UnsetPosition);
630        }
631        let callable_value: CallableValue<'ctx> = function.into();
632        let fn_val_ref = callable_value.as_value_ref();
633
634        // LLVM gets upset when void return calls are named because they don't return anything
635        let name = if callable_value.returns_void() { "" } else { name };
636
637        let c_string = to_c_str(name);
638        let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
639
640        #[allow(deprecated)]
641        let value = unsafe {
642            LLVMBuildInvoke(
643                self.builder,
644                fn_val_ref,
645                args.as_mut_ptr(),
646                args.len() as u32,
647                then_block.basic_block,
648                catch_block.basic_block,
649                c_string.as_ptr(),
650            )
651        };
652
653        Ok(unsafe { CallSiteValue::new(value) })
654    }
655
656    /// An invoke is similar to a normal function call, but used to
657    /// call functions that may throw an exception, and then respond to the exception.
658    ///
659    /// When the called function returns normally, the `then` block is evaluated next. If instead
660    /// the function threw an exception, the `catch` block is entered. The first non-phi
661    /// instruction of the catch block must be a `landingpad` instruction. See also
662    /// [`Builder::build_landing_pad`].
663    ///
664    /// The [`add_prune_eh_pass`] turns an invoke into a call when the called function is
665    /// guaranteed to never throw an exception.
666    ///
667    /// [`add_prune_eh_pass`]: crate::passes::PassManager::add_prune_eh_pass
668    ///
669    /// This example catches C++ exceptions of type `int`, and returns `0` if an exceptions is thrown.
670    /// For usage of a cleanup landing pad and the `resume` instruction, see [`Builder::build_resume`]
671    /// ```no_run
672    /// use inkwell::context::Context;
673    /// use inkwell::AddressSpace;
674    /// use inkwell::module::Linkage;
675    ///
676    /// let context = Context::create();
677    /// let module = context.create_module("sum");
678    /// let builder = context.create_builder();
679    ///
680    /// let f32_type = context.f32_type();
681    /// let fn_type = f32_type.fn_type(&[], false);
682    ///
683    /// // we will pretend this function can throw an exception
684    /// let function = module.add_function("bomb", fn_type, None);
685    /// let basic_block = context.append_basic_block(function, "entry");
686    ///
687    /// builder.position_at_end(basic_block);
688    ///
689    /// let pi = f32_type.const_float(std::f64::consts::PI);
690    ///
691    /// builder.build_return(Some(&pi)).unwrap();
692    ///
693    /// let function2 = module.add_function("wrapper", fn_type, None);
694    /// let basic_block2 = context.append_basic_block(function2, "entry");
695    ///
696    /// builder.position_at_end(basic_block2);
697    ///
698    /// let then_block = context.append_basic_block(function2, "then_block");
699    /// let catch_block = context.append_basic_block(function2, "catch_block");
700    ///
701    /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();
702    ///
703    /// {
704    ///     builder.position_at_end(then_block);
705    ///
706    ///     // in the then_block, the `call_site` value is defined and can be used
707    ///     let result = call_site.try_as_basic_value().unwrap_basic();
708    ///
709    ///     builder.build_return(Some(&result)).unwrap();
710    /// }
711    ///
712    /// {
713    ///     builder.position_at_end(catch_block);
714    ///
715    ///     // the personality function used by C++
716    ///     let personality_function = {
717    ///         let name = "__gxx_personality_v0";
718    ///         let linkage = Some(Linkage::External);
719    ///
720    ///         module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
721    ///     };
722    ///
723    ///     // type of an exception in C++
724    ///     #[cfg(feature = "typed-pointers")]
725    ///     let ptr_type = context.i8_type().ptr_type(AddressSpace::default());
726    ///     #[cfg(not(feature = "typed-pointers"))]
727    ///     let ptr_type = context.ptr_type(AddressSpace::default());
728    ///     let i32_type = context.i32_type();
729    ///     let exception_type = context.struct_type(&[ptr_type.into(), i32_type.into()], false);
730    ///
731    ///     let null = ptr_type.const_zero();
732    ///     let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
733    ///
734    ///     // we handle the exception by returning a default value
735    ///     builder.build_return(Some(&f32_type.const_zero())).unwrap();
736    /// }
737    /// ```
738    #[llvm_versions(15..)]
739    pub fn build_invoke(
740        &self,
741        function: FunctionValue<'ctx>,
742        args: &[BasicValueEnum<'ctx>],
743        then_block: BasicBlock<'ctx>,
744        catch_block: BasicBlock<'ctx>,
745        name: &str,
746    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
747        if self.positioned.get() != PositionState::Set {
748            return Err(BuilderError::UnsetPosition);
749        }
750        self.build_direct_invoke(function, args, then_block, catch_block, name)
751    }
752
753    #[llvm_versions(15..)]
754    pub fn build_direct_invoke(
755        &self,
756        function: FunctionValue<'ctx>,
757        args: &[BasicValueEnum<'ctx>],
758        then_block: BasicBlock<'ctx>,
759        catch_block: BasicBlock<'ctx>,
760        name: &str,
761    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
762        if self.positioned.get() != PositionState::Set {
763            return Err(BuilderError::UnsetPosition);
764        }
765        self.build_invoke_help(
766            function.get_type(),
767            function.as_value_ref(),
768            args,
769            then_block,
770            catch_block,
771            name,
772        )
773    }
774
775    #[llvm_versions(15..)]
776    pub fn build_indirect_invoke(
777        &self,
778        function_type: FunctionType<'ctx>,
779        function_pointer: PointerValue<'ctx>,
780        args: &[BasicValueEnum<'ctx>],
781        then_block: BasicBlock<'ctx>,
782        catch_block: BasicBlock<'ctx>,
783        name: &str,
784    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
785        if self.positioned.get() != PositionState::Set {
786            return Err(BuilderError::UnsetPosition);
787        }
788        self.build_invoke_help(
789            function_type,
790            function_pointer.as_value_ref(),
791            args,
792            then_block,
793            catch_block,
794            name,
795        )
796    }
797
798    #[llvm_versions(15..)]
799    fn build_invoke_help(
800        &self,
801        fn_ty: FunctionType<'ctx>,
802        fn_val_ref: LLVMValueRef,
803        args: &[BasicValueEnum<'ctx>],
804        then_block: BasicBlock<'ctx>,
805        catch_block: BasicBlock<'ctx>,
806        name: &str,
807    ) -> Result<CallSiteValue<'ctx>, BuilderError> {
808        if self.positioned.get() != PositionState::Set {
809            return Err(BuilderError::UnsetPosition);
810        }
811        let fn_ty_ref = fn_ty.as_type_ref();
812
813        // LLVM gets upset when void return calls are named because they don't return anything
814        let name = if fn_ty.get_return_type().is_none() { "" } else { name };
815
816        let c_string = to_c_str(name);
817        let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
818
819        let value = unsafe {
820            LLVMBuildInvoke2(
821                self.builder,
822                fn_ty_ref,
823                fn_val_ref,
824                args.as_mut_ptr(),
825                args.len() as u32,
826                then_block.basic_block,
827                catch_block.basic_block,
828                c_string.as_ptr(),
829            )
830        };
831
832        unsafe { Ok(CallSiteValue::new(value)) }
833    }
834
835    /// Landing pads are places where control flow jumps to if a [`Builder::build_invoke`] triggered an exception.
836    /// The landing pad will match the exception against its `clauses`. Depending on the clause
837    /// that is matched, the exception can then be handled, or resumed after some optional cleanup,
838    /// causing the exception to bubble up.
839    ///
840    /// Exceptions in LLVM are designed based on the needs of a C++ compiler, but can be used more generally.
841    /// Here are some specific examples of landing pads. For a full example of handling an exception, see [`Builder::build_invoke`].
842    ///
843    /// * **cleanup**: a cleanup landing pad is always visited when unwinding the stack.
844    ///   A cleanup is extra code that needs to be run when unwinding a scope. C++ destructors are a typical example.
845    ///   In a language with reference counting, the cleanup block can decrement the refcount of values in scope.
846    ///   The [`Builder::build_resume`] function has a full example using a cleanup lading pad.
847    ///
848    /// ```no_run
849    /// use inkwell::context::Context;
850    /// use inkwell::AddressSpace;
851    /// use inkwell::module::Linkage;
852    ///
853    /// let context = Context::create();
854    /// let module = context.create_module("sum");
855    /// let builder = context.create_builder();
856    ///
857    /// // type of an exception in C++
858    /// #[cfg(feature = "typed-pointers")]
859    /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
860    /// #[cfg(not(feature = "typed-pointers"))]
861    /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
862    /// let i32_type = context.i32_type();
863    /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
864    ///
865    /// // the personality function used by C++
866    /// let personality_function = {
867    ///     let name = "__gxx_personality_v0";
868    ///     let linkage = Some(Linkage::External);
869    ///
870    ///     module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
871    /// };
872    ///
873    /// // make the cleanup landing pad
874    /// let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res").unwrap();
875    /// ```
876    ///
877    /// * **catch all**: An implementation of the C++ `catch(...)`, which catches all exceptions.
878    ///   A catch clause with a NULL pointer value will match anything.
879    ///
880    /// ```no_run
881    /// use inkwell::context::Context;
882    /// use inkwell::AddressSpace;
883    /// use inkwell::module::Linkage;
884    ///
885    /// let context = Context::create();
886    /// let module = context.create_module("sum");
887    /// let builder = context.create_builder();
888    ///
889    /// // type of an exception in C++
890    /// #[cfg(feature = "typed-pointers")]
891    /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
892    /// #[cfg(not(feature = "typed-pointers"))]
893    /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
894    /// let i32_type = context.i32_type();
895    /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
896    ///
897    /// // the personality function used by C++
898    /// let personality_function = {
899    ///     let name = "__gxx_personality_v0";
900    ///     let linkage = Some(Linkage::External);
901    ///
902    ///     module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
903    /// };
904    ///
905    /// // make a null pointer of type i8
906    /// let null = i8_ptr_type.const_zero();
907    ///
908    /// // make the catch all landing pad
909    /// let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
910    /// ```
911    ///
912    /// * **catch a type of exception**: Catch a specific type of exception. The example uses C++'s type info.
913    ///
914    /// ```no_run
915    /// use inkwell::context::Context;
916    /// use inkwell::module::Linkage;
917    /// use inkwell::AddressSpace;
918    /// use inkwell::values::BasicValue;
919    ///
920    /// let context = Context::create();
921    /// let module = context.create_module("sum");
922    /// let builder = context.create_builder();
923    ///
924    /// // type of an exception in C++
925    /// #[cfg(feature = "typed-pointers")]
926    /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
927    /// #[cfg(not(feature = "typed-pointers"))]
928    /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
929    /// let i32_type = context.i32_type();
930    /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
931    ///
932    /// // the personality function used by C++
933    /// let personality_function = {
934    ///     let name = "__gxx_personality_v0";
935    ///     let linkage = Some(Linkage::External);
936    ///
937    ///     module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
938    /// };
939    ///
940    /// // link in the C++ type info for the `int` type
941    /// let type_info_int = module.add_global(i8_ptr_type, Some(AddressSpace::default()), "_ZTIi");
942    /// type_info_int.set_linkage(Linkage::External);
943    ///
944    /// // make the catch landing pad
945    /// let clause = type_info_int.as_basic_value_enum();
946    /// let res = builder.build_landing_pad(exception_type, personality_function, &[clause], false, "res").unwrap();
947    /// ```
948    ///
949    /// * **filter**: A filter clause encodes that only some types of exceptions are valid at this
950    ///   point. A filter clause is made by constructing a clause from a constant array.
951    ///
952    /// ```no_run
953    /// use inkwell::context::Context;
954    /// use inkwell::module::Linkage;
955    /// use inkwell::values::AnyValue;
956    /// use inkwell::AddressSpace;
957    ///
958    /// let context = Context::create();
959    /// let module = context.create_module("sum");
960    /// let builder = context.create_builder();
961    ///
962    /// // type of an exception in C++
963    /// #[cfg(feature = "typed-pointers")]
964    /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
965    /// #[cfg(not(feature = "typed-pointers"))]
966    /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
967    /// let i32_type = context.i32_type();
968    /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
969    ///
970    /// // the personality function used by C++
971    /// let personality_function = {
972    ///     let name = "__gxx_personality_v0";
973    ///     let linkage = Some(Linkage::External);
974    ///
975    ///     module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
976    /// };
977    ///
978    /// // link in the C++ type info for the `int` type
979    /// let type_info_int = module.add_global(i8_ptr_type, Some(AddressSpace::default()), "_ZTIi");
980    /// type_info_int.set_linkage(Linkage::External);
981    ///
982    /// // make the filter landing pad
983    /// let filter_pattern = i8_ptr_type.const_array(&[type_info_int.as_any_value_enum().into_pointer_value()]);
984    /// let res = builder.build_landing_pad(exception_type, personality_function, &[filter_pattern.into()], false, "res").unwrap();
985    /// ```
986    pub fn build_landing_pad<T>(
987        &self,
988        exception_type: T,
989        personality_function: FunctionValue<'ctx>,
990        clauses: &[BasicValueEnum<'ctx>],
991        is_cleanup: bool,
992        name: &str,
993    ) -> Result<BasicValueEnum<'ctx>, BuilderError>
994    where
995        T: BasicType<'ctx>,
996    {
997        if self.positioned.get() != PositionState::Set {
998            return Err(BuilderError::UnsetPosition);
999        }
1000        let c_string = to_c_str(name);
1001        let num_clauses = clauses.len() as u32;
1002
1003        let value = unsafe {
1004            LLVMBuildLandingPad(
1005                self.builder,
1006                exception_type.as_type_ref(),
1007                personality_function.as_value_ref(),
1008                num_clauses,
1009                c_string.as_ptr(),
1010            )
1011        };
1012
1013        for clause in clauses {
1014            unsafe {
1015                LLVMAddClause(value, clause.as_value_ref());
1016            }
1017        }
1018
1019        unsafe {
1020            LLVMSetCleanup(value, is_cleanup as _);
1021        };
1022
1023        unsafe { Ok(BasicValueEnum::new(value)) }
1024    }
1025
1026    /// Resume propagation of an existing (in-flight) exception whose unwinding was interrupted with a landingpad instruction.
1027    ///
1028    /// This example uses a cleanup landing pad. A cleanup is extra code that needs to be run when
1029    /// unwinding a scope. C++ destructors are a typical example. In a language with reference counting,
1030    /// the cleanup block can decrement the refcount of values in scope.
1031    ///
1032    /// ```no_run
1033    /// use inkwell::context::Context;
1034    /// use inkwell::AddressSpace;
1035    /// use inkwell::module::Linkage;
1036    ///
1037    /// let context = Context::create();
1038    /// let module = context.create_module("sum");
1039    /// let builder = context.create_builder();
1040    ///
1041    /// let f32_type = context.f32_type();
1042    /// let fn_type = f32_type.fn_type(&[], false);
1043    ///
1044    /// // we will pretend this function can throw an exception
1045    /// let function = module.add_function("bomb", fn_type, None);
1046    /// let basic_block = context.append_basic_block(function, "entry");
1047    ///
1048    /// builder.position_at_end(basic_block);
1049    ///
1050    /// let pi = f32_type.const_float(std::f64::consts::PI);
1051    ///
1052    /// builder.build_return(Some(&pi)).unwrap();
1053    ///
1054    /// let function2 = module.add_function("wrapper", fn_type, None);
1055    /// let basic_block2 = context.append_basic_block(function2, "entry");
1056    ///
1057    /// builder.position_at_end(basic_block2);
1058    ///
1059    /// let then_block = context.append_basic_block(function2, "then_block");
1060    /// let catch_block = context.append_basic_block(function2, "catch_block");
1061    ///
1062    /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();
1063    ///
1064    /// {
1065    ///     builder.position_at_end(then_block);
1066    ///
1067    ///     // in the then_block, the `call_site` value is defined and can be used
1068    ///     let result = call_site.try_as_basic_value().unwrap_basic();
1069    ///
1070    ///     builder.build_return(Some(&result)).unwrap();
1071    /// }
1072    ///
1073    /// {
1074    ///     builder.position_at_end(catch_block);
1075    ///
1076    ///     // the personality function used by C++
1077    ///     let personality_function = {
1078    ///         let name = "__gxx_personality_v0";
1079    ///         let linkage = Some(Linkage::External);
1080    ///
1081    ///         module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
1082    ///     };
1083    ///
1084    ///     // type of an exception in C++
1085    ///     #[cfg(feature = "typed-pointers")]
1086    ///     let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
1087    ///     #[cfg(not(feature = "typed-pointers"))]
1088    ///     let i8_ptr_type = context.ptr_type(AddressSpace::default());
1089    ///     let i32_type = context.i32_type();
1090    ///     let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
1091    ///
1092    ///     // make the landing pad; must give a concrete type to the slice
1093    ///     let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res").unwrap();
1094    ///
1095    ///     // do cleanup ...
1096    ///
1097    ///     builder.build_resume(res).unwrap();
1098    /// }
1099    /// ```
1100    pub fn build_resume<V: BasicValue<'ctx>>(&self, value: V) -> Result<InstructionValue<'ctx>, BuilderError> {
1101        if self.positioned.get() != PositionState::Set {
1102            return Err(BuilderError::UnsetPosition);
1103        }
1104        let val = unsafe { LLVMBuildResume(self.builder, value.as_value_ref()) };
1105
1106        unsafe { Ok(InstructionValue::new(val)) }
1107    }
1108
1109    // REVIEW: Doesn't GEP work on array too?
1110    /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1111    #[cfg(feature = "typed-pointers")]
1112    pub unsafe fn build_gep(
1113        &self,
1114        ptr: PointerValue<'ctx>,
1115        ordered_indexes: &[IntValue<'ctx>],
1116        name: &str,
1117    ) -> Result<PointerValue<'ctx>, BuilderError> {
1118        unsafe {
1119            if self.positioned.get() != PositionState::Set {
1120                return Err(BuilderError::UnsetPosition);
1121            }
1122            let c_string = to_c_str(name);
1123
1124            let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1125
1126            #[cfg(not(feature = "llvm16-0"))]
1127            #[allow(deprecated)]
1128            let value = LLVMBuildGEP(
1129                self.builder,
1130                ptr.as_value_ref(),
1131                index_values.as_mut_ptr(),
1132                index_values.len() as u32,
1133                c_string.as_ptr(),
1134            );
1135            #[cfg(feature = "llvm16-0")]
1136            let value = LLVMBuildGEP2(
1137                self.builder,
1138                ptr.get_type().get_element_type().as_type_ref(),
1139                ptr.as_value_ref(),
1140                index_values.as_mut_ptr(),
1141                index_values.len() as u32,
1142                c_string.as_ptr(),
1143            );
1144
1145            Ok(PointerValue::new(value))
1146        }
1147    }
1148
1149    // REVIEW: Doesn't GEP work on array too?
1150    /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1151    #[cfg(not(feature = "typed-pointers"))]
1152    pub unsafe fn build_gep<T: BasicType<'ctx>>(
1153        &self,
1154        pointee_ty: T,
1155        ptr: PointerValue<'ctx>,
1156        ordered_indexes: &[IntValue<'ctx>],
1157        name: &str,
1158    ) -> Result<PointerValue<'ctx>, BuilderError> {
1159        unsafe {
1160            if self.positioned.get() != PositionState::Set {
1161                return Err(BuilderError::UnsetPosition);
1162            }
1163            let c_string = to_c_str(name);
1164
1165            let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1166
1167            let value = LLVMBuildGEP2(
1168                self.builder,
1169                pointee_ty.as_type_ref(),
1170                ptr.as_value_ref(),
1171                index_values.as_mut_ptr(),
1172                index_values.len() as u32,
1173                c_string.as_ptr(),
1174            );
1175
1176            Ok(PointerValue::new(value))
1177        }
1178    }
1179
1180    // REVIEW: Doesn't GEP work on array too?
1181    // REVIEW: This could be merge in with build_gep via a in_bounds: bool param
1182    /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1183    #[cfg(feature = "typed-pointers")]
1184    pub unsafe fn build_in_bounds_gep(
1185        &self,
1186        ptr: PointerValue<'ctx>,
1187        ordered_indexes: &[IntValue<'ctx>],
1188        name: &str,
1189    ) -> Result<PointerValue<'ctx>, BuilderError> {
1190        unsafe {
1191            if self.positioned.get() != PositionState::Set {
1192                return Err(BuilderError::UnsetPosition);
1193            }
1194            let c_string = to_c_str(name);
1195
1196            let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1197
1198            #[cfg(not(feature = "llvm16-0"))]
1199            #[allow(deprecated)]
1200            let value = LLVMBuildInBoundsGEP(
1201                self.builder,
1202                ptr.as_value_ref(),
1203                index_values.as_mut_ptr(),
1204                index_values.len() as u32,
1205                c_string.as_ptr(),
1206            );
1207            #[cfg(feature = "llvm16-0")]
1208            let value = LLVMBuildInBoundsGEP2(
1209                self.builder,
1210                ptr.get_type().get_element_type().as_type_ref(),
1211                ptr.as_value_ref(),
1212                index_values.as_mut_ptr(),
1213                index_values.len() as u32,
1214                c_string.as_ptr(),
1215            );
1216
1217            Ok(PointerValue::new(value))
1218        }
1219    }
1220
1221    // REVIEW: Doesn't GEP work on array too?
1222    // REVIEW: This could be merge in with build_gep via a in_bounds: bool param
1223    /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1224    #[cfg(not(feature = "typed-pointers"))]
1225    pub unsafe fn build_in_bounds_gep<T: BasicType<'ctx>>(
1226        &self,
1227        pointee_ty: T,
1228        ptr: PointerValue<'ctx>,
1229        ordered_indexes: &[IntValue<'ctx>],
1230        name: &str,
1231    ) -> Result<PointerValue<'ctx>, BuilderError> {
1232        unsafe {
1233            if self.positioned.get() != PositionState::Set {
1234                return Err(BuilderError::UnsetPosition);
1235            }
1236            let c_string = to_c_str(name);
1237
1238            let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1239
1240            let value = LLVMBuildInBoundsGEP2(
1241                self.builder,
1242                pointee_ty.as_type_ref(),
1243                ptr.as_value_ref(),
1244                index_values.as_mut_ptr(),
1245                index_values.len() as u32,
1246                c_string.as_ptr(),
1247            );
1248
1249            Ok(PointerValue::new(value))
1250        }
1251    }
1252
1253    /// Builds a GEP instruction on a struct pointer. Returns `Err(BuilderError::GEPError)` if input `PointerValue` doesn't
1254    /// point to a struct or if index is out of bounds.
1255    ///
1256    /// # Example
1257    ///
1258    /// ```no_run
1259    /// use inkwell::AddressSpace;
1260    /// use inkwell::context::Context;
1261    ///
1262    /// let context = Context::create();
1263    /// let builder = context.create_builder();
1264    /// let module = context.create_module("struct_gep");
1265    /// let void_type = context.void_type();
1266    /// let i32_ty = context.i32_type();
1267    /// #[cfg(feature = "typed-pointers")]
1268    /// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default());
1269    /// #[cfg(not(feature = "typed-pointers"))]
1270    /// let i32_ptr_ty = context.ptr_type(AddressSpace::default());
1271    /// let field_types = &[i32_ty.into(), i32_ty.into()];
1272    /// let struct_ty = context.struct_type(field_types, false);
1273    /// let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default());
1274    /// let fn_type = void_type.fn_type(&[i32_ptr_ty.into(), struct_ptr_ty.into()], false);
1275    /// let fn_value = module.add_function("", fn_type, None);
1276    /// let entry = context.append_basic_block(fn_value, "entry");
1277    ///
1278    /// builder.position_at_end(entry);
1279    ///
1280    /// let i32_ptr = fn_value.get_first_param().unwrap().into_pointer_value();
1281    /// let struct_ptr = fn_value.get_last_param().unwrap().into_pointer_value();
1282    ///
1283    /// assert!(builder.build_struct_gep(i32_ptr, 0, "struct_gep").is_err());
1284    /// assert!(builder.build_struct_gep(i32_ptr, 10, "struct_gep").is_err());
1285    /// assert!(builder.build_struct_gep(struct_ptr, 0, "struct_gep").is_ok());
1286    /// assert!(builder.build_struct_gep(struct_ptr, 1, "struct_gep").is_ok());
1287    /// assert!(builder.build_struct_gep(struct_ptr, 2, "struct_gep").is_err());
1288    /// ```
1289    #[cfg(feature = "typed-pointers")]
1290    pub fn build_struct_gep(
1291        &self,
1292        ptr: PointerValue<'ctx>,
1293        index: u32,
1294        name: &str,
1295    ) -> Result<PointerValue<'ctx>, BuilderError> {
1296        if self.positioned.get() != PositionState::Set {
1297            return Err(BuilderError::UnsetPosition);
1298        }
1299        let ptr_ty = ptr.get_type();
1300        let pointee_ty = ptr_ty.get_element_type();
1301
1302        if !pointee_ty.is_struct_type() {
1303            return Err(BuilderError::GEPPointee);
1304        }
1305
1306        let struct_ty = pointee_ty.into_struct_type();
1307
1308        if index >= struct_ty.count_fields() {
1309            return Err(BuilderError::GEPIndex);
1310        }
1311
1312        let c_string = to_c_str(name);
1313
1314        #[cfg(not(feature = "llvm16-0"))]
1315        #[allow(deprecated)]
1316        let value = unsafe { LLVMBuildStructGEP(self.builder, ptr.as_value_ref(), index, c_string.as_ptr()) };
1317        #[cfg(feature = "llvm16-0")]
1318        let value = unsafe {
1319            LLVMBuildStructGEP2(
1320                self.builder,
1321                ptr.get_type().get_element_type().as_type_ref(),
1322                ptr.as_value_ref(),
1323                index,
1324                c_string.as_ptr(),
1325            )
1326        };
1327
1328        unsafe { Ok(PointerValue::new(value)) }
1329    }
1330
1331    /// Builds a GEP instruction on a struct pointer. Returns `Err` `BuilderError::GEPPointee` or `BuilderError::GEPIndex` if input `PointerValue` doesn't
1332    /// point to a struct or if index is out of bounds.
1333    ///
1334    /// # Example
1335    ///
1336    /// ```no_run
1337    /// use inkwell::AddressSpace;
1338    /// use inkwell::context::Context;
1339    ///
1340    /// let context = Context::create();
1341    /// let builder = context.create_builder();
1342    /// let module = context.create_module("struct_gep");
1343    /// let void_type = context.void_type();
1344    /// let i32_ty = context.i32_type();
1345    /// #[cfg(feature = "typed-pointers")]
1346    /// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default());
1347    /// #[cfg(not(feature = "typed-pointers"))]
1348    /// let i32_ptr_ty = context.ptr_type(AddressSpace::default());
1349    /// let field_types = &[i32_ty.into(), i32_ty.into()];
1350    /// let struct_ty = context.struct_type(field_types, false);
1351    /// let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default());
1352    /// let fn_type = void_type.fn_type(&[i32_ptr_ty.into(), struct_ptr_ty.into()], false);
1353    /// let fn_value = module.add_function("", fn_type, None);
1354    /// let entry = context.append_basic_block(fn_value, "entry");
1355    ///
1356    /// builder.position_at_end(entry);
1357    ///
1358    /// let i32_ptr = fn_value.get_first_param().unwrap().into_pointer_value();
1359    /// let struct_ptr = fn_value.get_last_param().unwrap().into_pointer_value();
1360    ///
1361    /// assert!(builder.build_struct_gep(i32_ty, i32_ptr, 0, "struct_gep").is_err());
1362    /// assert!(builder.build_struct_gep(i32_ty, i32_ptr, 10, "struct_gep").is_err());
1363    /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 0, "struct_gep").is_ok());
1364    /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 1, "struct_gep").is_ok());
1365    /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 2, "struct_gep").is_err());
1366    /// ```
1367    #[cfg(not(feature = "typed-pointers"))]
1368    pub fn build_struct_gep<T: BasicType<'ctx>>(
1369        &self,
1370        pointee_ty: T,
1371        ptr: PointerValue<'ctx>,
1372        index: u32,
1373        name: &str,
1374    ) -> Result<PointerValue<'ctx>, BuilderError> {
1375        if self.positioned.get() != PositionState::Set {
1376            return Err(BuilderError::UnsetPosition);
1377        }
1378        let pointee_ty = pointee_ty.as_any_type_enum();
1379
1380        if !pointee_ty.is_struct_type() {
1381            return Err(BuilderError::GEPPointee);
1382        }
1383
1384        let struct_ty = pointee_ty.into_struct_type();
1385
1386        if index >= struct_ty.count_fields() {
1387            return Err(BuilderError::GEPIndex);
1388        }
1389
1390        let c_string = to_c_str(name);
1391
1392        let value = unsafe {
1393            LLVMBuildStructGEP2(
1394                self.builder,
1395                pointee_ty.as_type_ref(),
1396                ptr.as_value_ref(),
1397                index,
1398                c_string.as_ptr(),
1399            )
1400        };
1401
1402        unsafe { Ok(PointerValue::new(value)) }
1403    }
1404
1405    /// Builds an instruction which calculates the difference of two pointers.
1406    ///
1407    /// # Example
1408    ///
1409    /// ```no_run
1410    /// use inkwell::context::Context;
1411    /// use inkwell::AddressSpace;
1412    ///
1413    /// // Builds a function which diffs two pointers
1414    /// let context = Context::create();
1415    /// let module = context.create_module("ret");
1416    /// let builder = context.create_builder();
1417    /// let void_type = context.void_type();
1418    /// let i32_type = context.i32_type();
1419    /// #[cfg(feature = "typed-pointers")]
1420    /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1421    /// #[cfg(not(feature = "typed-pointers"))]
1422    /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1423    /// let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_ptr_type.into()], false);
1424    /// let fn_value = module.add_function("ret", fn_type, None);
1425    /// let entry = context.append_basic_block(fn_value, "entry");
1426    /// let i32_ptr_param1 = fn_value.get_first_param().unwrap().into_pointer_value();
1427    /// let i32_ptr_param2 = fn_value.get_nth_param(1).unwrap().into_pointer_value();
1428    ///
1429    /// builder.position_at_end(entry);
1430    /// builder.build_ptr_diff(i32_ptr_param1, i32_ptr_param2, "diff").unwrap();
1431    /// builder.build_return(None).unwrap();
1432    /// ```
1433    #[cfg(feature = "typed-pointers")]
1434    pub fn build_ptr_diff(
1435        &self,
1436        lhs_ptr: PointerValue<'ctx>,
1437        rhs_ptr: PointerValue<'ctx>,
1438        name: &str,
1439    ) -> Result<IntValue<'ctx>, BuilderError> {
1440        if self.positioned.get() != PositionState::Set {
1441            return Err(BuilderError::UnsetPosition);
1442        }
1443        let c_string = to_c_str(name);
1444        #[cfg(not(feature = "llvm16-0"))]
1445        #[allow(deprecated)]
1446        let value = unsafe {
1447            LLVMBuildPtrDiff(
1448                self.builder,
1449                lhs_ptr.as_value_ref(),
1450                rhs_ptr.as_value_ref(),
1451                c_string.as_ptr(),
1452            )
1453        };
1454        #[cfg(feature = "llvm16-0")]
1455        let value = {
1456            if lhs_ptr.get_type().as_basic_type_enum() != rhs_ptr.get_type().as_basic_type_enum() {
1457                return Err(BuilderError::NotSameType);
1458            }
1459
1460            unsafe {
1461                LLVMBuildPtrDiff2(
1462                    self.builder,
1463                    lhs_ptr.get_type().get_element_type().as_type_ref(),
1464                    lhs_ptr.as_value_ref(),
1465                    rhs_ptr.as_value_ref(),
1466                    c_string.as_ptr(),
1467                )
1468            }
1469        };
1470
1471        unsafe { Ok(IntValue::new(value)) }
1472    }
1473
1474    /// Builds an instruction which calculates the difference of two pointers.
1475    ///
1476    /// # Example
1477    ///
1478    /// ```no_run
1479    /// use inkwell::context::Context;
1480    /// use inkwell::AddressSpace;
1481    ///
1482    /// // Builds a function which diffs two pointers
1483    /// let context = Context::create();
1484    /// let module = context.create_module("ret");
1485    /// let builder = context.create_builder();
1486    /// let void_type = context.void_type();
1487    /// let i32_type = context.i32_type();
1488    /// #[cfg(feature = "typed-pointers")]
1489    /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1490    /// #[cfg(not(feature = "typed-pointers"))]
1491    /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1492    /// let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_ptr_type.into()], false);
1493    /// let fn_value = module.add_function("ret", fn_type, None);
1494    /// let entry = context.append_basic_block(fn_value, "entry");
1495    /// let i32_ptr_param1 = fn_value.get_first_param().unwrap().into_pointer_value();
1496    /// let i32_ptr_param2 = fn_value.get_nth_param(1).unwrap().into_pointer_value();
1497    ///
1498    /// builder.position_at_end(entry);
1499    /// builder.build_ptr_diff(i32_ptr_type, i32_ptr_param1, i32_ptr_param2, "diff").unwrap();
1500    /// builder.build_return(None).unwrap();
1501    /// ```
1502    #[cfg(not(feature = "typed-pointers"))]
1503    pub fn build_ptr_diff<T: BasicType<'ctx>>(
1504        &self,
1505        pointee_ty: T,
1506        lhs_ptr: PointerValue<'ctx>,
1507        rhs_ptr: PointerValue<'ctx>,
1508        name: &str,
1509    ) -> Result<IntValue<'ctx>, BuilderError> {
1510        if self.positioned.get() != PositionState::Set {
1511            return Err(BuilderError::UnsetPosition);
1512        }
1513        let c_string = to_c_str(name);
1514
1515        let value = unsafe {
1516            LLVMBuildPtrDiff2(
1517                self.builder,
1518                pointee_ty.as_type_ref(),
1519                lhs_ptr.as_value_ref(),
1520                rhs_ptr.as_value_ref(),
1521                c_string.as_ptr(),
1522            )
1523        };
1524
1525        unsafe { Ok(IntValue::new(value)) }
1526    }
1527
1528    // SubTypes: Maybe this should return PhiValue<T>? That way we could force incoming values to be of T::Value?
1529    // That is, assuming LLVM complains about different phi types.. which I imagine it would. But this would get
1530    // tricky with VoidType since it has no instance value?
1531    // TODOC: Phi Instruction(s) must be first instruction(s) in a BasicBlock.
1532    // REVIEW: Not sure if we can enforce the above somehow via types.
1533    pub fn build_phi<T: BasicType<'ctx>>(&self, type_: T, name: &str) -> Result<PhiValue<'ctx>, BuilderError> {
1534        if self.positioned.get() != PositionState::Set {
1535            return Err(BuilderError::UnsetPosition);
1536        }
1537        let c_string = to_c_str(name);
1538        let value = unsafe { LLVMBuildPhi(self.builder, type_.as_type_ref(), c_string.as_ptr()) };
1539
1540        unsafe { Ok(PhiValue::new(value)) }
1541    }
1542
1543    /// Builds a store instruction. It allows you to store a value of type `T` in a pointer to a type `T`.
1544    ///
1545    /// # Example
1546    ///
1547    /// ```no_run
1548    /// use inkwell::context::Context;
1549    /// use inkwell::AddressSpace;
1550    ///
1551    /// // Builds a function which takes an i32 pointer and stores a 7 in it.
1552    /// let context = Context::create();
1553    /// let module = context.create_module("ret");
1554    /// let builder = context.create_builder();
1555    /// let void_type = context.void_type();
1556    /// let i32_type = context.i32_type();
1557    /// #[cfg(feature = "typed-pointers")]
1558    /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1559    /// #[cfg(not(feature = "typed-pointers"))]
1560    /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1561    /// let i32_seven = i32_type.const_int(7, false);
1562    /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
1563    /// let fn_value = module.add_function("ret", fn_type, None);
1564    /// let entry = context.append_basic_block(fn_value, "entry");
1565    /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
1566    ///
1567    /// builder.position_at_end(entry);
1568    /// builder.build_store(i32_ptr_param, i32_seven).unwrap();
1569    /// builder.build_return(None).unwrap();
1570    /// ```
1571    pub fn build_store<V: BasicValue<'ctx>>(
1572        &self,
1573        ptr: PointerValue<'ctx>,
1574        value: V,
1575    ) -> Result<InstructionValue<'ctx>, BuilderError> {
1576        if self.positioned.get() != PositionState::Set {
1577            return Err(BuilderError::UnsetPosition);
1578        }
1579        let value = unsafe { LLVMBuildStore(self.builder, value.as_value_ref(), ptr.as_value_ref()) };
1580
1581        unsafe { Ok(InstructionValue::new(value)) }
1582    }
1583
1584    /// Builds a load instruction. It allows you to retrieve a value of type `T` from a pointer to a type `T`.
1585    ///
1586    /// # Example
1587    ///
1588    /// ```no_run
1589    /// use inkwell::context::Context;
1590    /// use inkwell::AddressSpace;
1591    ///
1592    /// // Builds a function which takes an i32 pointer and returns the pointed at i32.
1593    /// let context = Context::create();
1594    /// let module = context.create_module("ret");
1595    /// let builder = context.create_builder();
1596    /// let i32_type = context.i32_type();
1597    /// #[cfg(feature = "typed-pointers")]
1598    /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1599    /// #[cfg(not(feature = "typed-pointers"))]
1600    /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1601    /// let fn_type = i32_type.fn_type(&[i32_ptr_type.into()], false);
1602    /// let fn_value = module.add_function("ret", fn_type, None);
1603    /// let entry = context.append_basic_block(fn_value, "entry");
1604    /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
1605    ///
1606    /// builder.position_at_end(entry);
1607    ///
1608    /// let pointee = builder.build_load(i32_ptr_param, "load").unwrap();
1609    ///
1610    /// builder.build_return(Some(&pointee)).unwrap();
1611    /// ```
1612    #[cfg(feature = "typed-pointers")]
1613    pub fn build_load(&self, ptr: PointerValue<'ctx>, name: &str) -> Result<BasicValueEnum<'ctx>, BuilderError> {
1614        if self.positioned.get() != PositionState::Set {
1615            return Err(BuilderError::UnsetPosition);
1616        }
1617        let c_string = to_c_str(name);
1618
1619        #[cfg(not(feature = "llvm16-0"))]
1620        #[allow(deprecated)]
1621        let value = unsafe { LLVMBuildLoad(self.builder, ptr.as_value_ref(), c_string.as_ptr()) };
1622        #[cfg(feature = "llvm16-0")]
1623        let value = unsafe {
1624            LLVMBuildLoad2(
1625                self.builder,
1626                ptr.get_type().get_element_type().as_type_ref(),
1627                ptr.as_value_ref(),
1628                c_string.as_ptr(),
1629            )
1630        };
1631
1632        unsafe { Ok(BasicValueEnum::new(value)) }
1633    }
1634
1635    /// Builds a load2 instruction. It allows you to retrieve a value of type `T` from a pointer to a type `T`.
1636    ///
1637    /// # Example
1638    ///
1639    /// ```no_run
1640    /// use inkwell::context::Context;
1641    /// use inkwell::AddressSpace;
1642    ///
1643    /// // Builds a function which takes an i32 pointer and returns the pointed at i32.
1644    /// let context = Context::create();
1645    /// let module = context.create_module("ret");
1646    /// let builder = context.create_builder();
1647    /// let i32_type = context.i32_type();
1648    /// #[cfg(feature = "typed-pointers")]
1649    /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1650    /// #[cfg(not(feature = "typed-pointers"))]
1651    /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1652    /// let fn_type = i32_type.fn_type(&[i32_ptr_type.into()], false);
1653    /// let fn_value = module.add_function("ret", fn_type, None);
1654    /// let entry = context.append_basic_block(fn_value, "entry");
1655    /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
1656    ///
1657    /// builder.position_at_end(entry);
1658    ///
1659    /// let pointee = builder.build_load(i32_type, i32_ptr_param, "load2").unwrap();
1660    ///
1661    /// builder.build_return(Some(&pointee)).unwrap();
1662    /// ```
1663    #[cfg(not(feature = "typed-pointers"))]
1664    pub fn build_load<T: BasicType<'ctx>>(
1665        &self,
1666        pointee_ty: T,
1667        ptr: PointerValue<'ctx>,
1668        name: &str,
1669    ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
1670        if self.positioned.get() != PositionState::Set {
1671            return Err(BuilderError::UnsetPosition);
1672        }
1673        let c_string = to_c_str(name);
1674
1675        let value = unsafe {
1676            LLVMBuildLoad2(
1677                self.builder,
1678                pointee_ty.as_type_ref(),
1679                ptr.as_value_ref(),
1680                c_string.as_ptr(),
1681            )
1682        };
1683
1684        unsafe { Ok(BasicValueEnum::new(value)) }
1685    }
1686
1687    // TODOC: Stack allocation
1688    pub fn build_alloca<T: BasicType<'ctx>>(&self, ty: T, name: &str) -> Result<PointerValue<'ctx>, BuilderError> {
1689        if self.positioned.get() != PositionState::Set {
1690            return Err(BuilderError::UnsetPosition);
1691        }
1692        let c_string = to_c_str(name);
1693        let value = unsafe { LLVMBuildAlloca(self.builder, ty.as_type_ref(), c_string.as_ptr()) };
1694
1695        unsafe { Ok(PointerValue::new(value)) }
1696    }
1697
1698    // TODOC: Stack allocation
1699    pub fn build_array_alloca<T: BasicType<'ctx>>(
1700        &self,
1701        ty: T,
1702        size: IntValue<'ctx>,
1703        name: &str,
1704    ) -> Result<PointerValue<'ctx>, BuilderError> {
1705        if self.positioned.get() != PositionState::Set {
1706            return Err(BuilderError::UnsetPosition);
1707        }
1708        let c_string = to_c_str(name);
1709        let value =
1710            unsafe { LLVMBuildArrayAlloca(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr()) };
1711
1712        unsafe { Ok(PointerValue::new(value)) }
1713    }
1714
1715    /// Build a [memcpy](https://llvm.org/docs/LangRef.html#llvm-memcpy-intrinsic) instruction.
1716    ///
1717    /// Alignment arguments are specified in bytes, and should always be
1718    /// both a power of 2 and under 2^64.
1719    ///
1720    /// The final argument should be a pointer-sized integer.
1721    ///
1722    /// Returns an `Err(BuilderError::AlignmentError)` if the source or destination alignments are not a power of 2.
1723    ///
1724    /// [`TargetData::ptr_sized_int_type_in_context`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those.
1725    pub fn build_memcpy(
1726        &self,
1727        dest: PointerValue<'ctx>,
1728        dest_align_bytes: u32,
1729        src: PointerValue<'ctx>,
1730        src_align_bytes: u32,
1731        size: IntValue<'ctx>,
1732    ) -> Result<PointerValue<'ctx>, BuilderError> {
1733        if self.positioned.get() != PositionState::Set {
1734            return Err(BuilderError::UnsetPosition);
1735        }
1736        if !is_alignment_ok(src_align_bytes) {
1737            return Err(BuilderError::AlignmentError(AlignmentError::SrcNonPowerOfTwo(
1738                src_align_bytes,
1739            )));
1740        }
1741
1742        if !is_alignment_ok(dest_align_bytes) {
1743            return Err(BuilderError::AlignmentError(AlignmentError::DestNonPowerOfTwo(
1744                dest_align_bytes,
1745            )));
1746        }
1747
1748        let value = unsafe {
1749            LLVMBuildMemCpy(
1750                self.builder,
1751                dest.as_value_ref(),
1752                dest_align_bytes,
1753                src.as_value_ref(),
1754                src_align_bytes,
1755                size.as_value_ref(),
1756            )
1757        };
1758
1759        unsafe { Ok(PointerValue::new(value)) }
1760    }
1761
1762    /// Build a [memmove](http://llvm.org/docs/LangRef.html#llvm-memmove-intrinsic) instruction.
1763    ///
1764    /// Alignment arguments are specified in bytes, and should always be
1765    /// both a power of 2 and under 2^64.
1766    ///
1767    /// The final argument should be a pointer-sized integer.
1768    ///
1769    /// Returns an `Err(BuilderError::AlignmentError)` if the source or destination alignments are not a power of 2 under 2^64.
1770    ///
1771    /// [`TargetData::ptr_sized_int_type_in_context`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those.
1772    pub fn build_memmove(
1773        &self,
1774        dest: PointerValue<'ctx>,
1775        dest_align_bytes: u32,
1776        src: PointerValue<'ctx>,
1777        src_align_bytes: u32,
1778        size: IntValue<'ctx>,
1779    ) -> Result<PointerValue<'ctx>, BuilderError> {
1780        if self.positioned.get() != PositionState::Set {
1781            return Err(BuilderError::UnsetPosition);
1782        }
1783        if !is_alignment_ok(src_align_bytes) {
1784            return Err(BuilderError::AlignmentError(AlignmentError::SrcNonPowerOfTwo(
1785                src_align_bytes,
1786            )));
1787        }
1788
1789        if !is_alignment_ok(dest_align_bytes) {
1790            return Err(BuilderError::AlignmentError(AlignmentError::DestNonPowerOfTwo(
1791                dest_align_bytes,
1792            )));
1793        }
1794
1795        let value = unsafe {
1796            LLVMBuildMemMove(
1797                self.builder,
1798                dest.as_value_ref(),
1799                dest_align_bytes,
1800                src.as_value_ref(),
1801                src_align_bytes,
1802                size.as_value_ref(),
1803            )
1804        };
1805
1806        unsafe { Ok(PointerValue::new(value)) }
1807    }
1808
1809    /// Build a [memset](http://llvm.org/docs/LangRef.html#llvm-memset-intrinsics) instruction.
1810    ///
1811    /// Alignment arguments are specified in bytes, and should always be
1812    /// both a power of 2 and under 2^64.
1813    ///
1814    /// The final argument should be a pointer-sized integer.
1815    ///
1816    /// Returns an `Err(BuilderError::AlignmentError)` if the source alignment is not a power of 2 under 2^64.
1817    ///
1818    /// [`TargetData::ptr_sized_int_type_in_context`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those.
1819    pub fn build_memset(
1820        &self,
1821        dest: PointerValue<'ctx>,
1822        dest_align_bytes: u32,
1823        val: IntValue<'ctx>,
1824        size: IntValue<'ctx>,
1825    ) -> Result<PointerValue<'ctx>, BuilderError> {
1826        if self.positioned.get() != PositionState::Set {
1827            return Err(BuilderError::UnsetPosition);
1828        }
1829        if !is_alignment_ok(dest_align_bytes) {
1830            return Err(BuilderError::AlignmentError(AlignmentError::DestNonPowerOfTwo(
1831                dest_align_bytes,
1832            )));
1833        }
1834
1835        let value = unsafe {
1836            LLVMBuildMemSet(
1837                self.builder,
1838                dest.as_value_ref(),
1839                val.as_value_ref(),
1840                size.as_value_ref(),
1841                dest_align_bytes,
1842            )
1843        };
1844
1845        unsafe { Ok(PointerValue::new(value)) }
1846    }
1847
1848    // TODOC: Heap allocation
1849    /// Returns `Err(BuilderError::AlignmentError)` if the type is unsized.
1850    pub fn build_malloc<T: BasicType<'ctx>>(&self, ty: T, name: &str) -> Result<PointerValue<'ctx>, BuilderError> {
1851        if self.positioned.get() != PositionState::Set {
1852            return Err(BuilderError::UnsetPosition);
1853        }
1854        // LLVMBuildMalloc segfaults if ty is unsized
1855        if !ty.is_sized() {
1856            return Err(BuilderError::AlignmentError(AlignmentError::Unsized));
1857        }
1858
1859        let c_string = to_c_str(name);
1860
1861        let value = unsafe { LLVMBuildMalloc(self.builder, ty.as_type_ref(), c_string.as_ptr()) };
1862
1863        unsafe { Ok(PointerValue::new(value)) }
1864    }
1865
1866    // TODOC: Heap allocation
1867    /// Returns `Err(BuilderError::AlignmentError)` if the type is unsized.
1868    pub fn build_array_malloc<T: BasicType<'ctx>>(
1869        &self,
1870        ty: T,
1871        size: IntValue<'ctx>,
1872        name: &str,
1873    ) -> Result<PointerValue<'ctx>, BuilderError> {
1874        if self.positioned.get() != PositionState::Set {
1875            return Err(BuilderError::UnsetPosition);
1876        }
1877        // LLVMBuildArrayMalloc segfaults if ty is unsized
1878        if !ty.is_sized() {
1879            return Err(BuilderError::AlignmentError(AlignmentError::Unsized));
1880        }
1881
1882        let c_string = to_c_str(name);
1883
1884        let value =
1885            unsafe { LLVMBuildArrayMalloc(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr()) };
1886
1887        unsafe { Ok(PointerValue::new(value)) }
1888    }
1889
1890    // SubType: <P>(&self, ptr: PointerValue<P>) -> InstructionValue {
1891    pub fn build_free(&self, ptr: PointerValue<'ctx>) -> Result<InstructionValue<'ctx>, BuilderError> {
1892        if self.positioned.get() != PositionState::Set {
1893            return Err(BuilderError::UnsetPosition);
1894        }
1895        unsafe { Ok(InstructionValue::new(LLVMBuildFree(self.builder, ptr.as_value_ref()))) }
1896    }
1897
1898    pub fn insert_instruction(&self, instruction: &InstructionValue<'ctx>, name: Option<&str>) {
1899        match name {
1900            Some(name) => {
1901                let c_string = to_c_str(name);
1902
1903                unsafe { LLVMInsertIntoBuilderWithName(self.builder, instruction.as_value_ref(), c_string.as_ptr()) }
1904            },
1905            None => unsafe {
1906                LLVMInsertIntoBuilder(self.builder, instruction.as_value_ref());
1907            },
1908        }
1909    }
1910
1911    pub fn get_insert_block(&self) -> Option<BasicBlock<'ctx>> {
1912        unsafe { BasicBlock::new(LLVMGetInsertBlock(self.builder)) }
1913    }
1914
1915    // TODO: Possibly make this generic over sign via struct metadata or subtypes
1916    // SubType: <I: IntSubType>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1917    //     if I::sign() == Unsigned { LLVMBuildUDiv() } else { LLVMBuildSDiv() }
1918    pub fn build_int_unsigned_div<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1919        if self.positioned.get() != PositionState::Set {
1920            return Err(BuilderError::UnsetPosition);
1921        }
1922        let c_string = to_c_str(name);
1923        let value = unsafe { LLVMBuildUDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1924
1925        unsafe { Ok(T::new(value)) }
1926    }
1927
1928    // TODO: Possibly make this generic over sign via struct metadata or subtypes
1929    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1930    pub fn build_int_signed_div<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1931        if self.positioned.get() != PositionState::Set {
1932            return Err(BuilderError::UnsetPosition);
1933        }
1934        let c_string = to_c_str(name);
1935        let value = unsafe { LLVMBuildSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1936
1937        unsafe { Ok(T::new(value)) }
1938    }
1939
1940    // TODO: Possibly make this generic over sign via struct metadata or subtypes
1941    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1942    pub fn build_int_exact_signed_div<T: IntMathValue<'ctx>>(
1943        &self,
1944        lhs: T,
1945        rhs: T,
1946        name: &str,
1947    ) -> Result<T, BuilderError> {
1948        if self.positioned.get() != PositionState::Set {
1949            return Err(BuilderError::UnsetPosition);
1950        }
1951        let c_string = to_c_str(name);
1952        let value =
1953            unsafe { LLVMBuildExactSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1954
1955        unsafe { Ok(T::new(value)) }
1956    }
1957
1958    // TODO: Possibly make this generic over sign via struct metadata or subtypes
1959    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1960    pub fn build_int_unsigned_rem<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1961        if self.positioned.get() != PositionState::Set {
1962            return Err(BuilderError::UnsetPosition);
1963        }
1964        let c_string = to_c_str(name);
1965        let value = unsafe { LLVMBuildURem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1966
1967        unsafe { Ok(T::new(value)) }
1968    }
1969
1970    // TODO: Possibly make this generic over sign via struct metadata or subtypes
1971    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1972    pub fn build_int_signed_rem<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1973        if self.positioned.get() != PositionState::Set {
1974            return Err(BuilderError::UnsetPosition);
1975        }
1976        let c_string = to_c_str(name);
1977        let value = unsafe { LLVMBuildSRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1978
1979        unsafe { Ok(T::new(value)) }
1980    }
1981
1982    pub fn build_int_s_extend<T: IntMathValue<'ctx>>(
1983        &self,
1984        int_value: T,
1985        int_type: T::BaseType,
1986        name: &str,
1987    ) -> Result<T, BuilderError> {
1988        if self.positioned.get() != PositionState::Set {
1989            return Err(BuilderError::UnsetPosition);
1990        }
1991        let c_string = to_c_str(name);
1992        let value = unsafe {
1993            LLVMBuildSExt(
1994                self.builder,
1995                int_value.as_value_ref(),
1996                int_type.as_type_ref(),
1997                c_string.as_ptr(),
1998            )
1999        };
2000
2001        unsafe { Ok(T::new(value)) }
2002    }
2003
2004    // REVIEW: Does this need vector support?
2005    pub fn build_address_space_cast(
2006        &self,
2007        ptr_val: PointerValue<'ctx>,
2008        ptr_type: PointerType<'ctx>,
2009        name: &str,
2010    ) -> Result<PointerValue<'ctx>, BuilderError> {
2011        if self.positioned.get() != PositionState::Set {
2012            return Err(BuilderError::UnsetPosition);
2013        }
2014        let c_string = to_c_str(name);
2015        let value = unsafe {
2016            LLVMBuildAddrSpaceCast(
2017                self.builder,
2018                ptr_val.as_value_ref(),
2019                ptr_type.as_type_ref(),
2020                c_string.as_ptr(),
2021            )
2022        };
2023
2024        unsafe { Ok(PointerValue::new(value)) }
2025    }
2026
2027    /// Builds a bitcast instruction. A bitcast reinterprets the bits of one value
2028    /// into a value of another type which has the same bit width.
2029    ///
2030    /// # Example
2031    ///
2032    /// ```no_run
2033    /// use inkwell::AddressSpace;
2034    /// use inkwell::context::Context;
2035    ///
2036    /// let context = Context::create();
2037    /// let module = context.create_module("bc");
2038    /// let void_type = context.void_type();
2039    /// let f32_type = context.f32_type();
2040    /// let i32_type = context.i32_type();
2041    /// let arg_types = [i32_type.into()];
2042    /// let fn_type = void_type.fn_type(&arg_types, false);
2043    /// let fn_value = module.add_function("bc", fn_type, None);
2044    /// let builder = context.create_builder();
2045    /// let entry = context.append_basic_block(fn_value, "entry");
2046    /// let i32_arg = fn_value.get_first_param().unwrap();
2047    ///
2048    /// builder.position_at_end(entry);
2049    ///
2050    /// builder.build_bit_cast(i32_arg, f32_type, "i32tof32").unwrap();
2051    /// builder.build_return(None).unwrap();
2052    ///
2053    /// assert!(module.verify().is_ok());
2054    /// ```
2055    pub fn build_bit_cast<T, V>(&self, val: V, ty: T, name: &str) -> Result<BasicValueEnum<'ctx>, BuilderError>
2056    where
2057        T: BasicType<'ctx>,
2058        V: BasicValue<'ctx>,
2059    {
2060        if self.positioned.get() != PositionState::Set {
2061            return Err(BuilderError::UnsetPosition);
2062        }
2063        let c_string = to_c_str(name);
2064        let value = unsafe { LLVMBuildBitCast(self.builder, val.as_value_ref(), ty.as_type_ref(), c_string.as_ptr()) };
2065
2066        unsafe { Ok(BasicValueEnum::new(value)) }
2067    }
2068
2069    pub fn build_int_s_extend_or_bit_cast<T: IntMathValue<'ctx>>(
2070        &self,
2071        int_value: T,
2072        int_type: T::BaseType,
2073        name: &str,
2074    ) -> Result<T, BuilderError> {
2075        if self.positioned.get() != PositionState::Set {
2076            return Err(BuilderError::UnsetPosition);
2077        }
2078        let c_string = to_c_str(name);
2079        let value = unsafe {
2080            LLVMBuildSExtOrBitCast(
2081                self.builder,
2082                int_value.as_value_ref(),
2083                int_type.as_type_ref(),
2084                c_string.as_ptr(),
2085            )
2086        };
2087
2088        unsafe { Ok(T::new(value)) }
2089    }
2090
2091    pub fn build_int_z_extend<T: IntMathValue<'ctx>>(
2092        &self,
2093        int_value: T,
2094        int_type: T::BaseType,
2095        name: &str,
2096    ) -> Result<T, BuilderError> {
2097        if self.positioned.get() != PositionState::Set {
2098            return Err(BuilderError::UnsetPosition);
2099        }
2100        let c_string = to_c_str(name);
2101        let value = unsafe {
2102            LLVMBuildZExt(
2103                self.builder,
2104                int_value.as_value_ref(),
2105                int_type.as_type_ref(),
2106                c_string.as_ptr(),
2107            )
2108        };
2109
2110        unsafe { Ok(T::new(value)) }
2111    }
2112
2113    pub fn build_int_z_extend_or_bit_cast<T: IntMathValue<'ctx>>(
2114        &self,
2115        int_value: T,
2116        int_type: T::BaseType,
2117        name: &str,
2118    ) -> Result<T, BuilderError> {
2119        if self.positioned.get() != PositionState::Set {
2120            return Err(BuilderError::UnsetPosition);
2121        }
2122        let c_string = to_c_str(name);
2123        let value = unsafe {
2124            LLVMBuildZExtOrBitCast(
2125                self.builder,
2126                int_value.as_value_ref(),
2127                int_type.as_type_ref(),
2128                c_string.as_ptr(),
2129            )
2130        };
2131
2132        unsafe { Ok(T::new(value)) }
2133    }
2134
2135    pub fn build_int_truncate<T: IntMathValue<'ctx>>(
2136        &self,
2137        int_value: T,
2138        int_type: T::BaseType,
2139        name: &str,
2140    ) -> Result<T, BuilderError> {
2141        if self.positioned.get() != PositionState::Set {
2142            return Err(BuilderError::UnsetPosition);
2143        }
2144        let c_string = to_c_str(name);
2145
2146        let value = unsafe {
2147            LLVMBuildTrunc(
2148                self.builder,
2149                int_value.as_value_ref(),
2150                int_type.as_type_ref(),
2151                c_string.as_ptr(),
2152            )
2153        };
2154
2155        unsafe { Ok(T::new(value)) }
2156    }
2157
2158    pub fn build_int_truncate_or_bit_cast<T: IntMathValue<'ctx>>(
2159        &self,
2160        int_value: T,
2161        int_type: T::BaseType,
2162        name: &str,
2163    ) -> Result<T, BuilderError> {
2164        if self.positioned.get() != PositionState::Set {
2165            return Err(BuilderError::UnsetPosition);
2166        }
2167        let c_string = to_c_str(name);
2168
2169        let value = unsafe {
2170            LLVMBuildTruncOrBitCast(
2171                self.builder,
2172                int_value.as_value_ref(),
2173                int_type.as_type_ref(),
2174                c_string.as_ptr(),
2175            )
2176        };
2177
2178        unsafe { Ok(T::new(value)) }
2179    }
2180
2181    pub fn build_float_rem<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2182        if self.positioned.get() != PositionState::Set {
2183            return Err(BuilderError::UnsetPosition);
2184        }
2185        let c_string = to_c_str(name);
2186        let value = unsafe { LLVMBuildFRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2187
2188        unsafe { Ok(T::new(value)) }
2189    }
2190
2191    // REVIEW: Consolidate these two casts into one via subtypes
2192    pub fn build_float_to_unsigned_int<T: FloatMathValue<'ctx>>(
2193        &self,
2194        float: T,
2195        int_type: <T::BaseType as FloatMathType<'ctx>>::MathConvType,
2196        name: &str,
2197    ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>
2198    {
2199        if self.positioned.get() != PositionState::Set {
2200            return Err(BuilderError::UnsetPosition);
2201        }
2202        let c_string = to_c_str(name);
2203        let value = unsafe {
2204            LLVMBuildFPToUI(
2205                self.builder,
2206                float.as_value_ref(),
2207                int_type.as_type_ref(),
2208                c_string.as_ptr(),
2209            )
2210        };
2211
2212        unsafe { Ok(<<T::BaseType as FloatMathType>::MathConvType as IntMathType>::ValueType::new(value)) }
2213    }
2214
2215    pub fn build_float_to_signed_int<T: FloatMathValue<'ctx>>(
2216        &self,
2217        float: T,
2218        int_type: <T::BaseType as FloatMathType<'ctx>>::MathConvType,
2219        name: &str,
2220    ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>
2221    {
2222        if self.positioned.get() != PositionState::Set {
2223            return Err(BuilderError::UnsetPosition);
2224        }
2225        let c_string = to_c_str(name);
2226        let value = unsafe {
2227            LLVMBuildFPToSI(
2228                self.builder,
2229                float.as_value_ref(),
2230                int_type.as_type_ref(),
2231                c_string.as_ptr(),
2232            )
2233        };
2234
2235        unsafe { Ok(<<T::BaseType as FloatMathType>::MathConvType as IntMathType>::ValueType::new(value)) }
2236    }
2237
2238    // REVIEW: Consolidate these two casts into one via subtypes
2239    pub fn build_unsigned_int_to_float<T: IntMathValue<'ctx>>(
2240        &self,
2241        int: T,
2242        float_type: <T::BaseType as IntMathType<'ctx>>::MathConvType,
2243        name: &str,
2244    ) -> Result<<<T::BaseType as IntMathType<'ctx>>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError>
2245    {
2246        if self.positioned.get() != PositionState::Set {
2247            return Err(BuilderError::UnsetPosition);
2248        }
2249        let c_string = to_c_str(name);
2250        let value = unsafe {
2251            LLVMBuildUIToFP(
2252                self.builder,
2253                int.as_value_ref(),
2254                float_type.as_type_ref(),
2255                c_string.as_ptr(),
2256            )
2257        };
2258
2259        unsafe { Ok(<<T::BaseType as IntMathType>::MathConvType as FloatMathType>::ValueType::new(value)) }
2260    }
2261
2262    pub fn build_signed_int_to_float<T: IntMathValue<'ctx>>(
2263        &self,
2264        int: T,
2265        float_type: <T::BaseType as IntMathType<'ctx>>::MathConvType,
2266        name: &str,
2267    ) -> Result<<<T::BaseType as IntMathType<'ctx>>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError>
2268    {
2269        if self.positioned.get() != PositionState::Set {
2270            return Err(BuilderError::UnsetPosition);
2271        }
2272        let c_string = to_c_str(name);
2273        let value = unsafe {
2274            LLVMBuildSIToFP(
2275                self.builder,
2276                int.as_value_ref(),
2277                float_type.as_type_ref(),
2278                c_string.as_ptr(),
2279            )
2280        };
2281
2282        unsafe { Ok(<<T::BaseType as IntMathType>::MathConvType as FloatMathType>::ValueType::new(value)) }
2283    }
2284
2285    pub fn build_float_trunc<T: FloatMathValue<'ctx>>(
2286        &self,
2287        float: T,
2288        float_type: T::BaseType,
2289        name: &str,
2290    ) -> Result<T, BuilderError> {
2291        if self.positioned.get() != PositionState::Set {
2292            return Err(BuilderError::UnsetPosition);
2293        }
2294        let c_string = to_c_str(name);
2295        let value = unsafe {
2296            LLVMBuildFPTrunc(
2297                self.builder,
2298                float.as_value_ref(),
2299                float_type.as_type_ref(),
2300                c_string.as_ptr(),
2301            )
2302        };
2303
2304        unsafe { Ok(T::new(value)) }
2305    }
2306
2307    pub fn build_float_ext<T: FloatMathValue<'ctx>>(
2308        &self,
2309        float: T,
2310        float_type: T::BaseType,
2311        name: &str,
2312    ) -> Result<T, BuilderError> {
2313        if self.positioned.get() != PositionState::Set {
2314            return Err(BuilderError::UnsetPosition);
2315        }
2316        let c_string = to_c_str(name);
2317        let value = unsafe {
2318            LLVMBuildFPExt(
2319                self.builder,
2320                float.as_value_ref(),
2321                float_type.as_type_ref(),
2322                c_string.as_ptr(),
2323            )
2324        };
2325
2326        unsafe { Ok(T::new(value)) }
2327    }
2328
2329    pub fn build_float_cast<T: FloatMathValue<'ctx>>(
2330        &self,
2331        float: T,
2332        float_type: T::BaseType,
2333        name: &str,
2334    ) -> Result<T, BuilderError> {
2335        if self.positioned.get() != PositionState::Set {
2336            return Err(BuilderError::UnsetPosition);
2337        }
2338        let c_string = to_c_str(name);
2339        let value = unsafe {
2340            LLVMBuildFPCast(
2341                self.builder,
2342                float.as_value_ref(),
2343                float_type.as_type_ref(),
2344                c_string.as_ptr(),
2345            )
2346        };
2347
2348        unsafe { Ok(T::new(value)) }
2349    }
2350
2351    // SubType: <L, R>(&self, lhs: &IntValue<L>, rhs: &IntType<R>, name: &str) -> IntValue<R> {
2352    pub fn build_int_cast<T: IntMathValue<'ctx>>(
2353        &self,
2354        int: T,
2355        int_type: T::BaseType,
2356        name: &str,
2357    ) -> Result<T, BuilderError> {
2358        if self.positioned.get() != PositionState::Set {
2359            return Err(BuilderError::UnsetPosition);
2360        }
2361        let c_string = to_c_str(name);
2362        let value = unsafe {
2363            LLVMBuildIntCast(
2364                self.builder,
2365                int.as_value_ref(),
2366                int_type.as_type_ref(),
2367                c_string.as_ptr(),
2368            )
2369        };
2370
2371        unsafe { Ok(T::new(value)) }
2372    }
2373
2374    /// Like `build_int_cast`, but respects the signedness of the type being cast to.
2375    pub fn build_int_cast_sign_flag<T: IntMathValue<'ctx>>(
2376        &self,
2377        int: T,
2378        int_type: T::BaseType,
2379        is_signed: bool,
2380        name: &str,
2381    ) -> Result<T, BuilderError> {
2382        if self.positioned.get() != PositionState::Set {
2383            return Err(BuilderError::UnsetPosition);
2384        }
2385        let c_string = to_c_str(name);
2386        let value = unsafe {
2387            LLVMBuildIntCast2(
2388                self.builder,
2389                int.as_value_ref(),
2390                int_type.as_type_ref(),
2391                is_signed.into(),
2392                c_string.as_ptr(),
2393            )
2394        };
2395
2396        unsafe { Ok(T::new(value)) }
2397    }
2398
2399    pub fn build_float_div<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2400        if self.positioned.get() != PositionState::Set {
2401            return Err(BuilderError::UnsetPosition);
2402        }
2403        let c_string = to_c_str(name);
2404        let value = unsafe { LLVMBuildFDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2405
2406        unsafe { Ok(T::new(value)) }
2407    }
2408
2409    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2410    pub fn build_int_add<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2411        if self.positioned.get() != PositionState::Set {
2412            return Err(BuilderError::UnsetPosition);
2413        }
2414        let c_string = to_c_str(name);
2415        let value = unsafe { LLVMBuildAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2416
2417        unsafe { Ok(T::new(value)) }
2418    }
2419
2420    // REVIEW: Possibly incorporate into build_int_add via flag param
2421    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2422    pub fn build_int_nsw_add<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2423        let c_string = to_c_str(name);
2424        let value = unsafe { LLVMBuildNSWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2425
2426        unsafe { Ok(T::new(value)) }
2427    }
2428
2429    // REVIEW: Possibly incorporate into build_int_add via flag param
2430    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2431    pub fn build_int_nuw_add<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2432        if self.positioned.get() != PositionState::Set {
2433            return Err(BuilderError::UnsetPosition);
2434        }
2435        let c_string = to_c_str(name);
2436        let value = unsafe { LLVMBuildNUWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2437
2438        unsafe { Ok(T::new(value)) }
2439    }
2440
2441    // SubType: <F>(&self, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name: &str) -> FloatValue<F> {
2442    pub fn build_float_add<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2443        if self.positioned.get() != PositionState::Set {
2444            return Err(BuilderError::UnsetPosition);
2445        }
2446        let c_string = to_c_str(name);
2447        let value = unsafe { LLVMBuildFAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2448
2449        unsafe { Ok(T::new(value)) }
2450    }
2451
2452    // SubType: (&self, lhs: &IntValue<bool>, rhs: &IntValue<bool>, name: &str) -> IntValue<bool> {
2453    pub fn build_xor<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2454        if self.positioned.get() != PositionState::Set {
2455            return Err(BuilderError::UnsetPosition);
2456        }
2457        let c_string = to_c_str(name);
2458        let value = unsafe { LLVMBuildXor(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2459
2460        unsafe { Ok(T::new(value)) }
2461    }
2462
2463    // SubType: (&self, lhs: &IntValue<bool>, rhs: &IntValue<bool>, name: &str) -> IntValue<bool> {
2464    pub fn build_and<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2465        if self.positioned.get() != PositionState::Set {
2466            return Err(BuilderError::UnsetPosition);
2467        }
2468        let c_string = to_c_str(name);
2469        let value = unsafe { LLVMBuildAnd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2470
2471        unsafe { Ok(T::new(value)) }
2472    }
2473
2474    // SubType: (&self, lhs: &IntValue<bool>, rhs: &IntValue<bool>, name: &str) -> IntValue<bool> {
2475    pub fn build_or<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2476        if self.positioned.get() != PositionState::Set {
2477            return Err(BuilderError::UnsetPosition);
2478        }
2479        let c_string = to_c_str(name);
2480        let value = unsafe { LLVMBuildOr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2481
2482        unsafe { Ok(T::new(value)) }
2483    }
2484
2485    /// Builds an `IntValue` containing the result of a logical left shift instruction.
2486    ///
2487    /// # Example
2488    /// A logical left shift is an operation in which an integer value's bits are shifted left by N number of positions.
2489    ///
2490    /// ```rust,no_run
2491    /// assert_eq!(0b0000_0001 << 0, 0b0000_0001);
2492    /// assert_eq!(0b0000_0001 << 1, 0b0000_0010);
2493    /// assert_eq!(0b0000_0011 << 2, 0b0000_1100);
2494    /// ```
2495    ///
2496    /// In Rust, a function that could do this for 8bit values looks like:
2497    ///
2498    /// ```rust,no_run
2499    /// fn left_shift(value: u8, n: u8) -> u8 {
2500    ///     value << n
2501    /// }
2502    /// ```
2503    ///
2504    /// And in Inkwell, the corresponding function would look roughly like:
2505    ///
2506    /// ```rust,no_run
2507    /// use inkwell::context::Context;
2508    ///
2509    /// // Setup
2510    /// let context = Context::create();
2511    /// let module = context.create_module("my_module");
2512    /// let builder = context.create_builder();
2513    /// let i8_type = context.i8_type();
2514    /// let fn_type = i8_type.fn_type(&[i8_type.into(), i8_type.into()], false);
2515    ///
2516    /// // Function Definition
2517    /// let function = module.add_function("left_shift", fn_type, None);
2518    /// let value = function.get_first_param().unwrap().into_int_value();
2519    /// let n = function.get_nth_param(1).unwrap().into_int_value();
2520    /// let entry_block = context.append_basic_block(function, "entry");
2521    ///
2522    /// builder.position_at_end(entry_block);
2523    ///
2524    /// let shift = builder.build_left_shift(value, n, "left_shift").unwrap(); // value << n
2525    ///
2526    /// builder.build_return(Some(&shift)).unwrap();
2527    /// ```
2528    pub fn build_left_shift<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2529        if self.positioned.get() != PositionState::Set {
2530            return Err(BuilderError::UnsetPosition);
2531        }
2532        let c_string = to_c_str(name);
2533        let value = unsafe { LLVMBuildShl(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2534
2535        unsafe { Ok(T::new(value)) }
2536    }
2537
2538    /// Builds an `IntValue` containing the result of a right shift instruction.
2539    ///
2540    /// # Example
2541    /// A right shift is an operation in which an integer value's bits are shifted right by N number of positions.
2542    /// It may either be logical and have its leftmost N bit(s) filled with zeros or sign extended and filled with ones
2543    /// if the leftmost bit was one.
2544    ///
2545    /// ```rust,no_run
2546    /// //fix doc error about overflowing_literals
2547    /// //rendered rfc: https://github.com/rust-lang/rfcs/blob/master/text/2438-deny-integer-literal-overflow-lint.md
2548    /// //tracking issue: https://github.com/rust-lang/rust/issues/54502
2549    /// #![allow(overflowing_literals)]
2550    ///
2551    /// // Logical Right Shift
2552    /// assert_eq!(0b1100_0000u8 >> 2, 0b0011_0000);
2553    /// assert_eq!(0b0000_0010u8 >> 1, 0b0000_0001);
2554    /// assert_eq!(0b0000_1100u8 >> 2, 0b0000_0011);
2555    ///
2556    /// // Sign Extended Right Shift
2557    /// assert_eq!(0b0100_0000i8 >> 2, 0b0001_0000);
2558    /// assert_eq!(0b1110_0000u8 as i8 >> 1, 0b1111_0000u8 as i8);
2559    /// assert_eq!(0b1100_0000u8 as i8 >> 2, 0b1111_0000u8 as i8);
2560    /// ```
2561    ///
2562    /// In Rust, functions that could do this for 8bit values look like:
2563    ///
2564    /// ```rust,no_run
2565    /// fn logical_right_shift(value: u8, n: u8) -> u8 {
2566    ///     value >> n
2567    /// }
2568    ///
2569    /// fn sign_extended_right_shift(value: i8, n: u8) -> i8 {
2570    ///     value >> n
2571    /// }
2572    /// ```
2573    /// Notice that, in Rust (and most other languages), whether or not a value is sign extended depends wholly on whether
2574    /// or not the type is signed (ie an i8 is a signed 8 bit value). LLVM does not make this distinction for you.
2575    ///
2576    /// In Inkwell, the corresponding functions would look roughly like:
2577    ///
2578    /// ```rust,no_run
2579    /// use inkwell::context::Context;
2580    ///
2581    /// // Setup
2582    /// let context = Context::create();
2583    /// let module = context.create_module("my_module");
2584    /// let builder = context.create_builder();
2585    /// let i8_type = context.i8_type();
2586    /// let fn_type = i8_type.fn_type(&[i8_type.into(), i8_type.into()], false);
2587    ///
2588    /// // Function Definition
2589    /// let function = module.add_function("right_shift", fn_type, None);
2590    /// let value = function.get_first_param().unwrap().into_int_value();
2591    /// let n = function.get_nth_param(1).unwrap().into_int_value();
2592    /// let entry_block = context.append_basic_block(function, "entry");
2593    ///
2594    /// builder.position_at_end(entry_block);
2595    ///
2596    /// // Whether or not your right shift is sign extended (true) or logical (false) depends
2597    /// // on the boolean input parameter:
2598    /// let shift = builder.build_right_shift(value, n, false, "right_shift").unwrap(); // value >> n
2599    ///
2600    /// builder.build_return(Some(&shift)).unwrap();
2601    /// ```
2602    pub fn build_right_shift<T: IntMathValue<'ctx>>(
2603        &self,
2604        lhs: T,
2605        rhs: T,
2606        sign_extend: bool,
2607        name: &str,
2608    ) -> Result<T, BuilderError> {
2609        if self.positioned.get() != PositionState::Set {
2610            return Err(BuilderError::UnsetPosition);
2611        }
2612        let c_string = to_c_str(name);
2613        let value = unsafe {
2614            if sign_extend {
2615                LLVMBuildAShr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr())
2616            } else {
2617                LLVMBuildLShr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr())
2618            }
2619        };
2620
2621        unsafe { Ok(T::new(value)) }
2622    }
2623
2624    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2625    pub fn build_int_sub<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2626        if self.positioned.get() != PositionState::Set {
2627            return Err(BuilderError::UnsetPosition);
2628        }
2629        let c_string = to_c_str(name);
2630        let value = unsafe { LLVMBuildSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2631
2632        unsafe { Ok(T::new(value)) }
2633    }
2634
2635    // REVIEW: Possibly incorporate into build_int_sub via flag param
2636    pub fn build_int_nsw_sub<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2637        if self.positioned.get() != PositionState::Set {
2638            return Err(BuilderError::UnsetPosition);
2639        }
2640        let c_string = to_c_str(name);
2641        let value = unsafe { LLVMBuildNSWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2642
2643        unsafe { Ok(T::new(value)) }
2644    }
2645
2646    // REVIEW: Possibly incorporate into build_int_sub via flag param
2647    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2648    pub fn build_int_nuw_sub<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2649        if self.positioned.get() != PositionState::Set {
2650            return Err(BuilderError::UnsetPosition);
2651        }
2652        let c_string = to_c_str(name);
2653        let value = unsafe { LLVMBuildNUWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2654
2655        unsafe { Ok(T::new(value)) }
2656    }
2657
2658    // SubType: <F>(&self, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name: &str) -> FloatValue<F> {
2659    pub fn build_float_sub<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2660        if self.positioned.get() != PositionState::Set {
2661            return Err(BuilderError::UnsetPosition);
2662        }
2663        let c_string = to_c_str(name);
2664        let value = unsafe { LLVMBuildFSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2665
2666        unsafe { Ok(T::new(value)) }
2667    }
2668
2669    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2670    pub fn build_int_mul<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2671        if self.positioned.get() != PositionState::Set {
2672            return Err(BuilderError::UnsetPosition);
2673        }
2674        let c_string = to_c_str(name);
2675        let value = unsafe { LLVMBuildMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2676
2677        unsafe { Ok(T::new(value)) }
2678    }
2679
2680    // REVIEW: Possibly incorporate into build_int_mul via flag param
2681    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2682    pub fn build_int_nsw_mul<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2683        if self.positioned.get() != PositionState::Set {
2684            return Err(BuilderError::UnsetPosition);
2685        }
2686        let c_string = to_c_str(name);
2687        let value = unsafe { LLVMBuildNSWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2688
2689        unsafe { Ok(T::new(value)) }
2690    }
2691
2692    // REVIEW: Possibly incorporate into build_int_mul via flag param
2693    // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2694    pub fn build_int_nuw_mul<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2695        if self.positioned.get() != PositionState::Set {
2696            return Err(BuilderError::UnsetPosition);
2697        }
2698        let c_string = to_c_str(name);
2699        let value = unsafe { LLVMBuildNUWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2700
2701        unsafe { Ok(T::new(value)) }
2702    }
2703
2704    // SubType: <F>(&self, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name: &str) -> FloatValue<F> {
2705    pub fn build_float_mul<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2706        if self.positioned.get() != PositionState::Set {
2707            return Err(BuilderError::UnsetPosition);
2708        }
2709        let c_string = to_c_str(name);
2710        let value = unsafe { LLVMBuildFMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2711
2712        unsafe { Ok(T::new(value)) }
2713    }
2714
2715    pub fn build_binop<T: BasicValue<'ctx>>(
2716        &self,
2717        op: InstructionOpcode,
2718        lhs: T,
2719        rhs: T,
2720        name: &str,
2721    ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
2722        if self.positioned.get() != PositionState::Set {
2723            return Err(BuilderError::UnsetPosition);
2724        }
2725        let c_string = to_c_str(name);
2726        let value = unsafe {
2727            LLVMBuildBinOp(
2728                self.builder,
2729                op.into(),
2730                lhs.as_value_ref(),
2731                rhs.as_value_ref(),
2732                c_string.as_ptr(),
2733            )
2734        };
2735
2736        unsafe { Ok(BasicValueEnum::new(value)) }
2737    }
2738
2739    pub fn build_cast<T: BasicType<'ctx>, V: BasicValue<'ctx>>(
2740        &self,
2741        op: InstructionOpcode,
2742        from_value: V,
2743        to_type: T,
2744        name: &str,
2745    ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
2746        if self.positioned.get() != PositionState::Set {
2747            return Err(BuilderError::UnsetPosition);
2748        }
2749        let c_string = to_c_str(name);
2750        let value = unsafe {
2751            LLVMBuildCast(
2752                self.builder,
2753                op.into(),
2754                from_value.as_value_ref(),
2755                to_type.as_type_ref(),
2756                c_string.as_ptr(),
2757            )
2758        };
2759
2760        unsafe { Ok(BasicValueEnum::new(value)) }
2761    }
2762
2763    // SubType: <F, T>(&self, from: &PointerValue<F>, to: &PointerType<T>, name: &str) -> PointerValue<T> {
2764    pub fn build_pointer_cast<T: PointerMathValue<'ctx>>(
2765        &self,
2766        from: T,
2767        to: T::BaseType,
2768        name: &str,
2769    ) -> Result<T, BuilderError> {
2770        if self.positioned.get() != PositionState::Set {
2771            return Err(BuilderError::UnsetPosition);
2772        }
2773        let c_string = to_c_str(name);
2774        let value =
2775            unsafe { LLVMBuildPointerCast(self.builder, from.as_value_ref(), to.as_type_ref(), c_string.as_ptr()) };
2776
2777        unsafe { Ok(T::new(value)) }
2778    }
2779
2780    // SubType: <I>(&self, op, lhs: &IntValue<I>, rhs: &IntValue<I>, name) -> IntValue<bool> { ?
2781    // Note: we need a way to get an appropriate return type, since this method's return value
2782    // is always a bool (or vector of bools), not necessarily the same as the input value
2783    // See https://github.com/TheDan64/inkwell/pull/47#discussion_r197599297
2784    pub fn build_int_compare<T: IntMathValue<'ctx>>(
2785        &self,
2786        op: IntPredicate,
2787        lhs: T,
2788        rhs: T,
2789        name: &str,
2790    ) -> Result<<T::BaseType as IntMathType<'ctx>>::ValueType, BuilderError> {
2791        if self.positioned.get() != PositionState::Set {
2792            return Err(BuilderError::UnsetPosition);
2793        }
2794        let c_string = to_c_str(name);
2795        let value = unsafe {
2796            LLVMBuildICmp(
2797                self.builder,
2798                op.into(),
2799                lhs.as_value_ref(),
2800                rhs.as_value_ref(),
2801                c_string.as_ptr(),
2802            )
2803        };
2804
2805        unsafe { Ok(<T::BaseType as IntMathType<'ctx>>::ValueType::new(value)) }
2806    }
2807
2808    // SubType: <F>(&self, op, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name) -> IntValue<bool> { ?
2809    // Note: see comment on build_int_compare regarding return value type
2810    pub fn build_float_compare<T: FloatMathValue<'ctx>>(
2811        &self,
2812        op: FloatPredicate,
2813        lhs: T,
2814        rhs: T,
2815        name: &str,
2816    ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>
2817    {
2818        if self.positioned.get() != PositionState::Set {
2819            return Err(BuilderError::UnsetPosition);
2820        }
2821        let c_string = to_c_str(name);
2822
2823        let value = unsafe {
2824            LLVMBuildFCmp(
2825                self.builder,
2826                op.into(),
2827                lhs.as_value_ref(),
2828                rhs.as_value_ref(),
2829                c_string.as_ptr(),
2830            )
2831        };
2832
2833        unsafe { Ok(<<T::BaseType as FloatMathType>::MathConvType as IntMathType>::ValueType::new(value)) }
2834    }
2835
2836    pub fn build_unconditional_branch(
2837        &self,
2838        destination_block: BasicBlock<'ctx>,
2839    ) -> Result<InstructionValue<'ctx>, BuilderError> {
2840        if self.positioned.get() != PositionState::Set {
2841            return Err(BuilderError::UnsetPosition);
2842        }
2843        let value = unsafe { LLVMBuildBr(self.builder, destination_block.basic_block) };
2844
2845        unsafe { Ok(InstructionValue::new(value)) }
2846    }
2847
2848    pub fn build_conditional_branch(
2849        &self,
2850        comparison: IntValue<'ctx>,
2851        then_block: BasicBlock<'ctx>,
2852        else_block: BasicBlock<'ctx>,
2853    ) -> Result<InstructionValue<'ctx>, BuilderError> {
2854        if self.positioned.get() != PositionState::Set {
2855            return Err(BuilderError::UnsetPosition);
2856        }
2857        let value = unsafe {
2858            LLVMBuildCondBr(
2859                self.builder,
2860                comparison.as_value_ref(),
2861                then_block.basic_block,
2862                else_block.basic_block,
2863            )
2864        };
2865
2866        unsafe { Ok(InstructionValue::new(value)) }
2867    }
2868
2869    pub fn build_indirect_branch<BV: BasicValue<'ctx>>(
2870        &self,
2871        address: BV,
2872        destinations: &[BasicBlock<'ctx>],
2873    ) -> Result<InstructionValue<'ctx>, BuilderError> {
2874        if self.positioned.get() != PositionState::Set {
2875            return Err(BuilderError::UnsetPosition);
2876        }
2877        let value = unsafe { LLVMBuildIndirectBr(self.builder, address.as_value_ref(), destinations.len() as u32) };
2878
2879        for destination in destinations {
2880            unsafe { LLVMAddDestination(value, destination.basic_block) }
2881        }
2882
2883        unsafe { Ok(InstructionValue::new(value)) }
2884    }
2885
2886    // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<I> {
2887    pub fn build_int_neg<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2888        if self.positioned.get() != PositionState::Set {
2889            return Err(BuilderError::UnsetPosition);
2890        }
2891        let c_string = to_c_str(name);
2892        let value = unsafe { LLVMBuildNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2893
2894        unsafe { Ok(T::new(value)) }
2895    }
2896
2897    // REVIEW: Possibly incorporate into build_int_neg via flag and subtypes
2898    // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<I> {
2899    pub fn build_int_nsw_neg<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2900        if self.positioned.get() != PositionState::Set {
2901            return Err(BuilderError::UnsetPosition);
2902        }
2903        let c_string = to_c_str(name);
2904        let value = unsafe { LLVMBuildNSWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2905
2906        unsafe { Ok(T::new(value)) }
2907    }
2908
2909    // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<I> {
2910    #[llvm_versions(..17)]
2911    pub fn build_int_nuw_neg<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2912        if self.positioned.get() != PositionState::Set {
2913            return Err(BuilderError::UnsetPosition);
2914        }
2915        let c_string = to_c_str(name);
2916        let value = unsafe { LLVMBuildNUWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2917        unsafe { Ok(T::new(value)) }
2918    }
2919
2920    // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<I> {
2921    #[llvm_versions(17..)]
2922    pub fn build_int_nuw_neg<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2923        if self.positioned.get() != PositionState::Set {
2924            return Err(BuilderError::UnsetPosition);
2925        }
2926        let c_string = to_c_str(name);
2927        let value = unsafe { LLVMBuildNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2928        unsafe {
2929            LLVMSetNUW(value, true.into());
2930        }
2931
2932        unsafe { Ok(T::new(value)) }
2933    }
2934
2935    // SubType: <F>(&self, value: &FloatValue<F>, name) -> FloatValue<F> {
2936    pub fn build_float_neg<T: FloatMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2937        if self.positioned.get() != PositionState::Set {
2938            return Err(BuilderError::UnsetPosition);
2939        }
2940        let c_string = to_c_str(name);
2941        let value = unsafe { LLVMBuildFNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2942
2943        unsafe { Ok(T::new(value)) }
2944    }
2945
2946    // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<bool> { ?
2947    pub fn build_not<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2948        if self.positioned.get() != PositionState::Set {
2949            return Err(BuilderError::UnsetPosition);
2950        }
2951        let c_string = to_c_str(name);
2952        let value = unsafe { LLVMBuildNot(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2953
2954        unsafe { Ok(T::new(value)) }
2955    }
2956
2957    // REVIEW: What if instruction and basic_block are completely unrelated?
2958    // It'd be great if we could get the BB from the instruction behind the scenes
2959    /// Set the position of the builder to after an instruction.
2960    ///
2961    /// Be sure to call one of the `position_*` methods or all `build_*` methods will return `Err(BuilderError::UnsetPosition)`.
2962    pub fn position_at(&self, basic_block: BasicBlock<'ctx>, instruction: &InstructionValue<'ctx>) {
2963        self.positioned.set(PositionState::Set);
2964
2965        unsafe { LLVMPositionBuilder(self.builder, basic_block.basic_block, instruction.as_value_ref()) }
2966    }
2967
2968    /// Set the position of the builder to before an instruction.
2969    ///
2970    /// Be sure to call one of the `position_*` methods or all `build_*` methods will return `Err(BuilderError::UnsetPosition)`.
2971    pub fn position_before(&self, instruction: &InstructionValue<'ctx>) {
2972        self.positioned.set(PositionState::Set);
2973
2974        unsafe { LLVMPositionBuilderBefore(self.builder, instruction.as_value_ref()) }
2975    }
2976
2977    /// Set the position of the builder to the end of a basic block.
2978    ///
2979    /// Be sure to call one of the `position_*` methods or all `build_*` methods will return `Err(BuilderError::UnsetPosition)`.
2980    pub fn position_at_end(&self, basic_block: BasicBlock<'ctx>) {
2981        self.positioned.set(PositionState::Set);
2982
2983        unsafe {
2984            LLVMPositionBuilderAtEnd(self.builder, basic_block.basic_block);
2985        }
2986    }
2987
2988    /// Builds an extract value instruction which extracts a `BasicValueEnum`
2989    /// from a struct or array.
2990    ///
2991    /// Returns `Err(BuilderError::ExtractOutOfRange)` if the provided index is out of bounds of the aggregate value length.
2992    ///
2993    /// # Example
2994    ///
2995    /// ```no_run
2996    /// use inkwell::context::Context;
2997    /// use inkwell::builder::BuilderError;
2998    ///
2999    /// let context = Context::create();
3000    /// let module = context.create_module("av");
3001    /// let void_type = context.void_type();
3002    /// let f32_type = context.f32_type();
3003    /// let i32_type = context.i32_type();
3004    /// let struct_type = context.struct_type(&[i32_type.into(), f32_type.into()], false);
3005    /// let array_type = i32_type.array_type(3);
3006    /// let fn_type = void_type.fn_type(&[], false);
3007    /// let fn_value = module.add_function("av_fn", fn_type, None);
3008    /// let builder = context.create_builder();
3009    /// let entry = context.append_basic_block(fn_value, "entry");
3010    ///
3011    /// builder.position_at_end(entry);
3012    ///
3013    /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap();
3014    ///
3015    /// #[cfg(feature = "typed-pointers")]
3016    /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value();
3017    /// #[cfg(not(feature = "typed-pointers"))]
3018    /// let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value();
3019    ///
3020    /// let const_int1 = i32_type.const_int(2, false);
3021    /// let const_int2 = i32_type.const_int(5, false);
3022    /// let const_int3 = i32_type.const_int(6, false);
3023    ///
3024    /// assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_ok());
3025    /// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_ok());
3026    /// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_ok());
3027    /// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
3028    ///
3029    /// assert!(builder.build_extract_value(array, 0, "extract").unwrap().is_int_value());
3030    /// assert!(builder.build_extract_value(array, 1, "extract").unwrap().is_int_value());
3031    /// assert!(builder.build_extract_value(array, 2, "extract").unwrap().is_int_value());
3032    /// assert!(builder.build_extract_value(array, 3, "extract").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
3033    /// ```
3034    pub fn build_extract_value<AV: AggregateValue<'ctx>>(
3035        &self,
3036        agg: AV,
3037        index: u32,
3038        name: &str,
3039    ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3040        if self.positioned.get() != PositionState::Set {
3041            return Err(BuilderError::UnsetPosition);
3042        }
3043        let size = match agg.as_aggregate_value_enum() {
3044            AggregateValueEnum::ArrayValue(av) => av.get_type().len(),
3045            AggregateValueEnum::StructValue(sv) => sv.get_type().count_fields(),
3046        };
3047
3048        if index >= size {
3049            return Err(BuilderError::ExtractOutOfRange);
3050        }
3051
3052        let c_string = to_c_str(name);
3053
3054        let value = unsafe { LLVMBuildExtractValue(self.builder, agg.as_value_ref(), index, c_string.as_ptr()) };
3055
3056        unsafe { Ok(BasicValueEnum::new(value)) }
3057    }
3058
3059    /// Builds an insert value instruction which inserts a `BasicValue` into a struct
3060    /// or array and returns the resulting aggregate value.
3061    ///
3062    /// Returns `Err(BuilderError::ExtractOutOfRange)` if the provided index is out of bounds of the aggregate value length.
3063    ///
3064    /// # Example
3065    ///
3066    /// ```no_run
3067    /// use inkwell::context::Context;
3068    /// use inkwell::builder::BuilderError;
3069    ///
3070    /// let context = Context::create();
3071    /// let module = context.create_module("av");
3072    /// let void_type = context.void_type();
3073    /// let f32_type = context.f32_type();
3074    /// let i32_type = context.i32_type();
3075    /// let struct_type = context.struct_type(&[i32_type.into(), f32_type.into()], false);
3076    /// let array_type = i32_type.array_type(3);
3077    /// let fn_type = void_type.fn_type(&[], false);
3078    /// let fn_value = module.add_function("av_fn", fn_type, None);
3079    /// let builder = context.create_builder();
3080    /// let entry = context.append_basic_block(fn_value, "entry");
3081    ///
3082    /// builder.position_at_end(entry);
3083    ///
3084    /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap();
3085    ///
3086    /// #[cfg(feature = "typed-pointers")]
3087    /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value();
3088    /// #[cfg(not(feature = "typed-pointers"))]
3089    /// let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value();
3090    ///
3091    /// let const_int1 = i32_type.const_int(2, false);
3092    /// let const_int2 = i32_type.const_int(5, false);
3093    /// let const_int3 = i32_type.const_int(6, false);
3094    ///
3095    /// assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_ok());
3096    /// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_ok());
3097    /// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_ok());
3098    /// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
3099    /// ```
3100    pub fn build_insert_value<AV, BV>(
3101        &self,
3102        agg: AV,
3103        value: BV,
3104        index: u32,
3105        name: &str,
3106    ) -> Result<AggregateValueEnum<'ctx>, BuilderError>
3107    where
3108        AV: AggregateValue<'ctx>,
3109        BV: BasicValue<'ctx>,
3110    {
3111        if self.positioned.get() != PositionState::Set {
3112            return Err(BuilderError::UnsetPosition);
3113        }
3114        let size = match agg.as_aggregate_value_enum() {
3115            AggregateValueEnum::ArrayValue(av) => av.get_type().len(),
3116            AggregateValueEnum::StructValue(sv) => sv.get_type().count_fields(),
3117        };
3118
3119        if index >= size {
3120            return Err(BuilderError::ExtractOutOfRange);
3121        }
3122
3123        let c_string = to_c_str(name);
3124
3125        let value = unsafe {
3126            LLVMBuildInsertValue(
3127                self.builder,
3128                agg.as_value_ref(),
3129                value.as_value_ref(),
3130                index,
3131                c_string.as_ptr(),
3132            )
3133        };
3134
3135        unsafe { Ok(AggregateValueEnum::new(value)) }
3136    }
3137
3138    /// Builds an extract element instruction which extracts a `BasicValueEnum`
3139    /// from a vector.
3140    /// # Example
3141    ///
3142    /// ```no_run
3143    /// use inkwell::context::Context;
3144    ///
3145    /// let context = Context::create();
3146    /// let module = context.create_module("av");
3147    /// let i32_type = context.i32_type();
3148    /// let i32_zero = i32_type.const_int(0, false);
3149    /// let vec_type = i32_type.vec_type(2);
3150    /// let fn_type = i32_type.fn_type(&[vec_type.into()], false);
3151    /// let fn_value = module.add_function("vec_fn", fn_type, None);
3152    /// let builder = context.create_builder();
3153    /// let entry = context.append_basic_block(fn_value, "entry");
3154    /// let vector_param = fn_value.get_first_param().unwrap().into_vector_value();
3155    ///
3156    /// builder.position_at_end(entry);
3157    ///
3158    /// let extracted = builder.build_extract_element(vector_param, i32_zero, "insert").unwrap();
3159    ///
3160    /// builder.build_return(Some(&extracted)).unwrap();
3161    /// ```
3162    pub fn build_extract_element<V: VectorBaseValue<'ctx>>(
3163        &self,
3164        vector: V,
3165        index: IntValue<'ctx>,
3166        name: &str,
3167    ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3168        if self.positioned.get() != PositionState::Set {
3169            return Err(BuilderError::UnsetPosition);
3170        }
3171        let c_string = to_c_str(name);
3172
3173        let value = unsafe {
3174            LLVMBuildExtractElement(
3175                self.builder,
3176                vector.as_value_ref(),
3177                index.as_value_ref(),
3178                c_string.as_ptr(),
3179            )
3180        };
3181
3182        unsafe { Ok(BasicValueEnum::new(value)) }
3183    }
3184
3185    /// Builds an insert element instruction which inserts a `BasicValue` into a vector
3186    /// and returns the resulting vector.
3187    ///
3188    /// # Example
3189    ///
3190    /// ```no_run
3191    /// use inkwell::context::Context;
3192    ///
3193    /// let context = Context::create();
3194    /// let module = context.create_module("av");
3195    /// let void_type = context.void_type();
3196    /// let i32_type = context.i32_type();
3197    /// let i32_zero = i32_type.const_int(0, false);
3198    /// let i32_seven = i32_type.const_int(7, false);
3199    /// let vec_type = i32_type.vec_type(2);
3200    /// let fn_type = void_type.fn_type(&[vec_type.into()], false);
3201    /// let fn_value = module.add_function("vec_fn", fn_type, None);
3202    /// let builder = context.create_builder();
3203    /// let entry = context.append_basic_block(fn_value, "entry");
3204    /// let vector_param = fn_value.get_first_param().unwrap().into_vector_value();
3205    ///
3206    /// builder.position_at_end(entry);
3207    /// builder.build_insert_element(vector_param, i32_seven, i32_zero, "insert").unwrap();
3208    /// builder.build_return(None).unwrap();
3209    /// ```
3210    pub fn build_insert_element<V: BasicValue<'ctx>, W: VectorBaseValue<'ctx>>(
3211        &self,
3212        vector: W,
3213        element: V,
3214        index: IntValue<'ctx>,
3215        name: &str,
3216    ) -> Result<W, BuilderError> {
3217        if self.positioned.get() != PositionState::Set {
3218            return Err(BuilderError::UnsetPosition);
3219        }
3220        let c_string = to_c_str(name);
3221
3222        let value = unsafe {
3223            LLVMBuildInsertElement(
3224                self.builder,
3225                vector.as_value_ref(),
3226                element.as_value_ref(),
3227                index.as_value_ref(),
3228                c_string.as_ptr(),
3229            )
3230        };
3231
3232        unsafe { Ok(W::new(value)) }
3233    }
3234
3235    pub fn build_unreachable(&self) -> Result<InstructionValue<'ctx>, BuilderError> {
3236        if self.positioned.get() != PositionState::Set {
3237            return Err(BuilderError::UnsetPosition);
3238        }
3239        let val = unsafe { LLVMBuildUnreachable(self.builder) };
3240
3241        unsafe { Ok(InstructionValue::new(val)) }
3242    }
3243
3244    // REVIEW: Not sure if this should return InstructionValue or an actual value
3245    pub fn build_fence(
3246        &self,
3247        atomic_ordering: AtomicOrdering,
3248        is_single_thread: bool,
3249        name: &str,
3250    ) -> Result<InstructionValue<'ctx>, BuilderError> {
3251        if self.positioned.get() != PositionState::Set {
3252            return Err(BuilderError::UnsetPosition);
3253        }
3254        let c_string = to_c_str(name);
3255
3256        // "They can only be given acquire, release, acq_rel, and seq_cst orderings."
3257        match atomic_ordering {
3258            AtomicOrdering::Acquire
3259            | AtomicOrdering::Release
3260            | AtomicOrdering::AcquireRelease
3261            | AtomicOrdering::SequentiallyConsistent => {},
3262            _ => return Err(BuilderError::AtomicOrdering(AtomicError::InvalidOrderingOnFence)),
3263        }
3264
3265        let val = unsafe {
3266            LLVMBuildFence(
3267                self.builder,
3268                atomic_ordering.into(),
3269                is_single_thread as i32,
3270                c_string.as_ptr(),
3271            )
3272        };
3273
3274        unsafe { Ok(InstructionValue::new(val)) }
3275    }
3276
3277    // SubType: <P>(&self, ptr: &PointerValue<P>, name) -> IntValue<bool> {
3278    pub fn build_is_null<T: PointerMathValue<'ctx>>(
3279        &self,
3280        ptr: T,
3281        name: &str,
3282    ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>
3283    {
3284        if self.positioned.get() != PositionState::Set {
3285            return Err(BuilderError::UnsetPosition);
3286        }
3287        let c_string = to_c_str(name);
3288        let val = unsafe { LLVMBuildIsNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) };
3289
3290        unsafe { Ok(<<T::BaseType as PointerMathType>::PtrConvType as IntMathType>::ValueType::new(val)) }
3291    }
3292
3293    // SubType: <P>(&self, ptr: &PointerValue<P>, name) -> IntValue<bool> {
3294    pub fn build_is_not_null<T: PointerMathValue<'ctx>>(
3295        &self,
3296        ptr: T,
3297        name: &str,
3298    ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>
3299    {
3300        if self.positioned.get() != PositionState::Set {
3301            return Err(BuilderError::UnsetPosition);
3302        }
3303        let c_string = to_c_str(name);
3304        let val = unsafe { LLVMBuildIsNotNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) };
3305
3306        unsafe { Ok(<<T::BaseType as PointerMathType>::PtrConvType as IntMathType>::ValueType::new(val)) }
3307    }
3308
3309    // SubType: <I, P>(&self, int: &IntValue<I>, ptr_type: &PointerType<P>, name) -> PointerValue<P> {
3310    pub fn build_int_to_ptr<T: IntMathValue<'ctx>>(
3311        &self,
3312        int: T,
3313        ptr_type: <T::BaseType as IntMathType<'ctx>>::PtrConvType,
3314        name: &str,
3315    ) -> Result<<<T::BaseType as IntMathType<'ctx>>::PtrConvType as PointerMathType<'ctx>>::ValueType, BuilderError>
3316    {
3317        if self.positioned.get() != PositionState::Set {
3318            return Err(BuilderError::UnsetPosition);
3319        }
3320        let c_string = to_c_str(name);
3321
3322        let value = unsafe {
3323            LLVMBuildIntToPtr(
3324                self.builder,
3325                int.as_value_ref(),
3326                ptr_type.as_type_ref(),
3327                c_string.as_ptr(),
3328            )
3329        };
3330
3331        unsafe { Ok(<<T::BaseType as IntMathType>::PtrConvType as PointerMathType>::ValueType::new(value)) }
3332    }
3333
3334    // SubType: <I, P>(&self, ptr: &PointerValue<P>, int_type: &IntType<I>, name) -> IntValue<I> {
3335    pub fn build_ptr_to_int<T: PointerMathValue<'ctx>>(
3336        &self,
3337        ptr: T,
3338        int_type: <T::BaseType as PointerMathType<'ctx>>::PtrConvType,
3339        name: &str,
3340    ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>
3341    {
3342        if self.positioned.get() != PositionState::Set {
3343            return Err(BuilderError::UnsetPosition);
3344        }
3345        let c_string = to_c_str(name);
3346
3347        let value = unsafe {
3348            LLVMBuildPtrToInt(
3349                self.builder,
3350                ptr.as_value_ref(),
3351                int_type.as_type_ref(),
3352                c_string.as_ptr(),
3353            )
3354        };
3355
3356        unsafe { Ok(<<T::BaseType as PointerMathType>::PtrConvType as IntMathType>::ValueType::new(value)) }
3357    }
3358
3359    pub fn clear_insertion_position(&self) {
3360        self.positioned.set(PositionState::NotSet);
3361        unsafe { LLVMClearInsertionPosition(self.builder) }
3362    }
3363
3364    // REVIEW: Returning InstructionValue is the safe move here; but if the value means something
3365    // (IE the result of the switch) it should probably return BasicValueEnum?
3366    // SubTypes: I think value and case values must be the same subtype (maybe). Case value might need to be constants
3367    pub fn build_switch(
3368        &self,
3369        value: IntValue<'ctx>,
3370        else_block: BasicBlock<'ctx>,
3371        cases: &[(IntValue<'ctx>, BasicBlock<'ctx>)],
3372    ) -> Result<InstructionValue<'ctx>, BuilderError> {
3373        if self.positioned.get() != PositionState::Set {
3374            return Err(BuilderError::UnsetPosition);
3375        }
3376        let switch_value = unsafe {
3377            LLVMBuildSwitch(
3378                self.builder,
3379                value.as_value_ref(),
3380                else_block.basic_block,
3381                cases.len() as u32,
3382            )
3383        };
3384
3385        for &(value, basic_block) in cases {
3386            unsafe { LLVMAddCase(switch_value, value.as_value_ref(), basic_block.basic_block) }
3387        }
3388
3389        unsafe { Ok(InstructionValue::new(switch_value)) }
3390    }
3391
3392    // SubTypes: condition can only be IntValue<bool> or VectorValue<IntValue<Bool>>
3393    pub fn build_select<BV: BasicValue<'ctx>, IMV: IntMathValue<'ctx>>(
3394        &self,
3395        condition: IMV,
3396        then: BV,
3397        else_: BV,
3398        name: &str,
3399    ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3400        if self.positioned.get() != PositionState::Set {
3401            return Err(BuilderError::UnsetPosition);
3402        }
3403        let c_string = to_c_str(name);
3404        let value = unsafe {
3405            LLVMBuildSelect(
3406                self.builder,
3407                condition.as_value_ref(),
3408                then.as_value_ref(),
3409                else_.as_value_ref(),
3410                c_string.as_ptr(),
3411            )
3412        };
3413
3414        unsafe { Ok(BasicValueEnum::new(value)) }
3415    }
3416
3417    // The unsafety of this function should be fixable with subtypes. See GH #32
3418    pub unsafe fn build_global_string(&self, value: &str, name: &str) -> Result<GlobalValue<'ctx>, BuilderError> {
3419        unsafe {
3420            if self.positioned.get() != PositionState::Set {
3421                return Err(BuilderError::UnsetPosition);
3422            }
3423            let c_string_value = to_c_str(value);
3424            let c_string_name = to_c_str(name);
3425            let value = LLVMBuildGlobalString(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr());
3426
3427            Ok(GlobalValue::new(value))
3428        }
3429    }
3430
3431    // REVIEW: Does this similar fn have the same issue build_global_string does? If so, mark as unsafe
3432    // and fix with subtypes.
3433    pub fn build_global_string_ptr(&self, value: &str, name: &str) -> Result<GlobalValue<'ctx>, BuilderError> {
3434        if self.positioned.get() != PositionState::Set {
3435            return Err(BuilderError::UnsetPosition);
3436        }
3437        let c_string_value = to_c_str(value);
3438        let c_string_name = to_c_str(name);
3439        let value = unsafe { LLVMBuildGlobalStringPtr(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr()) };
3440
3441        unsafe { Ok(GlobalValue::new(value)) }
3442    }
3443
3444    // REVIEW: Do we need to constrain types here? subtypes?
3445    pub fn build_shuffle_vector<V: VectorBaseValue<'ctx>>(
3446        &self,
3447        left: V,
3448        right: V,
3449        mask: V,
3450        name: &str,
3451    ) -> Result<V, BuilderError> {
3452        if self.positioned.get() != PositionState::Set {
3453            return Err(BuilderError::UnsetPosition);
3454        }
3455        let c_string = to_c_str(name);
3456        let value = unsafe {
3457            LLVMBuildShuffleVector(
3458                self.builder,
3459                left.as_value_ref(),
3460                right.as_value_ref(),
3461                mask.as_value_ref(),
3462                c_string.as_ptr(),
3463            )
3464        };
3465
3466        unsafe { Ok(V::new(value)) }
3467    }
3468
3469    // REVIEW: Is return type correct?
3470    // SubTypes: I think this should be type: BT -> BT::Value
3471    // https://llvm.org/docs/LangRef.html#i-va-arg
3472    pub fn build_va_arg<BT: BasicType<'ctx>>(
3473        &self,
3474        list: PointerValue<'ctx>,
3475        type_: BT,
3476        name: &str,
3477    ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3478        if self.positioned.get() != PositionState::Set {
3479            return Err(BuilderError::UnsetPosition);
3480        }
3481        let c_string = to_c_str(name);
3482
3483        let value = unsafe {
3484            LLVMBuildVAArg(
3485                self.builder,
3486                list.as_value_ref(),
3487                type_.as_type_ref(),
3488                c_string.as_ptr(),
3489            )
3490        };
3491
3492        unsafe { Ok(BasicValueEnum::new(value)) }
3493    }
3494
3495    /// Builds an atomicrmw instruction. It allows you to atomically modify memory.
3496    ///
3497    /// May return of the following errors:
3498    /// - `Err(BuilderError::BitwidthError)` if the bitwidth of the value is not a power of 2 and less than 8
3499    /// - `Err(BuilderError:PointeeTypeMismatch)` if the pointee type does not match the value's type
3500    ///
3501    /// # Example
3502    ///
3503    /// ```
3504    /// use inkwell::context::Context;
3505    /// use inkwell::{AddressSpace, AtomicOrdering, AtomicRMWBinOp};
3506    /// let context = Context::create();
3507    /// let module = context.create_module("rmw");
3508    /// let void_type = context.void_type();
3509    /// let i32_type = context.i32_type();
3510    /// let i32_seven = i32_type.const_int(7, false);
3511    /// #[cfg(feature = "typed-pointers")]
3512    /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
3513    /// #[cfg(not(feature = "typed-pointers"))]
3514    /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
3515    /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
3516    /// let fn_value = module.add_function("rmw", fn_type, None);
3517    /// let entry = context.append_basic_block(fn_value, "entry");
3518    /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
3519    /// let builder = context.create_builder();
3520    /// builder.position_at_end(entry);
3521    /// #[cfg(any(feature = "llvm21-1", feature = "llvm22-1"))]
3522    /// builder.build_atomicrmw(AtomicRMWBinOp::Add, i32_ptr_param, i32_seven, AtomicOrdering::Monotonic).unwrap();
3523    /// #[cfg(not(any(feature = "llvm21-1", feature = "llvm22-1")))]
3524    /// builder.build_atomicrmw(AtomicRMWBinOp::Add, i32_ptr_param, i32_seven, AtomicOrdering::AcquireRelease).unwrap();
3525    /// builder.build_return(None).unwrap();
3526    /// ```
3527    // https://llvm.org/docs/LangRef.html#atomicrmw-instruction
3528    pub fn build_atomicrmw(
3529        &self,
3530        op: AtomicRMWBinOp,
3531        ptr: PointerValue<'ctx>,
3532        value: IntValue<'ctx>,
3533        ordering: AtomicOrdering,
3534    ) -> Result<IntValue<'ctx>, BuilderError> {
3535        if self.positioned.get() != PositionState::Set {
3536            return Err(BuilderError::UnsetPosition);
3537        }
3538        // TODO: add support for fadd, fsub and xchg on floating point types in LLVM 9+.
3539
3540        // "The type of ‘<value>’ must be an integer type whose bit width is a power of two greater than or equal to eight and less than or equal to a target-specific size limit. The type of the ‘<pointer>’ operand must be a pointer to that type." -- https://releases.llvm.org/3.6.2/docs/LangRef.html#atomicrmw-instruction
3541        if value.get_type().get_bit_width() < 8 || !value.get_type().get_bit_width().is_power_of_two() {
3542            return Err(BuilderError::BitwidthError);
3543        }
3544
3545        #[cfg(feature = "typed-pointers")]
3546        if ptr.get_type().get_element_type() != value.get_type().into() {
3547            return Err(BuilderError::PointeeTypeMismatch);
3548        }
3549
3550        // "This ordering [unordered] cannot be specified for read-modify-write operations."
3551        match ordering {
3552            AtomicOrdering::NotAtomic | AtomicOrdering::Unordered => {
3553                return Err(BuilderError::AtomicOrdering(AtomicError::InvalidOrderingOnAtomicRMW));
3554            },
3555            _ => {},
3556        }
3557
3558        let val = unsafe {
3559            LLVMBuildAtomicRMW(
3560                self.builder,
3561                op.into(),
3562                ptr.as_value_ref(),
3563                value.as_value_ref(),
3564                ordering.into(),
3565                false as i32,
3566            )
3567        };
3568
3569        unsafe { Ok(IntValue::new(val)) }
3570    }
3571
3572    /// Builds a [`cmpxchg`](https://llvm.org/docs/LangRef.html#cmpxchg-instruction) instruction.
3573    ///
3574    /// This instruction allows to atomically compare and replace memory.
3575    ///
3576    /// May return one of the following errors:
3577    /// - `Err(BuilderError::PointeeTypeMismatch)` if the pointer does not point to an element of the value type
3578    /// - `Err(BuilderError::ValueTypeMismatch)` if the value to compare and the new values are not of the same type, or if
3579    ///   the value does not have a pointer or integer type
3580    /// - `Err(BuilderError::OrderingError)` if the following conditions are not satisfied:
3581    ///     - Both success and failure orderings are not Monotonic or stronger
3582    ///     - The failure ordering is stronger than the success ordering
3583    ///     - The failure ordering is release or acquire release
3584    ///
3585    /// # Example
3586    ///
3587    /// ```
3588    /// use inkwell::context::Context;
3589    /// use inkwell::{AddressSpace, AtomicOrdering};
3590    /// let context = Context::create();
3591    /// let module = context.create_module("cmpxchg");
3592    /// let void_type = context.void_type();
3593    /// let i32_type = context.i32_type();
3594    /// #[cfg(feature = "typed-pointers")]
3595    /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
3596    /// #[cfg(not(feature = "typed-pointers"))]
3597    /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
3598    /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
3599    /// let fn_value = module.add_function("", fn_type, None);
3600    /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
3601    /// let i32_seven = i32_type.const_int(7, false);
3602    /// let i32_eight = i32_type.const_int(8, false);
3603    /// let entry = context.append_basic_block(fn_value, "entry");
3604    /// let builder = context.create_builder();
3605    /// builder.position_at_end(entry);
3606    /// builder.build_cmpxchg(i32_ptr_param, i32_seven, i32_eight, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic).unwrap();
3607    /// builder.build_return(None).unwrap();
3608    /// ```
3609    pub fn build_cmpxchg<V: BasicValue<'ctx>>(
3610        &self,
3611        ptr: PointerValue<'ctx>,
3612        cmp: V,
3613        new: V,
3614        success: AtomicOrdering,
3615        failure: AtomicOrdering,
3616    ) -> Result<StructValue<'ctx>, BuilderError> {
3617        if self.positioned.get() != PositionState::Set {
3618            return Err(BuilderError::UnsetPosition);
3619        }
3620        let cmp = cmp.as_basic_value_enum();
3621        let new = new.as_basic_value_enum();
3622        if cmp.get_type() != new.get_type() {
3623            return Err(BuilderError::NotSameType);
3624        }
3625        if !cmp.is_int_value() && !cmp.is_pointer_value() {
3626            return Err(BuilderError::NotPointerOrInteger);
3627        }
3628
3629        #[cfg(feature = "typed-pointers")]
3630        if ptr.get_type().get_element_type().as_basic_type_enum() != cmp.get_type() {
3631            return Err(BuilderError::PointeeTypeMismatch);
3632        }
3633
3634        // "Both ordering parameters must be at least monotonic, the ordering constraint on failure must be no stronger than that on success, and the failure ordering cannot be either release or acq_rel." -- https://llvm.org/docs/LangRef.html#cmpxchg-instruction
3635        if success < AtomicOrdering::Monotonic || failure < AtomicOrdering::Monotonic {
3636            return Err(BuilderError::CmpxchgOrdering(CmpxchgOrderingError::WeakerThanMonotic));
3637        }
3638        if failure > success {
3639            return Err(BuilderError::CmpxchgOrdering(
3640                CmpxchgOrderingError::WeakerSuccessOrdering,
3641            ));
3642        }
3643        if failure == AtomicOrdering::Release || failure == AtomicOrdering::AcquireRelease {
3644            return Err(BuilderError::CmpxchgOrdering(CmpxchgOrderingError::ReleaseOrAcqRel));
3645        }
3646
3647        let val = unsafe {
3648            LLVMBuildAtomicCmpXchg(
3649                self.builder,
3650                ptr.as_value_ref(),
3651                cmp.as_value_ref(),
3652                new.as_value_ref(),
3653                success.into(),
3654                failure.into(),
3655                false as i32,
3656            )
3657        };
3658
3659        unsafe { Ok(StructValue::new(val)) }
3660    }
3661
3662    /// Set the debug info source location of the instruction currently pointed at by the builder
3663    pub fn set_current_debug_location(&self, location: DILocation<'ctx>) {
3664        use llvm_sys::core::LLVMSetCurrentDebugLocation2;
3665        unsafe {
3666            LLVMSetCurrentDebugLocation2(self.builder, location.metadata_ref);
3667        }
3668    }
3669
3670    /// Get the debug info source location of the instruction currently pointed at by the builder,
3671    /// if available.
3672    pub fn get_current_debug_location(&self) -> Option<DILocation<'ctx>> {
3673        use llvm_sys::core::LLVMGetCurrentDebugLocation;
3674        use llvm_sys::core::LLVMValueAsMetadata;
3675        let metadata_ref = unsafe { LLVMGetCurrentDebugLocation(self.builder) };
3676        if metadata_ref.is_null() {
3677            return None;
3678        }
3679        Some(DILocation {
3680            metadata_ref: unsafe { LLVMValueAsMetadata(metadata_ref) },
3681            _marker: PhantomData,
3682        })
3683    }
3684
3685    /// Unset the debug info source location of the instruction currently pointed at by the
3686    /// builder. If there isn't any debug info, this is a no-op.
3687    pub fn unset_current_debug_location(&self) {
3688        use llvm_sys::core::LLVMSetCurrentDebugLocation2;
3689        unsafe {
3690            LLVMSetCurrentDebugLocation2(self.builder, std::ptr::null_mut());
3691        }
3692    }
3693}
3694
3695/// Used by build_memcpy and build_memmove
3696fn is_alignment_ok(align: u32) -> bool {
3697    // This replicates the assertions LLVM runs.
3698    //
3699    // See https://github.com/TheDan64/inkwell/issues/168
3700    // is_power_of_two returns false for 0.
3701    align.is_power_of_two()
3702}
3703
3704impl Drop for Builder<'_> {
3705    fn drop(&mut self) {
3706        unsafe {
3707            LLVMDisposeBuilder(self.builder);
3708        }
3709    }
3710}