1use std::{
4 fmt::{self, Display, Formatter},
5 mem::MaybeUninit,
6 ptr,
7};
8
9use bitflags::bitflags;
10
11use llvm_sys::{
12 LLVMFastMathAllowContract, LLVMFastMathAllowReassoc, LLVMFastMathAllowReciprocal,
13 LLVMFastMathApproxFunc, LLVMFastMathFlags, LLVMFastMathNoInfs, LLVMFastMathNoNaNs,
14 LLVMFastMathNoSignedZeros, LLVMFastMathNone, LLVMIntPredicate, LLVMLinkage, LLVMOpcode,
15 LLVMRealPredicate, LLVMTypeKind, LLVMValueKind,
16 analysis::LLVMVerifyModule,
17 bit_writer::LLVMWriteBitcodeToFile,
18 core::{
19 LLVMAddCase, LLVMAddFunction, LLVMAddGlobal, LLVMAddIncoming,
20 LLVMAppendBasicBlockInContext, LLVMArrayType2, LLVMBasicBlockAsValue, LLVMBuildAShr,
21 LLVMBuildAdd, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildBitCast, LLVMBuildBr,
22 LLVMBuildCall2, LLVMBuildCondBr, LLVMBuildExtractElement, LLVMBuildExtractValue,
23 LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, LLVMBuildFMul, LLVMBuildFPExt,
24 LLVMBuildFPToSI, LLVMBuildFPToUI, LLVMBuildFPTrunc, LLVMBuildFRem, LLVMBuildFSub,
25 LLVMBuildFreeze, LLVMBuildGEP2, LLVMBuildICmp, LLVMBuildInsertElement,
26 LLVMBuildInsertValue, LLVMBuildIntToPtr, LLVMBuildLShr, LLVMBuildLoad2, LLVMBuildMul,
27 LLVMBuildOr, LLVMBuildPhi, LLVMBuildPtrToInt, LLVMBuildRet, LLVMBuildRetVoid,
28 LLVMBuildSDiv, LLVMBuildSExt, LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect,
29 LLVMBuildShl, LLVMBuildShuffleVector, LLVMBuildStore, LLVMBuildSub, LLVMBuildSwitch,
30 LLVMBuildTrunc, LLVMBuildUDiv, LLVMBuildUIToFP, LLVMBuildURem, LLVMBuildUnreachable,
31 LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt, LLVMCanValueUseFastMathFlags,
32 LLVMClearInsertionPosition, LLVMConstInt, LLVMConstIntGetZExtValue, LLVMConstNull,
33 LLVMConstReal, LLVMConstRealGetDouble, LLVMConstVector, LLVMContextCreate,
34 LLVMContextDispose, LLVMCountIncoming, LLVMCountParamTypes, LLVMCountParams,
35 LLVMCountStructElementTypes, LLVMCreateBuilderInContext,
36 LLVMCreateMemoryBufferWithContentsOfFile, LLVMCreateMemoryBufferWithMemoryRangeCopy,
37 LLVMDeleteFunction, LLVMDisposeMemoryBuffer, LLVMDisposeMessage, LLVMDisposeModule,
38 LLVMDoubleTypeInContext, LLVMDumpModule, LLVMDumpType, LLVMDumpValue,
39 LLVMFloatTypeInContext, LLVMFunctionType, LLVMGetAggregateElement, LLVMGetAlignment,
40 LLVMGetAllocatedType, LLVMGetArrayLength2, LLVMGetBasicBlockName, LLVMGetBasicBlockParent,
41 LLVMGetBasicBlockTerminator, LLVMGetCalledFunctionType, LLVMGetCalledValue,
42 LLVMGetConstOpcode, LLVMGetElementType, LLVMGetFCmpPredicate, LLVMGetFastMathFlags,
43 LLVMGetFirstBasicBlock, LLVMGetFirstFunction, LLVMGetFirstGlobal, LLVMGetFirstInstruction,
44 LLVMGetFirstParam, LLVMGetGEPSourceElementType, LLVMGetICmpPredicate, LLVMGetIncomingBlock,
45 LLVMGetIncomingValue, LLVMGetIndices, LLVMGetInitializer, LLVMGetInsertBlock,
46 LLVMGetInstructionOpcode, LLVMGetInstructionParent, LLVMGetIntTypeWidth,
47 LLVMGetIntrinsicDeclaration, LLVMGetLastFunction, LLVMGetLastGlobal, LLVMGetLinkage,
48 LLVMGetMaskValue, LLVMGetModuleIdentifier, LLVMGetNNeg, LLVMGetNSW, LLVMGetNUW,
49 LLVMGetNamedFunction, LLVMGetNamedGlobal, LLVMGetNextBasicBlock, LLVMGetNextFunction,
50 LLVMGetNextGlobal, LLVMGetNextInstruction, LLVMGetNextParam, LLVMGetNumArgOperands,
51 LLVMGetNumIndices, LLVMGetNumMaskElements, LLVMGetNumOperands, LLVMGetOperand,
52 LLVMGetParam, LLVMGetParamTypes, LLVMGetPoison, LLVMGetPreviousBasicBlock,
53 LLVMGetPreviousFunction, LLVMGetPreviousGlobal, LLVMGetPreviousInstruction,
54 LLVMGetPreviousParam, LLVMGetReturnType, LLVMGetStructElementTypes, LLVMGetStructName,
55 LLVMGetSwitchCaseValue, LLVMGetTypeKind, LLVMGetUndef, LLVMGetUndefMaskElem,
56 LLVMGetValueKind, LLVMGetValueName2, LLVMGetVectorSize, LLVMGlobalGetValueType,
57 LLVMIntTypeInContext, LLVMIntrinsicIsOverloaded, LLVMIsAFunction, LLVMIsATerminatorInst,
58 LLVMIsAUser, LLVMIsDeclaration, LLVMIsFunctionVarArg, LLVMIsOpaqueStruct,
59 LLVMLookupIntrinsicID, LLVMModuleCreateWithNameInContext, LLVMPointerTypeInContext,
60 LLVMPositionBuilderAtEnd, LLVMPositionBuilderBefore, LLVMPrintModuleToFile,
61 LLVMPrintModuleToString, LLVMPrintTypeToString, LLVMPrintValueToString,
62 LLVMScalableVectorType, LLVMSetAlignment, LLVMSetFastMathFlags, LLVMSetInitializer,
63 LLVMSetLinkage, LLVMSetNNeg, LLVMStructCreateNamed, LLVMStructSetBody,
64 LLVMStructTypeInContext, LLVMTypeIsSized, LLVMTypeOf, LLVMValueAsBasicBlock,
65 LLVMValueIsBasicBlock, LLVMVectorType, LLVMVoidTypeInContext,
66 },
67 error::{LLVMDisposeErrorMessage, LLVMErrorRef, LLVMGetErrorMessage},
68 prelude::{
69 LLVMBasicBlockRef, LLVMBuilderRef, LLVMContextRef, LLVMMemoryBufferRef, LLVMModuleRef,
70 LLVMTypeRef, LLVMValueRef,
71 },
72};
73
74use crate::llvm_sys::{
75 ToBool, c_array_to_vec, cstr_to_string, sized_cstr_to_string, to_c_str, uninitialized_vec,
76};
77
78#[derive(Clone, Copy, PartialEq, Eq, Hash)]
80pub struct LLVMValue(LLVMValueRef);
81
82impl From<LLVMValueRef> for LLVMValue {
83 fn from(value: LLVMValueRef) -> Self {
84 LLVMValue(value)
85 }
86}
87
88impl From<LLVMValue> for LLVMValueRef {
89 fn from(value: LLVMValue) -> Self {
90 value.0
91 }
92}
93
94impl Display for LLVMValue {
95 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
96 if let Some(s) = llvm_print_value_to_string(*self) {
97 write!(f, "{}", s)
98 } else {
99 write!(f, "<Error printing LLVMValue at {:p}>", self.0)
100 }
101 }
102}
103
104#[derive(Clone, Copy, PartialEq, Eq, Hash)]
106pub struct LLVMType(LLVMTypeRef);
107
108impl From<LLVMTypeRef> for LLVMType {
109 fn from(ty: LLVMTypeRef) -> Self {
110 LLVMType(ty)
111 }
112}
113
114impl From<LLVMType> for LLVMTypeRef {
115 fn from(ty: LLVMType) -> Self {
116 ty.0
117 }
118}
119
120impl Display for LLVMType {
121 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
122 if let Some(s) = llvm_print_type_to_string(*self) {
123 write!(f, "{}", s)
124 } else {
125 write!(f, "<Error printing LLVMType at {:p}>", self.0)
126 }
127 }
128}
129
130mod llvm_context {
132 use super::*;
133
134 pub struct LLVMContext(LLVMContextRef);
136
137 impl Default for LLVMContext {
138 fn default() -> Self {
139 unsafe { LLVMContext(LLVMContextCreate()) }
140 }
141 }
142
143 impl Drop for LLVMContext {
144 fn drop(&mut self) {
145 unsafe { LLVMContextDispose(self.0) }
146 }
147 }
148
149 impl LLVMContext {
150 pub(super) fn inner_ref(&self) -> LLVMContextRef {
151 self.0
152 }
153 }
154}
155pub use llvm_context::LLVMContext;
156
157#[derive(Clone, Copy, PartialEq, Eq, Hash)]
159pub struct LLVMBasicBlock(LLVMBasicBlockRef);
160
161impl From<LLVMBasicBlockRef> for LLVMBasicBlock {
162 fn from(ty: LLVMBasicBlockRef) -> Self {
163 LLVMBasicBlock(ty)
164 }
165}
166
167impl From<LLVMBasicBlock> for LLVMBasicBlockRef {
168 fn from(ty: LLVMBasicBlock) -> Self {
169 ty.0
170 }
171}
172
173impl Display for LLVMBasicBlock {
174 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
175 if let Some(s) = llvm_print_value_to_string(LLVMValue(self.0 as LLVMValueRef)) {
176 write!(f, "{}", s)
177 } else {
178 write!(f, "<Error printing LLVMBasicBlock at {:p}>", self.0)
179 }
180 }
181}
182
183mod llvm_builder {
184
185 use llvm_sys::core::LLVMDisposeBuilder;
186
187 use super::*;
188 pub struct LLVMBuilder(LLVMBuilderRef);
190
191 impl LLVMBuilder {
192 pub fn new(context: &LLVMContext) -> Self {
194 unsafe { LLVMBuilder(LLVMCreateBuilderInContext(context.inner_ref())) }
195 }
196
197 pub(crate) fn inner_ref(&self) -> LLVMBuilderRef {
199 self.0
200 }
201 }
202
203 impl Drop for LLVMBuilder {
204 fn drop(&mut self) {
205 unsafe { LLVMDisposeBuilder(self.0) }
206 }
207 }
208}
209
210pub use llvm_builder::LLVMBuilder;
211
212bitflags! {
213 #[derive(PartialEq, Eq, Clone, Debug, Hash, Copy)]
215 pub struct FastmathFlags: u8 {
216 const NNAN = 1;
217 const NINF = 2;
218 const NSZ = 4;
219 const ARCP = 8;
220 const CONTRACT = 16;
221 const AFN = 32;
222 const REASSOC = 64;
223 const FAST = 127;
224 }
225}
226
227impl From<LLVMFastMathFlags> for FastmathFlags {
228 fn from(flags: LLVMFastMathFlags) -> Self {
229 let mut result = FastmathFlags::empty();
230 if flags & LLVMFastMathNoNaNs != 0 {
231 result |= FastmathFlags::NNAN;
232 }
233 if flags & LLVMFastMathNoInfs != 0 {
234 result |= FastmathFlags::NINF;
235 }
236 if flags & LLVMFastMathNoSignedZeros != 0 {
237 result |= FastmathFlags::NSZ;
238 }
239 if flags & LLVMFastMathAllowReciprocal != 0 {
240 result |= FastmathFlags::ARCP;
241 }
242 if flags & LLVMFastMathAllowContract != 0 {
243 result |= FastmathFlags::CONTRACT;
244 }
245 if flags & LLVMFastMathApproxFunc != 0 {
246 result |= FastmathFlags::AFN;
247 }
248 if flags & LLVMFastMathAllowReassoc != 0 {
249 result |= FastmathFlags::REASSOC;
250 }
251 result
252 }
253}
254
255impl From<FastmathFlags> for LLVMFastMathFlags {
256 fn from(flags: FastmathFlags) -> Self {
257 let mut result = LLVMFastMathNone;
258 if flags.contains(FastmathFlags::NNAN) {
259 result |= LLVMFastMathNoNaNs;
260 }
261 if flags.contains(FastmathFlags::NINF) {
262 result |= LLVMFastMathNoInfs;
263 }
264 if flags.contains(FastmathFlags::NSZ) {
265 result |= LLVMFastMathNoSignedZeros;
266 }
267 if flags.contains(FastmathFlags::ARCP) {
268 result |= LLVMFastMathAllowReciprocal;
269 }
270 if flags.contains(FastmathFlags::CONTRACT) {
271 result |= LLVMFastMathAllowContract;
272 }
273 if flags.contains(FastmathFlags::AFN) {
274 result |= LLVMFastMathApproxFunc;
275 }
276 if flags.contains(FastmathFlags::REASSOC) {
277 result |= LLVMFastMathAllowReassoc;
278 }
279 result
280 }
281}
282
283pub fn llvm_print_value_to_string(val: LLVMValue) -> Option<String> {
285 let buf_ptr = unsafe { LLVMPrintValueToString(val.into()) };
286 if buf_ptr.is_null() {
287 return None;
288 }
289 let result = cstr_to_string(buf_ptr);
290 unsafe { LLVMDisposeMessage(buf_ptr) };
291 result
292}
293
294pub fn llvm_print_type_to_string(ty: LLVMType) -> Option<String> {
296 let buf_ptr = unsafe { LLVMPrintTypeToString(ty.into()) };
297 if buf_ptr.is_null() {
298 return None;
299 }
300 let result = cstr_to_string(buf_ptr);
301 unsafe { LLVMDisposeMessage(buf_ptr) };
302 result
303}
304
305pub fn llvm_print_module_to_string(module: &LLVMModule) -> Option<String> {
307 let buf_ptr = unsafe { LLVMPrintModuleToString(module.inner_ref()) };
308 if buf_ptr.is_null() {
309 return None;
310 }
311 let result = cstr_to_string(buf_ptr);
312 unsafe { LLVMDisposeMessage(buf_ptr) };
313 result
314}
315
316pub fn llvm_get_value_name(val: LLVMValue) -> Option<String> {
318 let mut len = 0;
319 let buf_ptr = unsafe { LLVMGetValueName2(val.into(), &mut len) };
320 if buf_ptr.is_null() {
321 return None;
322 }
323 sized_cstr_to_string(buf_ptr, len)
324}
325
326pub fn llvm_get_module_identifier(module: &LLVMModule) -> Option<String> {
328 let mut len = 0;
329 let buf_ptr = unsafe { LLVMGetModuleIdentifier(module.inner_ref(), &mut len) };
330 if buf_ptr.is_null() {
331 return None;
332 }
333 sized_cstr_to_string(buf_ptr, len)
334}
335
336pub fn llvm_dump_value(val: LLVMValue) {
338 unsafe { LLVMDumpValue(val.into()) }
339}
340
341pub fn llvm_dump_type(ty: LLVMType) {
343 unsafe { LLVMDumpType(ty.into()) }
344}
345
346pub fn llvm_dump_module(module: &LLVMModule) {
348 unsafe { LLVMDumpModule(module.inner_ref()) }
349}
350
351pub mod llvm_is_a {
353 use llvm_sys::core::{
354 LLVMIsAAllocaInst, LLVMIsAArgument, LLVMIsACallInst, LLVMIsAConstant, LLVMIsAConstantExpr,
355 LLVMIsAConstantFP, LLVMIsAConstantInt, LLVMIsAExtractElementInst, LLVMIsAExtractValueInst,
356 LLVMIsAFCmpInst, LLVMIsAFPToUIInst, LLVMIsAGetElementPtrInst, LLVMIsAGlobalValue,
357 LLVMIsAGlobalVariable, LLVMIsAICmpInst, LLVMIsAInsertElementInst, LLVMIsAInsertValueInst,
358 LLVMIsAInstruction, LLVMIsAInvokeInst, LLVMIsALoadInst, LLVMIsAPHINode,
359 LLVMIsAShuffleVectorInst, LLVMIsAStoreInst, LLVMIsASwitchInst, LLVMIsAUIToFPInst,
360 LLVMIsAZExtInst,
361 };
362
363 use super::*;
364
365 pub fn function(val: LLVMValue) -> bool {
367 unsafe { !LLVMIsAFunction(val.into()).is_null() }
368 }
369
370 pub fn user(val: LLVMValue) -> bool {
372 unsafe { !LLVMIsAUser(val.into()).is_null() }
373 }
374
375 pub fn constant(val: LLVMValue) -> bool {
377 unsafe { !LLVMIsAConstant(val.into()).is_null() }
378 }
379
380 pub fn instruction(val: LLVMValue) -> bool {
382 unsafe { !LLVMIsAInstruction(val.into()).is_null() }
383 }
384
385 pub fn constant_int(val: LLVMValue) -> bool {
387 unsafe { !LLVMIsAConstantInt(val.into()).is_null() }
388 }
389
390 pub fn constant_fp(val: LLVMValue) -> bool {
392 unsafe { !LLVMIsAConstantFP(val.into()).is_null() }
393 }
394
395 pub fn constant_expr(val: LLVMValue) -> bool {
397 unsafe { !LLVMIsAConstantExpr(val.into()).is_null() }
398 }
399
400 pub fn phi_node(val: LLVMValue) -> bool {
402 unsafe { !LLVMIsAPHINode(val.into()).is_null() }
403 }
404
405 pub fn alloca_inst(val: LLVMValue) -> bool {
407 unsafe { !LLVMIsAAllocaInst(val.into()).is_null() }
408 }
409
410 pub fn icmp_inst(val: LLVMValue) -> bool {
412 unsafe { !LLVMIsAICmpInst(val.into()).is_null() }
413 }
414
415 pub fn fcmp_inst(val: LLVMValue) -> bool {
417 unsafe { !LLVMIsAFCmpInst(val.into()).is_null() }
418 }
419
420 pub fn zext_inst(val: LLVMValue) -> bool {
422 unsafe { !LLVMIsAZExtInst(val.into()).is_null() }
423 }
424
425 pub fn fptoui_inst(val: LLVMValue) -> bool {
427 unsafe { !LLVMIsAFPToUIInst(val.into()).is_null() }
428 }
429
430 pub fn uitofp_inst(val: LLVMValue) -> bool {
432 unsafe { !LLVMIsAUIToFPInst(val.into()).is_null() }
433 }
434
435 pub fn switch_inst(val: LLVMValue) -> bool {
437 unsafe { !LLVMIsASwitchInst(val.into()).is_null() }
438 }
439
440 pub fn argument(val: LLVMValue) -> bool {
442 unsafe { !LLVMIsAArgument(val.into()).is_null() }
443 }
444
445 pub fn global_value(val: LLVMValue) -> bool {
447 unsafe { !LLVMIsAGlobalValue(val.into()).is_null() }
448 }
449
450 pub fn global_variable(val: LLVMValue) -> bool {
452 unsafe { !LLVMIsAGlobalVariable(val.into()).is_null() }
453 }
454
455 pub fn call_inst(val: LLVMValue) -> bool {
457 unsafe { !LLVMIsACallInst(val.into()).is_null() }
458 }
459
460 pub fn invoke_inst(val: LLVMValue) -> bool {
462 unsafe { !LLVMIsAInvokeInst(val.into()).is_null() }
463 }
464
465 pub fn get_element_ptr_inst(val: LLVMValue) -> bool {
467 unsafe { !LLVMIsAGetElementPtrInst(val.into()).is_null() }
468 }
469
470 pub fn insert_value_inst(val: LLVMValue) -> bool {
472 unsafe { !LLVMIsAInsertValueInst(val.into()).is_null() }
473 }
474
475 pub fn extract_value_inst(val: LLVMValue) -> bool {
477 unsafe { !LLVMIsAExtractValueInst(val.into()).is_null() }
478 }
479
480 pub fn shuffle_vector_inst(val: LLVMValue) -> bool {
482 unsafe { !LLVMIsAShuffleVectorInst(val.into()).is_null() }
483 }
484
485 pub fn insert_element_inst(val: LLVMValue) -> bool {
487 unsafe { !LLVMIsAInsertElementInst(val.into()).is_null() }
488 }
489
490 pub fn extract_element_inst(val: LLVMValue) -> bool {
492 unsafe { !LLVMIsAExtractElementInst(val.into()).is_null() }
493 }
494
495 pub fn load_inst(val: LLVMValue) -> bool {
497 unsafe { !LLVMIsALoadInst(val.into()).is_null() }
498 }
499
500 pub fn store_inst(val: LLVMValue) -> bool {
502 unsafe { !LLVMIsAStoreInst(val.into()).is_null() }
503 }
504}
505
506pub fn llvm_type_of(val: LLVMValue) -> LLVMType {
508 unsafe { LLVMTypeOf(val.into()).into() }
509}
510
511pub fn llvm_global_get_value_type(val: LLVMValue) -> LLVMType {
513 assert!(llvm_is_a::global_value(val));
514 unsafe { LLVMGlobalGetValueType(val.into()).into() }
515}
516
517pub fn llvm_get_global_parent(val: LLVMValue) -> Option<LLVMModule> {
519 assert!(llvm_is_a::global_value(val));
520 unimplemented!("Returning LLVMModule, which owns the underlying LLVMModuleRef is not safe");
521}
522
523pub fn llvm_get_named_global(module: &LLVMModule, name: &str) -> Option<LLVMValue> {
525 let gv_ref = unsafe { LLVMGetNamedGlobal(module.inner_ref(), to_c_str(name).as_ptr()) };
526 (!gv_ref.is_null()).then_some(gv_ref.into())
527}
528
529pub fn llvm_is_declaration(val: LLVMValue) -> bool {
531 assert!(llvm_is_a::global_value(val));
532 unsafe { LLVMIsDeclaration(val.into()).to_bool() }
533}
534
535pub fn llvm_type_is_sized(ty: LLVMType) -> bool {
537 unsafe { LLVMTypeIsSized(ty.into()).to_bool() }
538}
539
540pub fn llvm_is_aggregate_type(ty: LLVMType) -> bool {
542 matches!(
543 llvm_get_type_kind(ty),
544 LLVMTypeKind::LLVMArrayTypeKind | LLVMTypeKind::LLVMStructTypeKind
545 )
546}
547
548pub fn llvm_get_type_kind(ty: LLVMType) -> LLVMTypeKind {
550 unsafe { LLVMGetTypeKind(ty.into()) }
551}
552
553pub fn llvm_get_linkage(val: LLVMValue) -> LLVMLinkage {
555 unsafe { LLVMGetLinkage(val.into()) }
556}
557
558pub fn llvm_set_linkage(val: LLVMValue, linkage: LLVMLinkage) {
560 unsafe { LLVMSetLinkage(val.into(), linkage) }
561}
562
563pub fn llvm_vector_type(element_type: LLVMType, num_elems: u32) -> LLVMType {
565 assert!(llvm_is_valid_vector_element_type(element_type));
566 unsafe { LLVMVectorType(element_type.into(), num_elems).into() }
567}
568
569pub fn llvm_scalable_vector_type(element_type: LLVMType, num_elems: u32) -> LLVMType {
571 assert!(llvm_is_valid_vector_element_type(element_type));
572 unsafe { LLVMScalableVectorType(element_type.into(), num_elems).into() }
573}
574
575pub fn llvm_get_vector_size(ty: LLVMType) -> u32 {
577 assert!(matches!(
578 llvm_get_type_kind(ty),
579 LLVMTypeKind::LLVMVectorTypeKind | LLVMTypeKind::LLVMScalableVectorTypeKind
580 ));
581 unsafe { LLVMGetVectorSize(ty.into()) as u32 }
582}
583
584pub fn llvm_get_element_type(ty: LLVMType) -> LLVMType {
586 assert!(matches!(
587 llvm_get_type_kind(ty),
588 LLVMTypeKind::LLVMArrayTypeKind
589 | LLVMTypeKind::LLVMVectorTypeKind
590 | LLVMTypeKind::LLVMScalableVectorTypeKind
591 ));
592 unsafe { LLVMGetElementType(ty.into()).into() }
593}
594
595pub fn llvm_is_valid_vector_element_type(ty: LLVMType) -> bool {
597 matches!(
598 llvm_get_type_kind(ty),
599 LLVMTypeKind::LLVMIntegerTypeKind
600 | LLVMTypeKind::LLVMPointerTypeKind
601 | LLVMTypeKind::LLVMFloatTypeKind
602 | LLVMTypeKind::LLVMDoubleTypeKind
603 | LLVMTypeKind::LLVMHalfTypeKind
604 | LLVMTypeKind::LLVMFP128TypeKind
605 | LLVMTypeKind::LLVMPPC_FP128TypeKind
606 | LLVMTypeKind::LLVMX86_FP80TypeKind
607 )
608}
609
610pub fn llvm_get_array_length2(ty: LLVMType) -> u64 {
612 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMArrayTypeKind);
613 unsafe { LLVMGetArrayLength2(ty.into()) }
614}
615
616pub fn llvm_get_return_type(ty: LLVMType) -> LLVMType {
618 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
619 unsafe { LLVMGetReturnType(ty.into()).into() }
620}
621
622pub fn llvm_count_param_types(ty: LLVMType) -> u32 {
624 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
625 unsafe { LLVMCountParamTypes(ty.into()) }
626}
627
628pub fn llvm_get_param_types(ty: LLVMType) -> Vec<LLVMType> {
630 let params_count = llvm_count_param_types(ty) as usize;
631 unsafe {
632 let mut buffer = uninitialized_vec::<LLVMTypeRef>(params_count);
633 LLVMGetParamTypes(ty.into(), (*buffer.as_mut_ptr()).as_mut_ptr());
634 buffer.assume_init()
635 }
636 .into_iter()
637 .map(Into::into)
638 .collect()
639}
640
641pub fn llvm_is_function_type_var_arg(ty: LLVMType) -> bool {
643 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
644 unsafe { LLVMIsFunctionVarArg(ty.into()).to_bool() }
645}
646
647pub fn llvm_get_int_type_width(ty: LLVMType) -> u32 {
649 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMIntegerTypeKind);
650 unsafe { LLVMGetIntTypeWidth(ty.into()) }
651}
652
653pub fn llvm_is_opaque_struct(ty: LLVMType) -> bool {
655 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMStructTypeKind);
656 unsafe { LLVMIsOpaqueStruct(ty.into()) }.to_bool()
657}
658
659pub fn llvm_count_struct_element_types(ty: LLVMType) -> u32 {
661 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMStructTypeKind);
662 unsafe { LLVMCountStructElementTypes(ty.into()) }
663}
664
665pub fn llvm_get_struct_element_types(ty: LLVMType) -> Vec<LLVMType> {
667 let element_types_count = llvm_count_struct_element_types(ty) as usize;
668 unsafe {
669 let mut buffer = uninitialized_vec::<LLVMTypeRef>(element_types_count);
670 LLVMGetStructElementTypes(ty.into(), (*buffer.as_mut_ptr()).as_mut_ptr());
671 buffer.assume_init()
672 }
673 .into_iter()
674 .map(Into::into)
675 .collect()
676}
677
678pub fn llvm_get_struct_name(ty: LLVMType) -> Option<String> {
680 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMStructTypeKind);
681 cstr_to_string(unsafe { LLVMGetStructName(ty.into()) })
682}
683
684pub fn llvm_is_a_terminator_inst(val: LLVMValue) -> bool {
686 !unsafe { LLVMIsATerminatorInst(val.into()) }.is_null()
687}
688
689pub fn llvm_get_basic_block_terminator(bb: LLVMBasicBlock) -> Option<LLVMValue> {
691 let bbref = unsafe { LLVMGetBasicBlockTerminator(bb.into()) };
692 (!bbref.is_null()).then_some(bbref.into())
693}
694
695pub fn llvm_get_value_kind(val: LLVMValue) -> LLVMValueKind {
697 unsafe { LLVMGetValueKind(val.into()) }
698}
699
700pub fn llvm_get_instruction_opcode(val: LLVMValue) -> LLVMOpcode {
702 assert!(llvm_get_value_kind(val) == LLVMValueKind::LLVMInstructionValueKind);
703 unsafe { LLVMGetInstructionOpcode(val.into()) }
704}
705
706pub fn llvm_get_const_opcode(val: LLVMValue) -> LLVMOpcode {
708 assert!(llvm_is_a::constant_expr(val));
709 unsafe { LLVMGetConstOpcode(val.into()) }
710}
711
712pub fn llvm_get_instruction_parent(inst: LLVMValue) -> Option<LLVMBasicBlock> {
714 assert!(llvm_is_a::instruction(inst));
715 unsafe {
716 let parent = LLVMGetInstructionParent(inst.into());
717 (!parent.is_null()).then_some(parent.into())
718 }
719}
720
721pub fn llvm_get_num_operands(val: LLVMValue) -> u32 {
723 assert!(llvm_is_a::user(val));
724 unsafe { LLVMGetNumOperands(val.into()) as u32 }
725}
726
727pub fn llvm_get_operand(val: LLVMValue, index: u32) -> LLVMValue {
729 assert!(index < llvm_get_num_operands(val));
730 unsafe { LLVMGetOperand(val.into(), index).into() }
731}
732
733pub fn llvm_get_aggregate_element(val: LLVMValue, index: u32) -> Option<LLVMValue> {
735 assert!(llvm_is_a::constant(val));
736 unsafe {
737 let elem = LLVMGetAggregateElement(val.into(), index);
738 (!elem.is_null()).then_some(elem.into())
739 }
740}
741
742pub fn llvm_basic_block_as_value(block: LLVMBasicBlock) -> LLVMValue {
744 unsafe { LLVMBasicBlockAsValue(block.into()).into() }
745}
746
747pub fn llvm_value_is_basic_block(val: LLVMValue) -> bool {
749 unsafe { LLVMValueIsBasicBlock(val.into()).to_bool() }
750}
751
752pub fn llvm_value_as_basic_block(val: LLVMValue) -> LLVMBasicBlock {
754 assert!(llvm_value_is_basic_block(val));
755 unsafe { LLVMValueAsBasicBlock(val.into()).into() }
756}
757
758pub fn llvm_get_basic_block_name(block: LLVMBasicBlock) -> Option<String> {
760 cstr_to_string(unsafe { LLVMGetBasicBlockName(block.into()) })
761}
762
763pub fn llvm_get_basic_block_parent(block: LLVMBasicBlock) -> Option<LLVMValue> {
765 unsafe {
766 let parent = LLVMGetBasicBlockParent(block.into());
767 (!parent.is_null()).then_some(parent.into())
768 }
769}
770
771pub fn llvm_get_first_basic_block(fn_val: LLVMValue) -> Option<LLVMBasicBlock> {
773 assert!(llvm_is_a::function(fn_val));
774 unsafe {
775 let first_block = LLVMGetFirstBasicBlock(fn_val.into());
776 (!first_block.is_null()).then_some(first_block.into())
777 }
778}
779
780pub fn llvm_get_next_basic_block(bb: LLVMBasicBlock) -> Option<LLVMBasicBlock> {
782 unsafe {
783 let next_block = LLVMGetNextBasicBlock(bb.into());
784 (!next_block.is_null()).then_some(next_block.into())
785 }
786}
787
788pub fn llvm_get_previous_basic_block(bb: LLVMBasicBlock) -> Option<LLVMBasicBlock> {
790 unsafe {
791 let prev_block = LLVMGetPreviousBasicBlock(bb.into());
792 (!prev_block.is_null()).then_some(prev_block.into())
793 }
794}
795
796pub struct BasicBlockIter(pub Option<LLVMBasicBlock>);
798
799impl Iterator for BasicBlockIter {
800 type Item = LLVMBasicBlock;
801
802 fn next(&mut self) -> Option<Self::Item> {
803 if let Some(bb) = self.0 {
804 self.0 = llvm_get_next_basic_block(bb);
805 Some(bb)
806 } else {
807 None
808 }
809 }
810}
811
812pub fn basic_block_iter(fn_val: LLVMValue) -> BasicBlockIter {
814 BasicBlockIter(llvm_get_first_basic_block(fn_val))
815}
816
817pub fn llvm_get_first_instruction(bb: LLVMBasicBlock) -> Option<LLVMValue> {
819 unsafe {
820 let first_instr = LLVMGetFirstInstruction(bb.into());
821 (!first_instr.is_null()).then_some(first_instr.into())
822 }
823}
824
825pub fn llvm_get_next_instruction(instr: LLVMValue) -> Option<LLVMValue> {
827 assert!(llvm_is_a::instruction(instr));
828 unsafe {
829 let next_instr = LLVMGetNextInstruction(instr.into());
830 (!next_instr.is_null()).then_some(next_instr.into())
831 }
832}
833
834pub fn llvm_get_previous_instruction(instr: LLVMValue) -> Option<LLVMValue> {
836 assert!(llvm_is_a::instruction(instr));
837 unsafe {
838 let prev_instr = LLVMGetPreviousInstruction(instr.into());
839 (!prev_instr.is_null()).then_some(prev_instr.into())
840 }
841}
842
843pub struct InstructionIter(pub Option<LLVMValue>);
845
846impl Iterator for InstructionIter {
847 type Item = LLVMValue;
848
849 fn next(&mut self) -> Option<Self::Item> {
850 if let Some(instr) = self.0 {
851 self.0 = llvm_get_next_instruction(instr);
852 Some(instr)
853 } else {
854 None
855 }
856 }
857}
858
859pub fn instruction_iter(bb: LLVMBasicBlock) -> InstructionIter {
861 InstructionIter(llvm_get_first_instruction(bb))
862}
863
864pub fn llvm_count_incoming(phi_node: LLVMValue) -> u32 {
866 assert!(llvm_is_a::phi_node(phi_node));
867 unsafe { LLVMCountIncoming(phi_node.into()) }
868}
869
870pub fn llvm_get_incoming_value(phi_node: LLVMValue, index: u32) -> LLVMValue {
872 assert!(index < llvm_count_incoming(phi_node));
873 unsafe { LLVMGetIncomingValue(phi_node.into(), index).into() }
874}
875
876pub fn llvm_get_incoming_block(phi_node: LLVMValue, index: u32) -> LLVMBasicBlock {
878 assert!(index < llvm_count_incoming(phi_node));
879 unsafe { LLVMGetIncomingBlock(phi_node.into(), index).into() }
880}
881
882pub struct IncomingIter {
884 phi_node: LLVMValue,
885 i: u32,
886 count: u32,
887}
888
889impl Iterator for IncomingIter {
890 type Item = (LLVMValue, LLVMBasicBlock);
891
892 fn next(&mut self) -> Option<Self::Item> {
893 if self.i < self.count {
894 let result = (
895 llvm_get_incoming_value(self.phi_node, self.i),
896 llvm_get_incoming_block(self.phi_node, self.i),
897 );
898 self.i += 1;
899 Some(result)
900 } else {
901 None
902 }
903 }
904}
905
906pub fn incoming_iter(phi_node: LLVMValue) -> IncomingIter {
908 IncomingIter {
909 phi_node,
910 i: 0,
911 count: llvm_count_incoming(phi_node),
912 }
913}
914
915pub fn llvm_const_vector(elements: &[LLVMValue]) -> LLVMValue {
917 assert!(elements.iter().all(|elem| llvm_is_a::constant(*elem)));
918 let mut elements = elements.iter().cloned().map(Into::into).collect::<Vec<_>>();
919 unsafe { LLVMConstVector(elements.as_mut_ptr(), elements.len().try_into().unwrap()).into() }
920}
921
922pub fn llvm_const_int_get_zext_value(val: LLVMValue) -> u64 {
924 assert!(llvm_is_a::constant_int(val));
925 unsafe { LLVMConstIntGetZExtValue(val.into()) }
926}
927
928pub fn llvm_const_real_get_double(val: LLVMValue) -> (f64, bool) {
930 assert!(llvm_is_a::constant_fp(val));
931 let mut loses_info = 0;
932 let result = unsafe { LLVMConstRealGetDouble(val.into(), &mut loses_info) };
933 (result, loses_info.to_bool())
934}
935
936pub fn llvm_const_real(ty: LLVMType, n: f64) -> LLVMValue {
938 assert!(
939 llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFloatTypeKind
940 || llvm_get_type_kind(ty) == LLVMTypeKind::LLVMDoubleTypeKind
941 );
942 unsafe { LLVMConstReal(ty.into(), n).into() }
943}
944
945pub fn llvm_const_null(ty: LLVMType) -> LLVMValue {
947 unsafe { LLVMConstNull(ty.into()).into() }
948}
949
950pub fn llvm_get_allocated_type(val: LLVMValue) -> LLVMType {
952 assert!(llvm_is_a::alloca_inst(val));
953 unsafe { LLVMGetAllocatedType(val.into()).into() }
954}
955
956pub fn llvm_get_icmp_predicate(val: LLVMValue) -> LLVMIntPredicate {
958 assert!(llvm_is_a::icmp_inst(val) || llvm_get_const_opcode(val) == LLVMOpcode::LLVMICmp);
959 unsafe { LLVMGetICmpPredicate(val.into()) }
960}
961
962pub fn llvm_get_fcmp_predicate(val: LLVMValue) -> LLVMRealPredicate {
964 assert!(llvm_is_a::fcmp_inst(val) || llvm_get_const_opcode(val) == LLVMOpcode::LLVMFCmp);
965 unsafe { LLVMGetFCmpPredicate(val.into()) }
966}
967
968pub fn llvm_get_nneg(val: LLVMValue) -> bool {
970 assert!(llvm_is_a::zext_inst(val) || llvm_is_a::uitofp_inst(val));
971 unsafe { LLVMGetNNeg(val.into()).to_bool() }
972}
973
974pub fn llvm_set_nneg(val: LLVMValue, nneg: bool) {
976 assert!(llvm_is_a::zext_inst(val) || llvm_is_a::uitofp_inst(val));
977 unsafe { LLVMSetNNeg(val.into(), nneg.into()) }
978}
979
980pub fn llvm_get_alignment(val: LLVMValue) -> u32 {
982 assert!(
983 llvm_is_a::alloca_inst(val)
984 || llvm_is_a::global_variable(val)
985 || llvm_is_a::load_inst(val)
986 || llvm_is_a::store_inst(val)
987 );
988 unsafe { LLVMGetAlignment(val.into()) }
989}
990
991pub fn llvm_set_alignment(val: LLVMValue, align: u32) {
993 assert!(
994 llvm_is_a::alloca_inst(val)
995 || llvm_is_a::global_variable(val)
996 || llvm_is_a::load_inst(val)
997 || llvm_is_a::store_inst(val)
998 );
999 unsafe { LLVMSetAlignment(val.into(), align) }
1000}
1001
1002pub fn llvm_get_num_mask_elements(val: LLVMValue) -> u32 {
1004 assert!(llvm_is_a::shuffle_vector_inst(val));
1005 unsafe { LLVMGetNumMaskElements(val.into()) }
1006}
1007
1008pub fn llvm_get_undef_mask_elem() -> i32 {
1010 unsafe { LLVMGetUndefMaskElem() }
1011}
1012
1013pub fn llvm_get_mask_value(val: LLVMValue, index: u32) -> i32 {
1015 assert!(index < llvm_get_num_mask_elements(val));
1016 unsafe { LLVMGetMaskValue(val.into(), index) }
1017}
1018
1019pub fn llvm_count_params(func: LLVMValue) -> u32 {
1021 assert!(llvm_is_a::function(func));
1022 unsafe { LLVMCountParams(func.into()) }
1023}
1024
1025pub fn llvm_get_first_param(func: LLVMValue) -> Option<LLVMValue> {
1027 assert!(llvm_is_a::function(func));
1028 unsafe {
1029 let first_param = LLVMGetFirstParam(func.into());
1030 (!first_param.is_null()).then_some(first_param.into())
1031 }
1032}
1033
1034pub fn llvm_get_next_param(val: LLVMValue) -> Option<LLVMValue> {
1036 assert!(llvm_is_a::argument(val));
1037 unsafe {
1038 let next_param = LLVMGetNextParam(val.into());
1039 (!next_param.is_null()).then_some(next_param.into())
1040 }
1041}
1042
1043pub fn llvm_get_previous_param(val: LLVMValue) -> Option<LLVMValue> {
1045 assert!(llvm_is_a::argument(val));
1046 unsafe {
1047 let prev_param = LLVMGetPreviousParam(val.into());
1048 (!prev_param.is_null()).then_some(prev_param.into())
1049 }
1050}
1051
1052pub struct ParamIter(pub Option<LLVMValue>);
1054
1055impl Iterator for ParamIter {
1056 type Item = LLVMValue;
1057
1058 fn next(&mut self) -> Option<Self::Item> {
1059 if let Some(param) = self.0 {
1060 self.0 = llvm_get_next_param(param);
1061 Some(param)
1062 } else {
1063 None
1064 }
1065 }
1066}
1067
1068pub fn param_iter(func: LLVMValue) -> ParamIter {
1070 assert!(llvm_is_a::function(func));
1071 ParamIter(llvm_get_first_param(func))
1072}
1073
1074pub fn llvm_get_param(func: LLVMValue, idx: u32) -> LLVMValue {
1076 assert!(idx < llvm_count_params(func));
1077 unsafe { LLVMGetParam(func.into(), idx).into() }
1078}
1079
1080pub fn llvm_get_first_function(module: &LLVMModule) -> Option<LLVMValue> {
1082 unsafe {
1083 let first_func = LLVMGetFirstFunction(module.inner_ref());
1084 (!first_func.is_null()).then_some(first_func.into())
1085 }
1086}
1087
1088pub fn llvm_get_next_function(func: LLVMValue) -> Option<LLVMValue> {
1090 assert!(llvm_is_a::function(func));
1091 unsafe {
1092 let next_func = LLVMGetNextFunction(func.into());
1093 (!next_func.is_null()).then_some(next_func.into())
1094 }
1095}
1096
1097pub fn llvm_get_previous_function(func: LLVMValue) -> Option<LLVMValue> {
1099 assert!(llvm_is_a::function(func));
1100 unsafe {
1101 let prev_func = LLVMGetPreviousFunction(func.into());
1102 (!prev_func.is_null()).then_some(prev_func.into())
1103 }
1104}
1105
1106pub fn llvm_get_last_function(module: &LLVMModule) -> Option<LLVMValue> {
1108 unsafe {
1109 let last_func = LLVMGetLastFunction(module.inner_ref());
1110 (!last_func.is_null()).then_some(last_func.into())
1111 }
1112}
1113
1114pub struct FunctionIter(pub Option<LLVMValue>);
1116
1117impl Iterator for FunctionIter {
1118 type Item = LLVMValue;
1119
1120 fn next(&mut self) -> Option<Self::Item> {
1121 if let Some(param) = self.0 {
1122 self.0 = llvm_get_next_function(param);
1123 Some(param)
1124 } else {
1125 None
1126 }
1127 }
1128}
1129
1130pub fn function_iter(module: &LLVMModule) -> FunctionIter {
1132 FunctionIter(llvm_get_first_function(module))
1133}
1134
1135pub fn llvm_get_first_global(module: &LLVMModule) -> Option<LLVMValue> {
1137 unsafe {
1138 let first_global = LLVMGetFirstGlobal(module.inner_ref());
1139 (!first_global.is_null()).then_some(first_global.into())
1140 }
1141}
1142
1143pub fn llvm_get_next_global(val: LLVMValue) -> Option<LLVMValue> {
1145 assert!(llvm_is_a::global_variable(val));
1146 unsafe {
1147 let next_global = LLVMGetNextGlobal(val.into());
1148 (!next_global.is_null()).then_some(next_global.into())
1149 }
1150}
1151
1152pub fn llvm_get_previous_global(val: LLVMValue) -> Option<LLVMValue> {
1154 assert!(llvm_is_a::global_variable(val));
1155 unsafe {
1156 let prev_global = LLVMGetPreviousGlobal(val.into());
1157 (!prev_global.is_null()).then_some(prev_global.into())
1158 }
1159}
1160
1161pub fn llvm_get_last_global(module: &LLVMModule) -> Option<LLVMValue> {
1163 unsafe {
1164 let last_global = LLVMGetLastGlobal(module.inner_ref());
1165 (!last_global.is_null()).then_some(last_global.into())
1166 }
1167}
1168
1169pub struct GlobalVariableIter(pub Option<LLVMValue>);
1171
1172impl Iterator for GlobalVariableIter {
1173 type Item = LLVMValue;
1174
1175 fn next(&mut self) -> Option<Self::Item> {
1176 if let Some(param) = self.0 {
1177 self.0 = llvm_get_next_global(param);
1178 Some(param)
1179 } else {
1180 None
1181 }
1182 }
1183}
1184
1185pub fn global_iter(module: &LLVMModule) -> GlobalVariableIter {
1187 GlobalVariableIter(llvm_get_first_global(module))
1188}
1189
1190pub fn llvm_get_initializer(val: LLVMValue) -> Option<LLVMValue> {
1192 assert!(llvm_is_a::global_variable(val));
1193 unsafe {
1194 let initializer = LLVMGetInitializer(val.into());
1195 (!initializer.is_null()).then_some(initializer.into())
1196 }
1197}
1198
1199pub fn llvm_set_initializer(val: LLVMValue, init: LLVMValue) {
1201 assert!(llvm_is_a::global_variable(val));
1202 assert!(llvm_is_a::constant(init));
1203 unsafe { LLVMSetInitializer(val.into(), init.into()) }
1204}
1205
1206pub fn llvm_add_global(module: &LLVMModule, ty: LLVMType, name: &str) -> LLVMValue {
1208 unsafe { LLVMAddGlobal(module.inner_ref(), ty.into(), to_c_str(name).as_ptr()).into() }
1209}
1210
1211pub fn llvm_get_insert_block(builder: &LLVMBuilder) -> Option<LLVMBasicBlock> {
1213 unsafe {
1214 let insert_block = LLVMGetInsertBlock(builder.inner_ref());
1215 (!insert_block.is_null()).then_some(insert_block.into())
1216 }
1217}
1218
1219pub fn llvm_clear_insertion_position(builder: &LLVMBuilder) {
1221 unsafe { LLVMClearInsertionPosition(builder.inner_ref()) }
1222}
1223
1224pub fn llvm_position_builder_at_end(builder: &LLVMBuilder, block: LLVMBasicBlock) {
1226 unsafe { LLVMPositionBuilderAtEnd(builder.inner_ref(), block.into()) }
1227}
1228
1229pub fn llvm_position_builder_before(builder: &LLVMBuilder, inst: LLVMValue) {
1231 assert!(llvm_is_a::instruction(inst));
1232 unsafe { LLVMPositionBuilderBefore(builder.inner_ref(), inst.into()) }
1233}
1234
1235pub fn llvm_int_type_in_context(context: &LLVMContext, width: u32) -> LLVMType {
1237 unsafe { LLVMIntTypeInContext(context.inner_ref(), width).into() }
1238}
1239
1240pub fn llvm_float_type_in_context(context: &LLVMContext) -> LLVMType {
1242 unsafe { LLVMFloatTypeInContext(context.inner_ref()).into() }
1243}
1244
1245pub fn llvm_double_type_in_context(context: &LLVMContext) -> LLVMType {
1247 unsafe { LLVMDoubleTypeInContext(context.inner_ref()).into() }
1248}
1249
1250pub fn llvm_is_valid_array_element_type(ty: LLVMType) -> bool {
1252 !matches!(
1253 llvm_get_type_kind(ty),
1254 LLVMTypeKind::LLVMVoidTypeKind
1255 | LLVMTypeKind::LLVMLabelTypeKind
1256 | LLVMTypeKind::LLVMMetadataTypeKind
1257 | LLVMTypeKind::LLVMFunctionTypeKind
1258 | LLVMTypeKind::LLVMTokenTypeKind
1259 | LLVMTypeKind::LLVMX86_AMXTypeKind
1260 )
1261}
1262
1263pub fn llvm_array_type2(elem_ty: LLVMType, element_count: u64) -> LLVMType {
1265 assert!(llvm_is_valid_array_element_type(elem_ty));
1266 unsafe { LLVMArrayType2(elem_ty.into(), element_count).into() }
1267}
1268
1269pub fn llvm_is_first_class_type(ty: LLVMType) -> bool {
1271 !matches!(
1272 llvm_get_type_kind(ty),
1273 LLVMTypeKind::LLVMVoidTypeKind | LLVMTypeKind::LLVMFunctionTypeKind
1274 )
1275}
1276
1277pub fn llvm_is_valid_function_argument_type(arg_ty: LLVMType) -> bool {
1279 llvm_is_first_class_type(arg_ty)
1280}
1281
1282pub fn llvm_is_valid_function_return_type(ret_ty: LLVMType) -> bool {
1284 !matches!(
1285 llvm_get_type_kind(ret_ty),
1286 LLVMTypeKind::LLVMLabelTypeKind
1287 | LLVMTypeKind::LLVMFunctionTypeKind
1288 | LLVMTypeKind::LLVMMetadataTypeKind
1289 )
1290}
1291
1292pub fn llvm_function_type(ret_ty: LLVMType, param_tys: &[LLVMType], is_var_arg: bool) -> LLVMType {
1294 assert!(llvm_is_valid_function_return_type(ret_ty));
1295 assert!(
1296 param_tys
1297 .iter()
1298 .all(|param_ty| llvm_is_valid_function_argument_type(*param_ty))
1299 );
1300 let mut param_tys: Vec<_> = param_tys.iter().cloned().map(Into::into).collect();
1301 unsafe {
1302 LLVMFunctionType(
1303 ret_ty.into(),
1304 param_tys.as_mut_ptr(),
1305 param_tys.len().try_into().unwrap(),
1306 is_var_arg.into(),
1307 )
1308 .into()
1309 }
1310}
1311
1312pub fn llvm_void_type_in_context(context: &LLVMContext) -> LLVMType {
1314 unsafe { LLVMVoidTypeInContext(context.inner_ref()).into() }
1315}
1316
1317pub fn llvm_pointer_type_in_context(context: &LLVMContext, addr_space: u32) -> LLVMType {
1319 unsafe { LLVMPointerTypeInContext(context.inner_ref(), addr_space).into() }
1320}
1321
1322pub fn llvm_struct_create_named(context: &LLVMContext, name: &str) -> LLVMType {
1324 unsafe { LLVMStructCreateNamed(context.inner_ref(), to_c_str(name).as_ptr()).into() }
1325}
1326
1327pub fn llvm_is_valid_struct_element_type(ty: LLVMType) -> bool {
1329 !matches!(
1330 llvm_get_type_kind(ty),
1331 LLVMTypeKind::LLVMVoidTypeKind
1332 | LLVMTypeKind::LLVMLabelTypeKind
1333 | LLVMTypeKind::LLVMMetadataTypeKind
1334 | LLVMTypeKind::LLVMFunctionTypeKind
1335 | LLVMTypeKind::LLVMTokenTypeKind
1336 )
1337}
1338
1339pub fn llvm_struct_type_in_context(
1341 context: &LLVMContext,
1342 elem_tys: &[LLVMType],
1343 is_packed: bool,
1344) -> LLVMType {
1345 assert!(
1346 elem_tys
1347 .iter()
1348 .all(|elem_ty| llvm_is_valid_struct_element_type(*elem_ty))
1349 );
1350 let mut elem_tys: Vec<_> = elem_tys.iter().cloned().map(Into::into).collect();
1351 unsafe {
1352 LLVMStructTypeInContext(
1353 context.inner_ref(),
1354 elem_tys.as_mut_ptr(),
1355 elem_tys.len().try_into().unwrap(),
1356 is_packed.into(),
1357 )
1358 .into()
1359 }
1360}
1361
1362pub fn llvm_struct_set_body(struct_ty: LLVMType, elem_tys: &[LLVMType], is_packed: bool) {
1364 assert!(llvm_get_type_kind(struct_ty) == LLVMTypeKind::LLVMStructTypeKind);
1365 assert!(
1366 elem_tys
1367 .iter()
1368 .all(|elem_ty| llvm_is_valid_struct_element_type(*elem_ty))
1369 );
1370 let mut elem_tys: Vec<_> = elem_tys.iter().cloned().map(Into::into).collect();
1371 unsafe {
1372 LLVMStructSetBody(
1373 struct_ty.into(),
1374 elem_tys.as_mut_ptr(),
1375 elem_tys.len().try_into().unwrap(),
1376 is_packed as i32,
1377 )
1378 }
1379}
1380
1381pub fn llvm_build_add(
1383 builder: &LLVMBuilder,
1384 lhs: LLVMValue,
1385 rhs: LLVMValue,
1386 name: &str,
1387) -> LLVMValue {
1388 assert!(llvm_get_insert_block(builder).is_some());
1389 unsafe {
1390 LLVMBuildAdd(
1391 builder.inner_ref(),
1392 lhs.into(),
1393 rhs.into(),
1394 to_c_str(name).as_ptr(),
1395 )
1396 .into()
1397 }
1398}
1399
1400pub fn llvm_build_sub(
1402 builder: &LLVMBuilder,
1403 lhs: LLVMValue,
1404 rhs: LLVMValue,
1405 name: &str,
1406) -> LLVMValue {
1407 assert!(llvm_get_insert_block(builder).is_some());
1408 unsafe {
1409 LLVMBuildSub(
1410 builder.inner_ref(),
1411 lhs.into(),
1412 rhs.into(),
1413 to_c_str(name).as_ptr(),
1414 )
1415 .into()
1416 }
1417}
1418
1419pub fn llvm_build_mul(
1421 builder: &LLVMBuilder,
1422 lhs: LLVMValue,
1423 rhs: LLVMValue,
1424 name: &str,
1425) -> LLVMValue {
1426 assert!(llvm_get_insert_block(builder).is_some());
1427 unsafe {
1428 LLVMBuildMul(
1429 builder.inner_ref(),
1430 lhs.into(),
1431 rhs.into(),
1432 to_c_str(name).as_ptr(),
1433 )
1434 .into()
1435 }
1436}
1437
1438pub fn llvm_build_sdiv(
1440 builder: &LLVMBuilder,
1441 lhs: LLVMValue,
1442 rhs: LLVMValue,
1443 name: &str,
1444) -> LLVMValue {
1445 assert!(llvm_get_insert_block(builder).is_some());
1446 unsafe {
1447 LLVMBuildSDiv(
1448 builder.inner_ref(),
1449 lhs.into(),
1450 rhs.into(),
1451 to_c_str(name).as_ptr(),
1452 )
1453 .into()
1454 }
1455}
1456
1457pub fn llvm_build_udiv(
1459 builder: &LLVMBuilder,
1460 lhs: LLVMValue,
1461 rhs: LLVMValue,
1462 name: &str,
1463) -> LLVMValue {
1464 assert!(llvm_get_insert_block(builder).is_some());
1465 unsafe {
1466 LLVMBuildUDiv(
1467 builder.inner_ref(),
1468 lhs.into(),
1469 rhs.into(),
1470 to_c_str(name).as_ptr(),
1471 )
1472 .into()
1473 }
1474}
1475
1476pub fn llvm_build_urem(
1478 builder: &LLVMBuilder,
1479 lhs: LLVMValue,
1480 rhs: LLVMValue,
1481 name: &str,
1482) -> LLVMValue {
1483 assert!(llvm_get_insert_block(builder).is_some());
1484 unsafe {
1485 LLVMBuildURem(
1486 builder.inner_ref(),
1487 lhs.into(),
1488 rhs.into(),
1489 to_c_str(name).as_ptr(),
1490 )
1491 .into()
1492 }
1493}
1494
1495pub fn llvm_build_srem(
1497 builder: &LLVMBuilder,
1498 lhs: LLVMValue,
1499 rhs: LLVMValue,
1500 name: &str,
1501) -> LLVMValue {
1502 assert!(llvm_get_insert_block(builder).is_some());
1503 unsafe {
1504 LLVMBuildSRem(
1505 builder.inner_ref(),
1506 lhs.into(),
1507 rhs.into(),
1508 to_c_str(name).as_ptr(),
1509 )
1510 .into()
1511 }
1512}
1513
1514pub fn llvm_build_and(
1516 builder: &LLVMBuilder,
1517 lhs: LLVMValue,
1518 rhs: LLVMValue,
1519 name: &str,
1520) -> LLVMValue {
1521 assert!(llvm_get_insert_block(builder).is_some());
1522 unsafe {
1523 LLVMBuildAnd(
1524 builder.inner_ref(),
1525 lhs.into(),
1526 rhs.into(),
1527 to_c_str(name).as_ptr(),
1528 )
1529 .into()
1530 }
1531}
1532
1533pub fn llvm_build_or(
1535 builder: &LLVMBuilder,
1536 lhs: LLVMValue,
1537 rhs: LLVMValue,
1538 name: &str,
1539) -> LLVMValue {
1540 assert!(llvm_get_insert_block(builder).is_some());
1541 unsafe {
1542 LLVMBuildOr(
1543 builder.inner_ref(),
1544 lhs.into(),
1545 rhs.into(),
1546 to_c_str(name).as_ptr(),
1547 )
1548 .into()
1549 }
1550}
1551
1552pub fn llvm_build_xor(
1554 builder: &LLVMBuilder,
1555 lhs: LLVMValue,
1556 rhs: LLVMValue,
1557 name: &str,
1558) -> LLVMValue {
1559 assert!(llvm_get_insert_block(builder).is_some());
1560 unsafe {
1561 LLVMBuildXor(
1562 builder.inner_ref(),
1563 lhs.into(),
1564 rhs.into(),
1565 to_c_str(name).as_ptr(),
1566 )
1567 .into()
1568 }
1569}
1570
1571pub fn llvm_build_shl(
1573 builder: &LLVMBuilder,
1574 lhs: LLVMValue,
1575 rhs: LLVMValue,
1576 name: &str,
1577) -> LLVMValue {
1578 assert!(llvm_get_insert_block(builder).is_some());
1579 unsafe {
1580 LLVMBuildShl(
1581 builder.inner_ref(),
1582 lhs.into(),
1583 rhs.into(),
1584 to_c_str(name).as_ptr(),
1585 )
1586 .into()
1587 }
1588}
1589
1590pub fn llvm_build_lshr(
1592 builder: &LLVMBuilder,
1593 lhs: LLVMValue,
1594 rhs: LLVMValue,
1595 name: &str,
1596) -> LLVMValue {
1597 assert!(llvm_get_insert_block(builder).is_some());
1598 unsafe {
1599 LLVMBuildLShr(
1600 builder.inner_ref(),
1601 lhs.into(),
1602 rhs.into(),
1603 to_c_str(name).as_ptr(),
1604 )
1605 .into()
1606 }
1607}
1608
1609pub fn llvm_build_ashr(
1611 builder: &LLVMBuilder,
1612 lhs: LLVMValue,
1613 rhs: LLVMValue,
1614 name: &str,
1615) -> LLVMValue {
1616 assert!(llvm_get_insert_block(builder).is_some());
1617 unsafe {
1618 LLVMBuildAShr(
1619 builder.inner_ref(),
1620 lhs.into(),
1621 rhs.into(),
1622 to_c_str(name).as_ptr(),
1623 )
1624 .into()
1625 }
1626}
1627
1628pub fn llvm_build_array_alloca(
1630 builder: &LLVMBuilder,
1631 ty: LLVMType,
1632 size: LLVMValue,
1633 name: &str,
1634) -> LLVMValue {
1635 assert!(llvm_get_insert_block(builder).is_some());
1636 unsafe {
1637 LLVMBuildArrayAlloca(
1638 builder.inner_ref(),
1639 ty.into(),
1640 size.into(),
1641 to_c_str(name).as_ptr(),
1642 )
1643 .into()
1644 }
1645}
1646
1647pub fn llvm_build_bitcast(
1649 builder: &LLVMBuilder,
1650 val: LLVMValue,
1651 dest_ty: LLVMType,
1652 name: &str,
1653) -> LLVMValue {
1654 assert!(llvm_get_insert_block(builder).is_some());
1655 unsafe {
1656 LLVMBuildBitCast(
1657 builder.inner_ref(),
1658 val.into(),
1659 dest_ty.into(),
1660 to_c_str(name).as_ptr(),
1661 )
1662 .into()
1663 }
1664}
1665
1666pub fn llvm_build_int_to_ptr(
1668 builder: &LLVMBuilder,
1669 val: LLVMValue,
1670 dest_ty: LLVMType,
1671 name: &str,
1672) -> LLVMValue {
1673 assert!(llvm_get_insert_block(builder).is_some());
1674 unsafe {
1675 LLVMBuildIntToPtr(
1676 builder.inner_ref(),
1677 val.into(),
1678 dest_ty.into(),
1679 to_c_str(name).as_ptr(),
1680 )
1681 .into()
1682 }
1683}
1684pub fn llvm_build_ptr_to_int(
1686 builder: &LLVMBuilder,
1687 val: LLVMValue,
1688 dest_ty: LLVMType,
1689 name: &str,
1690) -> LLVMValue {
1691 assert!(llvm_get_insert_block(builder).is_some());
1692 unsafe {
1693 LLVMBuildPtrToInt(
1694 builder.inner_ref(),
1695 val.into(),
1696 dest_ty.into(),
1697 to_c_str(name).as_ptr(),
1698 )
1699 .into()
1700 }
1701}
1702
1703pub fn llvm_build_trunc(
1705 builder: &LLVMBuilder,
1706 val: LLVMValue,
1707 dest_ty: LLVMType,
1708 name: &str,
1709) -> LLVMValue {
1710 assert!(llvm_get_insert_block(builder).is_some());
1711 unsafe {
1712 LLVMBuildTrunc(
1713 builder.inner_ref(),
1714 val.into(),
1715 dest_ty.into(),
1716 to_c_str(name).as_ptr(),
1717 )
1718 .into()
1719 }
1720}
1721
1722pub fn llvm_build_sext(
1724 builder: &LLVMBuilder,
1725 val: LLVMValue,
1726 dest_ty: LLVMType,
1727 name: &str,
1728) -> LLVMValue {
1729 assert!(llvm_get_insert_block(builder).is_some());
1730 unsafe {
1731 LLVMBuildSExt(
1732 builder.inner_ref(),
1733 val.into(),
1734 dest_ty.into(),
1735 to_c_str(name).as_ptr(),
1736 )
1737 .into()
1738 }
1739}
1740
1741pub fn llvm_build_zext(
1743 builder: &LLVMBuilder,
1744 val: LLVMValue,
1745 dest_ty: LLVMType,
1746 name: &str,
1747) -> LLVMValue {
1748 assert!(llvm_get_insert_block(builder).is_some());
1749 unsafe {
1750 LLVMBuildZExt(
1751 builder.inner_ref(),
1752 val.into(),
1753 dest_ty.into(),
1754 to_c_str(name).as_ptr(),
1755 )
1756 .into()
1757 }
1758}
1759
1760pub fn llvm_build_gep2(
1762 builder: &LLVMBuilder,
1763 ty: LLVMType,
1764 ptr: LLVMValue,
1765 indices: &[LLVMValue],
1766 name: &str,
1767) -> LLVMValue {
1768 assert!(llvm_get_insert_block(builder).is_some());
1769 let mut indices: Vec<_> = indices.iter().cloned().map(Into::into).collect();
1770 unsafe {
1771 LLVMBuildGEP2(
1772 builder.inner_ref(),
1773 ty.into(),
1774 ptr.into(),
1775 indices.as_mut_ptr(),
1776 indices.len().try_into().unwrap(),
1777 to_c_str(name).as_ptr(),
1778 )
1779 .into()
1780 }
1781}
1782
1783pub fn llvm_build_insert_element(
1785 builder: &LLVMBuilder,
1786 agg_val: LLVMValue,
1787 element_val: LLVMValue,
1788 index: LLVMValue,
1789 name: &str,
1790) -> LLVMValue {
1791 assert!(llvm_get_insert_block(builder).is_some());
1792 unsafe {
1793 LLVMBuildInsertElement(
1794 builder.inner_ref(),
1795 agg_val.into(),
1796 element_val.into(),
1797 index.into(),
1798 to_c_str(name).as_ptr(),
1799 )
1800 .into()
1801 }
1802}
1803
1804pub fn llvm_build_extract_element(
1806 builder: &LLVMBuilder,
1807 agg_val: LLVMValue,
1808 index: LLVMValue,
1809 name: &str,
1810) -> LLVMValue {
1811 assert!(llvm_get_insert_block(builder).is_some());
1812 unsafe {
1813 LLVMBuildExtractElement(
1814 builder.inner_ref(),
1815 agg_val.into(),
1816 index.into(),
1817 to_c_str(name).as_ptr(),
1818 )
1819 .into()
1820 }
1821}
1822
1823pub fn llvm_build_shuffle_vector(
1825 builder: &LLVMBuilder,
1826 vec1: LLVMValue,
1827 vec2: LLVMValue,
1828 mask: LLVMValue,
1829 name: &str,
1830) -> LLVMValue {
1831 assert!(llvm_get_insert_block(builder).is_some());
1832 unsafe {
1833 LLVMBuildShuffleVector(
1834 builder.inner_ref(),
1835 vec1.into(),
1836 vec2.into(),
1837 mask.into(),
1838 to_c_str(name).as_ptr(),
1839 )
1840 .into()
1841 }
1842}
1843
1844pub fn llvm_build_insert_value(
1846 builder: &LLVMBuilder,
1847 agg_val: LLVMValue,
1848 element_val: LLVMValue,
1849 index: u32,
1850 name: &str,
1851) -> LLVMValue {
1852 assert!(llvm_get_insert_block(builder).is_some());
1853 unsafe {
1854 LLVMBuildInsertValue(
1855 builder.inner_ref(),
1856 agg_val.into(),
1857 element_val.into(),
1858 index,
1859 to_c_str(name).as_ptr(),
1860 )
1861 .into()
1862 }
1863}
1864
1865pub fn llvm_build_extract_value(
1867 builder: &LLVMBuilder,
1868 agg_val: LLVMValue,
1869 index: u32,
1870 name: &str,
1871) -> LLVMValue {
1872 assert!(llvm_get_insert_block(builder).is_some());
1873 unsafe {
1874 LLVMBuildExtractValue(
1875 builder.inner_ref(),
1876 agg_val.into(),
1877 index,
1878 to_c_str(name).as_ptr(),
1879 )
1880 .into()
1881 }
1882}
1883
1884pub fn llvm_build_select(
1886 builder: &LLVMBuilder,
1887 if_val: LLVMValue,
1888 then_val: LLVMValue,
1889 else_val: LLVMValue,
1890 name: &str,
1891) -> LLVMValue {
1892 assert!(llvm_get_insert_block(builder).is_some());
1893 unsafe {
1894 LLVMBuildSelect(
1895 builder.inner_ref(),
1896 if_val.into(),
1897 then_val.into(),
1898 else_val.into(),
1899 to_c_str(name).as_ptr(),
1900 )
1901 .into()
1902 }
1903}
1904
1905pub fn llvm_build_fadd(
1907 builder: &LLVMBuilder,
1908 lhs: LLVMValue,
1909 rhs: LLVMValue,
1910 name: &str,
1911) -> LLVMValue {
1912 assert!(llvm_get_insert_block(builder).is_some());
1913 unsafe {
1914 LLVMBuildFAdd(
1915 builder.inner_ref(),
1916 lhs.into(),
1917 rhs.into(),
1918 to_c_str(name).as_ptr(),
1919 )
1920 .into()
1921 }
1922}
1923
1924pub fn llvm_build_fsub(
1926 builder: &LLVMBuilder,
1927 lhs: LLVMValue,
1928 rhs: LLVMValue,
1929 name: &str,
1930) -> LLVMValue {
1931 assert!(llvm_get_insert_block(builder).is_some());
1932 unsafe {
1933 LLVMBuildFSub(
1934 builder.inner_ref(),
1935 lhs.into(),
1936 rhs.into(),
1937 to_c_str(name).as_ptr(),
1938 )
1939 .into()
1940 }
1941}
1942
1943pub fn llvm_build_fmul(
1945 builder: &LLVMBuilder,
1946 lhs: LLVMValue,
1947 rhs: LLVMValue,
1948 name: &str,
1949) -> LLVMValue {
1950 assert!(llvm_get_insert_block(builder).is_some());
1951 unsafe {
1952 LLVMBuildFMul(
1953 builder.inner_ref(),
1954 lhs.into(),
1955 rhs.into(),
1956 to_c_str(name).as_ptr(),
1957 )
1958 .into()
1959 }
1960}
1961
1962pub fn llvm_build_fdiv(
1964 builder: &LLVMBuilder,
1965 lhs: LLVMValue,
1966 rhs: LLVMValue,
1967 name: &str,
1968) -> LLVMValue {
1969 assert!(llvm_get_insert_block(builder).is_some());
1970 unsafe {
1971 LLVMBuildFDiv(
1972 builder.inner_ref(),
1973 lhs.into(),
1974 rhs.into(),
1975 to_c_str(name).as_ptr(),
1976 )
1977 .into()
1978 }
1979}
1980
1981pub fn llvm_build_frem(
1983 builder: &LLVMBuilder,
1984 lhs: LLVMValue,
1985 rhs: LLVMValue,
1986 name: &str,
1987) -> LLVMValue {
1988 assert!(llvm_get_insert_block(builder).is_some());
1989 unsafe {
1990 LLVMBuildFRem(
1991 builder.inner_ref(),
1992 lhs.into(),
1993 rhs.into(),
1994 to_c_str(name).as_ptr(),
1995 )
1996 .into()
1997 }
1998}
1999
2000pub fn llvm_build_fcmp(
2002 builder: &LLVMBuilder,
2003 op: LLVMRealPredicate,
2004 lhs: LLVMValue,
2005 rhs: LLVMValue,
2006 name: &str,
2007) -> LLVMValue {
2008 assert!(llvm_get_insert_block(builder).is_some());
2009 unsafe {
2010 LLVMBuildFCmp(
2011 builder.inner_ref(),
2012 op,
2013 lhs.into(),
2014 rhs.into(),
2015 to_c_str(name).as_ptr(),
2016 )
2017 .into()
2018 }
2019}
2020
2021pub fn llvm_build_fpext(
2023 builder: &LLVMBuilder,
2024 val: LLVMValue,
2025 dest_ty: LLVMType,
2026 name: &str,
2027) -> LLVMValue {
2028 assert!(llvm_get_insert_block(builder).is_some());
2029 unsafe {
2030 LLVMBuildFPExt(
2031 builder.inner_ref(),
2032 val.into(),
2033 dest_ty.into(),
2034 to_c_str(name).as_ptr(),
2035 )
2036 .into()
2037 }
2038}
2039
2040pub fn llvm_build_fptrunc(
2042 builder: &LLVMBuilder,
2043 val: LLVMValue,
2044 dest_ty: LLVMType,
2045 name: &str,
2046) -> LLVMValue {
2047 assert!(llvm_get_insert_block(builder).is_some());
2048 unsafe {
2049 LLVMBuildFPTrunc(
2050 builder.inner_ref(),
2051 val.into(),
2052 dest_ty.into(),
2053 to_c_str(name).as_ptr(),
2054 )
2055 .into()
2056 }
2057}
2058
2059pub fn llvm_build_fptosi(
2061 builder: &LLVMBuilder,
2062 val: LLVMValue,
2063 dest_ty: LLVMType,
2064 name: &str,
2065) -> LLVMValue {
2066 assert!(llvm_get_insert_block(builder).is_some());
2067 unsafe {
2068 LLVMBuildFPToSI(
2069 builder.inner_ref(),
2070 val.into(),
2071 dest_ty.into(),
2072 to_c_str(name).as_ptr(),
2073 )
2074 .into()
2075 }
2076}
2077
2078pub fn llvm_build_sitofp(
2080 builder: &LLVMBuilder,
2081 val: LLVMValue,
2082 dest_ty: LLVMType,
2083 name: &str,
2084) -> LLVMValue {
2085 assert!(llvm_get_insert_block(builder).is_some());
2086 unsafe {
2087 LLVMBuildSIToFP(
2088 builder.inner_ref(),
2089 val.into(),
2090 dest_ty.into(),
2091 to_c_str(name).as_ptr(),
2092 )
2093 .into()
2094 }
2095}
2096
2097pub fn llvm_build_uitofp(
2099 builder: &LLVMBuilder,
2100 val: LLVMValue,
2101 dest_ty: LLVMType,
2102 name: &str,
2103) -> LLVMValue {
2104 assert!(llvm_get_insert_block(builder).is_some());
2105 unsafe {
2106 LLVMBuildUIToFP(
2107 builder.inner_ref(),
2108 val.into(),
2109 dest_ty.into(),
2110 to_c_str(name).as_ptr(),
2111 )
2112 .into()
2113 }
2114}
2115
2116pub fn llvm_build_fptoui(
2118 builder: &LLVMBuilder,
2119 val: LLVMValue,
2120 dest_ty: LLVMType,
2121 name: &str,
2122) -> LLVMValue {
2123 assert!(llvm_get_insert_block(builder).is_some());
2124 unsafe {
2125 LLVMBuildFPToUI(
2126 builder.inner_ref(),
2127 val.into(),
2128 dest_ty.into(),
2129 to_c_str(name).as_ptr(),
2130 )
2131 .into()
2132 }
2133}
2134
2135pub fn llvm_add_incoming(
2137 phi_node: LLVMValue,
2138 incoming_values: &[LLVMValue],
2139 incoming_blocks: &[LLVMBasicBlock],
2140) {
2141 assert!(llvm_is_a::phi_node(phi_node));
2142 assert!(incoming_values.len() == incoming_blocks.len());
2143 let mut incoming_values: Vec<LLVMValueRef> =
2144 incoming_values.iter().cloned().map(Into::into).collect();
2145 let mut incoming_blocks: Vec<_> = incoming_blocks.iter().cloned().map(Into::into).collect();
2146 unsafe {
2147 LLVMAddIncoming(
2148 phi_node.into(),
2149 incoming_values.as_mut_ptr(),
2150 incoming_blocks.as_mut_ptr(),
2151 incoming_blocks.len().try_into().unwrap(),
2152 )
2153 }
2154}
2155
2156pub fn llvm_build_cond_br(
2158 builder: &LLVMBuilder,
2159 if_val: LLVMValue,
2160 then_block: LLVMBasicBlock,
2161 else_block: LLVMBasicBlock,
2162) -> LLVMValue {
2163 assert!(llvm_get_insert_block(builder).is_some());
2164 unsafe {
2165 LLVMBuildCondBr(
2166 builder.inner_ref(),
2167 if_val.into(),
2168 then_block.into(),
2169 else_block.into(),
2170 )
2171 .into()
2172 }
2173}
2174
2175pub fn llvm_build_br(builder: &LLVMBuilder, dest: LLVMBasicBlock) -> LLVMValue {
2177 assert!(llvm_get_insert_block(builder).is_some());
2178 unsafe { LLVMBuildBr(builder.inner_ref(), dest.into()).into() }
2179}
2180
2181pub fn llvm_build_switch(
2183 builder: &LLVMBuilder,
2184 val: LLVMValue,
2185 default_block: LLVMBasicBlock,
2186 num_cases: u32,
2187) -> LLVMValue {
2188 assert!(llvm_get_insert_block(builder).is_some());
2189 unsafe {
2190 LLVMBuildSwitch(
2191 builder.inner_ref(),
2192 val.into(),
2193 default_block.into(),
2194 num_cases,
2195 )
2196 .into()
2197 }
2198}
2199
2200pub fn llvm_get_switch_case_value(switch_inst: LLVMValue, case_idx: u32) -> LLVMValue {
2202 assert!(llvm_is_a::switch_inst(switch_inst));
2203 unsafe { LLVMGetSwitchCaseValue(switch_inst.into(), case_idx).into() }
2204}
2205
2206pub fn llvm_add_case(switch_inst: LLVMValue, on_val: LLVMValue, dest_block: LLVMBasicBlock) {
2208 assert!(llvm_is_a::switch_inst(switch_inst));
2209 unsafe {
2210 LLVMAddCase(switch_inst.into(), on_val.into(), dest_block.into());
2211 }
2212}
2213
2214pub fn llvm_build_load2(
2216 builder: &LLVMBuilder,
2217 ty: LLVMType,
2218 pointer_val: LLVMValue,
2219 name: &str,
2220) -> LLVMValue {
2221 assert!(llvm_get_insert_block(builder).is_some());
2222 unsafe {
2223 LLVMBuildLoad2(
2224 builder.inner_ref(),
2225 ty.into(),
2226 pointer_val.into(),
2227 to_c_str(name).as_ptr(),
2228 )
2229 .into()
2230 }
2231}
2232
2233pub fn llvm_build_store(builder: &LLVMBuilder, val: LLVMValue, ptr: LLVMValue) -> LLVMValue {
2235 assert!(llvm_get_insert_block(builder).is_some());
2236 unsafe { LLVMBuildStore(builder.inner_ref(), val.into(), ptr.into()).into() }
2237}
2238
2239pub fn llvm_build_icmp(
2241 builder: &LLVMBuilder,
2242 op: LLVMIntPredicate,
2243 lhs: LLVMValue,
2244 rhs: LLVMValue,
2245 name: &str,
2246) -> LLVMValue {
2247 assert!(llvm_get_insert_block(builder).is_some());
2248 unsafe {
2249 LLVMBuildICmp(
2250 builder.inner_ref(),
2251 op,
2252 lhs.into(),
2253 rhs.into(),
2254 to_c_str(name).as_ptr(),
2255 )
2256 .into()
2257 }
2258}
2259
2260pub fn llvm_build_ret_void(builder: &LLVMBuilder) -> LLVMValue {
2262 assert!(llvm_get_insert_block(builder).is_some());
2263 unsafe { LLVMBuildRetVoid(builder.inner_ref()).into() }
2264}
2265
2266pub fn llvm_build_ret(builder: &LLVMBuilder, val: LLVMValue) -> LLVMValue {
2268 assert!(llvm_get_insert_block(builder).is_some());
2269 unsafe { LLVMBuildRet(builder.inner_ref(), val.into()).into() }
2270}
2271
2272pub fn llvm_build_unreachable(builder: &LLVMBuilder) -> LLVMValue {
2274 assert!(llvm_get_insert_block(builder).is_some());
2275 unsafe { LLVMBuildUnreachable(builder.inner_ref()).into() }
2276}
2277
2278pub fn llvm_build_phi(builder: &LLVMBuilder, ty: LLVMType, name: &str) -> LLVMValue {
2280 assert!(llvm_get_insert_block(builder).is_some());
2281 unsafe { LLVMBuildPhi(builder.inner_ref(), ty.into(), to_c_str(name).as_ptr()).into() }
2282}
2283
2284pub fn llvm_build_call2(
2286 builder: &LLVMBuilder,
2287 ty: LLVMType,
2288 callee: LLVMValue,
2289 args: &[LLVMValue],
2290 name: &str,
2291) -> LLVMValue {
2292 assert!(llvm_get_insert_block(builder).is_some());
2293 assert!(llvm_get_type_kind(ty) == LLVMTypeKind::LLVMFunctionTypeKind);
2294 let mut args: Vec<_> = args.iter().cloned().map(Into::into).collect();
2295 unsafe {
2296 LLVMBuildCall2(
2297 builder.inner_ref(),
2298 ty.into(),
2299 callee.into(),
2300 args.as_mut_ptr(),
2301 args.len().try_into().unwrap(),
2302 to_c_str(name).as_ptr(),
2303 )
2304 .into()
2305 }
2306}
2307
2308pub fn llvm_build_va_arg(
2310 builder: &LLVMBuilder,
2311 val: LLVMValue,
2312 ty: LLVMType,
2313 name: &str,
2314) -> LLVMValue {
2315 assert!(llvm_get_insert_block(builder).is_some());
2316 unsafe {
2317 LLVMBuildVAArg(
2318 builder.inner_ref(),
2319 val.into(),
2320 ty.into(),
2321 to_c_str(name).as_ptr(),
2322 )
2323 .into()
2324 }
2325}
2326
2327pub fn llvm_build_freeze(builder: &LLVMBuilder, val: LLVMValue, name: &str) -> LLVMValue {
2329 assert!(llvm_get_insert_block(builder).is_some());
2330 unsafe { LLVMBuildFreeze(builder.inner_ref(), val.into(), to_c_str(name).as_ptr()).into() }
2331}
2332
2333pub fn llvm_const_int(int_ty: LLVMType, val: u64, sign_extend: bool) -> LLVMValue {
2335 assert!(llvm_get_type_kind(int_ty) == LLVMTypeKind::LLVMIntegerTypeKind);
2336 unsafe { LLVMConstInt(int_ty.into(), val, sign_extend.into()).into() }
2337}
2338
2339pub fn llvm_get_undef(ty: LLVMType) -> LLVMValue {
2341 unsafe { LLVMGetUndef(ty.into()).into() }
2342}
2343
2344pub fn llvm_get_poison(ty: LLVMType) -> LLVMValue {
2346 unsafe { LLVMGetPoison(ty.into()).into() }
2347}
2348
2349pub fn llvm_add_function(module: &LLVMModule, name: &str, fn_ty: LLVMType) -> LLVMValue {
2351 assert!(llvm_get_type_kind(fn_ty) == LLVMTypeKind::LLVMFunctionTypeKind);
2352 unsafe { LLVMAddFunction(module.inner_ref(), to_c_str(name).as_ptr(), fn_ty.into()).into() }
2353}
2354
2355pub fn llvm_get_named_function(module: &LLVMModule, name: &str) -> Option<LLVMValue> {
2357 unsafe {
2358 let func = LLVMGetNamedFunction(module.inner_ref(), to_c_str(name).as_ptr());
2359 (!func.is_null()).then_some(func.into())
2360 }
2361}
2362
2363pub fn llvm_delete_function(func: LLVMValue) {
2365 assert!(llvm_is_a::function(func));
2366 unsafe { LLVMDeleteFunction(func.into()) }
2367}
2368
2369pub fn llvm_append_basic_block_in_context(
2371 context: &LLVMContext,
2372 func: LLVMValue,
2373 name: &str,
2374) -> LLVMBasicBlock {
2375 assert!(llvm_is_a::function(func));
2376 unsafe {
2377 LLVMAppendBasicBlockInContext(context.inner_ref(), func.into(), to_c_str(name).as_ptr())
2378 .into()
2379 }
2380}
2381
2382pub fn llvm_get_called_value(inst: LLVMValue) -> LLVMValue {
2384 assert!(llvm_is_a::call_inst(inst) || llvm_is_a::invoke_inst(inst));
2385 unsafe { LLVMGetCalledValue(inst.into()).into() }
2386}
2387
2388pub fn llvm_get_num_arg_operands(inst: LLVMValue) -> u32 {
2390 assert!(llvm_is_a::call_inst(inst) || llvm_is_a::invoke_inst(inst));
2391 unsafe { LLVMGetNumArgOperands(inst.into()) }
2392}
2393
2394pub fn llvm_get_called_function_type(inst: LLVMValue) -> LLVMType {
2396 assert!(llvm_is_a::call_inst(inst) || llvm_is_a::invoke_inst(inst));
2397 unsafe { LLVMGetCalledFunctionType(inst.into()).into() }
2398}
2399
2400pub fn llvm_get_nuw(arith_inst: LLVMValue) -> bool {
2402 assert!(llvm_is_a::instruction(arith_inst));
2403 unsafe { LLVMGetNUW(arith_inst.into()).to_bool() }
2404}
2405
2406pub fn llvm_get_nsw(arith_inst: LLVMValue) -> bool {
2408 assert!(llvm_is_a::instruction(arith_inst));
2409 unsafe { LLVMGetNSW(arith_inst.into()).to_bool() }
2410}
2411
2412pub fn llvm_can_value_use_fast_math_flags(fpmath_inst: LLVMValue) -> bool {
2414 unsafe { LLVMCanValueUseFastMathFlags(fpmath_inst.into()).to_bool() }
2415}
2416
2417pub fn llvm_get_fast_math_flags(fpmath_inst: LLVMValue) -> FastmathFlags {
2419 assert!(llvm_can_value_use_fast_math_flags(fpmath_inst));
2420 unsafe { LLVMGetFastMathFlags(fpmath_inst.into()) }.into()
2421}
2422
2423pub fn llvm_set_fast_math_flags(fpmath_inst: LLVMValue, flags: FastmathFlags) {
2425 assert!(llvm_can_value_use_fast_math_flags(fpmath_inst));
2426 unsafe { LLVMSetFastMathFlags(fpmath_inst.into(), flags.into()) }
2427}
2428
2429pub fn llvm_get_gep_source_element_type(gep: LLVMValue) -> LLVMType {
2431 assert!(
2432 llvm_is_a::get_element_ptr_inst(gep)
2433 || (llvm_is_a::constant_expr(gep)
2434 && llvm_get_const_opcode(gep) == LLVMOpcode::LLVMGetElementPtr)
2435 );
2436 unsafe { LLVMGetGEPSourceElementType(gep.into()).into() }
2437}
2438
2439pub fn llvm_get_num_indices(inst: LLVMValue) -> u32 {
2441 assert!(llvm_is_a::insert_value_inst(inst) || llvm_is_a::extract_value_inst(inst));
2442 unsafe { LLVMGetNumIndices(inst.into()) }
2443}
2444
2445pub fn llvm_get_indices(inst: LLVMValue) -> Vec<u32> {
2447 assert!(llvm_is_a::insert_value_inst(inst) || llvm_is_a::extract_value_inst(inst));
2448 let num_indices = llvm_get_num_indices(inst);
2449 let indices = unsafe { LLVMGetIndices(inst.into()) };
2450 c_array_to_vec(indices, num_indices as usize)
2451}
2452
2453#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2454pub struct IntrinsicID(u32);
2455
2456fn llvm_name_has_intrinsic_prefix(name: &str) -> bool {
2459 name.starts_with("llvm.")
2460}
2461
2462pub fn llvm_lookup_intrinsic_id(name: &str) -> Option<IntrinsicID> {
2464 if !llvm_name_has_intrinsic_prefix(name) {
2465 return None;
2466 }
2467 let id = unsafe { LLVMLookupIntrinsicID(to_c_str(name).as_ptr(), name.len()) };
2468 (id != 0).then_some(IntrinsicID(id))
2469}
2470
2471pub fn llvm_intrinsic_is_overloaded(id: IntrinsicID) -> bool {
2473 unsafe { LLVMIntrinsicIsOverloaded(id.0).to_bool() }
2474}
2475
2476pub fn llvm_get_intrinsic_declaration(
2478 module: &LLVMModule,
2479 id: IntrinsicID,
2480 param_tys: &[LLVMType],
2481) -> Result<LLVMValue, String> {
2482 let overloaded = llvm_intrinsic_is_overloaded(id);
2483
2484 if overloaded && param_tys.is_empty() {
2487 return Err(format!(
2488 "Intrinsic with ID {} is overloaded and requires parameter types",
2489 id.0
2490 ));
2491 }
2492
2493 if !overloaded && !param_tys.is_empty() {
2497 return Err(format!(
2498 "Intrinsic with ID {} is not overloaded and does not accept parameter types",
2499 id.0
2500 ));
2501 }
2502
2503 let mut param_tys: Vec<_> = param_tys.iter().cloned().map(Into::into).collect();
2504 unsafe {
2505 let decl = LLVMGetIntrinsicDeclaration(
2506 module.inner_ref(),
2507 id.0,
2508 param_tys.as_mut_ptr(),
2509 param_tys.len(),
2510 );
2511 (!decl.is_null()).then_some(decl.into())
2512 }
2513 .ok_or_else(|| {
2514 format!(
2515 "Failed to get intrinsic declaration for ID {} in the given module",
2516 id.0
2517 )
2518 })
2519}
2520
2521mod llvm_module {
2523 use llvm_sys::ir_reader::LLVMParseIRInContext2;
2524
2525 use super::*;
2526
2527 pub struct LLVMModule(LLVMModuleRef);
2529
2530 impl Drop for LLVMModule {
2531 fn drop(&mut self) {
2532 unsafe { LLVMDisposeModule(self.0) }
2533 }
2534 }
2535
2536 impl LLVMModule {
2537 pub fn new(module_id: &str, context: &LLVMContext) -> Self {
2538 Self(unsafe {
2539 LLVMModuleCreateWithNameInContext(to_c_str(module_id).as_ptr(), context.inner_ref())
2540 })
2541 }
2542
2543 pub fn from_ir_in_memory_buffer(
2545 context: &LLVMContext,
2546 memory_buffer: LLVMMemoryBuffer,
2547 ) -> Result<LLVMModule, String> {
2548 let mut module_ref = MaybeUninit::uninit();
2549 let mut err_string = MaybeUninit::uninit();
2550
2551 let success = unsafe {
2552 LLVMParseIRInContext2(
2553 context.inner_ref(),
2554 memory_buffer.inner_ref(),
2555 module_ref.as_mut_ptr(),
2556 err_string.as_mut_ptr(),
2557 )
2558 };
2559
2560 if success != 0 {
2561 unsafe {
2562 let err_str = err_string.assume_init();
2563 let err_string = cstr_to_string(err_str).unwrap();
2564 LLVMDisposeMessage(err_str);
2565 return Err(err_string);
2566 }
2567 }
2568
2569 unsafe { Ok(LLVMModule(module_ref.assume_init())) }
2570 }
2571
2572 pub fn from_ir_in_file(
2574 context: &LLVMContext,
2575 filename: &str,
2576 ) -> Result<LLVMModule, String> {
2577 let memory_buffer = LLVMMemoryBuffer::from_file_name(filename)?;
2578 Self::from_ir_in_memory_buffer(context, memory_buffer)
2579 }
2580
2581 pub fn asm_to_file(&self, filename: &str) -> Result<(), String> {
2583 let mut err_string = MaybeUninit::uninit();
2584 let return_code = unsafe {
2585 LLVMPrintModuleToFile(self.0, to_c_str(filename).as_ptr(), err_string.as_mut_ptr())
2586 };
2587
2588 if return_code == 1 {
2589 unsafe {
2590 let err_str = err_string.assume_init();
2591 let err_string = cstr_to_string(err_str).unwrap();
2592 LLVMDisposeMessage(err_str);
2593 return Err(err_string);
2594 }
2595 }
2596
2597 Ok(())
2598 }
2599
2600 pub fn bitcode_to_file(&self, filename: &str) -> Result<(), String> {
2602 unsafe {
2603 if LLVMWriteBitcodeToFile(self.0, to_c_str(filename).as_ptr()) == 0 {
2604 Ok(())
2605 } else {
2606 Err("Error writing bitcode to file".into())
2607 }
2608 }
2609 }
2610
2611 pub fn verify(&self) -> Result<(), String> {
2613 let mut err_string = MaybeUninit::uninit();
2614 let return_code = unsafe {
2615 LLVMVerifyModule(
2616 self.0,
2617 llvm_sys::analysis::LLVMVerifierFailureAction::LLVMReturnStatusAction,
2618 err_string.as_mut_ptr(),
2619 )
2620 };
2621 if return_code == 1 {
2622 unsafe {
2623 let err_str = err_string.assume_init();
2624 let err_string = cstr_to_string(err_str).unwrap();
2625 LLVMDisposeMessage(err_str);
2626 return Err(err_string);
2627 }
2628 }
2629 Ok(())
2630 }
2631
2632 pub(in crate::llvm_sys) fn inner_ref(&self) -> LLVMModuleRef {
2634 self.0
2635 }
2636 }
2637}
2638
2639pub use llvm_module::LLVMModule;
2640
2641impl Display for LLVMModule {
2642 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2643 if let Some(module_str) = llvm_print_module_to_string(self) {
2644 write!(f, "{}", module_str)
2645 } else {
2646 write!(f, "<Error printing LLVMModule at {:p}>", self.inner_ref())
2647 }
2648 }
2649}
2650
2651mod llvm_memory_buffer {
2653 use super::*;
2654
2655 pub struct LLVMMemoryBuffer(LLVMMemoryBufferRef);
2657
2658 impl LLVMMemoryBuffer {
2659 pub fn from_file_name(name: &str) -> Result<LLVMMemoryBuffer, String> {
2661 let mut memory_buffer_ref = ptr::null_mut();
2662 let mut err_string = MaybeUninit::uninit();
2663
2664 let return_code = unsafe {
2665 LLVMCreateMemoryBufferWithContentsOfFile(
2666 to_c_str(name).as_ptr(),
2667 &mut memory_buffer_ref,
2668 err_string.as_mut_ptr(),
2669 )
2670 };
2671
2672 if return_code == 1 {
2673 unsafe {
2674 let err_str = err_string.assume_init();
2675 let err_string = cstr_to_string(err_str).unwrap();
2676 LLVMDisposeMessage(err_str);
2677 return Err(err_string);
2678 }
2679 }
2680
2681 Ok(LLVMMemoryBuffer(memory_buffer_ref))
2682 }
2683
2684 pub fn from_str(contents: &str, buffer_name: &str) -> LLVMMemoryBuffer {
2686 unsafe {
2687 LLVMMemoryBuffer(LLVMCreateMemoryBufferWithMemoryRangeCopy(
2688 contents.as_ptr() as *const _,
2689 contents.len(),
2690 to_c_str(buffer_name).as_ptr(),
2691 ))
2692 }
2693 }
2694 }
2695
2696 impl Drop for LLVMMemoryBuffer {
2697 fn drop(&mut self) {
2698 unsafe { LLVMDisposeMemoryBuffer(self.inner_ref()) }
2699 }
2700 }
2701
2702 impl LLVMMemoryBuffer {
2703 pub(super) fn inner_ref(&self) -> LLVMMemoryBufferRef {
2705 self.0
2706 }
2707 }
2708}
2709
2710pub use llvm_memory_buffer::LLVMMemoryBuffer;
2711
2712pub(super) fn handle_err(err: LLVMErrorRef) -> Result<(), String> {
2714 if err.is_null() {
2715 Ok(())
2716 } else {
2717 unsafe {
2718 let err_msg_ptr = LLVMGetErrorMessage(err);
2719 let err_msg = cstr_to_string(err_msg_ptr).unwrap();
2720 LLVMDisposeErrorMessage(err_msg_ptr);
2721 Err(err_msg)
2722 }
2723 }
2724}