Skip to main content

pliron_llvm/llvm_sys/
core.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) The pliron contributors
3
4//! Safe(r) wrappers around llvm_sys::core.
5
6use std::{
7    fmt::{self, Display, Formatter},
8    mem::MaybeUninit,
9    ptr,
10};
11
12use llvm_sys::{
13    LLVMFastMathAllowContract, LLVMFastMathAllowReassoc, LLVMFastMathAllowReciprocal,
14    LLVMFastMathApproxFunc, LLVMFastMathFlags, LLVMFastMathNoInfs, LLVMFastMathNoNaNs,
15    LLVMFastMathNoSignedZeros, LLVMFastMathNone, LLVMIntPredicate, LLVMLinkage, LLVMOpcode,
16    LLVMRealPredicate, LLVMTypeKind, LLVMValueKind,
17    analysis::LLVMVerifyModule,
18    bit_writer::LLVMWriteBitcodeToFile,
19    core::{
20        LLVMAddCase, LLVMAddDestination, LLVMAddFunction, LLVMAddGlobal,
21        LLVMAddGlobalInAddressSpace, LLVMAddIncoming, LLVMAppendBasicBlockInContext,
22        LLVMArrayType2, LLVMBasicBlockAsValue, LLVMBlockAddress, LLVMBuildAShr, LLVMBuildAdd,
23        LLVMBuildAddrSpaceCast, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildBitCast, LLVMBuildBr,
24        LLVMBuildCall2, LLVMBuildCondBr, LLVMBuildExtractElement, LLVMBuildExtractValue,
25        LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFPExt,
26        LLVMBuildFPToSI, LLVMBuildFPToUI, LLVMBuildFPTrunc, LLVMBuildFRem, LLVMBuildFSub,
27        LLVMBuildFreeze, LLVMBuildGEP2, LLVMBuildICmp, LLVMBuildIndirectBr, LLVMBuildInsertElement,
28        LLVMBuildInsertValue, LLVMBuildIntToPtr, LLVMBuildLShr, LLVMBuildLoad2, LLVMBuildMul,
29        LLVMBuildOr, LLVMBuildPhi, LLVMBuildPtrToInt, LLVMBuildRet, LLVMBuildRetVoid,
30        LLVMBuildSDiv, LLVMBuildSExt, LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect,
31        LLVMBuildShl, LLVMBuildShuffleVector, LLVMBuildStore, LLVMBuildSub, LLVMBuildSwitch,
32        LLVMBuildTrunc, LLVMBuildUDiv, LLVMBuildUIToFP, LLVMBuildURem, LLVMBuildUnreachable,
33        LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt, LLVMCanValueUseFastMathFlags,
34        LLVMClearInsertionPosition, LLVMConstInt, LLVMConstIntGetZExtValue, LLVMConstNull,
35        LLVMConstReal, LLVMConstRealGetDouble, LLVMConstVector, LLVMContextCreate,
36        LLVMContextDispose, LLVMCountIncoming, LLVMCountParamTypes, LLVMCountParams,
37        LLVMCountStructElementTypes, LLVMCreateBuilderInContext,
38        LLVMCreateMemoryBufferWithContentsOfFile, LLVMCreateMemoryBufferWithMemoryRangeCopy,
39        LLVMDeleteFunction, LLVMDeleteGlobal, LLVMDisposeMemoryBuffer, LLVMDisposeMessage,
40        LLVMDisposeModule, LLVMDoubleTypeInContext, LLVMDumpModule, LLVMDumpType, LLVMDumpValue,
41        LLVMFloatTypeInContext, LLVMFunctionType, LLVMGetAggregateElement, LLVMGetAlignment,
42        LLVMGetAllocatedType, LLVMGetArrayLength2, LLVMGetBasicBlockName, LLVMGetBasicBlockParent,
43        LLVMGetBasicBlockTerminator, LLVMGetBlockAddressBasicBlock, LLVMGetBlockAddressFunction,
44        LLVMGetCalledFunctionType, LLVMGetCalledValue, LLVMGetConstOpcode, LLVMGetElementType,
45        LLVMGetFCmpPredicate, LLVMGetFastMathFlags, LLVMGetFirstBasicBlock, LLVMGetFirstFunction,
46        LLVMGetFirstGlobal, LLVMGetFirstInstruction, LLVMGetFirstParam,
47        LLVMGetGEPSourceElementType, LLVMGetICmpPredicate, LLVMGetIncomingBlock,
48        LLVMGetIncomingValue, LLVMGetIndices, LLVMGetInitializer, LLVMGetInsertBlock,
49        LLVMGetInstructionOpcode, LLVMGetInstructionParent, LLVMGetIntTypeWidth,
50        LLVMGetIntrinsicDeclaration, LLVMGetLastFunction, LLVMGetLastGlobal, LLVMGetLinkage,
51        LLVMGetMaskValue, LLVMGetModuleIdentifier, LLVMGetNNeg, LLVMGetNSW, LLVMGetNUW,
52        LLVMGetNamedFunction, LLVMGetNamedGlobal, LLVMGetNextBasicBlock, LLVMGetNextFunction,
53        LLVMGetNextGlobal, LLVMGetNextInstruction, LLVMGetNextParam, LLVMGetNumArgOperands,
54        LLVMGetNumIndices, LLVMGetNumMaskElements, LLVMGetNumOperands, LLVMGetOperand,
55        LLVMGetParam, LLVMGetParamTypes, LLVMGetPointerAddressSpace, LLVMGetPoison,
56        LLVMGetPreviousBasicBlock, LLVMGetPreviousFunction, LLVMGetPreviousGlobal,
57        LLVMGetPreviousInstruction, LLVMGetPreviousParam, LLVMGetReturnType,
58        LLVMGetStructElementTypes, LLVMGetStructName, LLVMGetSwitchCaseValue, LLVMGetTypeKind,
59        LLVMGetUndef, LLVMGetUndefMaskElem, LLVMGetValueKind, LLVMGetValueName2, LLVMGetVectorSize,
60        LLVMGlobalGetValueType, LLVMHalfTypeInContext, LLVMInstructionEraseFromParent,
61        LLVMIntTypeInContext, LLVMIntrinsicIsOverloaded, LLVMIsAFunction, LLVMIsATerminatorInst,
62        LLVMIsAUser, LLVMIsDeclaration, LLVMIsFunctionVarArg, LLVMIsOpaqueStruct,
63        LLVMLookupIntrinsicID, LLVMModuleCreateWithNameInContext, LLVMPointerTypeInContext,
64        LLVMPositionBuilderAtEnd, LLVMPositionBuilderBefore, LLVMPrintModuleToFile,
65        LLVMPrintModuleToString, LLVMPrintTypeToString, LLVMPrintValueToString,
66        LLVMReplaceAllUsesWith, LLVMScalableVectorType, LLVMSetAlignment, LLVMSetFastMathFlags,
67        LLVMSetInitializer, LLVMSetLinkage, LLVMSetNNeg, LLVMStructCreateNamed, LLVMStructSetBody,
68        LLVMStructTypeInContext, LLVMTypeIsSized, LLVMTypeOf, LLVMValueAsBasicBlock,
69        LLVMValueIsBasicBlock, LLVMVectorType, LLVMVoidTypeInContext,
70    },
71    error::{LLVMDisposeErrorMessage, LLVMErrorRef, LLVMGetErrorMessage},
72    prelude::{
73        LLVMBasicBlockRef, LLVMBuilderRef, LLVMContextRef, LLVMMemoryBufferRef, LLVMModuleRef,
74        LLVMTypeRef, LLVMValueRef,
75    },
76};
77
78use crate::llvm_sys::{
79    ToBool, c_array_to_vec, cstr_to_string, sized_cstr_to_string, to_c_str, uninitialized_vec,
80};
81
82use crate::attributes::FastmathFlags;
83
84/// Opaque wrapper around LLVMValueRef to hide the raw pointer
85#[derive(Clone, Copy, PartialEq, Eq, Hash)]
86pub struct LLVMValue(LLVMValueRef);
87
88impl From<LLVMValueRef> for LLVMValue {
89    fn from(value: LLVMValueRef) -> Self {
90        LLVMValue(value)
91    }
92}
93
94impl From<LLVMValue> for LLVMValueRef {
95    fn from(value: LLVMValue) -> Self {
96        value.0
97    }
98}
99
100impl Display for LLVMValue {
101    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
102        if let Some(s) = llvm_print_value_to_string(*self) {
103            write!(f, "{}", s)
104        } else {
105            write!(f, "<Error printing LLVMValue at {:p}>", self.0)
106        }
107    }
108}
109
110/// Opaque wrapper around LLVMTypeRef to hide the raw pointer
111#[derive(Clone, Copy, PartialEq, Eq, Hash)]
112pub struct LLVMType(LLVMTypeRef);
113
114impl From<LLVMTypeRef> for LLVMType {
115    fn from(ty: LLVMTypeRef) -> Self {
116        LLVMType(ty)
117    }
118}
119
120impl From<LLVMType> for LLVMTypeRef {
121    fn from(ty: LLVMType) -> Self {
122        ty.0
123    }
124}
125
126impl Display for LLVMType {
127    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
128        if let Some(s) = llvm_print_type_to_string(*self) {
129            write!(f, "{}", s)
130        } else {
131            write!(f, "<Error printing LLVMType at {:p}>", self.0)
132        }
133    }
134}
135
136// We wrap LLVMContext in a module to limit its visibility for constructing
137mod llvm_context {
138    use super::*;
139
140    /// Managed LLVMContext
141    pub struct LLVMContext(LLVMContextRef);
142
143    impl Default for LLVMContext {
144        fn default() -> Self {
145            unsafe { LLVMContext(LLVMContextCreate()) }
146        }
147    }
148
149    impl Drop for LLVMContext {
150        fn drop(&mut self) {
151            unsafe { LLVMContextDispose(self.0) }
152        }
153    }
154
155    impl LLVMContext {
156        pub(super) fn inner_ref(&self) -> LLVMContextRef {
157            self.0
158        }
159    }
160}
161pub use llvm_context::LLVMContext;
162
163/// Opaque wrapper around LLVMBasicBlockRef to hide the raw pointer
164#[derive(Clone, Copy, PartialEq, Eq, Hash)]
165pub struct LLVMBasicBlock(LLVMBasicBlockRef);
166
167impl From<LLVMBasicBlockRef> for LLVMBasicBlock {
168    fn from(ty: LLVMBasicBlockRef) -> Self {
169        LLVMBasicBlock(ty)
170    }
171}
172
173impl From<LLVMBasicBlock> for LLVMBasicBlockRef {
174    fn from(ty: LLVMBasicBlock) -> Self {
175        ty.0
176    }
177}
178
179impl Display for LLVMBasicBlock {
180    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
181        if let Some(s) = llvm_print_value_to_string(LLVMValue(self.0 as LLVMValueRef)) {
182            write!(f, "{}", s)
183        } else {
184            write!(f, "<Error printing LLVMBasicBlock at {:p}>", self.0)
185        }
186    }
187}
188
189mod llvm_builder {
190
191    use llvm_sys::core::LLVMDisposeBuilder;
192
193    use super::*;
194    /// Managed LLVMBuilder.
195    pub struct LLVMBuilder(LLVMBuilderRef);
196
197    impl LLVMBuilder {
198        /// Create a new LLVMBuilder in the given context.
199        pub fn new(context: &LLVMContext) -> Self {
200            unsafe { LLVMBuilder(LLVMCreateBuilderInContext(context.inner_ref())) }
201        }
202
203        /// Get the inner LLVMBuilderRef
204        pub(crate) fn inner_ref(&self) -> LLVMBuilderRef {
205            self.0
206        }
207    }
208
209    impl Drop for LLVMBuilder {
210        fn drop(&mut self) {
211            unsafe { LLVMDisposeBuilder(self.0) }
212        }
213    }
214}
215
216pub use llvm_builder::LLVMBuilder;
217
218impl From<LLVMFastMathFlags> for FastmathFlags {
219    fn from(flags: LLVMFastMathFlags) -> Self {
220        let mut result = FastmathFlags::empty();
221        if flags & LLVMFastMathNoNaNs != 0 {
222            result |= FastmathFlags::NNAN;
223        }
224        if flags & LLVMFastMathNoInfs != 0 {
225            result |= FastmathFlags::NINF;
226        }
227        if flags & LLVMFastMathNoSignedZeros != 0 {
228            result |= FastmathFlags::NSZ;
229        }
230        if flags & LLVMFastMathAllowReciprocal != 0 {
231            result |= FastmathFlags::ARCP;
232        }
233        if flags & LLVMFastMathAllowContract != 0 {
234            result |= FastmathFlags::CONTRACT;
235        }
236        if flags & LLVMFastMathApproxFunc != 0 {
237            result |= FastmathFlags::AFN;
238        }
239        if flags & LLVMFastMathAllowReassoc != 0 {
240            result |= FastmathFlags::REASSOC;
241        }
242        result
243    }
244}
245
246impl From<FastmathFlags> for LLVMFastMathFlags {
247    fn from(flags: FastmathFlags) -> Self {
248        let mut result = LLVMFastMathNone;
249        if flags.contains(FastmathFlags::NNAN) {
250            result |= LLVMFastMathNoNaNs;
251        }
252        if flags.contains(FastmathFlags::NINF) {
253            result |= LLVMFastMathNoInfs;
254        }
255        if flags.contains(FastmathFlags::NSZ) {
256            result |= LLVMFastMathNoSignedZeros;
257        }
258        if flags.contains(FastmathFlags::ARCP) {
259            result |= LLVMFastMathAllowReciprocal;
260        }
261        if flags.contains(FastmathFlags::CONTRACT) {
262            result |= LLVMFastMathAllowContract;
263        }
264        if flags.contains(FastmathFlags::AFN) {
265            result |= LLVMFastMathApproxFunc;
266        }
267        if flags.contains(FastmathFlags::REASSOC) {
268            result |= LLVMFastMathAllowReassoc;
269        }
270        result
271    }
272}
273
274/// LLVMPrintValueToString
275pub fn llvm_print_value_to_string(val: LLVMValue) -> Option<String> {
276    let buf_ptr = unsafe { LLVMPrintValueToString(val.into()) };
277    if buf_ptr.is_null() {
278        return None;
279    }
280    let result = cstr_to_string(buf_ptr);
281    unsafe { LLVMDisposeMessage(buf_ptr) };
282    result
283}
284
285/// LLVMPrintTypeToString
286pub fn llvm_print_type_to_string(ty: LLVMType) -> Option<String> {
287    let buf_ptr = unsafe { LLVMPrintTypeToString(ty.into()) };
288    if buf_ptr.is_null() {
289        return None;
290    }
291    let result = cstr_to_string(buf_ptr);
292    unsafe { LLVMDisposeMessage(buf_ptr) };
293    result
294}
295
296/// LLVMPrintModuleToString
297pub fn llvm_print_module_to_string(module: &LLVMModule) -> Option<String> {
298    let buf_ptr = unsafe { LLVMPrintModuleToString(module.inner_ref()) };
299    if buf_ptr.is_null() {
300        return None;
301    }
302    let result = cstr_to_string(buf_ptr);
303    unsafe { LLVMDisposeMessage(buf_ptr) };
304    result
305}
306
307/// LLVMGetValueName2
308pub fn llvm_get_value_name(val: LLVMValue) -> Option<String> {
309    let mut len = 0;
310    let buf_ptr = unsafe { LLVMGetValueName2(val.into(), &mut len) };
311    if buf_ptr.is_null() {
312        return None;
313    }
314    sized_cstr_to_string(buf_ptr, len)
315}
316
317/// LLVMGetModuleIdentifier
318pub fn llvm_get_module_identifier(module: &LLVMModule) -> Option<String> {
319    let mut len = 0;
320    let buf_ptr = unsafe { LLVMGetModuleIdentifier(module.inner_ref(), &mut len) };
321    if buf_ptr.is_null() {
322        return None;
323    }
324    sized_cstr_to_string(buf_ptr, len)
325}
326
327/// LLVMDumpValue
328pub fn llvm_dump_value(val: LLVMValue) {
329    unsafe { LLVMDumpValue(val.into()) }
330}
331
332/// LLVMDumpType
333pub fn llvm_dump_type(ty: LLVMType) {
334    unsafe { LLVMDumpType(ty.into()) }
335}
336
337/// LLVMDumpModule
338pub fn llvm_dump_module(module: &LLVMModule) {
339    unsafe { LLVMDumpModule(module.inner_ref()) }
340}
341
342/// The family of LLVMIsA* functions for Value
343pub mod llvm_is_a {
344    use llvm_sys::core::{
345        LLVMIsAAllocaInst, LLVMIsAArgument, LLVMIsABlockAddress, LLVMIsACallInst, LLVMIsAConstant,
346        LLVMIsAConstantExpr, LLVMIsAConstantFP, LLVMIsAConstantInt, LLVMIsAExtractElementInst,
347        LLVMIsAExtractValueInst, LLVMIsAFCmpInst, LLVMIsAFPToUIInst, LLVMIsAGetElementPtrInst,
348        LLVMIsAGlobalValue, LLVMIsAGlobalVariable, LLVMIsAICmpInst, LLVMIsAIndirectBrInst,
349        LLVMIsAInsertElementInst, LLVMIsAInsertValueInst, LLVMIsAInstruction, LLVMIsAInvokeInst,
350        LLVMIsALoadInst, LLVMIsAPHINode, LLVMIsAShuffleVectorInst, LLVMIsAStoreInst,
351        LLVMIsASwitchInst, LLVMIsAUIToFPInst, LLVMIsAZExtInst,
352    };
353
354    use super::*;
355
356    /// LLVMIsAFunction
357    pub fn function(val: LLVMValue) -> bool {
358        unsafe { !LLVMIsAFunction(val.into()).is_null() }
359    }
360
361    /// LLVMIsAUser
362    pub fn user(val: LLVMValue) -> bool {
363        unsafe { !LLVMIsAUser(val.into()).is_null() }
364    }
365
366    /// LLVMIsAConsant
367    pub fn constant(val: LLVMValue) -> bool {
368        unsafe { !LLVMIsAConstant(val.into()).is_null() }
369    }
370
371    /// LLVMIsAInstruction
372    pub fn instruction(val: LLVMValue) -> bool {
373        unsafe { !LLVMIsAInstruction(val.into()).is_null() }
374    }
375
376    /// LLVMIsAConstantInt
377    pub fn constant_int(val: LLVMValue) -> bool {
378        unsafe { !LLVMIsAConstantInt(val.into()).is_null() }
379    }
380
381    /// LLVMIsAConstantFP
382    pub fn constant_fp(val: LLVMValue) -> bool {
383        unsafe { !LLVMIsAConstantFP(val.into()).is_null() }
384    }
385
386    /// LLVMIsAConstantExpr
387    pub fn constant_expr(val: LLVMValue) -> bool {
388        unsafe { !LLVMIsAConstantExpr(val.into()).is_null() }
389    }
390
391    /// LLVMIsAPHINode
392    pub fn phi_node(val: LLVMValue) -> bool {
393        unsafe { !LLVMIsAPHINode(val.into()).is_null() }
394    }
395
396    /// LLVMIsAAllocaInst
397    pub fn alloca_inst(val: LLVMValue) -> bool {
398        unsafe { !LLVMIsAAllocaInst(val.into()).is_null() }
399    }
400
401    /// LLVMIsAICmpInst
402    pub fn icmp_inst(val: LLVMValue) -> bool {
403        unsafe { !LLVMIsAICmpInst(val.into()).is_null() }
404    }
405
406    /// LLVMIsAFCmpInst
407    pub fn fcmp_inst(val: LLVMValue) -> bool {
408        unsafe { !LLVMIsAFCmpInst(val.into()).is_null() }
409    }
410
411    /// LLVMIsAZExtInst
412    pub fn zext_inst(val: LLVMValue) -> bool {
413        unsafe { !LLVMIsAZExtInst(val.into()).is_null() }
414    }
415
416    /// LLVMIsAFPToUIInst
417    pub fn fptoui_inst(val: LLVMValue) -> bool {
418        unsafe { !LLVMIsAFPToUIInst(val.into()).is_null() }
419    }
420
421    /// LLVMIsAUIToFPInst
422    pub fn uitofp_inst(val: LLVMValue) -> bool {
423        unsafe { !LLVMIsAUIToFPInst(val.into()).is_null() }
424    }
425
426    /// LLVMIsASwitchInst
427    pub fn switch_inst(val: LLVMValue) -> bool {
428        unsafe { !LLVMIsASwitchInst(val.into()).is_null() }
429    }
430
431    /// LLVMIsAIndirectBrInst
432    pub fn indirect_br_inst(val: LLVMValue) -> bool {
433        unsafe { !LLVMIsAIndirectBrInst(val.into()).is_null() }
434    }
435
436    /// LLVMIsAArgument
437    pub fn argument(val: LLVMValue) -> bool {
438        unsafe { !LLVMIsAArgument(val.into()).is_null() }
439    }
440
441    /// LLVMIsAGlobalValue
442    pub fn global_value(val: LLVMValue) -> bool {
443        unsafe { !LLVMIsAGlobalValue(val.into()).is_null() }
444    }
445
446    /// LLVMIsAGlobalVariable
447    pub fn global_variable(val: LLVMValue) -> bool {
448        unsafe { !LLVMIsAGlobalVariable(val.into()).is_null() }
449    }
450
451    /// LLVMIsACallInst
452    pub fn call_inst(val: LLVMValue) -> bool {
453        unsafe { !LLVMIsACallInst(val.into()).is_null() }
454    }
455
456    /// LLVMIsAInvokeInst
457    pub fn invoke_inst(val: LLVMValue) -> bool {
458        unsafe { !LLVMIsAInvokeInst(val.into()).is_null() }
459    }
460
461    /// LLVMIsAGetElementPtrInst
462    pub fn get_element_ptr_inst(val: LLVMValue) -> bool {
463        unsafe { !LLVMIsAGetElementPtrInst(val.into()).is_null() }
464    }
465
466    /// LLVMIsAInsertValueInst
467    pub fn insert_value_inst(val: LLVMValue) -> bool {
468        unsafe { !LLVMIsAInsertValueInst(val.into()).is_null() }
469    }
470
471    /// LLVMIsAExtractValueInst
472    pub fn extract_value_inst(val: LLVMValue) -> bool {
473        unsafe { !LLVMIsAExtractValueInst(val.into()).is_null() }
474    }
475
476    /// LLVMIsAShuffleVectorInst
477    pub fn shuffle_vector_inst(val: LLVMValue) -> bool {
478        unsafe { !LLVMIsAShuffleVectorInst(val.into()).is_null() }
479    }
480
481    /// LLVMIsAInsertElementInst
482    pub fn insert_element_inst(val: LLVMValue) -> bool {
483        unsafe { !LLVMIsAInsertElementInst(val.into()).is_null() }
484    }
485
486    /// LLVMIsAExtractElementInst
487    pub fn extract_element_inst(val: LLVMValue) -> bool {
488        unsafe { !LLVMIsAExtractElementInst(val.into()).is_null() }
489    }
490
491    /// LLVMIsALoadInst
492    pub fn load_inst(val: LLVMValue) -> bool {
493        unsafe { !LLVMIsALoadInst(val.into()).is_null() }
494    }
495
496    /// LLVMIsAStoreInst
497    pub fn store_inst(val: LLVMValue) -> bool {
498        unsafe { !LLVMIsAStoreInst(val.into()).is_null() }
499    }
500
501    /// LLVMIsABlockAddress
502    pub fn block_address(val: LLVMValue) -> bool {
503        unsafe { !LLVMIsABlockAddress(val.into()).is_null() }
504    }
505}
506
507/// The family of LLVMIs* functions for Value
508pub mod llvm_is {
509    use llvm_sys::core::{LLVMIsConstant, LLVMIsPoison, LLVMIsUndef};
510
511    use super::*;
512
513    /// LLVMIsConstant
514    pub fn constant(val: LLVMValue) -> bool {
515        unsafe { !LLVMIsConstant(val.into()).to_bool() }
516    }
517
518    /// LLVMIsUndef
519    pub fn undef(val: LLVMValue) -> bool {
520        unsafe { !LLVMIsUndef(val.into()).to_bool() }
521    }
522
523    /// LLVMIsPoison
524    pub fn poison(val: LLVMValue) -> bool {
525        unsafe { !LLVMIsPoison(val.into()).to_bool() }
526    }
527}
528
529/// LLVMReplaceAllUsesWith
530pub fn llvm_replace_all_uses_with(old_val: LLVMValue, new_val: LLVMValue) {
531    unsafe { LLVMReplaceAllUsesWith(old_val.into(), new_val.into()) }
532}
533
534/// LLVMTypeOf
535pub fn llvm_type_of(val: LLVMValue) -> LLVMType {
536    unsafe { LLVMTypeOf(val.into()).into() }
537}
538
539/// LLVMGlobalGetValueType
540pub fn llvm_global_get_value_type(val: LLVMValue) -> LLVMType {
541    assert!(llvm_is_a::global_value(val));
542    unsafe { LLVMGlobalGetValueType(val.into()).into() }
543}
544
545/// LLVMGetGlobalParent
546pub fn llvm_get_global_parent(val: LLVMValue) -> Option<LLVMModule> {
547    assert!(llvm_is_a::global_value(val));
548    unimplemented!("Returning LLVMModule, which owns the underlying LLVMModuleRef is not safe");
549}
550
551/// LLVMGetNamedGlobal
552pub fn llvm_get_named_global(module: &LLVMModule, name: &str) -> Option<LLVMValue> {
553    let gv_ref = unsafe { LLVMGetNamedGlobal(module.inner_ref(), to_c_str(name).as_ptr()) };
554    (!gv_ref.is_null()).then_some(gv_ref.into())
555}
556
557/// LLVMIsDeclaration
558pub fn llvm_is_declaration(val: LLVMValue) -> bool {
559    assert!(llvm_is_a::global_value(val));
560    unsafe { LLVMIsDeclaration(val.into()).to_bool() }
561}
562
563/// LLVMTypeIsSized
564pub fn llvm_type_is_sized(ty: LLVMType) -> bool {
565    unsafe { LLVMTypeIsSized(ty.into()).to_bool() }
566}
567
568/// Type.h: isAggregateType()
569pub fn llvm_is_aggregate_type(ty: LLVMType) -> bool {
570    matches!(
571        llvm_get_type_kind(ty),
572        LLVMTypeKind::LLVMArrayTypeKind | LLVMTypeKind::LLVMStructTypeKind
573    )
574}
575
576/// LLVMGetTypeKind
577pub fn llvm_get_type_kind(ty: LLVMType) -> LLVMTypeKind {
578    unsafe { LLVMGetTypeKind(ty.into()) }
579}
580
581/// LLVMGetLinkage
582pub fn llvm_get_linkage(val: LLVMValue) -> LLVMLinkage {
583    unsafe { LLVMGetLinkage(val.into()) }
584}
585
586/// LLVMSetLinkage
587pub fn llvm_set_linkage(val: LLVMValue, linkage: LLVMLinkage) {
588    unsafe { LLVMSetLinkage(val.into(), linkage) }
589}
590
591/// LLVMVectorType
592pub fn llvm_vector_type(element_type: LLVMType, num_elems: u32) -> LLVMType {
593    assert!(llvm_is_valid_vector_element_type(element_type));
594    unsafe { LLVMVectorType(element_type.into(), num_elems).into() }
595}
596
597/// LLVMScalableVectorType
598pub fn llvm_scalable_vector_type(element_type: LLVMType, num_elems: u32) -> LLVMType {
599    assert!(llvm_is_valid_vector_element_type(element_type));
600    unsafe { LLVMScalableVectorType(element_type.into(), num_elems).into() }
601}
602
603/// LLVMGetVectorSize
604pub fn llvm_get_vector_size(ty: LLVMType) -> u32 {
605    assert!(matches!(
606        llvm_get_type_kind(ty),
607        LLVMTypeKind::LLVMVectorTypeKind | LLVMTypeKind::LLVMScalableVectorTypeKind
608    ));
609    unsafe { LLVMGetVectorSize(ty.into()) as u32 }
610}
611
612/// LLVMGetElementType
613pub fn llvm_get_element_type(ty: LLVMType) -> LLVMType {
614    assert!(matches!(
615        llvm_get_type_kind(ty),
616        LLVMTypeKind::LLVMArrayTypeKind
617            | LLVMTypeKind::LLVMVectorTypeKind
618            | LLVMTypeKind::LLVMScalableVectorTypeKind
619    ));
620    unsafe { LLVMGetElementType(ty.into()).into() }
621}
622
623/// VectorType::isValidElementType
624pub fn llvm_is_valid_vector_element_type(ty: LLVMType) -> bool {
625    matches!(
626        llvm_get_type_kind(ty),
627        LLVMTypeKind::LLVMIntegerTypeKind
628            | LLVMTypeKind::LLVMPointerTypeKind
629            | LLVMTypeKind::LLVMFloatTypeKind
630            | LLVMTypeKind::LLVMDoubleTypeKind
631            | LLVMTypeKind::LLVMHalfTypeKind
632            | LLVMTypeKind::LLVMFP128TypeKind
633            | LLVMTypeKind::LLVMPPC_FP128TypeKind
634            | LLVMTypeKind::LLVMX86_FP80TypeKind
635    )
636}
637
638/// LLVMGetArrayLength2
639pub fn llvm_get_array_length2(ty: LLVMType) -> u64 {
640    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMArrayTypeKind);
641    unsafe { LLVMGetArrayLength2(ty.into()) }
642}
643
644/// LLVMGetReturnType
645pub fn llvm_get_return_type(ty: LLVMType) -> LLVMType {
646    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
647    unsafe { LLVMGetReturnType(ty.into()).into() }
648}
649
650/// LLVMCountParamTypes
651pub fn llvm_count_param_types(ty: LLVMType) -> u32 {
652    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
653    unsafe { LLVMCountParamTypes(ty.into()) }
654}
655
656/// LLVMGetParamTypes
657pub fn llvm_get_param_types(ty: LLVMType) -> Vec<LLVMType> {
658    let params_count = llvm_count_param_types(ty) as usize;
659    unsafe {
660        let mut buffer = uninitialized_vec::<LLVMTypeRef>(params_count);
661        LLVMGetParamTypes(ty.into(), (*buffer.as_mut_ptr()).as_mut_ptr());
662        buffer.assume_init()
663    }
664    .into_iter()
665    .map(Into::into)
666    .collect()
667}
668
669/// LLVMIsFunctionVarArg
670pub fn llvm_is_function_type_var_arg(ty: LLVMType) -> bool {
671    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
672    unsafe { LLVMIsFunctionVarArg(ty.into()).to_bool() }
673}
674
675/// LLVMGetIntTypeWidth
676pub fn llvm_get_int_type_width(ty: LLVMType) -> u32 {
677    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMIntegerTypeKind);
678    unsafe { LLVMGetIntTypeWidth(ty.into()) }
679}
680
681/// LLVMGetPointerAddressSpace
682pub fn llvm_get_pointer_address_space(ty: LLVMType) -> u32 {
683    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMPointerTypeKind);
684    unsafe { LLVMGetPointerAddressSpace(ty.into()) }
685}
686
687/// LLVMIsOpaqueStruct
688pub fn llvm_is_opaque_struct(ty: LLVMType) -> bool {
689    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMStructTypeKind);
690    unsafe { LLVMIsOpaqueStruct(ty.into()) }.to_bool()
691}
692
693/// LLVMCountStructElementTypes
694pub fn llvm_count_struct_element_types(ty: LLVMType) -> u32 {
695    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMStructTypeKind);
696    unsafe { LLVMCountStructElementTypes(ty.into()) }
697}
698
699/// LLVMGetStructElementTypes
700pub fn llvm_get_struct_element_types(ty: LLVMType) -> Vec<LLVMType> {
701    let element_types_count = llvm_count_struct_element_types(ty) as usize;
702    unsafe {
703        let mut buffer = uninitialized_vec::<LLVMTypeRef>(element_types_count);
704        LLVMGetStructElementTypes(ty.into(), (*buffer.as_mut_ptr()).as_mut_ptr());
705        buffer.assume_init()
706    }
707    .into_iter()
708    .map(Into::into)
709    .collect()
710}
711
712/// LLVMGetStructName
713pub fn llvm_get_struct_name(ty: LLVMType) -> Option<String> {
714    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMStructTypeKind);
715    cstr_to_string(unsafe { LLVMGetStructName(ty.into()) })
716}
717
718/// LLVMIsATerminatorInst
719pub fn llvm_is_a_terminator_inst(val: LLVMValue) -> bool {
720    !unsafe { LLVMIsATerminatorInst(val.into()) }.is_null()
721}
722
723/// LLVMGetBasicBlockTerminator
724pub fn llvm_get_basic_block_terminator(bb: LLVMBasicBlock) -> Option<LLVMValue> {
725    let bbref = unsafe { LLVMGetBasicBlockTerminator(bb.into()) };
726    (!bbref.is_null()).then_some(bbref.into())
727}
728
729// LLVMGetValueKind
730pub fn llvm_get_value_kind(val: LLVMValue) -> LLVMValueKind {
731    unsafe { LLVMGetValueKind(val.into()) }
732}
733
734/// LLVMGetInstructionOpcode
735pub fn llvm_get_instruction_opcode(val: LLVMValue) -> LLVMOpcode {
736    assert!(llvm_get_value_kind(val) == LLVMValueKind::LLVMInstructionValueKind);
737    unsafe { LLVMGetInstructionOpcode(val.into()) }
738}
739
740/// LLVMGetConstOpcode
741pub fn llvm_get_const_opcode(val: LLVMValue) -> LLVMOpcode {
742    assert!(llvm_is_a::constant_expr(val));
743    unsafe { LLVMGetConstOpcode(val.into()) }
744}
745
746/// LLVMGetInstructionParent
747pub fn llvm_get_instruction_parent(inst: LLVMValue) -> Option<LLVMBasicBlock> {
748    assert!(llvm_is_a::instruction(inst));
749    unsafe {
750        let parent = LLVMGetInstructionParent(inst.into());
751        (!parent.is_null()).then_some(parent.into())
752    }
753}
754
755/// LLVMInstructionEraseFromParent
756pub fn llvm_instruction_erase_from_parent(inst: LLVMValue) {
757    assert!(llvm_is_a::instruction(inst));
758    unsafe { LLVMInstructionEraseFromParent(inst.into()) }
759}
760
761/// LLVMGetNumOperands
762pub fn llvm_get_num_operands(val: LLVMValue) -> u32 {
763    assert!(llvm_is_a::user(val));
764    unsafe { LLVMGetNumOperands(val.into()) as u32 }
765}
766
767/// LLVMGetOperand
768pub fn llvm_get_operand(val: LLVMValue, index: u32) -> LLVMValue {
769    assert!(index < llvm_get_num_operands(val));
770    unsafe { LLVMGetOperand(val.into(), index).into() }
771}
772
773/// LLVMGetAggregateElement
774pub fn llvm_get_aggregate_element(val: LLVMValue, index: u32) -> Option<LLVMValue> {
775    assert!(llvm_is_a::constant(val));
776    unsafe {
777        let elem = LLVMGetAggregateElement(val.into(), index);
778        (!elem.is_null()).then_some(elem.into())
779    }
780}
781
782/// LLVMBlockAddress
783pub fn llvm_block_address(function: LLVMValue, block: LLVMBasicBlock) -> LLVMValue {
784    assert!(llvm_is_a::function(function));
785    unsafe { LLVMBlockAddress(function.into(), block.into()).into() }
786}
787
788/// LLVMGetBlockAddressFunction
789pub fn llvm_get_block_address_function(val: LLVMValue) -> LLVMValue {
790    assert!(llvm_is_a::block_address(val));
791    unsafe { LLVMGetBlockAddressFunction(val.into()).into() }
792}
793
794/// LLVMGetBlockAddressBasicBlock
795pub fn llvm_get_block_address_basic_block(val: LLVMValue) -> LLVMBasicBlock {
796    assert!(llvm_is_a::block_address(val));
797    unsafe { LLVMGetBlockAddressBasicBlock(val.into()).into() }
798}
799
800/// LLVMBasicBlockAsValue
801pub fn llvm_basic_block_as_value(block: LLVMBasicBlock) -> LLVMValue {
802    unsafe { LLVMBasicBlockAsValue(block.into()).into() }
803}
804
805/// LLVMValueIsBasicBlock
806pub fn llvm_value_is_basic_block(val: LLVMValue) -> bool {
807    unsafe { LLVMValueIsBasicBlock(val.into()).to_bool() }
808}
809
810/// LLVMValueAsBasicBlock
811pub fn llvm_value_as_basic_block(val: LLVMValue) -> LLVMBasicBlock {
812    assert!(llvm_value_is_basic_block(val));
813    unsafe { LLVMValueAsBasicBlock(val.into()).into() }
814}
815
816/// LLVMGetBasicBlockName
817pub fn llvm_get_basic_block_name(block: LLVMBasicBlock) -> Option<String> {
818    cstr_to_string(unsafe { LLVMGetBasicBlockName(block.into()) })
819}
820
821/// LLVMGetBasicBlockParent
822pub fn llvm_get_basic_block_parent(block: LLVMBasicBlock) -> Option<LLVMValue> {
823    unsafe {
824        let parent = LLVMGetBasicBlockParent(block.into());
825        (!parent.is_null()).then_some(parent.into())
826    }
827}
828
829/// LLVMGetFirstBasicBlock
830pub fn llvm_get_first_basic_block(fn_val: LLVMValue) -> Option<LLVMBasicBlock> {
831    assert!(llvm_is_a::function(fn_val));
832    unsafe {
833        let first_block = LLVMGetFirstBasicBlock(fn_val.into());
834        (!first_block.is_null()).then_some(first_block.into())
835    }
836}
837
838/// LLVMGetNextBasicBlock
839pub fn llvm_get_next_basic_block(bb: LLVMBasicBlock) -> Option<LLVMBasicBlock> {
840    unsafe {
841        let next_block = LLVMGetNextBasicBlock(bb.into());
842        (!next_block.is_null()).then_some(next_block.into())
843    }
844}
845
846/// LLVMGetPreviousBasicBlock
847pub fn llvm_get_previous_basic_block(bb: LLVMBasicBlock) -> Option<LLVMBasicBlock> {
848    unsafe {
849        let prev_block = LLVMGetPreviousBasicBlock(bb.into());
850        (!prev_block.is_null()).then_some(prev_block.into())
851    }
852}
853
854/// Iterate over all `BasicBlock`s in a function.
855pub struct BasicBlockIter(pub Option<LLVMBasicBlock>);
856
857impl Iterator for BasicBlockIter {
858    type Item = LLVMBasicBlock;
859
860    fn next(&mut self) -> Option<Self::Item> {
861        if let Some(bb) = self.0 {
862            self.0 = llvm_get_next_basic_block(bb);
863            Some(bb)
864        } else {
865            None
866        }
867    }
868}
869
870/// Get an iterator over the basic blocks of a function.
871pub fn basic_block_iter(fn_val: LLVMValue) -> BasicBlockIter {
872    BasicBlockIter(llvm_get_first_basic_block(fn_val))
873}
874
875/// LLVMGetFirstInstruction
876pub fn llvm_get_first_instruction(bb: LLVMBasicBlock) -> Option<LLVMValue> {
877    unsafe {
878        let first_instr = LLVMGetFirstInstruction(bb.into());
879        (!first_instr.is_null()).then_some(first_instr.into())
880    }
881}
882
883/// LLVMGetNextInstruction
884pub fn llvm_get_next_instruction(instr: LLVMValue) -> Option<LLVMValue> {
885    assert!(llvm_is_a::instruction(instr));
886    unsafe {
887        let next_instr = LLVMGetNextInstruction(instr.into());
888        (!next_instr.is_null()).then_some(next_instr.into())
889    }
890}
891
892/// LLVMGetPreviousInstruction
893pub fn llvm_get_previous_instruction(instr: LLVMValue) -> Option<LLVMValue> {
894    assert!(llvm_is_a::instruction(instr));
895    unsafe {
896        let prev_instr = LLVMGetPreviousInstruction(instr.into());
897        (!prev_instr.is_null()).then_some(prev_instr.into())
898    }
899}
900
901/// Iterate over all `Instruction`s in a basic block.
902pub struct InstructionIter(pub Option<LLVMValue>);
903
904impl Iterator for InstructionIter {
905    type Item = LLVMValue;
906
907    fn next(&mut self) -> Option<Self::Item> {
908        if let Some(instr) = self.0 {
909            self.0 = llvm_get_next_instruction(instr);
910            Some(instr)
911        } else {
912            None
913        }
914    }
915}
916
917/// Get an iterator over the instructions of a basic block.
918pub fn instruction_iter(bb: LLVMBasicBlock) -> InstructionIter {
919    InstructionIter(llvm_get_first_instruction(bb))
920}
921
922/// LLVMCountIncoming
923pub fn llvm_count_incoming(phi_node: LLVMValue) -> u32 {
924    assert!(llvm_is_a::phi_node(phi_node));
925    unsafe { LLVMCountIncoming(phi_node.into()) }
926}
927
928/// LLVMGetIncomingValue
929pub fn llvm_get_incoming_value(phi_node: LLVMValue, index: u32) -> LLVMValue {
930    assert!(index < llvm_count_incoming(phi_node));
931    unsafe { LLVMGetIncomingValue(phi_node.into(), index).into() }
932}
933
934/// LLVMGetIncomingBlock
935pub fn llvm_get_incoming_block(phi_node: LLVMValue, index: u32) -> LLVMBasicBlock {
936    assert!(index < llvm_count_incoming(phi_node));
937    unsafe { LLVMGetIncomingBlock(phi_node.into(), index).into() }
938}
939
940/// Iterate over all the incoming edges of a phi value.
941pub struct IncomingIter {
942    phi_node: LLVMValue,
943    i: u32,
944    count: u32,
945}
946
947impl Iterator for IncomingIter {
948    type Item = (LLVMValue, LLVMBasicBlock);
949
950    fn next(&mut self) -> Option<Self::Item> {
951        if self.i < self.count {
952            let result = (
953                llvm_get_incoming_value(self.phi_node, self.i),
954                llvm_get_incoming_block(self.phi_node, self.i),
955            );
956            self.i += 1;
957            Some(result)
958        } else {
959            None
960        }
961    }
962}
963
964/// Get an incoming edge iterator.
965pub fn incoming_iter(phi_node: LLVMValue) -> IncomingIter {
966    IncomingIter {
967        phi_node,
968        i: 0,
969        count: llvm_count_incoming(phi_node),
970    }
971}
972
973/// LLVMConstVector
974pub fn llvm_const_vector(elements: &[LLVMValue]) -> LLVMValue {
975    assert!(elements.iter().all(|elem| llvm_is_a::constant(*elem)));
976    let mut elements = elements.iter().cloned().map(Into::into).collect::<Vec<_>>();
977    unsafe { LLVMConstVector(elements.as_mut_ptr(), elements.len().try_into().unwrap()).into() }
978}
979
980/// LLVMConstIntGetZExtValue
981pub fn llvm_const_int_get_zext_value(val: LLVMValue) -> u64 {
982    assert!(llvm_is_a::constant_int(val));
983    unsafe { LLVMConstIntGetZExtValue(val.into()) }
984}
985
986/// LLVMConstRealGetDouble
987pub fn llvm_const_real_get_double(val: LLVMValue) -> (f64, bool) {
988    assert!(llvm_is_a::constant_fp(val));
989    let mut loses_info = 0;
990    let result = unsafe { LLVMConstRealGetDouble(val.into(), &mut loses_info) };
991    (result, loses_info.to_bool())
992}
993
994/// LLVMConstReal
995pub fn llvm_const_real(ty: LLVMType, n: f64) -> LLVMValue {
996    assert!(
997        llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFloatTypeKind
998            || llvm_get_type_kind(ty) == LLVMTypeKind::LLVMDoubleTypeKind
999    );
1000    unsafe { LLVMConstReal(ty.into(), n).into() }
1001}
1002
1003/// LLVMConstNull
1004pub fn llvm_const_null(ty: LLVMType) -> LLVMValue {
1005    unsafe { LLVMConstNull(ty.into()).into() }
1006}
1007
1008/// LLVMGetAllocatedType
1009pub fn llvm_get_allocated_type(val: LLVMValue) -> LLVMType {
1010    assert!(llvm_is_a::alloca_inst(val));
1011    unsafe { LLVMGetAllocatedType(val.into()).into() }
1012}
1013
1014/// LLVMGetICmpPredicate
1015pub fn llvm_get_icmp_predicate(val: LLVMValue) -> LLVMIntPredicate {
1016    assert!(llvm_is_a::icmp_inst(val) || llvm_get_const_opcode(val) == LLVMOpcode::LLVMICmp);
1017    unsafe { LLVMGetICmpPredicate(val.into()) }
1018}
1019
1020/// LLVMGetFCmpPredicate
1021pub fn llvm_get_fcmp_predicate(val: LLVMValue) -> LLVMRealPredicate {
1022    assert!(llvm_is_a::fcmp_inst(val) || llvm_get_const_opcode(val) == LLVMOpcode::LLVMFCmp);
1023    unsafe { LLVMGetFCmpPredicate(val.into()) }
1024}
1025
1026/// LLVMGetNNeg
1027pub fn llvm_get_nneg(val: LLVMValue) -> bool {
1028    assert!(llvm_is_a::zext_inst(val) || llvm_is_a::uitofp_inst(val));
1029    unsafe { LLVMGetNNeg(val.into()).to_bool() }
1030}
1031
1032/// LLVMSetNNeg
1033pub fn llvm_set_nneg(val: LLVMValue, nneg: bool) {
1034    assert!(llvm_is_a::zext_inst(val) || llvm_is_a::uitofp_inst(val));
1035    unsafe { LLVMSetNNeg(val.into(), nneg.into()) }
1036}
1037
1038/// LLVMGetAlignment
1039pub fn llvm_get_alignment(val: LLVMValue) -> u32 {
1040    assert!(
1041        llvm_is_a::alloca_inst(val)
1042            || llvm_is_a::global_variable(val)
1043            || llvm_is_a::load_inst(val)
1044            || llvm_is_a::store_inst(val)
1045    );
1046    unsafe { LLVMGetAlignment(val.into()) }
1047}
1048
1049/// LLVMSetAlignment
1050pub fn llvm_set_alignment(val: LLVMValue, align: u32) {
1051    assert!(
1052        llvm_is_a::alloca_inst(val)
1053            || llvm_is_a::global_variable(val)
1054            || llvm_is_a::load_inst(val)
1055            || llvm_is_a::store_inst(val)
1056    );
1057    unsafe { LLVMSetAlignment(val.into(), align) }
1058}
1059
1060/// LLVMGetNumMaskElements
1061pub fn llvm_get_num_mask_elements(val: LLVMValue) -> u32 {
1062    assert!(llvm_is_a::shuffle_vector_inst(val));
1063    unsafe { LLVMGetNumMaskElements(val.into()) }
1064}
1065
1066/// LLVMGetUndefMaskElem
1067pub fn llvm_get_undef_mask_elem() -> i32 {
1068    unsafe { LLVMGetUndefMaskElem() }
1069}
1070
1071/// LLVMGetMaskValue
1072pub fn llvm_get_mask_value(val: LLVMValue, index: u32) -> i32 {
1073    assert!(index < llvm_get_num_mask_elements(val));
1074    unsafe { LLVMGetMaskValue(val.into(), index) }
1075}
1076
1077/// LLVMCountParams
1078pub fn llvm_count_params(func: LLVMValue) -> u32 {
1079    assert!(llvm_is_a::function(func));
1080    unsafe { LLVMCountParams(func.into()) }
1081}
1082
1083/// LLVMGetFirstParam
1084pub fn llvm_get_first_param(func: LLVMValue) -> Option<LLVMValue> {
1085    assert!(llvm_is_a::function(func));
1086    unsafe {
1087        let first_param = LLVMGetFirstParam(func.into());
1088        (!first_param.is_null()).then_some(first_param.into())
1089    }
1090}
1091
1092/// LLVMGetNextParam
1093pub fn llvm_get_next_param(val: LLVMValue) -> Option<LLVMValue> {
1094    assert!(llvm_is_a::argument(val));
1095    unsafe {
1096        let next_param = LLVMGetNextParam(val.into());
1097        (!next_param.is_null()).then_some(next_param.into())
1098    }
1099}
1100
1101/// LLVMGetPreviousParam
1102pub fn llvm_get_previous_param(val: LLVMValue) -> Option<LLVMValue> {
1103    assert!(llvm_is_a::argument(val));
1104    unsafe {
1105        let prev_param = LLVMGetPreviousParam(val.into());
1106        (!prev_param.is_null()).then_some(prev_param.into())
1107    }
1108}
1109
1110/// Iterate over all `Parameters`s of a `Function`.
1111pub struct ParamIter(pub Option<LLVMValue>);
1112
1113impl Iterator for ParamIter {
1114    type Item = LLVMValue;
1115
1116    fn next(&mut self) -> Option<Self::Item> {
1117        if let Some(param) = self.0 {
1118            self.0 = llvm_get_next_param(param);
1119            Some(param)
1120        } else {
1121            None
1122        }
1123    }
1124}
1125
1126/// Get an iterator over the parameters of a function.
1127pub fn param_iter(func: LLVMValue) -> ParamIter {
1128    assert!(llvm_is_a::function(func));
1129    ParamIter(llvm_get_first_param(func))
1130}
1131
1132/// LLVMGetParam
1133pub fn llvm_get_param(func: LLVMValue, idx: u32) -> LLVMValue {
1134    assert!(idx < llvm_count_params(func));
1135    unsafe { LLVMGetParam(func.into(), idx).into() }
1136}
1137
1138/// LLVMGetFirstFunction
1139pub fn llvm_get_first_function(module: &LLVMModule) -> Option<LLVMValue> {
1140    unsafe {
1141        let first_func = LLVMGetFirstFunction(module.inner_ref());
1142        (!first_func.is_null()).then_some(first_func.into())
1143    }
1144}
1145
1146/// LLVMGetNextFunction
1147pub fn llvm_get_next_function(func: LLVMValue) -> Option<LLVMValue> {
1148    assert!(llvm_is_a::function(func));
1149    unsafe {
1150        let next_func = LLVMGetNextFunction(func.into());
1151        (!next_func.is_null()).then_some(next_func.into())
1152    }
1153}
1154
1155/// LLVMGetPreviousFunction
1156pub fn llvm_get_previous_function(func: LLVMValue) -> Option<LLVMValue> {
1157    assert!(llvm_is_a::function(func));
1158    unsafe {
1159        let prev_func = LLVMGetPreviousFunction(func.into());
1160        (!prev_func.is_null()).then_some(prev_func.into())
1161    }
1162}
1163
1164/// LLVMGetLasFunction
1165pub fn llvm_get_last_function(module: &LLVMModule) -> Option<LLVMValue> {
1166    unsafe {
1167        let last_func = LLVMGetLastFunction(module.inner_ref());
1168        (!last_func.is_null()).then_some(last_func.into())
1169    }
1170}
1171
1172/// Iterate over all `Function`s in a `Module`.
1173pub struct FunctionIter(pub Option<LLVMValue>);
1174
1175impl Iterator for FunctionIter {
1176    type Item = LLVMValue;
1177
1178    fn next(&mut self) -> Option<Self::Item> {
1179        if let Some(param) = self.0 {
1180            self.0 = llvm_get_next_function(param);
1181            Some(param)
1182        } else {
1183            None
1184        }
1185    }
1186}
1187
1188/// Get an iterator over the functions of a module.
1189pub fn function_iter(module: &LLVMModule) -> FunctionIter {
1190    FunctionIter(llvm_get_first_function(module))
1191}
1192
1193/// LLVMGetFirstGlobal
1194pub fn llvm_get_first_global(module: &LLVMModule) -> Option<LLVMValue> {
1195    unsafe {
1196        let first_global = LLVMGetFirstGlobal(module.inner_ref());
1197        (!first_global.is_null()).then_some(first_global.into())
1198    }
1199}
1200
1201/// LLVMGetNextGlobal
1202pub fn llvm_get_next_global(val: LLVMValue) -> Option<LLVMValue> {
1203    assert!(llvm_is_a::global_variable(val));
1204    unsafe {
1205        let next_global = LLVMGetNextGlobal(val.into());
1206        (!next_global.is_null()).then_some(next_global.into())
1207    }
1208}
1209
1210/// LLVMGetPreviousGlobal
1211pub fn llvm_get_previous_global(val: LLVMValue) -> Option<LLVMValue> {
1212    assert!(llvm_is_a::global_variable(val));
1213    unsafe {
1214        let prev_global = LLVMGetPreviousGlobal(val.into());
1215        (!prev_global.is_null()).then_some(prev_global.into())
1216    }
1217}
1218
1219/// LLVMGetLastGlobal
1220pub fn llvm_get_last_global(module: &LLVMModule) -> Option<LLVMValue> {
1221    unsafe {
1222        let last_global = LLVMGetLastGlobal(module.inner_ref());
1223        (!last_global.is_null()).then_some(last_global.into())
1224    }
1225}
1226
1227/// Iterate over all `GlobalVariable`s in a `Module`.
1228pub struct GlobalVariableIter(pub Option<LLVMValue>);
1229
1230impl Iterator for GlobalVariableIter {
1231    type Item = LLVMValue;
1232
1233    fn next(&mut self) -> Option<Self::Item> {
1234        if let Some(param) = self.0 {
1235            self.0 = llvm_get_next_global(param);
1236            Some(param)
1237        } else {
1238            None
1239        }
1240    }
1241}
1242
1243/// Get an iterator over the global variables of a module.
1244pub fn global_iter(module: &LLVMModule) -> GlobalVariableIter {
1245    GlobalVariableIter(llvm_get_first_global(module))
1246}
1247
1248/// LLVMGetInitializer
1249pub fn llvm_get_initializer(val: LLVMValue) -> Option<LLVMValue> {
1250    assert!(llvm_is_a::global_variable(val));
1251    unsafe {
1252        let initializer = LLVMGetInitializer(val.into());
1253        (!initializer.is_null()).then_some(initializer.into())
1254    }
1255}
1256
1257/// LLVMSetInitializer
1258pub fn llvm_set_initializer(val: LLVMValue, init: LLVMValue) {
1259    assert!(llvm_is_a::global_variable(val));
1260    assert!(llvm_is_a::constant(init));
1261    unsafe { LLVMSetInitializer(val.into(), init.into()) }
1262}
1263
1264/// LLVMAddGlobal
1265pub fn llvm_add_global(module: &LLVMModule, ty: LLVMType, name: &str) -> LLVMValue {
1266    unsafe { LLVMAddGlobal(module.inner_ref(), ty.into(), to_c_str(name).as_ptr()).into() }
1267}
1268
1269/// LLVMAddGlobalInAddressSpace
1270pub fn llvm_add_global_in_address_space(
1271    module: &LLVMModule,
1272    ty: LLVMType,
1273    name: &str,
1274    addr_space: u32,
1275) -> LLVMValue {
1276    unsafe {
1277        LLVMAddGlobalInAddressSpace(
1278            module.inner_ref(),
1279            ty.into(),
1280            to_c_str(name).as_ptr(),
1281            addr_space,
1282        )
1283        .into()
1284    }
1285}
1286
1287/// LLVMDeleteGlobal
1288pub fn llvm_delete_global(global: LLVMValue) {
1289    assert!(llvm_is_a::global_variable(global));
1290    unsafe { LLVMDeleteGlobal(global.into()) }
1291}
1292
1293/// LLVMGetInsertBlock
1294pub fn llvm_get_insert_block(builder: &LLVMBuilder) -> Option<LLVMBasicBlock> {
1295    unsafe {
1296        let insert_block = LLVMGetInsertBlock(builder.inner_ref());
1297        (!insert_block.is_null()).then_some(insert_block.into())
1298    }
1299}
1300
1301/// LLVMClearInsertionPosition
1302pub fn llvm_clear_insertion_position(builder: &LLVMBuilder) {
1303    unsafe { LLVMClearInsertionPosition(builder.inner_ref()) }
1304}
1305
1306/// LLVMPositionBuilderAtEnd
1307pub fn llvm_position_builder_at_end(builder: &LLVMBuilder, block: LLVMBasicBlock) {
1308    unsafe { LLVMPositionBuilderAtEnd(builder.inner_ref(), block.into()) }
1309}
1310
1311/// LLVMPositionBuilderBefore
1312pub fn llvm_position_builder_before(builder: &LLVMBuilder, inst: LLVMValue) {
1313    assert!(llvm_is_a::instruction(inst));
1314    unsafe { LLVMPositionBuilderBefore(builder.inner_ref(), inst.into()) }
1315}
1316
1317/// LLVMIntTypeInContext
1318pub fn llvm_int_type_in_context(context: &LLVMContext, width: u32) -> LLVMType {
1319    unsafe { LLVMIntTypeInContext(context.inner_ref(), width).into() }
1320}
1321
1322/// LLVMFloatTypeInContext
1323pub fn llvm_float_type_in_context(context: &LLVMContext) -> LLVMType {
1324    unsafe { LLVMFloatTypeInContext(context.inner_ref()).into() }
1325}
1326
1327/// LLVMDoubleTypeInContext
1328pub fn llvm_double_type_in_context(context: &LLVMContext) -> LLVMType {
1329    unsafe { LLVMDoubleTypeInContext(context.inner_ref()).into() }
1330}
1331
1332/// LLVMHalfTypeInContext
1333pub fn llvm_half_type_in_context(context: &LLVMContext) -> LLVMType {
1334    unsafe { LLVMHalfTypeInContext(context.inner_ref()).into() }
1335}
1336
1337/// ArrayType::isValidElementType
1338pub fn llvm_is_valid_array_element_type(ty: LLVMType) -> bool {
1339    !matches!(
1340        llvm_get_type_kind(ty),
1341        LLVMTypeKind::LLVMVoidTypeKind
1342            | LLVMTypeKind::LLVMLabelTypeKind
1343            | LLVMTypeKind::LLVMMetadataTypeKind
1344            | LLVMTypeKind::LLVMFunctionTypeKind
1345            | LLVMTypeKind::LLVMTokenTypeKind
1346            | LLVMTypeKind::LLVMX86_AMXTypeKind
1347    )
1348}
1349
1350/// LLVMArrayType2
1351pub fn llvm_array_type2(elem_ty: LLVMType, element_count: u64) -> LLVMType {
1352    assert!(llvm_is_valid_array_element_type(elem_ty));
1353    unsafe { LLVMArrayType2(elem_ty.into(), element_count).into() }
1354}
1355
1356/// isFirstClassType
1357pub fn llvm_is_first_class_type(ty: LLVMType) -> bool {
1358    !matches!(
1359        llvm_get_type_kind(ty),
1360        LLVMTypeKind::LLVMVoidTypeKind | LLVMTypeKind::LLVMFunctionTypeKind
1361    )
1362}
1363
1364/// FunctionType::isValidArgumentType
1365pub fn llvm_is_valid_function_argument_type(arg_ty: LLVMType) -> bool {
1366    llvm_is_first_class_type(arg_ty)
1367}
1368
1369/// FunctionType::isValidReturnType
1370pub fn llvm_is_valid_function_return_type(ret_ty: LLVMType) -> bool {
1371    !matches!(
1372        llvm_get_type_kind(ret_ty),
1373        LLVMTypeKind::LLVMLabelTypeKind
1374            | LLVMTypeKind::LLVMFunctionTypeKind
1375            | LLVMTypeKind::LLVMMetadataTypeKind
1376    )
1377}
1378
1379/// LLVMFunctionType
1380pub fn llvm_function_type(ret_ty: LLVMType, param_tys: &[LLVMType], is_var_arg: bool) -> LLVMType {
1381    assert!(llvm_is_valid_function_return_type(ret_ty));
1382    assert!(
1383        param_tys
1384            .iter()
1385            .all(|param_ty| llvm_is_valid_function_argument_type(*param_ty))
1386    );
1387    let mut param_tys: Vec<_> = param_tys.iter().cloned().map(Into::into).collect();
1388    unsafe {
1389        LLVMFunctionType(
1390            ret_ty.into(),
1391            param_tys.as_mut_ptr(),
1392            param_tys.len().try_into().unwrap(),
1393            is_var_arg.into(),
1394        )
1395        .into()
1396    }
1397}
1398
1399/// LLVMVoidTypeInContext
1400pub fn llvm_void_type_in_context(context: &LLVMContext) -> LLVMType {
1401    unsafe { LLVMVoidTypeInContext(context.inner_ref()).into() }
1402}
1403
1404/// LLVMPointerTypeInContext
1405pub fn llvm_pointer_type_in_context(context: &LLVMContext, addr_space: u32) -> LLVMType {
1406    unsafe { LLVMPointerTypeInContext(context.inner_ref(), addr_space).into() }
1407}
1408
1409/// LLVMStructCreateNamed
1410pub fn llvm_struct_create_named(context: &LLVMContext, name: &str) -> LLVMType {
1411    unsafe { LLVMStructCreateNamed(context.inner_ref(), to_c_str(name).as_ptr()).into() }
1412}
1413
1414/// StructType::isValidElementType
1415pub fn llvm_is_valid_struct_element_type(ty: LLVMType) -> bool {
1416    !matches!(
1417        llvm_get_type_kind(ty),
1418        LLVMTypeKind::LLVMVoidTypeKind
1419            | LLVMTypeKind::LLVMLabelTypeKind
1420            | LLVMTypeKind::LLVMMetadataTypeKind
1421            | LLVMTypeKind::LLVMFunctionTypeKind
1422            | LLVMTypeKind::LLVMTokenTypeKind
1423    )
1424}
1425
1426/// LLVMStructTypeInContext
1427pub fn llvm_struct_type_in_context(
1428    context: &LLVMContext,
1429    elem_tys: &[LLVMType],
1430    is_packed: bool,
1431) -> LLVMType {
1432    assert!(
1433        elem_tys
1434            .iter()
1435            .all(|elem_ty| llvm_is_valid_struct_element_type(*elem_ty))
1436    );
1437    let mut elem_tys: Vec<_> = elem_tys.iter().cloned().map(Into::into).collect();
1438    unsafe {
1439        LLVMStructTypeInContext(
1440            context.inner_ref(),
1441            elem_tys.as_mut_ptr(),
1442            elem_tys.len().try_into().unwrap(),
1443            is_packed.into(),
1444        )
1445        .into()
1446    }
1447}
1448
1449/// LLVMStructSetBody
1450pub fn llvm_struct_set_body(struct_ty: LLVMType, elem_tys: &[LLVMType], is_packed: bool) {
1451    assert!(llvm_get_type_kind(struct_ty) == LLVMTypeKind::LLVMStructTypeKind);
1452    assert!(
1453        elem_tys
1454            .iter()
1455            .all(|elem_ty| llvm_is_valid_struct_element_type(*elem_ty))
1456    );
1457    let mut elem_tys: Vec<_> = elem_tys.iter().cloned().map(Into::into).collect();
1458    unsafe {
1459        LLVMStructSetBody(
1460            struct_ty.into(),
1461            elem_tys.as_mut_ptr(),
1462            elem_tys.len().try_into().unwrap(),
1463            is_packed as i32,
1464        )
1465    }
1466}
1467
1468/// LLVMBuildAdd
1469pub fn llvm_build_add(
1470    builder: &LLVMBuilder,
1471    lhs: LLVMValue,
1472    rhs: LLVMValue,
1473    name: &str,
1474) -> LLVMValue {
1475    assert!(llvm_get_insert_block(builder).is_some());
1476    unsafe {
1477        LLVMBuildAdd(
1478            builder.inner_ref(),
1479            lhs.into(),
1480            rhs.into(),
1481            to_c_str(name).as_ptr(),
1482        )
1483        .into()
1484    }
1485}
1486
1487/// LLVMBuildSub
1488pub fn llvm_build_sub(
1489    builder: &LLVMBuilder,
1490    lhs: LLVMValue,
1491    rhs: LLVMValue,
1492    name: &str,
1493) -> LLVMValue {
1494    assert!(llvm_get_insert_block(builder).is_some());
1495    unsafe {
1496        LLVMBuildSub(
1497            builder.inner_ref(),
1498            lhs.into(),
1499            rhs.into(),
1500            to_c_str(name).as_ptr(),
1501        )
1502        .into()
1503    }
1504}
1505
1506/// LLVMBuildMul
1507pub fn llvm_build_mul(
1508    builder: &LLVMBuilder,
1509    lhs: LLVMValue,
1510    rhs: LLVMValue,
1511    name: &str,
1512) -> LLVMValue {
1513    assert!(llvm_get_insert_block(builder).is_some());
1514    unsafe {
1515        LLVMBuildMul(
1516            builder.inner_ref(),
1517            lhs.into(),
1518            rhs.into(),
1519            to_c_str(name).as_ptr(),
1520        )
1521        .into()
1522    }
1523}
1524
1525/// LLVMBuildSDiv
1526pub fn llvm_build_sdiv(
1527    builder: &LLVMBuilder,
1528    lhs: LLVMValue,
1529    rhs: LLVMValue,
1530    name: &str,
1531) -> LLVMValue {
1532    assert!(llvm_get_insert_block(builder).is_some());
1533    unsafe {
1534        LLVMBuildSDiv(
1535            builder.inner_ref(),
1536            lhs.into(),
1537            rhs.into(),
1538            to_c_str(name).as_ptr(),
1539        )
1540        .into()
1541    }
1542}
1543
1544/// LLVMBuildUDiv
1545pub fn llvm_build_udiv(
1546    builder: &LLVMBuilder,
1547    lhs: LLVMValue,
1548    rhs: LLVMValue,
1549    name: &str,
1550) -> LLVMValue {
1551    assert!(llvm_get_insert_block(builder).is_some());
1552    unsafe {
1553        LLVMBuildUDiv(
1554            builder.inner_ref(),
1555            lhs.into(),
1556            rhs.into(),
1557            to_c_str(name).as_ptr(),
1558        )
1559        .into()
1560    }
1561}
1562
1563/// LLVMBuildURem
1564pub fn llvm_build_urem(
1565    builder: &LLVMBuilder,
1566    lhs: LLVMValue,
1567    rhs: LLVMValue,
1568    name: &str,
1569) -> LLVMValue {
1570    assert!(llvm_get_insert_block(builder).is_some());
1571    unsafe {
1572        LLVMBuildURem(
1573            builder.inner_ref(),
1574            lhs.into(),
1575            rhs.into(),
1576            to_c_str(name).as_ptr(),
1577        )
1578        .into()
1579    }
1580}
1581
1582/// LLVMBuildSRem
1583pub fn llvm_build_srem(
1584    builder: &LLVMBuilder,
1585    lhs: LLVMValue,
1586    rhs: LLVMValue,
1587    name: &str,
1588) -> LLVMValue {
1589    assert!(llvm_get_insert_block(builder).is_some());
1590    unsafe {
1591        LLVMBuildSRem(
1592            builder.inner_ref(),
1593            lhs.into(),
1594            rhs.into(),
1595            to_c_str(name).as_ptr(),
1596        )
1597        .into()
1598    }
1599}
1600
1601/// LLVMBuildAnd
1602pub fn llvm_build_and(
1603    builder: &LLVMBuilder,
1604    lhs: LLVMValue,
1605    rhs: LLVMValue,
1606    name: &str,
1607) -> LLVMValue {
1608    assert!(llvm_get_insert_block(builder).is_some());
1609    unsafe {
1610        LLVMBuildAnd(
1611            builder.inner_ref(),
1612            lhs.into(),
1613            rhs.into(),
1614            to_c_str(name).as_ptr(),
1615        )
1616        .into()
1617    }
1618}
1619
1620/// LLVMBuildOr
1621pub fn llvm_build_or(
1622    builder: &LLVMBuilder,
1623    lhs: LLVMValue,
1624    rhs: LLVMValue,
1625    name: &str,
1626) -> LLVMValue {
1627    assert!(llvm_get_insert_block(builder).is_some());
1628    unsafe {
1629        LLVMBuildOr(
1630            builder.inner_ref(),
1631            lhs.into(),
1632            rhs.into(),
1633            to_c_str(name).as_ptr(),
1634        )
1635        .into()
1636    }
1637}
1638
1639/// LLVMBuildXor
1640pub fn llvm_build_xor(
1641    builder: &LLVMBuilder,
1642    lhs: LLVMValue,
1643    rhs: LLVMValue,
1644    name: &str,
1645) -> LLVMValue {
1646    assert!(llvm_get_insert_block(builder).is_some());
1647    unsafe {
1648        LLVMBuildXor(
1649            builder.inner_ref(),
1650            lhs.into(),
1651            rhs.into(),
1652            to_c_str(name).as_ptr(),
1653        )
1654        .into()
1655    }
1656}
1657
1658/// LLVMBuildShl
1659pub fn llvm_build_shl(
1660    builder: &LLVMBuilder,
1661    lhs: LLVMValue,
1662    rhs: LLVMValue,
1663    name: &str,
1664) -> LLVMValue {
1665    assert!(llvm_get_insert_block(builder).is_some());
1666    unsafe {
1667        LLVMBuildShl(
1668            builder.inner_ref(),
1669            lhs.into(),
1670            rhs.into(),
1671            to_c_str(name).as_ptr(),
1672        )
1673        .into()
1674    }
1675}
1676
1677/// LLVMBuildLShr
1678pub fn llvm_build_lshr(
1679    builder: &LLVMBuilder,
1680    lhs: LLVMValue,
1681    rhs: LLVMValue,
1682    name: &str,
1683) -> LLVMValue {
1684    assert!(llvm_get_insert_block(builder).is_some());
1685    unsafe {
1686        LLVMBuildLShr(
1687            builder.inner_ref(),
1688            lhs.into(),
1689            rhs.into(),
1690            to_c_str(name).as_ptr(),
1691        )
1692        .into()
1693    }
1694}
1695
1696/// LLVMBuildAShr
1697pub fn llvm_build_ashr(
1698    builder: &LLVMBuilder,
1699    lhs: LLVMValue,
1700    rhs: LLVMValue,
1701    name: &str,
1702) -> LLVMValue {
1703    assert!(llvm_get_insert_block(builder).is_some());
1704    unsafe {
1705        LLVMBuildAShr(
1706            builder.inner_ref(),
1707            lhs.into(),
1708            rhs.into(),
1709            to_c_str(name).as_ptr(),
1710        )
1711        .into()
1712    }
1713}
1714
1715/// LLVMBuildArrayAlloca
1716pub fn llvm_build_array_alloca(
1717    builder: &LLVMBuilder,
1718    ty: LLVMType,
1719    size: LLVMValue,
1720    name: &str,
1721) -> LLVMValue {
1722    assert!(llvm_get_insert_block(builder).is_some());
1723    unsafe {
1724        LLVMBuildArrayAlloca(
1725            builder.inner_ref(),
1726            ty.into(),
1727            size.into(),
1728            to_c_str(name).as_ptr(),
1729        )
1730        .into()
1731    }
1732}
1733
1734/// LLVMBuildBitCast
1735pub fn llvm_build_bitcast(
1736    builder: &LLVMBuilder,
1737    val: LLVMValue,
1738    dest_ty: LLVMType,
1739    name: &str,
1740) -> LLVMValue {
1741    assert!(llvm_get_insert_block(builder).is_some());
1742    unsafe {
1743        LLVMBuildBitCast(
1744            builder.inner_ref(),
1745            val.into(),
1746            dest_ty.into(),
1747            to_c_str(name).as_ptr(),
1748        )
1749        .into()
1750    }
1751}
1752
1753/// LLVMBuildAddrSpaceCast
1754pub fn llvm_build_addrspacecast(
1755    builder: &LLVMBuilder,
1756    val: LLVMValue,
1757    dest_ty: LLVMType,
1758    name: &str,
1759) -> LLVMValue {
1760    assert!(llvm_get_insert_block(builder).is_some());
1761    unsafe {
1762        LLVMBuildAddrSpaceCast(
1763            builder.inner_ref(),
1764            val.into(),
1765            dest_ty.into(),
1766            to_c_str(name).as_ptr(),
1767        )
1768        .into()
1769    }
1770}
1771
1772/// LLVMBuildIntToPtr
1773pub fn llvm_build_int_to_ptr(
1774    builder: &LLVMBuilder,
1775    val: LLVMValue,
1776    dest_ty: LLVMType,
1777    name: &str,
1778) -> LLVMValue {
1779    assert!(llvm_get_insert_block(builder).is_some());
1780    unsafe {
1781        LLVMBuildIntToPtr(
1782            builder.inner_ref(),
1783            val.into(),
1784            dest_ty.into(),
1785            to_c_str(name).as_ptr(),
1786        )
1787        .into()
1788    }
1789}
1790/// LLVMBuildPtrToInt
1791pub fn llvm_build_ptr_to_int(
1792    builder: &LLVMBuilder,
1793    val: LLVMValue,
1794    dest_ty: LLVMType,
1795    name: &str,
1796) -> LLVMValue {
1797    assert!(llvm_get_insert_block(builder).is_some());
1798    unsafe {
1799        LLVMBuildPtrToInt(
1800            builder.inner_ref(),
1801            val.into(),
1802            dest_ty.into(),
1803            to_c_str(name).as_ptr(),
1804        )
1805        .into()
1806    }
1807}
1808
1809/// LLVMBuildTrunc
1810pub fn llvm_build_trunc(
1811    builder: &LLVMBuilder,
1812    val: LLVMValue,
1813    dest_ty: LLVMType,
1814    name: &str,
1815) -> LLVMValue {
1816    assert!(llvm_get_insert_block(builder).is_some());
1817    unsafe {
1818        LLVMBuildTrunc(
1819            builder.inner_ref(),
1820            val.into(),
1821            dest_ty.into(),
1822            to_c_str(name).as_ptr(),
1823        )
1824        .into()
1825    }
1826}
1827
1828/// LLVMBuildSExt
1829pub fn llvm_build_sext(
1830    builder: &LLVMBuilder,
1831    val: LLVMValue,
1832    dest_ty: LLVMType,
1833    name: &str,
1834) -> LLVMValue {
1835    assert!(llvm_get_insert_block(builder).is_some());
1836    unsafe {
1837        LLVMBuildSExt(
1838            builder.inner_ref(),
1839            val.into(),
1840            dest_ty.into(),
1841            to_c_str(name).as_ptr(),
1842        )
1843        .into()
1844    }
1845}
1846
1847/// LLVMBuildZExt
1848pub fn llvm_build_zext(
1849    builder: &LLVMBuilder,
1850    val: LLVMValue,
1851    dest_ty: LLVMType,
1852    name: &str,
1853) -> LLVMValue {
1854    assert!(llvm_get_insert_block(builder).is_some());
1855    unsafe {
1856        LLVMBuildZExt(
1857            builder.inner_ref(),
1858            val.into(),
1859            dest_ty.into(),
1860            to_c_str(name).as_ptr(),
1861        )
1862        .into()
1863    }
1864}
1865
1866/// LLVMBuildGEP2
1867pub fn llvm_build_gep2(
1868    builder: &LLVMBuilder,
1869    ty: LLVMType,
1870    ptr: LLVMValue,
1871    indices: &[LLVMValue],
1872    name: &str,
1873) -> LLVMValue {
1874    assert!(llvm_get_insert_block(builder).is_some());
1875    let mut indices: Vec<_> = indices.iter().cloned().map(Into::into).collect();
1876    unsafe {
1877        LLVMBuildGEP2(
1878            builder.inner_ref(),
1879            ty.into(),
1880            ptr.into(),
1881            indices.as_mut_ptr(),
1882            indices.len().try_into().unwrap(),
1883            to_c_str(name).as_ptr(),
1884        )
1885        .into()
1886    }
1887}
1888
1889/// LLVMBuildInsertElement
1890pub fn llvm_build_insert_element(
1891    builder: &LLVMBuilder,
1892    agg_val: LLVMValue,
1893    element_val: LLVMValue,
1894    index: LLVMValue,
1895    name: &str,
1896) -> LLVMValue {
1897    assert!(llvm_get_insert_block(builder).is_some());
1898    unsafe {
1899        LLVMBuildInsertElement(
1900            builder.inner_ref(),
1901            agg_val.into(),
1902            element_val.into(),
1903            index.into(),
1904            to_c_str(name).as_ptr(),
1905        )
1906        .into()
1907    }
1908}
1909
1910/// LLVMBuildExtractElement
1911pub fn llvm_build_extract_element(
1912    builder: &LLVMBuilder,
1913    agg_val: LLVMValue,
1914    index: LLVMValue,
1915    name: &str,
1916) -> LLVMValue {
1917    assert!(llvm_get_insert_block(builder).is_some());
1918    unsafe {
1919        LLVMBuildExtractElement(
1920            builder.inner_ref(),
1921            agg_val.into(),
1922            index.into(),
1923            to_c_str(name).as_ptr(),
1924        )
1925        .into()
1926    }
1927}
1928
1929/// LLVMBuildShuffleVector
1930pub fn llvm_build_shuffle_vector(
1931    builder: &LLVMBuilder,
1932    vec1: LLVMValue,
1933    vec2: LLVMValue,
1934    mask: LLVMValue,
1935    name: &str,
1936) -> LLVMValue {
1937    assert!(llvm_get_insert_block(builder).is_some());
1938    unsafe {
1939        LLVMBuildShuffleVector(
1940            builder.inner_ref(),
1941            vec1.into(),
1942            vec2.into(),
1943            mask.into(),
1944            to_c_str(name).as_ptr(),
1945        )
1946        .into()
1947    }
1948}
1949
1950/// LLVMBuildInsertValue
1951pub fn llvm_build_insert_value(
1952    builder: &LLVMBuilder,
1953    agg_val: LLVMValue,
1954    element_val: LLVMValue,
1955    index: u32,
1956    name: &str,
1957) -> LLVMValue {
1958    assert!(llvm_get_insert_block(builder).is_some());
1959    unsafe {
1960        LLVMBuildInsertValue(
1961            builder.inner_ref(),
1962            agg_val.into(),
1963            element_val.into(),
1964            index,
1965            to_c_str(name).as_ptr(),
1966        )
1967        .into()
1968    }
1969}
1970
1971/// LLVMBuildExtractValue
1972pub fn llvm_build_extract_value(
1973    builder: &LLVMBuilder,
1974    agg_val: LLVMValue,
1975    index: u32,
1976    name: &str,
1977) -> LLVMValue {
1978    assert!(llvm_get_insert_block(builder).is_some());
1979    unsafe {
1980        LLVMBuildExtractValue(
1981            builder.inner_ref(),
1982            agg_val.into(),
1983            index,
1984            to_c_str(name).as_ptr(),
1985        )
1986        .into()
1987    }
1988}
1989
1990/// LLVMBuildSelect
1991pub fn llvm_build_select(
1992    builder: &LLVMBuilder,
1993    if_val: LLVMValue,
1994    then_val: LLVMValue,
1995    else_val: LLVMValue,
1996    name: &str,
1997) -> LLVMValue {
1998    assert!(llvm_get_insert_block(builder).is_some());
1999    unsafe {
2000        LLVMBuildSelect(
2001            builder.inner_ref(),
2002            if_val.into(),
2003            then_val.into(),
2004            else_val.into(),
2005            to_c_str(name).as_ptr(),
2006        )
2007        .into()
2008    }
2009}
2010
2011/// LLVMBuildFAdd
2012pub fn llvm_build_fadd(
2013    builder: &LLVMBuilder,
2014    lhs: LLVMValue,
2015    rhs: LLVMValue,
2016    name: &str,
2017) -> LLVMValue {
2018    assert!(llvm_get_insert_block(builder).is_some());
2019    unsafe {
2020        LLVMBuildFAdd(
2021            builder.inner_ref(),
2022            lhs.into(),
2023            rhs.into(),
2024            to_c_str(name).as_ptr(),
2025        )
2026        .into()
2027    }
2028}
2029
2030/// LLVMBuildFSub
2031pub fn llvm_build_fsub(
2032    builder: &LLVMBuilder,
2033    lhs: LLVMValue,
2034    rhs: LLVMValue,
2035    name: &str,
2036) -> LLVMValue {
2037    assert!(llvm_get_insert_block(builder).is_some());
2038    unsafe {
2039        LLVMBuildFSub(
2040            builder.inner_ref(),
2041            lhs.into(),
2042            rhs.into(),
2043            to_c_str(name).as_ptr(),
2044        )
2045        .into()
2046    }
2047}
2048
2049/// LLVMBuildFMul
2050pub fn llvm_build_fmul(
2051    builder: &LLVMBuilder,
2052    lhs: LLVMValue,
2053    rhs: LLVMValue,
2054    name: &str,
2055) -> LLVMValue {
2056    assert!(llvm_get_insert_block(builder).is_some());
2057    unsafe {
2058        LLVMBuildFMul(
2059            builder.inner_ref(),
2060            lhs.into(),
2061            rhs.into(),
2062            to_c_str(name).as_ptr(),
2063        )
2064        .into()
2065    }
2066}
2067
2068/// LLVMBuildFDiv
2069pub fn llvm_build_fdiv(
2070    builder: &LLVMBuilder,
2071    lhs: LLVMValue,
2072    rhs: LLVMValue,
2073    name: &str,
2074) -> LLVMValue {
2075    assert!(llvm_get_insert_block(builder).is_some());
2076    unsafe {
2077        LLVMBuildFDiv(
2078            builder.inner_ref(),
2079            lhs.into(),
2080            rhs.into(),
2081            to_c_str(name).as_ptr(),
2082        )
2083        .into()
2084    }
2085}
2086
2087/// LLVMBuildFRem
2088pub fn llvm_build_frem(
2089    builder: &LLVMBuilder,
2090    lhs: LLVMValue,
2091    rhs: LLVMValue,
2092    name: &str,
2093) -> LLVMValue {
2094    assert!(llvm_get_insert_block(builder).is_some());
2095    unsafe {
2096        LLVMBuildFRem(
2097            builder.inner_ref(),
2098            lhs.into(),
2099            rhs.into(),
2100            to_c_str(name).as_ptr(),
2101        )
2102        .into()
2103    }
2104}
2105
2106/// LLVMBuildFNeg
2107pub fn llvm_build_fneg(builder: &LLVMBuilder, val: LLVMValue, name: &str) -> LLVMValue {
2108    assert!(llvm_get_insert_block(builder).is_some());
2109    unsafe { LLVMBuildFNeg(builder.inner_ref(), val.into(), to_c_str(name).as_ptr()).into() }
2110}
2111
2112/// LLVMBuildFCmp
2113pub fn llvm_build_fcmp(
2114    builder: &LLVMBuilder,
2115    op: LLVMRealPredicate,
2116    lhs: LLVMValue,
2117    rhs: LLVMValue,
2118    name: &str,
2119) -> LLVMValue {
2120    assert!(llvm_get_insert_block(builder).is_some());
2121    unsafe {
2122        LLVMBuildFCmp(
2123            builder.inner_ref(),
2124            op,
2125            lhs.into(),
2126            rhs.into(),
2127            to_c_str(name).as_ptr(),
2128        )
2129        .into()
2130    }
2131}
2132
2133/// LLVMBuildFPExt
2134pub fn llvm_build_fpext(
2135    builder: &LLVMBuilder,
2136    val: LLVMValue,
2137    dest_ty: LLVMType,
2138    name: &str,
2139) -> LLVMValue {
2140    assert!(llvm_get_insert_block(builder).is_some());
2141    unsafe {
2142        LLVMBuildFPExt(
2143            builder.inner_ref(),
2144            val.into(),
2145            dest_ty.into(),
2146            to_c_str(name).as_ptr(),
2147        )
2148        .into()
2149    }
2150}
2151
2152/// LLVMBuildFPTrunc
2153pub fn llvm_build_fptrunc(
2154    builder: &LLVMBuilder,
2155    val: LLVMValue,
2156    dest_ty: LLVMType,
2157    name: &str,
2158) -> LLVMValue {
2159    assert!(llvm_get_insert_block(builder).is_some());
2160    unsafe {
2161        LLVMBuildFPTrunc(
2162            builder.inner_ref(),
2163            val.into(),
2164            dest_ty.into(),
2165            to_c_str(name).as_ptr(),
2166        )
2167        .into()
2168    }
2169}
2170
2171/// LLVMBuildFPToSI
2172pub fn llvm_build_fptosi(
2173    builder: &LLVMBuilder,
2174    val: LLVMValue,
2175    dest_ty: LLVMType,
2176    name: &str,
2177) -> LLVMValue {
2178    assert!(llvm_get_insert_block(builder).is_some());
2179    unsafe {
2180        LLVMBuildFPToSI(
2181            builder.inner_ref(),
2182            val.into(),
2183            dest_ty.into(),
2184            to_c_str(name).as_ptr(),
2185        )
2186        .into()
2187    }
2188}
2189
2190/// LLVMBuildSIToFP
2191pub fn llvm_build_sitofp(
2192    builder: &LLVMBuilder,
2193    val: LLVMValue,
2194    dest_ty: LLVMType,
2195    name: &str,
2196) -> LLVMValue {
2197    assert!(llvm_get_insert_block(builder).is_some());
2198    unsafe {
2199        LLVMBuildSIToFP(
2200            builder.inner_ref(),
2201            val.into(),
2202            dest_ty.into(),
2203            to_c_str(name).as_ptr(),
2204        )
2205        .into()
2206    }
2207}
2208
2209/// LLVMBuildUIToFP
2210pub fn llvm_build_uitofp(
2211    builder: &LLVMBuilder,
2212    val: LLVMValue,
2213    dest_ty: LLVMType,
2214    name: &str,
2215) -> LLVMValue {
2216    assert!(llvm_get_insert_block(builder).is_some());
2217    unsafe {
2218        LLVMBuildUIToFP(
2219            builder.inner_ref(),
2220            val.into(),
2221            dest_ty.into(),
2222            to_c_str(name).as_ptr(),
2223        )
2224        .into()
2225    }
2226}
2227
2228/// LLVMBuildFPToUI
2229pub fn llvm_build_fptoui(
2230    builder: &LLVMBuilder,
2231    val: LLVMValue,
2232    dest_ty: LLVMType,
2233    name: &str,
2234) -> LLVMValue {
2235    assert!(llvm_get_insert_block(builder).is_some());
2236    unsafe {
2237        LLVMBuildFPToUI(
2238            builder.inner_ref(),
2239            val.into(),
2240            dest_ty.into(),
2241            to_c_str(name).as_ptr(),
2242        )
2243        .into()
2244    }
2245}
2246
2247/// LLVMAddIncoming
2248pub fn llvm_add_incoming(
2249    phi_node: LLVMValue,
2250    incoming_values: &[LLVMValue],
2251    incoming_blocks: &[LLVMBasicBlock],
2252) {
2253    assert!(llvm_is_a::phi_node(phi_node));
2254    assert!(incoming_values.len() == incoming_blocks.len());
2255    let mut incoming_values: Vec<LLVMValueRef> =
2256        incoming_values.iter().cloned().map(Into::into).collect();
2257    let mut incoming_blocks: Vec<_> = incoming_blocks.iter().cloned().map(Into::into).collect();
2258    unsafe {
2259        LLVMAddIncoming(
2260            phi_node.into(),
2261            incoming_values.as_mut_ptr(),
2262            incoming_blocks.as_mut_ptr(),
2263            incoming_blocks.len().try_into().unwrap(),
2264        )
2265    }
2266}
2267
2268/// LLVMBuildCondBr
2269pub fn llvm_build_cond_br(
2270    builder: &LLVMBuilder,
2271    if_val: LLVMValue,
2272    then_block: LLVMBasicBlock,
2273    else_block: LLVMBasicBlock,
2274) -> LLVMValue {
2275    assert!(llvm_get_insert_block(builder).is_some());
2276    unsafe {
2277        LLVMBuildCondBr(
2278            builder.inner_ref(),
2279            if_val.into(),
2280            then_block.into(),
2281            else_block.into(),
2282        )
2283        .into()
2284    }
2285}
2286
2287/// LLVMBuildBr
2288pub fn llvm_build_br(builder: &LLVMBuilder, dest: LLVMBasicBlock) -> LLVMValue {
2289    assert!(llvm_get_insert_block(builder).is_some());
2290    unsafe { LLVMBuildBr(builder.inner_ref(), dest.into()).into() }
2291}
2292
2293/// LLVMBuildSwitch
2294pub fn llvm_build_switch(
2295    builder: &LLVMBuilder,
2296    val: LLVMValue,
2297    default_block: LLVMBasicBlock,
2298    num_cases: u32,
2299) -> LLVMValue {
2300    assert!(llvm_get_insert_block(builder).is_some());
2301    unsafe {
2302        LLVMBuildSwitch(
2303            builder.inner_ref(),
2304            val.into(),
2305            default_block.into(),
2306            num_cases,
2307        )
2308        .into()
2309    }
2310}
2311
2312/// LLVMGetSwitchCaseValue
2313pub fn llvm_get_switch_case_value(switch_inst: LLVMValue, case_idx: u32) -> LLVMValue {
2314    assert!(llvm_is_a::switch_inst(switch_inst));
2315    unsafe { LLVMGetSwitchCaseValue(switch_inst.into(), case_idx).into() }
2316}
2317
2318/// LLVMAddCase
2319pub fn llvm_add_case(switch_inst: LLVMValue, on_val: LLVMValue, dest_block: LLVMBasicBlock) {
2320    assert!(llvm_is_a::switch_inst(switch_inst));
2321    unsafe {
2322        LLVMAddCase(switch_inst.into(), on_val.into(), dest_block.into());
2323    }
2324}
2325
2326/// LLVMBuildIndirectBr
2327pub fn llvm_build_indirect_br(builder: &LLVMBuilder, addr: LLVMValue, num_dests: u32) -> LLVMValue {
2328    assert!(llvm_get_insert_block(builder).is_some());
2329    unsafe { LLVMBuildIndirectBr(builder.inner_ref(), addr.into(), num_dests).into() }
2330}
2331
2332/// LLVMAddDestination
2333pub fn llvm_add_destination(indirect_br_inst: LLVMValue, dest_block: LLVMBasicBlock) {
2334    assert!(llvm_is_a::indirect_br_inst(indirect_br_inst));
2335    unsafe {
2336        LLVMAddDestination(indirect_br_inst.into(), dest_block.into());
2337    }
2338}
2339
2340/// LLVMBuildLoad2
2341pub fn llvm_build_load2(
2342    builder: &LLVMBuilder,
2343    ty: LLVMType,
2344    pointer_val: LLVMValue,
2345    name: &str,
2346) -> LLVMValue {
2347    assert!(llvm_get_insert_block(builder).is_some());
2348    unsafe {
2349        LLVMBuildLoad2(
2350            builder.inner_ref(),
2351            ty.into(),
2352            pointer_val.into(),
2353            to_c_str(name).as_ptr(),
2354        )
2355        .into()
2356    }
2357}
2358
2359/// LLVMBuildStore
2360pub fn llvm_build_store(builder: &LLVMBuilder, val: LLVMValue, ptr: LLVMValue) -> LLVMValue {
2361    assert!(llvm_get_insert_block(builder).is_some());
2362    unsafe { LLVMBuildStore(builder.inner_ref(), val.into(), ptr.into()).into() }
2363}
2364
2365/// LLVMBuildICmp
2366pub fn llvm_build_icmp(
2367    builder: &LLVMBuilder,
2368    op: LLVMIntPredicate,
2369    lhs: LLVMValue,
2370    rhs: LLVMValue,
2371    name: &str,
2372) -> LLVMValue {
2373    assert!(llvm_get_insert_block(builder).is_some());
2374    unsafe {
2375        LLVMBuildICmp(
2376            builder.inner_ref(),
2377            op,
2378            lhs.into(),
2379            rhs.into(),
2380            to_c_str(name).as_ptr(),
2381        )
2382        .into()
2383    }
2384}
2385
2386/// LLVMBuildRetVoid
2387pub fn llvm_build_ret_void(builder: &LLVMBuilder) -> LLVMValue {
2388    assert!(llvm_get_insert_block(builder).is_some());
2389    unsafe { LLVMBuildRetVoid(builder.inner_ref()).into() }
2390}
2391
2392/// LLVMBuildRet
2393pub fn llvm_build_ret(builder: &LLVMBuilder, val: LLVMValue) -> LLVMValue {
2394    assert!(llvm_get_insert_block(builder).is_some());
2395    unsafe { LLVMBuildRet(builder.inner_ref(), val.into()).into() }
2396}
2397
2398/// LLVMBuildUnreachable
2399pub fn llvm_build_unreachable(builder: &LLVMBuilder) -> LLVMValue {
2400    assert!(llvm_get_insert_block(builder).is_some());
2401    unsafe { LLVMBuildUnreachable(builder.inner_ref()).into() }
2402}
2403
2404/// LLVMBuildPhi
2405pub fn llvm_build_phi(builder: &LLVMBuilder, ty: LLVMType, name: &str) -> LLVMValue {
2406    assert!(llvm_get_insert_block(builder).is_some());
2407    unsafe { LLVMBuildPhi(builder.inner_ref(), ty.into(), to_c_str(name).as_ptr()).into() }
2408}
2409
2410/// LLVMBuildCall2
2411pub fn llvm_build_call2(
2412    builder: &LLVMBuilder,
2413    ty: LLVMType,
2414    callee: LLVMValue,
2415    args: &[LLVMValue],
2416    name: &str,
2417) -> LLVMValue {
2418    assert!(llvm_get_insert_block(builder).is_some());
2419    assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
2420    let mut args: Vec<_> = args.iter().cloned().map(Into::into).collect();
2421    unsafe {
2422        LLVMBuildCall2(
2423            builder.inner_ref(),
2424            ty.into(),
2425            callee.into(),
2426            args.as_mut_ptr(),
2427            args.len().try_into().unwrap(),
2428            to_c_str(name).as_ptr(),
2429        )
2430        .into()
2431    }
2432}
2433
2434/// LLVMBuildVAArg
2435pub fn llvm_build_va_arg(
2436    builder: &LLVMBuilder,
2437    val: LLVMValue,
2438    ty: LLVMType,
2439    name: &str,
2440) -> LLVMValue {
2441    assert!(llvm_get_insert_block(builder).is_some());
2442    unsafe {
2443        LLVMBuildVAArg(
2444            builder.inner_ref(),
2445            val.into(),
2446            ty.into(),
2447            to_c_str(name).as_ptr(),
2448        )
2449        .into()
2450    }
2451}
2452
2453/// LLVMBuildFreeze
2454pub fn llvm_build_freeze(builder: &LLVMBuilder, val: LLVMValue, name: &str) -> LLVMValue {
2455    assert!(llvm_get_insert_block(builder).is_some());
2456    unsafe { LLVMBuildFreeze(builder.inner_ref(), val.into(), to_c_str(name).as_ptr()).into() }
2457}
2458
2459/// LLVMConstInt
2460pub fn llvm_const_int(int_ty: LLVMType, val: u64, sign_extend: bool) -> LLVMValue {
2461    assert!(llvm_get_type_kind(int_ty) == LLVMTypeKind::LLVMIntegerTypeKind);
2462    unsafe { LLVMConstInt(int_ty.into(), val, sign_extend.into()).into() }
2463}
2464
2465/// LLVMGetUndef
2466pub fn llvm_get_undef(ty: LLVMType) -> LLVMValue {
2467    unsafe { LLVMGetUndef(ty.into()).into() }
2468}
2469
2470/// LLVMGetPoison
2471pub fn llvm_get_poison(ty: LLVMType) -> LLVMValue {
2472    unsafe { LLVMGetPoison(ty.into()).into() }
2473}
2474
2475/// LLVMAddFunction
2476pub fn llvm_add_function(module: &LLVMModule, name: &str, fn_ty: LLVMType) -> LLVMValue {
2477    assert!(llvm_get_type_kind(fn_ty) == LLVMTypeKind::LLVMFunctionTypeKind);
2478    unsafe { LLVMAddFunction(module.inner_ref(), to_c_str(name).as_ptr(), fn_ty.into()).into() }
2479}
2480
2481/// LLVMGetNamedFunction
2482pub fn llvm_get_named_function(module: &LLVMModule, name: &str) -> Option<LLVMValue> {
2483    unsafe {
2484        let func = LLVMGetNamedFunction(module.inner_ref(), to_c_str(name).as_ptr());
2485        (!func.is_null()).then_some(func.into())
2486    }
2487}
2488
2489/// LLVMDeleteFunction
2490pub fn llvm_delete_function(func: LLVMValue) {
2491    assert!(llvm_is_a::function(func));
2492    unsafe { LLVMDeleteFunction(func.into()) }
2493}
2494
2495/// LLVMAppendBasicBlockInContext
2496pub fn llvm_append_basic_block_in_context(
2497    context: &LLVMContext,
2498    func: LLVMValue,
2499    name: &str,
2500) -> LLVMBasicBlock {
2501    assert!(llvm_is_a::function(func));
2502    unsafe {
2503        LLVMAppendBasicBlockInContext(context.inner_ref(), func.into(), to_c_str(name).as_ptr())
2504            .into()
2505    }
2506}
2507
2508/// LLVMGetCalledValue
2509pub fn llvm_get_called_value(inst: LLVMValue) -> LLVMValue {
2510    assert!(llvm_is_a::call_inst(inst) || llvm_is_a::invoke_inst(inst));
2511    unsafe { LLVMGetCalledValue(inst.into()).into() }
2512}
2513
2514/// LLVMGetNumArgOperands
2515pub fn llvm_get_num_arg_operands(inst: LLVMValue) -> u32 {
2516    assert!(llvm_is_a::call_inst(inst) || llvm_is_a::invoke_inst(inst));
2517    unsafe { LLVMGetNumArgOperands(inst.into()) }
2518}
2519
2520/// LLVMGetCalledFunctionType
2521pub fn llvm_get_called_function_type(inst: LLVMValue) -> LLVMType {
2522    assert!(llvm_is_a::call_inst(inst) || llvm_is_a::invoke_inst(inst));
2523    unsafe { LLVMGetCalledFunctionType(inst.into()).into() }
2524}
2525
2526/// LLVMGetNUW
2527pub fn llvm_get_nuw(arith_inst: LLVMValue) -> bool {
2528    assert!(llvm_is_a::instruction(arith_inst));
2529    unsafe { LLVMGetNUW(arith_inst.into()).to_bool() }
2530}
2531
2532/// LLVMGetNSW
2533pub fn llvm_get_nsw(arith_inst: LLVMValue) -> bool {
2534    assert!(llvm_is_a::instruction(arith_inst));
2535    unsafe { LLVMGetNSW(arith_inst.into()).to_bool() }
2536}
2537
2538/// LLVMCanValueUseFastMathFlags
2539pub fn llvm_can_value_use_fast_math_flags(fpmath_inst: LLVMValue) -> bool {
2540    unsafe { LLVMCanValueUseFastMathFlags(fpmath_inst.into()).to_bool() }
2541}
2542
2543/// LLVMGetFastMathFlags
2544pub fn llvm_get_fast_math_flags(fpmath_inst: LLVMValue) -> FastmathFlags {
2545    assert!(llvm_can_value_use_fast_math_flags(fpmath_inst));
2546    unsafe { LLVMGetFastMathFlags(fpmath_inst.into()) }.into()
2547}
2548
2549/// LLVMSetFastMathFlags
2550pub fn llvm_set_fast_math_flags(fpmath_inst: LLVMValue, flags: FastmathFlags) {
2551    assert!(llvm_can_value_use_fast_math_flags(fpmath_inst));
2552    unsafe { LLVMSetFastMathFlags(fpmath_inst.into(), flags.into()) }
2553}
2554
2555/// LLVMGetGEPSourceElementType
2556pub fn llvm_get_gep_source_element_type(gep: LLVMValue) -> LLVMType {
2557    assert!(
2558        llvm_is_a::get_element_ptr_inst(gep)
2559            || (llvm_is_a::constant_expr(gep)
2560                && llvm_get_const_opcode(gep) == LLVMOpcode::LLVMGetElementPtr)
2561    );
2562    unsafe { LLVMGetGEPSourceElementType(gep.into()).into() }
2563}
2564
2565/// LLVMGetNumIndices
2566pub fn llvm_get_num_indices(inst: LLVMValue) -> u32 {
2567    assert!(llvm_is_a::insert_value_inst(inst) || llvm_is_a::extract_value_inst(inst));
2568    unsafe { LLVMGetNumIndices(inst.into()) }
2569}
2570
2571/// LLVMGetIndices
2572pub fn llvm_get_indices(inst: LLVMValue) -> Vec<u32> {
2573    assert!(llvm_is_a::insert_value_inst(inst) || llvm_is_a::extract_value_inst(inst));
2574    let num_indices = llvm_get_num_indices(inst);
2575    let indices = unsafe { LLVMGetIndices(inst.into()) };
2576    c_array_to_vec(indices, num_indices as usize)
2577}
2578
2579#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2580pub struct IntrinsicID(u32);
2581
2582/// Can this be an intrinsic name?
2583/// Valid intrinsic names start with "llvm."
2584fn llvm_name_has_intrinsic_prefix(name: &str) -> bool {
2585    name.starts_with("llvm.")
2586}
2587
2588/// LLVMLookupIntrinsicID
2589pub fn llvm_lookup_intrinsic_id(name: &str) -> Option<IntrinsicID> {
2590    if !llvm_name_has_intrinsic_prefix(name) {
2591        return None;
2592    }
2593    let id = unsafe { LLVMLookupIntrinsicID(to_c_str(name).as_ptr(), name.len()) };
2594    (id != 0).then_some(IntrinsicID(id))
2595}
2596
2597/// LLVMIntrinsicIsOverloaded
2598pub fn llvm_intrinsic_is_overloaded(id: IntrinsicID) -> bool {
2599    unsafe { LLVMIntrinsicIsOverloaded(id.0).to_bool() }
2600}
2601
2602/// LLVMGetIntrinsicDeclaration
2603pub fn llvm_get_intrinsic_declaration(
2604    module: &LLVMModule,
2605    id: IntrinsicID,
2606    param_tys: &[LLVMType],
2607) -> Result<LLVMValue, String> {
2608    let overloaded = llvm_intrinsic_is_overloaded(id);
2609
2610    // For overloaded intrinsics, param_tys must not be empty.
2611    // Intrinsic::getName(ID) asserts for overloaded intrinsics
2612    if overloaded && param_tys.is_empty() {
2613        return Err(format!(
2614            "Intrinsic with ID {} is overloaded and requires parameter types",
2615            id.0
2616        ));
2617    }
2618
2619    // For non-overloaded intrinsics, param_tys must be empty.
2620    // Intrinsic::getName(ID Id, ArrayRef<Type *>, Module *M, FunctionType *)
2621    //   asserts for non-overloaded intrinsics.
2622    if !overloaded && !param_tys.is_empty() {
2623        return Err(format!(
2624            "Intrinsic with ID {} is not overloaded and does not accept parameter types",
2625            id.0
2626        ));
2627    }
2628
2629    let mut param_tys: Vec<_> = param_tys.iter().cloned().map(Into::into).collect();
2630    unsafe {
2631        let decl = LLVMGetIntrinsicDeclaration(
2632            module.inner_ref(),
2633            id.0,
2634            param_tys.as_mut_ptr(),
2635            param_tys.len(),
2636        );
2637        (!decl.is_null()).then_some(decl.into())
2638    }
2639    .ok_or_else(|| {
2640        format!(
2641            "Failed to get intrinsic declaration for ID {} in the given module",
2642            id.0
2643        )
2644    })
2645}
2646
2647// We wrap LLVMModule in a module to limit its visibility for constructing
2648mod llvm_module {
2649    use llvm_sys::ir_reader::LLVMParseIRInContext2;
2650
2651    use super::*;
2652
2653    /// RAII wrapper around LLVMModuleRef
2654    pub struct LLVMModule(LLVMModuleRef);
2655
2656    impl Drop for LLVMModule {
2657        fn drop(&mut self) {
2658            unsafe { LLVMDisposeModule(self.0) }
2659        }
2660    }
2661
2662    impl LLVMModule {
2663        pub fn new(module_id: &str, context: &LLVMContext) -> Self {
2664            Self(unsafe {
2665                LLVMModuleCreateWithNameInContext(to_c_str(module_id).as_ptr(), context.inner_ref())
2666            })
2667        }
2668
2669        /// Parse IR in memory buffer to [LLVMModule]
2670        pub fn from_ir_in_memory_buffer(
2671            context: &LLVMContext,
2672            memory_buffer: LLVMMemoryBuffer,
2673        ) -> Result<LLVMModule, String> {
2674            let mut module_ref = MaybeUninit::uninit();
2675            let mut err_string = MaybeUninit::uninit();
2676
2677            let success = unsafe {
2678                LLVMParseIRInContext2(
2679                    context.inner_ref(),
2680                    memory_buffer.inner_ref(),
2681                    module_ref.as_mut_ptr(),
2682                    err_string.as_mut_ptr(),
2683                )
2684            };
2685
2686            if success != 0 {
2687                unsafe {
2688                    let err_str = err_string.assume_init();
2689                    let err_string = cstr_to_string(err_str).unwrap();
2690                    LLVMDisposeMessage(err_str);
2691                    return Err(err_string);
2692                }
2693            }
2694
2695            unsafe { Ok(LLVMModule(module_ref.assume_init())) }
2696        }
2697
2698        /// Parse IR in file given by filename into a [LLVMModule]
2699        pub fn from_ir_in_file(
2700            context: &LLVMContext,
2701            filename: &str,
2702        ) -> Result<LLVMModule, String> {
2703            let memory_buffer = LLVMMemoryBuffer::from_file_name(filename)?;
2704            Self::from_ir_in_memory_buffer(context, memory_buffer)
2705        }
2706
2707        /// Print [LLVMModule] to a text assembly file
2708        pub fn asm_to_file(&self, filename: &str) -> Result<(), String> {
2709            let mut err_string = MaybeUninit::uninit();
2710            let return_code = unsafe {
2711                LLVMPrintModuleToFile(self.0, to_c_str(filename).as_ptr(), err_string.as_mut_ptr())
2712            };
2713
2714            if return_code == 1 {
2715                unsafe {
2716                    let err_str = err_string.assume_init();
2717                    let err_string = cstr_to_string(err_str).unwrap();
2718                    LLVMDisposeMessage(err_str);
2719                    return Err(err_string);
2720                }
2721            }
2722
2723            Ok(())
2724        }
2725
2726        /// Print this [LLVMModule] to a bitcode file
2727        pub fn bitcode_to_file(&self, filename: &str) -> Result<(), String> {
2728            unsafe {
2729                if LLVMWriteBitcodeToFile(self.0, to_c_str(filename).as_ptr()) == 0 {
2730                    Ok(())
2731                } else {
2732                    Err("Error writing bitcode to file".into())
2733                }
2734            }
2735        }
2736
2737        /// Verify this module
2738        pub fn verify(&self) -> Result<(), String> {
2739            let mut err_string = MaybeUninit::uninit();
2740            let return_code = unsafe {
2741                LLVMVerifyModule(
2742                    self.0,
2743                    llvm_sys::analysis::LLVMVerifierFailureAction::LLVMReturnStatusAction,
2744                    err_string.as_mut_ptr(),
2745                )
2746            };
2747            if return_code == 1 {
2748                unsafe {
2749                    let err_str = err_string.assume_init();
2750                    let err_string = cstr_to_string(err_str).unwrap();
2751                    LLVMDisposeMessage(err_str);
2752                    return Err(err_string);
2753                }
2754            }
2755            Ok(())
2756        }
2757
2758        ///  Get internal reference
2759        pub(in crate::llvm_sys) fn inner_ref(&self) -> LLVMModuleRef {
2760            self.0
2761        }
2762    }
2763}
2764
2765pub use llvm_module::LLVMModule;
2766
2767impl Display for LLVMModule {
2768    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2769        if let Some(module_str) = llvm_print_module_to_string(self) {
2770            write!(f, "{}", module_str)
2771        } else {
2772            write!(f, "<Error printing LLVMModule at {:p}>", self.inner_ref())
2773        }
2774    }
2775}
2776
2777// We wrap LLVMMemoryBuffer in a module to limit its visibility for constructing
2778mod llvm_memory_buffer {
2779    use super::*;
2780
2781    /// RAII wrapper around LLVMMemoryBufferRef
2782    pub struct LLVMMemoryBuffer(LLVMMemoryBufferRef);
2783
2784    impl LLVMMemoryBuffer {
2785        /// Create [LLVMMemoryBuffer] from a filename.
2786        pub fn from_file_name(name: &str) -> Result<LLVMMemoryBuffer, String> {
2787            let mut memory_buffer_ref = ptr::null_mut();
2788            let mut err_string = MaybeUninit::uninit();
2789
2790            let return_code = unsafe {
2791                LLVMCreateMemoryBufferWithContentsOfFile(
2792                    to_c_str(name).as_ptr(),
2793                    &mut memory_buffer_ref,
2794                    err_string.as_mut_ptr(),
2795                )
2796            };
2797
2798            if return_code == 1 {
2799                unsafe {
2800                    let err_str = err_string.assume_init();
2801                    let err_string = cstr_to_string(err_str).unwrap();
2802                    LLVMDisposeMessage(err_str);
2803                    return Err(err_string);
2804                }
2805            }
2806
2807            Ok(LLVMMemoryBuffer(memory_buffer_ref))
2808        }
2809
2810        /// Create [LLVMMemoryBuffer] from [str].
2811        pub fn from_str(contents: &str, buffer_name: &str) -> LLVMMemoryBuffer {
2812            unsafe {
2813                LLVMMemoryBuffer(LLVMCreateMemoryBufferWithMemoryRangeCopy(
2814                    contents.as_ptr() as *const _,
2815                    contents.len(),
2816                    to_c_str(buffer_name).as_ptr(),
2817                ))
2818            }
2819        }
2820    }
2821
2822    impl Drop for LLVMMemoryBuffer {
2823        fn drop(&mut self) {
2824            unsafe { LLVMDisposeMemoryBuffer(self.inner_ref()) }
2825        }
2826    }
2827
2828    impl LLVMMemoryBuffer {
2829        /// Get internal reference
2830        pub(super) fn inner_ref(&self) -> LLVMMemoryBufferRef {
2831            self.0
2832        }
2833    }
2834}
2835
2836pub use llvm_memory_buffer::LLVMMemoryBuffer;
2837
2838/// Process [LLVMErrorRef] into Result<(), String>.
2839pub(super) fn handle_err(err: LLVMErrorRef) -> Result<(), String> {
2840    if err.is_null() {
2841        Ok(())
2842    } else {
2843        unsafe {
2844            let err_msg_ptr = LLVMGetErrorMessage(err);
2845            let err_msg = cstr_to_string(err_msg_ptr).unwrap();
2846            LLVMDisposeErrorMessage(err_msg_ptr);
2847            Err(err_msg)
2848        }
2849    }
2850}
2851
2852// =============================================================================
2853// Atomics + inline assembly.
2854//
2855// Wrappers for the LLVM-C atomic and inline-asm builders/accessors, used by the
2856// to_llvm_ir / from_llvm_ir bridge for `llvm.atomicrmw`, `llvm.cmpxchg`,
2857// `llvm.fence`, `llvm.atomic_load`, `llvm.atomic_store` and `llvm.inline_asm`.
2858// =============================================================================
2859
2860// llvm-sys 221's binding for `LLVMGetSyncScopeID` is missing its return type
2861// (it is declared as returning `()`), so we re-declare the correct signature.
2862// The real LLVM-C symbol returns the `unsigned` synchronization-scope id.
2863unsafe extern "C" {
2864    fn LLVMGetSyncScopeID(
2865        c: llvm_sys::prelude::LLVMContextRef,
2866        name: *const core::ffi::c_char,
2867        slen: usize,
2868    ) -> core::ffi::c_uint;
2869}
2870
2871/// Resolve a synchronization-scope id by name within `ctx`. The empty string is
2872/// the system scope (id 1); `"singlethread"` is the single-thread scope (id 0).
2873pub fn llvm_get_sync_scope_id(ctx: &LLVMContext, name: &str) -> u32 {
2874    unsafe {
2875        LLVMGetSyncScopeID(
2876            ctx.inner_ref(),
2877            name.as_ptr() as *const core::ffi::c_char,
2878            name.len(),
2879        )
2880    }
2881}
2882
2883/// LLVMBuildAtomicRMWSyncScope
2884pub fn llvm_build_atomic_rmw(
2885    builder: &LLVMBuilder,
2886    op: llvm_sys::LLVMAtomicRMWBinOp,
2887    ptr: LLVMValue,
2888    val: LLVMValue,
2889    ordering: llvm_sys::LLVMAtomicOrdering,
2890    ssid: u32,
2891) -> LLVMValue {
2892    assert!(llvm_get_insert_block(builder).is_some());
2893    unsafe {
2894        llvm_sys::core::LLVMBuildAtomicRMWSyncScope(
2895            builder.inner_ref(),
2896            op,
2897            ptr.into(),
2898            val.into(),
2899            ordering,
2900            ssid,
2901        )
2902        .into()
2903    }
2904}
2905
2906/// LLVMBuildAtomicCmpXchgSyncScope (result is the `{ T, i1 }` pair).
2907pub fn llvm_build_atomic_cmpxchg(
2908    builder: &LLVMBuilder,
2909    ptr: LLVMValue,
2910    cmp: LLVMValue,
2911    new: LLVMValue,
2912    success: llvm_sys::LLVMAtomicOrdering,
2913    failure: llvm_sys::LLVMAtomicOrdering,
2914    ssid: u32,
2915) -> LLVMValue {
2916    assert!(llvm_get_insert_block(builder).is_some());
2917    unsafe {
2918        llvm_sys::core::LLVMBuildAtomicCmpXchgSyncScope(
2919            builder.inner_ref(),
2920            ptr.into(),
2921            cmp.into(),
2922            new.into(),
2923            success,
2924            failure,
2925            ssid,
2926        )
2927        .into()
2928    }
2929}
2930
2931/// LLVMBuildFenceSyncScope
2932pub fn llvm_build_fence(
2933    builder: &LLVMBuilder,
2934    ordering: llvm_sys::LLVMAtomicOrdering,
2935    ssid: u32,
2936    name: &str,
2937) -> LLVMValue {
2938    assert!(llvm_get_insert_block(builder).is_some());
2939    unsafe {
2940        llvm_sys::core::LLVMBuildFenceSyncScope(
2941            builder.inner_ref(),
2942            ordering,
2943            ssid,
2944            to_c_str(name).as_ptr(),
2945        )
2946        .into()
2947    }
2948}
2949
2950/// LLVMSetOrdering: turn a plain load/store into an atomic one.
2951pub fn llvm_set_ordering(inst: LLVMValue, ordering: llvm_sys::LLVMAtomicOrdering) {
2952    unsafe { llvm_sys::core::LLVMSetOrdering(inst.into(), ordering) }
2953}
2954
2955/// LLVMGetOrdering
2956pub fn llvm_get_ordering(inst: LLVMValue) -> llvm_sys::LLVMAtomicOrdering {
2957    unsafe { llvm_sys::core::LLVMGetOrdering(inst.into()) }
2958}
2959
2960/// LLVMSetAtomicSyncScopeID
2961pub fn llvm_set_atomic_sync_scope_id(inst: LLVMValue, ssid: u32) {
2962    unsafe { llvm_sys::core::LLVMSetAtomicSyncScopeID(inst.into(), ssid) }
2963}
2964
2965/// LLVMGetAtomicSyncScopeID
2966pub fn llvm_get_atomic_sync_scope_id(inst: LLVMValue) -> u32 {
2967    unsafe { llvm_sys::core::LLVMGetAtomicSyncScopeID(inst.into()) }
2968}
2969
2970/// LLVMGetAtomicRMWBinOp
2971pub fn llvm_get_atomic_rmw_bin_op(inst: LLVMValue) -> llvm_sys::LLVMAtomicRMWBinOp {
2972    unsafe { llvm_sys::core::LLVMGetAtomicRMWBinOp(inst.into()) }
2973}
2974
2975/// LLVMGetCmpXchgSuccessOrdering
2976pub fn llvm_get_cmpxchg_success_ordering(inst: LLVMValue) -> llvm_sys::LLVMAtomicOrdering {
2977    unsafe { llvm_sys::core::LLVMGetCmpXchgSuccessOrdering(inst.into()) }
2978}
2979
2980/// LLVMGetCmpXchgFailureOrdering
2981pub fn llvm_get_cmpxchg_failure_ordering(inst: LLVMValue) -> llvm_sys::LLVMAtomicOrdering {
2982    unsafe { llvm_sys::core::LLVMGetCmpXchgFailureOrdering(inst.into()) }
2983}
2984
2985/// LLVMGetInlineAsm: create an inline-asm callee value of function type `fn_ty`.
2986#[allow(clippy::too_many_arguments)]
2987pub fn llvm_get_inline_asm(
2988    fn_ty: LLVMType,
2989    asm: &str,
2990    constraints: &str,
2991    has_side_effects: bool,
2992    is_align_stack: bool,
2993    dialect: llvm_sys::LLVMInlineAsmDialect,
2994    can_throw: bool,
2995) -> LLVMValue {
2996    unsafe {
2997        llvm_sys::core::LLVMGetInlineAsm(
2998            fn_ty.into(),
2999            asm.as_ptr() as *const core::ffi::c_char,
3000            asm.len(),
3001            constraints.as_ptr() as *const core::ffi::c_char,
3002            constraints.len(),
3003            has_side_effects as llvm_sys::prelude::LLVMBool,
3004            is_align_stack as llvm_sys::prelude::LLVMBool,
3005            dialect,
3006            can_throw as llvm_sys::prelude::LLVMBool,
3007        )
3008        .into()
3009    }
3010}
3011
3012/// LLVMGetInlineAsmAsmString
3013pub fn llvm_get_inline_asm_asm_string(v: LLVMValue) -> String {
3014    unsafe {
3015        let mut len: usize = 0;
3016        let ptr = llvm_sys::core::LLVMGetInlineAsmAsmString(v.into(), &mut len);
3017        String::from_utf8_lossy(std::slice::from_raw_parts(ptr as *const u8, len)).into_owned()
3018    }
3019}
3020
3021/// LLVMGetInlineAsmConstraintString
3022pub fn llvm_get_inline_asm_constraint_string(v: LLVMValue) -> String {
3023    unsafe {
3024        let mut len: usize = 0;
3025        let ptr = llvm_sys::core::LLVMGetInlineAsmConstraintString(v.into(), &mut len);
3026        String::from_utf8_lossy(std::slice::from_raw_parts(ptr as *const u8, len)).into_owned()
3027    }
3028}
3029
3030/// LLVMGetInlineAsmHasSideEffects
3031pub fn llvm_get_inline_asm_has_side_effects(v: LLVMValue) -> bool {
3032    unsafe { llvm_sys::core::LLVMGetInlineAsmHasSideEffects(v.into()) != 0 }
3033}
3034
3035/// LLVMGetInlineAsmFunctionType
3036pub fn llvm_get_inline_asm_function_type(v: LLVMValue) -> LLVMType {
3037    unsafe { llvm_sys::core::LLVMGetInlineAsmFunctionType(v.into()).into() }
3038}