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