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