1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
pub use crate::iterators::*;
use crate::llvm_sys::*;
use std::ffi::CStr;
use std::os::raw::c_char;
pub unsafe fn raw_to_string(raw: *const c_char) -> String {
let cstr = CStr::from_ptr(raw);
cstr.to_str().expect("Failed to convert CStr").into()
}
macro_rules! wrap {
($llvmFunc:ident, $argty:ty, $wrapperFunc:ident) => {
pub unsafe fn $wrapperFunc(arg: $argty) -> String {
debug_assert!(!arg.is_null());
let ptr = $llvmFunc(arg);
raw_to_string(ptr)
}
};
}
macro_rules! wrap_maybe_null {
($llvmFunc: ident, $argty:ty, $wrapperFunc:ident) => {
pub unsafe fn $wrapperFunc(arg: $argty) -> Option<String> {
debug_assert!(!arg.is_null());
let ptr = $llvmFunc(arg);
if ptr.is_null() {
None
} else {
Some(raw_to_string(ptr))
}
}
};
}
macro_rules! wrap_with_len {
($llvmFunc:ident, $argty:ty, $wrapperFunc:ident) => {
pub unsafe fn $wrapperFunc(arg: $argty) -> String {
debug_assert!(!arg.is_null());
let mut len = 0;
let ptr = $llvmFunc(arg, &mut len);
raw_to_string(ptr)
}
};
}
#[cfg(feature="llvm-9-or-greater")]
macro_rules! wrap_with_len_maybe_null {
($llvmFunc:ident, $argty:ty, $wrapperFunc:ident) => {
pub unsafe fn $wrapperFunc(arg: $argty) -> Option<String> {
debug_assert!(!arg.is_null());
let mut len = 0;
let ptr = $llvmFunc(arg, &mut len);
if ptr.is_null() {
None
} else {
Some(raw_to_string(ptr))
}
}
};
}
wrap_with_len!(LLVMGetModuleInlineAsm, LLVMModuleRef, get_module_inline_asm);
wrap_with_len!(LLVMGetModuleIdentifier, LLVMModuleRef, get_module_identifier);
wrap_with_len!(LLVMGetSourceFileName, LLVMModuleRef, get_source_file_name);
wrap!(LLVMGetDataLayoutStr, LLVMModuleRef, get_data_layout_str);
wrap_maybe_null!(LLVMGetTarget, LLVMModuleRef, get_target);
wrap_with_len!(LLVMGetValueName2, LLVMValueRef, get_value_name);
wrap_maybe_null!(LLVMGetStructName, LLVMTypeRef, get_struct_name);
wrap_maybe_null!(LLVMGetSection, LLVMValueRef, get_section);
wrap_maybe_null!(LLVMGetGC, LLVMValueRef, get_gc);
wrap!(LLVMGetBasicBlockName, LLVMBasicBlockRef, get_bb_name);
wrap!(LLVMPrintValueToString, LLVMValueRef, print_to_string);
wrap_with_len!(LLVMGetStringAttributeKind, LLVMAttributeRef, get_string_attribute_kind);
wrap_with_len!(LLVMGetStringAttributeValue, LLVMAttributeRef, get_string_attribute_value);
#[cfg(feature="llvm-9-or-greater")]
wrap_with_len_maybe_null!(LLVMGetDebugLocFilename, LLVMValueRef, get_debugloc_filename);
#[cfg(feature="llvm-9-or-greater")]
wrap_with_len_maybe_null!(LLVMGetDebugLocDirectory, LLVMValueRef, get_debugloc_directory);
pub unsafe fn op_to_bb(op: LLVMValueRef) -> LLVMBasicBlockRef {
assert!(LLVMValueIsBasicBlock(op) != 0);
LLVMValueAsBasicBlock(op)
}
macro_rules! debug {
($($arg:expr),+) => {
if log::log_enabled!(log::Level::Debug) {
log::debug!($($arg),+)
}
};
}
pub struct Context {
pub ctx: LLVMContextRef,
}
impl Context {
pub fn new() -> Self {
Self {
ctx: unsafe { LLVMContextCreate() },
}
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
LLVMContextDispose(self.ctx);
}
}
}