Skip to main content

pliron_llvm/llvm_sys/
core.rs

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