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