1use std::ops::Deref;
2
3use llvm_sys::core;
4use llvm_sys::prelude::{
5 LLVMMetadataRef, LLVMModuleFlagEntry, LLVMModuleRef, LLVMNamedMDNodeRef, LLVMValueRef,
6};
7use llvm_sys::{LLVMInlineAsmDialect, LLVMModuleFlagBehavior};
8
9use crate::core::context::ContextRef;
10use crate::core::types::TypeRef;
11use crate::core::values::ValueRef;
12use crate::{CInt, CStr, CString, GetRef, SizeT};
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub enum InlineAsmDialect {
17 InlineAsmDialectATT,
18 InlineAsmDialectIntel,
19}
20
21impl From<InlineAsmDialect> for LLVMInlineAsmDialect {
22 fn from(value: InlineAsmDialect) -> Self {
23 match value {
24 InlineAsmDialect::InlineAsmDialectATT => Self::LLVMInlineAsmDialectATT,
25 InlineAsmDialect::InlineAsmDialectIntel => Self::LLVMInlineAsmDialectIntel,
26 }
27 }
28}
29
30impl From<LLVMInlineAsmDialect> for InlineAsmDialect {
31 fn from(value: LLVMInlineAsmDialect) -> Self {
32 match value {
33 LLVMInlineAsmDialect::LLVMInlineAsmDialectATT => Self::InlineAsmDialectATT,
34 LLVMInlineAsmDialect::LLVMInlineAsmDialectIntel => Self::InlineAsmDialectIntel,
35 }
36 }
37}
38
39#[derive(Debug)]
44pub struct NamedMetadataNodeRef(LLVMNamedMDNodeRef);
45
46impl From<LLVMNamedMDNodeRef> for NamedMetadataNodeRef {
47 fn from(value: LLVMNamedMDNodeRef) -> Self {
48 Self(value)
49 }
50}
51
52impl NamedMetadataNodeRef {
53 #[must_use]
58 pub fn get_next(&self) -> Option<Self> {
59 let next_md = unsafe { core::LLVMGetNextNamedMetadata(self.0) };
60 if next_md.is_null() {
61 None
62 } else {
63 Some(next_md.into())
64 }
65 }
66
67 #[must_use]
72 pub fn get_previous(&self) -> Option<Self> {
73 let prev_md = unsafe { core::LLVMGetPreviousNamedMetadata(self.0) };
74 if prev_md.is_null() {
75 None
76 } else {
77 Some(prev_md.into())
78 }
79 }
80
81 #[must_use]
83 pub fn get_name(&self) -> Option<String> {
84 let mut length = SizeT::from(0_usize);
85 unsafe {
86 let c_str = core::LLVMGetNamedMetadataName(self.0, &mut *length);
87 if c_str.is_null() {
88 return None;
89 }
90 Some(CStr::new(c_str).to_string())
91 }
92 }
93}
94
95#[derive(Debug, Clone)]
96pub struct MetadataRef(LLVMMetadataRef);
97
98impl From<LLVMMetadataRef> for MetadataRef {
99 fn from(metadata: LLVMMetadataRef) -> Self {
100 Self(metadata)
101 }
102}
103
104impl GetRef for MetadataRef {
105 type RawRef = LLVMMetadataRef;
106 fn get_ref(&self) -> Self::RawRef {
107 self.0
108 }
109}
110
111#[allow(dead_code)]
114#[derive(Debug)]
115pub struct ModuleFlagEntry(*mut LLVMModuleFlagEntry, SizeT);
116
117impl ModuleFlagEntry {
118 #[must_use]
120 pub fn get_count(&self) -> usize {
121 *self.1
122 }
123
124 pub fn dispose_module_flags_metadata(&self) {
126 unsafe {
127 core::LLVMDisposeModuleFlagsMetadata(self.0);
128 }
129 }
130
131 #[must_use]
133 pub fn get_flag_behavior(&self, index: u32) -> ModuleFlagBehavior {
134 let behavior = unsafe { core::LLVMModuleFlagEntriesGetFlagBehavior(self.0, index) };
135 behavior.into()
136 }
137
138 #[must_use]
140 pub fn get_key(&self, index: u32) -> Option<String> {
141 unsafe {
142 let mut length: usize = 0;
143 let c_str = core::LLVMModuleFlagEntriesGetKey(self.0, index, &mut length);
144 if c_str.is_null() {
145 return None;
146 }
147 Some(CStr::new(c_str).to_string())
148 }
149 }
150
151 #[must_use]
153 pub fn get_metadata(&self, index: u32) -> MetadataRef {
154 let metadata = unsafe { core::LLVMModuleFlagEntriesGetMetadata(self.0, index) };
155 MetadataRef(metadata)
156 }
157}
158
159#[derive(Clone, Copy, Debug, PartialEq, Eq)]
160pub enum ModuleFlagBehavior {
161 ModuleFlagBehaviorError,
163 ModuleFlagBehaviorWarning,
166 ModuleFlagBehaviorRequire,
172 ModuleFlagBehaviorOverride,
175 ModuleFlagBehaviorAppend,
177 ModuleFlagBehaviorAppendUnique,
180}
181
182impl From<LLVMModuleFlagBehavior> for ModuleFlagBehavior {
183 fn from(value: LLVMModuleFlagBehavior) -> Self {
184 match value {
185 LLVMModuleFlagBehavior::LLVMModuleFlagBehaviorError => Self::ModuleFlagBehaviorError,
186 LLVMModuleFlagBehavior::LLVMModuleFlagBehaviorWarning => {
187 Self::ModuleFlagBehaviorWarning
188 }
189 LLVMModuleFlagBehavior::LLVMModuleFlagBehaviorRequire => {
190 Self::ModuleFlagBehaviorRequire
191 }
192 LLVMModuleFlagBehavior::LLVMModuleFlagBehaviorOverride => {
193 Self::ModuleFlagBehaviorOverride
194 }
195 LLVMModuleFlagBehavior::LLVMModuleFlagBehaviorAppend => Self::ModuleFlagBehaviorAppend,
196 LLVMModuleFlagBehavior::LLVMModuleFlagBehaviorAppendUnique => {
197 Self::ModuleFlagBehaviorAppendUnique
198 }
199 }
200 }
201}
202
203impl From<ModuleFlagBehavior> for LLVMModuleFlagBehavior {
204 fn from(value: ModuleFlagBehavior) -> Self {
205 match value {
206 ModuleFlagBehavior::ModuleFlagBehaviorError => Self::LLVMModuleFlagBehaviorError,
207 ModuleFlagBehavior::ModuleFlagBehaviorWarning => Self::LLVMModuleFlagBehaviorWarning,
208 ModuleFlagBehavior::ModuleFlagBehaviorRequire => Self::LLVMModuleFlagBehaviorRequire,
209 ModuleFlagBehavior::ModuleFlagBehaviorOverride => Self::LLVMModuleFlagBehaviorOverride,
210 ModuleFlagBehavior::ModuleFlagBehaviorAppend => Self::LLVMModuleFlagBehaviorAppend,
211 ModuleFlagBehavior::ModuleFlagBehaviorAppendUnique => {
212 Self::LLVMModuleFlagBehaviorAppendUnique
213 }
214 }
215 }
216}
217
218pub struct ModuleRef(LLVMModuleRef);
220
221impl Deref for ModuleRef {
222 type Target = LLVMModuleRef;
223 fn deref(&self) -> &Self::Target {
224 &self.0
225 }
226}
227
228impl Drop for ModuleRef {
229 fn drop(&mut self) {
231 unsafe {
232 core::LLVMDisposeModule(self.0);
233 }
234 }
235}
236
237impl From<LLVMModuleRef> for ModuleRef {
238 fn from(module: LLVMModuleRef) -> Self {
239 Self(module)
240 }
241}
242
243impl GetRef for ModuleRef {
244 type RawRef = LLVMModuleRef;
245 fn get_ref(&self) -> Self::RawRef {
246 self.0
247 }
248}
249
250impl ModuleRef {
251 #[must_use]
256 pub fn new(module_name: &str) -> Self {
257 Self::create_module_with_name(module_name)
258 }
259
260 #[must_use]
263 pub fn create_module_with_name(module_name: &str) -> Self {
264 let c_name = CString::from(module_name);
265 let module_ref = unsafe { core::LLVMModuleCreateWithName(c_name.as_ptr()) };
266 assert!(!module_ref.is_null(), "Failed to create LLVM module");
268 Self(module_ref)
269 }
270
271 #[must_use]
274 pub fn create_module_with_name_in_context(module_name: &str, context: &ContextRef) -> Self {
275 let c_name = CString::from(module_name);
276 let module_ref =
277 unsafe { core::LLVMModuleCreateWithNameInContext(c_name.as_ptr(), context.get_ref()) };
278 assert!(!module_ref.is_null(), "Failed to create LLVM module");
280 Self(module_ref)
281 }
282
283 #[must_use]
285 pub fn clone_module(&self) -> Self {
286 let module_ref = unsafe { core::LLVMCloneModule(self.0) };
287 Self(module_ref)
288 }
289
290 #[must_use]
292 pub fn get_module_identifier(&self) -> Option<String> {
293 let mut length = *SizeT::from(0_usize);
294 unsafe {
295 let c_str = core::LLVMGetModuleIdentifier(self.0, &mut length);
296 if c_str.is_null() {
297 return None;
298 }
299 Some(CStr::new(c_str).to_string())
300 }
301 }
302
303 pub fn set_module_identifier(&self, ident: &str) {
305 let c_ident = CString::from(ident);
306 unsafe {
307 core::LLVMSetModuleIdentifier(
308 self.0,
309 c_ident.as_ptr(),
310 *SizeT::from(c_ident.count_bytes()),
311 );
312 }
313 }
314
315 #[must_use]
317 pub fn get_source_file_name(&self) -> Option<String> {
318 let mut length = *SizeT::from(0_usize);
319 unsafe {
320 let c_str = core::LLVMGetSourceFileName(self.0, &mut length);
321 if c_str.is_null() {
322 return None;
323 }
324 Some(CStr::new(c_str).to_string())
325 }
326 }
327
328 pub fn set_source_file_name(&self, name: &str) {
330 let c_name = CString::from(name);
331 unsafe {
332 core::LLVMSetSourceFileName(
333 self.0,
334 c_name.as_ptr(),
335 *SizeT::from(c_name.count_bytes()),
336 );
337 }
338 }
339
340 #[must_use]
342 pub fn get_data_layout_str(&self) -> Option<String> {
343 unsafe {
344 let c_str = core::LLVMGetDataLayoutStr(self.0);
345 if c_str.is_null() {
346 return None;
347 }
348 Some(CStr::new(c_str).to_string())
349 }
350 }
351
352 pub fn set_data_layout(&self, data_layout_str: &str) {
354 let c_data_layout_str = CString::from(data_layout_str);
355 unsafe {
356 core::LLVMSetDataLayout(self.0, c_data_layout_str.as_ptr());
357 }
358 }
359
360 #[must_use]
362 pub fn get_target(&self) -> Option<String> {
363 unsafe {
364 let c_str = core::LLVMGetTarget(self.0);
365 if c_str.is_null() {
366 return None;
367 }
368 Some(CStr::new(c_str).to_string())
369 }
370 }
371
372 pub fn set_target(&self, triple: &str) {
374 let c_triple = CString::from(triple);
375 unsafe {
376 core::LLVMSetTarget(self.0, c_triple.as_ptr());
377 }
378 }
379
380 #[must_use]
383 pub fn copy_module_flags_metadata(&self) -> Option<ModuleFlagEntry> {
384 unsafe {
385 let mut length = SizeT(0_usize);
386 let entries = core::LLVMCopyModuleFlagsMetadata(self.0, &mut *length);
387 if entries.is_null() {
388 None
389 } else {
390 Some(ModuleFlagEntry(entries, length))
391 }
392 }
393 }
394
395 #[must_use]
397 pub fn get_module_flag(&self, key: &str) -> MetadataRef {
398 let c_key = CString::from(key);
399 let metadata =
400 unsafe { core::LLVMGetModuleFlag(self.0, c_key.as_ptr(), *SizeT(c_key.count_bytes())) };
401 MetadataRef(metadata)
402 }
403
404 pub fn add_module_flag(&self, behavior: &ModuleFlagBehavior, key: &str, val: &MetadataRef) {
405 let c_key = CString::from(key);
406 unsafe {
407 core::LLVMAddModuleFlag(
408 self.0,
409 (*behavior).into(),
410 c_key.as_ptr(),
411 c_key.count_bytes(),
412 val.0,
413 );
414 }
415 }
416
417 pub fn dump_module(&self) {
419 unsafe {
420 core::LLVMDumpModule(self.0);
421 }
422 }
423
424 pub fn print_module_to_file(&self, filename: &str) -> Result<(), String> {
430 let c_filename = CString::from(filename);
431 let mut error_message: *mut std::ffi::c_char = std::ptr::null_mut();
432 let result =
433 unsafe { core::LLVMPrintModuleToFile(self.0, c_filename.as_ptr(), &mut error_message) };
434 if result == 0 {
435 Ok(())
436 } else {
437 unsafe {
438 let error = CStr::new(error_message).to_string();
439 core::LLVMDisposeMessage(error_message);
440 Err(error)
441 }
442 }
443 }
444
445 #[must_use]
447 pub fn print_module_to_string(&self) -> Option<String> {
448 unsafe {
449 let c_str = core::LLVMPrintModuleToString(self.0);
450 if c_str.is_null() {
451 return None;
452 }
453 let result = CStr::new(c_str).to_string();
454 core::LLVMDisposeMessage(c_str);
455 Some(result)
456 }
457 }
458
459 #[must_use]
461 pub fn get_module_inline_asm(&self) -> Option<String> {
462 unsafe {
463 let mut len = SizeT::from(0_usize);
464 let c_str = core::LLVMGetModuleInlineAsm(self.0, &mut *len);
465 if c_str.is_null() {
466 return None;
467 }
468 Some(CStr::new(c_str).to_string())
469 }
470 }
471
472 pub fn set_module_inline_asm(&self, asm: &str) {
474 let c_asm = CString::from(asm);
475 unsafe {
476 core::LLVMSetModuleInlineAsm2(self.0, c_asm.as_ptr(), *SizeT(c_asm.count_bytes()));
477 }
478 }
479
480 pub fn append_module_inline_asm(&self, asm: &str) {
482 let c_asm = CString::from(asm);
483 unsafe {
484 core::LLVMAppendModuleInlineAsm(self.0, c_asm.as_ptr(), *SizeT(c_asm.count_bytes()));
485 }
486 }
487
488 #[must_use]
490 pub fn get_module_context(&self) -> ContextRef {
491 ContextRef::from(unsafe { core::LLVMGetModuleContext(self.0) })
492 }
493
494 #[must_use]
496 pub fn get_first_named_metadata(&self) -> Option<NamedMetadataNodeRef> {
497 let md = unsafe { core::LLVMGetFirstNamedMetadata(self.0) };
498 if md.is_null() {
499 None
500 } else {
501 Some(md.into())
502 }
503 }
504
505 #[must_use]
507 pub fn get_last_named_metadata(&self) -> Option<NamedMetadataNodeRef> {
508 let md = unsafe { core::LLVMGetLastNamedMetadata(self.0) };
509 if md.is_null() {
510 None
511 } else {
512 Some(md.into())
513 }
514 }
515
516 #[must_use]
518 pub fn get_named_metadata(&self, name: &str) -> Option<NamedMetadataNodeRef> {
519 let c_name = CString::from(name);
520 let md = unsafe {
521 core::LLVMGetNamedMetadata(self.0, c_name.as_ptr(), *SizeT(c_name.as_bytes().len()))
522 };
523 if md.is_null() {
524 None
525 } else {
526 Some(md.into())
527 }
528 }
529
530 #[must_use]
532 pub fn get_or_insert_named_metadata(&self, name: &str) -> NamedMetadataNodeRef {
533 let c_name = CString::from(name);
534 let md = unsafe {
535 core::LLVMGetOrInsertNamedMetadata(
536 self.0,
537 c_name.as_ptr(),
538 *SizeT(c_name.as_bytes().len()),
539 )
540 };
541 md.into()
542 }
543
544 #[must_use]
546 pub fn get_named_metadata_num_operands(&self, name: &str) -> u32 {
547 let c_name = CString::from(name);
548 unsafe { core::LLVMGetNamedMetadataNumOperands(self.0, c_name.as_ptr()) }
549 }
550
551 #[must_use]
558 pub fn get_named_metadata_operands(&self, name: &str) -> Vec<ValueRef> {
559 let c_name = CString::from(name);
560 let num_operands = self.get_named_metadata_num_operands(name);
561 let mut raw_operands: Vec<LLVMValueRef> = Vec::with_capacity(num_operands as usize);
562 unsafe {
563 core::LLVMGetNamedMetadataOperands(self.0, c_name.as_ptr(), raw_operands.as_mut_ptr());
564 raw_operands.set_len(num_operands as usize);
565 }
566 raw_operands.into_iter().map(ValueRef::from).collect()
567 }
568
569 pub fn add_named_metadata_operand(&self, name: &str, val: &ValueRef) {
571 let c_name = CString::from(name);
572 unsafe { core::LLVMAddNamedMetadataOperand(self.0, c_name.as_ptr(), val.get_ref()) };
573 }
574
575 #[must_use]
577 pub fn add_function(&self, fn_name: &str, fn_type: &TypeRef) -> ValueRef {
578 unsafe {
579 let c_name = CString::from(fn_name);
580 ValueRef::from(core::LLVMAddFunction(self.0, c_name.as_ptr(), **fn_type))
581 }
582 }
583
584 #[must_use]
588 pub fn get_named_function(&self, name: &str) -> ValueRef {
589 let c_name = CString::from(name);
590 ValueRef::from(unsafe { core::LLVMGetNamedFunction(self.0, c_name.as_ptr()) })
591 }
592
593 #[must_use]
595 pub fn get_first_function(&self) -> ValueRef {
596 ValueRef::from(unsafe { core::LLVMGetFirstFunction(self.0) })
597 }
598
599 #[must_use]
601 pub fn get_last_function(&self) -> ValueRef {
602 ValueRef::from(unsafe { core::LLVMGetLastFunction(self.0) })
603 }
604}
605
606#[must_use]
608pub fn get_inline_asm_asm_string(inline_asm_val: &ValueRef) -> Option<String> {
609 inline_asm_val.get_inline_asm_asm_string()
610}
611
612#[must_use]
614pub fn get_inline_asm(
615 ty: &TypeRef,
616 asm_string: &str,
617 constraints: &str,
618 has_side_effects: bool,
619 is_align_stack: bool,
620 dialect: InlineAsmDialect,
621 can_throw: bool,
622) -> ValueRef {
623 let c_asm_string = CString::from(asm_string);
624 let c_constraints = CString::from(constraints);
625 let value_ref = unsafe {
626 core::LLVMGetInlineAsm(
627 ty.get_ref(),
628 c_asm_string.as_ptr(),
629 *SizeT(c_asm_string.count_bytes()),
630 c_constraints.as_ptr(),
631 *SizeT(c_constraints.count_bytes()),
632 *CInt::from(has_side_effects),
633 *CInt::from(is_align_stack),
634 dialect.into(),
635 *CInt::from(can_throw),
636 )
637 };
638 ValueRef::from(value_ref)
639}
640
641#[must_use]
643pub fn get_inline_asm_constraint_string(inline_asm_val: &ValueRef) -> Option<String> {
644 inline_asm_val.get_inline_asm_constraint_string()
645}
646
647#[must_use]
649pub fn get_inline_asm_dialect(inline_asm_val: &ValueRef) -> InlineAsmDialect {
650 inline_asm_val.get_inline_asm_dialect()
651}
652
653#[must_use]
657pub fn get_inline_asm_function_type(inline_asm_val: &ValueRef) -> TypeRef {
658 inline_asm_val.get_inline_asm_function_type()
659}
660
661#[must_use]
663pub fn get_inline_asm_has_side_effects(inline_asm_val: &ValueRef) -> bool {
664 inline_asm_val.get_inline_asm_has_side_effects()
665}
666
667#[must_use]
669pub fn get_inline_asm_needs_aligned_stack(inline_asm_val: &ValueRef) -> bool {
670 inline_asm_val.get_inline_asm_needs_aligned_stack()
671}
672
673#[must_use]
675pub fn get_inline_asm_can_unwind(inline_asm_val: &ValueRef) -> bool {
676 inline_asm_val.get_inline_asm_can_unwind()
677}
678
679#[must_use]
682pub fn get_debug_loc_directory(val: &ValueRef) -> Option<String> {
683 val.get_debug_loc_directory()
684}
685
686#[must_use]
689pub fn get_debug_loc_filename(val: &ValueRef) -> Option<String> {
690 val.get_debug_loc_filename()
691}
692
693#[must_use]
696pub fn get_debug_loc_line(val: &ValueRef) -> u32 {
697 val.get_debug_loc_line()
698}
699
700#[must_use]
703pub fn get_debug_loc_column(val: &ValueRef) -> u32 {
704 val.get_debug_loc_column()
705}
706
707#[must_use]
711pub fn get_next_function(func: &ValueRef) -> Option<ValueRef> {
712 func.get_next_function()
713}
714
715#[must_use]
719pub fn get_previous_function(func: &ValueRef) -> Option<ValueRef> {
720 func.get_previous_function()
721}