1use 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#[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#[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
166mod llvm_context {
168 use super::*;
169
170 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#[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 pub struct LLVMBuilder(LLVMBuilderRef);
226
227 impl LLVMBuilder {
228 pub fn new(context: &LLVMContext) -> Self {
230 unsafe { LLVMBuilder(LLVMCreateBuilderInContext(context.inner_ref())) }
231 }
232
233 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
337pub 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
348pub 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
359pub 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
370pub 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
380pub 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
390pub fn llvm_dump_value(val: LLVMValue) {
392 unsafe { LLVMDumpValue(val.into()) }
393}
394
395pub fn llvm_dump_type(ty: LLVMType) {
397 unsafe { LLVMDumpType(ty.into()) }
398}
399
400pub fn llvm_dump_module(module: &LLVMModule) {
402 unsafe { LLVMDumpModule(module.inner_ref()) }
403}
404
405pub 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 pub fn function(val: LLVMValue) -> bool {
423 unsafe { !LLVMIsAFunction(val.into()).is_null() }
424 }
425
426 pub fn user(val: LLVMValue) -> bool {
428 unsafe { !LLVMIsAUser(val.into()).is_null() }
429 }
430
431 pub fn constant(val: LLVMValue) -> bool {
433 unsafe { !LLVMIsAConstant(val.into()).is_null() }
434 }
435
436 pub fn instruction(val: LLVMValue) -> bool {
438 unsafe { !LLVMIsAInstruction(val.into()).is_null() }
439 }
440
441 pub fn global_object(val: LLVMValue) -> bool {
443 unsafe { !LLVMIsAGlobalObject(val.into()).is_null() }
444 }
445
446 pub fn md_node(val: LLVMValue) -> bool {
448 unsafe { !LLVMIsAMDNode(val.into()).is_null() }
449 }
450
451 pub fn value_as_metadata(val: LLVMValue) -> bool {
453 unsafe { !LLVMIsAValueAsMetadata(val.into()).is_null() }
454 }
455
456 pub fn md_string(val: LLVMValue) -> bool {
458 unsafe { !LLVMIsAMDString(val.into()).is_null() }
459 }
460
461 pub fn constant_int(val: LLVMValue) -> bool {
463 unsafe { !LLVMIsAConstantInt(val.into()).is_null() }
464 }
465
466 pub fn constant_fp(val: LLVMValue) -> bool {
468 unsafe { !LLVMIsAConstantFP(val.into()).is_null() }
469 }
470
471 pub fn constant_expr(val: LLVMValue) -> bool {
473 unsafe { !LLVMIsAConstantExpr(val.into()).is_null() }
474 }
475
476 pub fn phi_node(val: LLVMValue) -> bool {
478 unsafe { !LLVMIsAPHINode(val.into()).is_null() }
479 }
480
481 pub fn alloca_inst(val: LLVMValue) -> bool {
483 unsafe { !LLVMIsAAllocaInst(val.into()).is_null() }
484 }
485
486 pub fn icmp_inst(val: LLVMValue) -> bool {
488 unsafe { !LLVMIsAICmpInst(val.into()).is_null() }
489 }
490
491 pub fn fcmp_inst(val: LLVMValue) -> bool {
493 unsafe { !LLVMIsAFCmpInst(val.into()).is_null() }
494 }
495
496 pub fn zext_inst(val: LLVMValue) -> bool {
498 unsafe { !LLVMIsAZExtInst(val.into()).is_null() }
499 }
500
501 pub fn fptoui_inst(val: LLVMValue) -> bool {
503 unsafe { !LLVMIsAFPToUIInst(val.into()).is_null() }
504 }
505
506 pub fn uitofp_inst(val: LLVMValue) -> bool {
508 unsafe { !LLVMIsAUIToFPInst(val.into()).is_null() }
509 }
510
511 pub fn switch_inst(val: LLVMValue) -> bool {
513 unsafe { !LLVMIsASwitchInst(val.into()).is_null() }
514 }
515
516 pub fn indirect_br_inst(val: LLVMValue) -> bool {
518 unsafe { !LLVMIsAIndirectBrInst(val.into()).is_null() }
519 }
520
521 pub fn argument(val: LLVMValue) -> bool {
523 unsafe { !LLVMIsAArgument(val.into()).is_null() }
524 }
525
526 pub fn global_value(val: LLVMValue) -> bool {
528 unsafe { !LLVMIsAGlobalValue(val.into()).is_null() }
529 }
530
531 pub fn global_variable(val: LLVMValue) -> bool {
533 unsafe { !LLVMIsAGlobalVariable(val.into()).is_null() }
534 }
535
536 pub fn call_inst(val: LLVMValue) -> bool {
538 unsafe { !LLVMIsACallInst(val.into()).is_null() }
539 }
540
541 pub fn invoke_inst(val: LLVMValue) -> bool {
543 unsafe { !LLVMIsAInvokeInst(val.into()).is_null() }
544 }
545
546 pub fn get_element_ptr_inst(val: LLVMValue) -> bool {
548 unsafe { !LLVMIsAGetElementPtrInst(val.into()).is_null() }
549 }
550
551 pub fn insert_value_inst(val: LLVMValue) -> bool {
553 unsafe { !LLVMIsAInsertValueInst(val.into()).is_null() }
554 }
555
556 pub fn extract_value_inst(val: LLVMValue) -> bool {
558 unsafe { !LLVMIsAExtractValueInst(val.into()).is_null() }
559 }
560
561 pub fn shuffle_vector_inst(val: LLVMValue) -> bool {
563 unsafe { !LLVMIsAShuffleVectorInst(val.into()).is_null() }
564 }
565
566 pub fn insert_element_inst(val: LLVMValue) -> bool {
568 unsafe { !LLVMIsAInsertElementInst(val.into()).is_null() }
569 }
570
571 pub fn extract_element_inst(val: LLVMValue) -> bool {
573 unsafe { !LLVMIsAExtractElementInst(val.into()).is_null() }
574 }
575
576 pub fn load_inst(val: LLVMValue) -> bool {
578 unsafe { !LLVMIsALoadInst(val.into()).is_null() }
579 }
580
581 pub fn store_inst(val: LLVMValue) -> bool {
583 unsafe { !LLVMIsAStoreInst(val.into()).is_null() }
584 }
585
586 pub fn block_address(val: LLVMValue) -> bool {
588 unsafe { !LLVMIsABlockAddress(val.into()).is_null() }
589 }
590
591 pub fn atomic_rmw_inst(val: LLVMValue) -> bool {
593 unsafe { !LLVMIsAAtomicRMWInst(val.into()).is_null() }
594 }
595
596 pub fn atomic_cmpxchg_inst(val: LLVMValue) -> bool {
598 unsafe { !LLVMIsAAtomicCmpXchgInst(val.into()).is_null() }
599 }
600
601 pub fn fence_inst(val: LLVMValue) -> bool {
603 unsafe { !LLVMIsAFenceInst(val.into()).is_null() }
604 }
605
606 pub fn inline_asm(val: LLVMValue) -> bool {
608 unsafe { !LLVMIsAInlineAsm(val.into()).is_null() }
609 }
610}
611
612pub mod llvm_is {
614 use llvm_sys::core::{LLVMIsAtomic, LLVMIsConstant, LLVMIsPoison, LLVMIsUndef};
615
616 use super::*;
617
618 pub fn constant(val: LLVMValue) -> bool {
620 unsafe { LLVMIsConstant(val.into()).to_bool() }
621 }
622
623 pub fn undef(val: LLVMValue) -> bool {
625 unsafe { LLVMIsUndef(val.into()).to_bool() }
626 }
627
628 pub fn poison(val: LLVMValue) -> bool {
630 unsafe { LLVMIsPoison(val.into()).to_bool() }
631 }
632
633 pub fn atomic(inst: LLVMValue) -> bool {
635 assert!(llvm_is_a::instruction(inst));
636 unsafe { LLVMIsAtomic(inst.into()).to_bool() }
637 }
638}
639
640pub fn llvm_replace_all_uses_with(old_val: LLVMValue, new_val: LLVMValue) {
642 unsafe { LLVMReplaceAllUsesWith(old_val.into(), new_val.into()) }
643}
644
645pub fn llvm_type_of(val: LLVMValue) -> LLVMType {
647 unsafe { LLVMTypeOf(val.into()).into() }
648}
649
650pub 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
656pub 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
662pub 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
668pub fn llvm_is_declaration(val: LLVMValue) -> bool {
670 assert!(llvm_is_a::global_value(val));
671 unsafe { LLVMIsDeclaration(val.into()).to_bool() }
672}
673
674pub 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
680pub fn llvm_type_is_sized(ty: LLVMType) -> bool {
682 unsafe { LLVMTypeIsSized(ty.into()).to_bool() }
683}
684
685pub fn llvm_is_aggregate_type(ty: LLVMType) -> bool {
687 matches!(
688 llvm_get_type_kind(ty),
689 LLVMTypeKind::LLVMArrayTypeKind | LLVMTypeKind::LLVMStructTypeKind
690 )
691}
692
693pub fn llvm_get_type_kind(ty: LLVMType) -> LLVMTypeKind {
695 unsafe { LLVMGetTypeKind(ty.into()) }
696}
697
698pub fn llvm_get_linkage(val: LLVMValue) -> LLVMLinkage {
700 assert!(llvm_is_a::global_value(val));
701 unsafe { LLVMGetLinkage(val.into()) }
702}
703
704pub fn llvm_set_linkage(val: LLVMValue, linkage: LLVMLinkage) {
706 assert!(llvm_is_a::global_value(val));
707 unsafe { LLVMSetLinkage(val.into(), linkage) }
708}
709
710pub 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
716pub 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
722pub 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
731pub 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
742pub 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
758pub 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
770pub fn llvm_get_array_length2(ty: LLVMType) -> u64 {
772 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMArrayTypeKind);
773 unsafe { LLVMGetArrayLength2(ty.into()) }
774}
775
776pub 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
782pub fn llvm_count_param_types(ty: LLVMType) -> u32 {
784 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
785 unsafe { LLVMCountParamTypes(ty.into()) }
786}
787
788pub 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
801pub 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
807pub 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
813pub 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
819pub 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
825pub 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
831pub 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
837pub 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
850pub 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
856pub fn llvm_is_a_terminator_inst(val: LLVMValue) -> bool {
858 !unsafe { LLVMIsATerminatorInst(val.into()) }.is_null()
859}
860
861pub 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
867pub fn llvm_get_value_kind(val: LLVMValue) -> LLVMValueKind {
869 unsafe { LLVMGetValueKind(val.into()) }
870}
871
872pub fn llvm_get_instruction_opcode(val: LLVMValue) -> LLVMOpcode {
874 assert!(llvm_get_value_kind(val) == LLVMValueKind::LLVMInstructionValueKind);
875 unsafe { LLVMGetInstructionOpcode(val.into()) }
876}
877
878pub fn llvm_get_const_opcode(val: LLVMValue) -> LLVMOpcode {
880 assert!(llvm_is_a::constant_expr(val));
881 unsafe { LLVMGetConstOpcode(val.into()) }
882}
883
884pub 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
893pub fn llvm_instruction_erase_from_parent(inst: LLVMValue) {
895 assert!(llvm_is_a::instruction(inst));
896 unsafe { LLVMInstructionEraseFromParent(inst.into()) }
897}
898
899pub fn llvm_get_num_operands(val: LLVMValue) -> u32 {
901 assert!(llvm_is_a::user(val));
902 unsafe { LLVMGetNumOperands(val.into()) as u32 }
903}
904
905pub 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
911pub 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
920pub 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
926pub 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
932pub 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
938pub fn llvm_basic_block_as_value(block: LLVMBasicBlock) -> LLVMValue {
940 unsafe { LLVMBasicBlockAsValue(block.into()).into() }
941}
942
943pub fn llvm_value_is_basic_block(val: LLVMValue) -> bool {
945 unsafe { LLVMValueIsBasicBlock(val.into()).to_bool() }
946}
947
948pub 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
954pub fn llvm_get_basic_block_name(block: LLVMBasicBlock) -> Option<String> {
956 cstr_to_string(unsafe { LLVMGetBasicBlockName(block.into()) })
957}
958
959pub 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
967pub 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
976pub 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
984pub 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
992pub 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
1008pub fn basic_block_iter(fn_val: LLVMValue) -> BasicBlockIter {
1010 BasicBlockIter(llvm_get_first_basic_block(fn_val))
1011}
1012
1013pub 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
1021pub 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
1030pub 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
1039pub 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
1055pub fn instruction_iter(bb: LLVMBasicBlock) -> InstructionIter {
1057 InstructionIter(llvm_get_first_instruction(bb))
1058}
1059
1060pub 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
1066pub 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
1072pub 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
1078pub 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
1102pub 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
1111pub 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
1118pub 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
1133pub 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
1148pub 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
1159pub 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
1167pub 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
1179pub fn llvm_const_null(ty: LLVMType) -> LLVMValue {
1181 unsafe { LLVMConstNull(ty.into()).into() }
1182}
1183
1184pub 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 true.into(),
1193 )
1194 .into()
1195 }
1196}
1197
1198pub fn llvm_is_constant_string(val: LLVMValue) -> bool {
1200 matches!(
1204 llvm_get_value_kind(val),
1205 LLVMValueKind::LLVMConstantDataArrayValueKind
1206 | LLVMValueKind::LLVMConstantDataVectorValueKind
1207 ) && unsafe { LLVMIsConstantString(val.into()).to_bool() }
1208}
1209
1210pub 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 Some(unsafe { core::slice::from_raw_parts(ptr as *const u8, len) }.to_vec())
1222}
1223
1224pub fn llvm_get_allocated_type(val: LLVMValue) -> LLVMType {
1226 assert!(llvm_is_a::alloca_inst(val));
1227 unsafe { LLVMGetAllocatedType(val.into()).into() }
1228}
1229
1230pub 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
1236pub 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
1242pub 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
1248pub 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
1254pub 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
1265pub 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
1276pub 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
1282pub 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
1288pub 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
1294pub fn llvm_get_undef_mask_elem() -> i32 {
1296 unsafe { LLVMGetUndefMaskElem() }
1297}
1298
1299pub 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
1305pub fn llvm_count_params(func: LLVMValue) -> u32 {
1307 assert!(llvm_is_a::function(func));
1308 unsafe { LLVMCountParams(func.into()) }
1309}
1310
1311pub 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
1320pub 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
1329pub 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
1338pub 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
1354pub fn param_iter(func: LLVMValue) -> ParamIter {
1356 assert!(llvm_is_a::function(func));
1357 ParamIter(llvm_get_first_param(func))
1358}
1359
1360pub 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
1366pub 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
1374pub 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
1383pub 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
1392pub 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
1400pub 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
1416pub fn function_iter(module: &LLVMModule) -> FunctionIter {
1418 FunctionIter(llvm_get_first_function(module))
1419}
1420
1421pub 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
1429pub 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
1438pub 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
1447pub 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
1455pub 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
1471pub fn global_iter(module: &LLVMModule) -> GlobalVariableIter {
1473 GlobalVariableIter(llvm_get_first_global(module))
1474}
1475
1476pub 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
1485pub 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
1492pub 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
1498pub 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
1503pub 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
1521pub fn llvm_delete_global(global: LLVMValue) {
1523 assert!(llvm_is_a::global_variable(global));
1524 unsafe { LLVMDeleteGlobal(global.into()) }
1525}
1526
1527pub 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
1535pub fn llvm_clear_insertion_position(builder: &LLVMBuilder) {
1537 unsafe { LLVMClearInsertionPosition(builder.inner_ref()) }
1538}
1539
1540pub fn llvm_position_builder_at_end(builder: &LLVMBuilder, block: LLVMBasicBlock) {
1542 unsafe { LLVMPositionBuilderAtEnd(builder.inner_ref(), block.into()) }
1543}
1544
1545pub 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
1551pub fn llvm_int_type_in_context(context: &LLVMContext, width: u32) -> LLVMType {
1553 unsafe { LLVMIntTypeInContext(context.inner_ref(), width).into() }
1554}
1555
1556pub fn llvm_float_type_in_context(context: &LLVMContext) -> LLVMType {
1558 unsafe { LLVMFloatTypeInContext(context.inner_ref()).into() }
1559}
1560
1561pub fn llvm_double_type_in_context(context: &LLVMContext) -> LLVMType {
1563 unsafe { LLVMDoubleTypeInContext(context.inner_ref()).into() }
1564}
1565
1566pub fn llvm_half_type_in_context(context: &LLVMContext) -> LLVMType {
1568 unsafe { LLVMHalfTypeInContext(context.inner_ref()).into() }
1569}
1570
1571pub fn llvm_bfloat_type_in_context(context: &LLVMContext) -> LLVMType {
1573 unsafe { LLVMBFloatTypeInContext(context.inner_ref()).into() }
1574}
1575
1576pub 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
1589pub 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
1595pub 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
1603pub fn llvm_is_valid_function_argument_type(arg_ty: LLVMType) -> bool {
1605 llvm_is_first_class_type(arg_ty)
1606}
1607
1608pub 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
1618pub 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
1638pub fn llvm_void_type_in_context(context: &LLVMContext) -> LLVMType {
1640 unsafe { LLVMVoidTypeInContext(context.inner_ref()).into() }
1641}
1642
1643pub fn llvm_pointer_type_in_context(context: &LLVMContext, addr_space: u32) -> LLVMType {
1645 unsafe { LLVMPointerTypeInContext(context.inner_ref(), addr_space).into() }
1646}
1647
1648pub 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
1653pub 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
1665pub 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
1688pub 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
1707pub 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
1726pub 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
1745pub 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
1764pub 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
1783pub 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
1802pub 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
1821pub 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
1840pub 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
1859pub 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
1878pub 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
1897pub 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
1916pub 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
1935pub 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
1954pub 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
1975pub 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
1994pub 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
2013pub 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}
2031pub 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
2050pub 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
2069pub 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
2088pub 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
2107pub 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
2134pub 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
2163pub 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 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
2192pub 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 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
2217pub 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 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
2244pub 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
2265pub 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
2284pub 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
2305pub 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
2324pub 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
2343pub 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
2362pub 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
2381pub 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
2400pub 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
2406pub 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
2427pub 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
2446pub 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
2465pub 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
2484pub 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
2503pub 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
2522pub 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
2541pub 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
2562pub 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 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
2587pub 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
2593pub 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
2613pub 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
2619pub 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
2628pub 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
2635pub 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
2643pub 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
2663pub 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
2670pub 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
2691pub 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
2697pub 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
2703pub 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
2709pub 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
2715pub 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
2739pub 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
2758pub 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
2764pub 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
2770pub fn llvm_get_undef(ty: LLVMType) -> LLVMValue {
2772 unsafe { LLVMGetUndef(ty.into()).into() }
2773}
2774
2775pub fn llvm_get_poison(ty: LLVMType) -> LLVMValue {
2777 unsafe { LLVMGetPoison(ty.into()).into() }
2778}
2779
2780#[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
2796pub use llvm_sys::LLVMAttributeIndex;
2799
2800pub const LLVM_ATTRIBUTE_FUNCTION_INDEX: LLVMAttributeIndex =
2802 LLVMAttributeFunctionIndex as LLVMAttributeIndex;
2803
2804pub const LLVM_ATTRIBUTE_RETURN_INDEX: LLVMAttributeIndex =
2806 LLVMAttributeReturnIndex as LLVMAttributeIndex;
2807
2808fn is_valid_enum_attribute_kind(kind: u32) -> bool {
2810 kind != 0 && kind < llvm_get_last_enum_attribute_kind()
2811}
2812
2813pub fn llvm_get_last_enum_attribute_kind() -> u32 {
2815 unsafe { LLVMGetLastEnumAttributeKind() }
2816}
2817
2818pub 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
2826pub fn llvm_is_enum_attribute(attr: LLVMAttribute) -> bool {
2828 unsafe { LLVMIsEnumAttribute(attr.into()).to_bool() }
2829}
2830
2831pub fn llvm_is_string_attribute(attr: LLVMAttribute) -> bool {
2833 unsafe { LLVMIsStringAttribute(attr.into()).to_bool() }
2834}
2835
2836pub fn llvm_is_type_attribute(attr: LLVMAttribute) -> bool {
2838 unsafe { LLVMIsTypeAttribute(attr.into()).to_bool() }
2839}
2840
2841pub fn llvm_get_enum_attribute_kind(attr: LLVMAttribute) -> u32 {
2843 assert!(!llvm_is_string_attribute(attr));
2844 unsafe { LLVMGetEnumAttributeKind(attr.into()) }
2845}
2846
2847pub fn llvm_get_enum_attribute_value(attr: LLVMAttribute) -> u64 {
2849 assert!(llvm_is_enum_attribute(attr));
2850 unsafe { LLVMGetEnumAttributeValue(attr.into()) }
2851}
2852
2853pub fn llvm_get_type_attribute_value(attr: LLVMAttribute) -> LLVMType {
2855 assert!(llvm_is_type_attribute(attr));
2856 unsafe { LLVMGetTypeAttributeValue(attr.into()).into() }
2857}
2858
2859pub 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
2867pub 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
2875pub 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
2881pub 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
2887pub 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
2904pub 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
2921pub 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
2927pub 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
2944pub 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
2950pub 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
2956pub 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
2964pub fn llvm_delete_function(func: LLVMValue) {
2966 assert!(llvm_is_a::function(func));
2967 unsafe { LLVMDeleteFunction(func.into()) }
2968}
2969
2970pub 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
2983pub 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
2989pub 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
2995pub 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
3001pub 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
3007pub 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
3013pub fn llvm_can_value_use_fast_math_flags(fpmath_inst: LLVMValue) -> bool {
3015 unsafe { LLVMCanValueUseFastMathFlags(fpmath_inst.into()).to_bool() }
3016}
3017
3018pub 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
3024pub 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
3030pub 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
3040pub 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
3050pub 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
3056pub 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
3067fn llvm_name_has_intrinsic_prefix(name: &str) -> bool {
3070 name.starts_with("llvm.")
3071}
3072
3073pub 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
3082pub fn llvm_intrinsic_is_overloaded(id: IntrinsicID) -> bool {
3084 unsafe { LLVMIntrinsicIsOverloaded(id.0).to_bool() }
3085}
3086
3087pub 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 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 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
3132mod llvm_module {
3134 use llvm_sys::ir_reader::LLVMParseIRInContext2;
3135
3136 use super::*;
3137
3138 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 pub fn set_data_layout(&self, data_layout: &str) {
3156 unsafe { LLVMSetDataLayout(self.0, to_c_str(data_layout).as_ptr()) }
3157 }
3158
3159 pub fn data_layout(&self) -> String {
3161 cstr_to_string(unsafe { LLVMGetDataLayoutStr(self.0) }).unwrap_or_default()
3162 }
3163
3164 pub fn set_target_triple(&self, target_triple: &str) {
3166 unsafe { LLVMSetTarget(self.0, to_c_str(target_triple).as_ptr()) }
3167 }
3168
3169 pub fn target_triple(&self) -> String {
3171 cstr_to_string(unsafe { LLVMGetTarget(self.0) }).unwrap_or_default()
3172 }
3173
3174 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 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 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 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 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 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 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
3292mod llvm_memory_buffer {
3294 use super::*;
3295
3296 pub struct LLVMMemoryBuffer(LLVMMemoryBufferRef);
3298
3299 impl LLVMMemoryBuffer {
3300 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 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 pub(super) fn inner_ref(&self) -> LLVMMemoryBufferRef {
3346 self.0
3347 }
3348 }
3349}
3350
3351pub use llvm_memory_buffer::LLVMMemoryBuffer;
3352
3353pub(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
3367pub 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
3378pub 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 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
3408pub 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 assert!(!matches!(
3423 success,
3424 LLVMAtomicOrdering::LLVMAtomicOrderingNotAtomic
3425 | LLVMAtomicOrdering::LLVMAtomicOrderingUnordered
3426 ));
3427 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
3449pub 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 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
3470fn 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
3479pub fn llvm_set_ordering(inst: LLVMValue, ordering: LLVMAtomicOrdering) {
3481 assert!(has_ordering(inst));
3482 unsafe { LLVMSetOrdering(inst.into(), ordering) }
3483}
3484
3485pub fn llvm_get_ordering(inst: LLVMValue) -> LLVMAtomicOrdering {
3487 assert!(has_ordering(inst));
3488 unsafe { LLVMGetOrdering(inst.into()) }
3489}
3490
3491pub 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
3497pub fn llvm_get_atomic_sync_scope_id(inst: LLVMValue) -> u32 {
3499 assert!(llvm_is::atomic(inst));
3500 unsafe { LLVMGetAtomicSyncScopeID(inst.into()) }
3501}
3502
3503pub 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
3509pub 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
3515pub 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#[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
3549pub 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
3559pub 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
3569pub 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
3575pub 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#[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
3597fn 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
3609fn 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
3617pub 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
3625pub 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
3637pub 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
3646pub 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
3658pub fn llvm_dispose_temporary_md_node(temp: LLVMMetadata) {
3660 unsafe { LLVMDisposeTemporaryMDNode(temp.into()) }
3661}
3662
3663pub fn llvm_metadata_replace_all_uses_with(temp: LLVMMetadata, replacement: LLVMMetadata) {
3667 unsafe { LLVMMetadataReplaceAllUsesWith(temp.into(), replacement.into()) }
3668}
3669
3670pub fn llvm_get_metadata_kind(md: LLVMMetadata) -> LLVMMetadataKind {
3672 unsafe { LLVMGetMetadataKind(md.into()) }
3673}
3674
3675pub fn llvm_metadata_as_value(ctx: &LLVMContext, md: LLVMMetadata) -> LLVMValue {
3677 unsafe { LLVMMetadataAsValue(ctx.inner_ref(), md.into()).into() }
3678}
3679
3680pub fn llvm_value_as_metadata(val: LLVMValue) -> LLVMMetadata {
3682 unsafe { LLVMValueAsMetadata(val.into()).into() }
3683}
3684
3685pub 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
3696pub 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
3708pub 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
3726pub 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
3740pub 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
3757fn 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
3775pub 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
3789pub 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
3797pub 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
3804pub 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
3811pub 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
3827pub 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
3844pub 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
3851pub 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
3860pub 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
3872pub 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}