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