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