llvm_plugin_inkwell/
builder.rs

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