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