llvm_quick/core/
modules.rs

1use std::ffi::CStr;
2use std::fmt::{Debug, Formatter};
3use std::ptr::null_mut;
4
5use llvm_sys::core::*;
6use llvm_sys::*;
7
8use crate::core::Message;
9use crate::owning::{OpaqueClone, OpaqueDrop, Owning};
10use crate::type_tag::*;
11use crate::*;
12
13impl<'c> Debug for Module<'c> {
14    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
15        f.write_str(self.print_to_string().to_str().unwrap())
16    }
17}
18
19impl Context {
20    /// Create a new, empty module in a specific context.
21    pub fn create_module(&self, name: &CStr) -> Owning<Module> {
22        unsafe {
23            let ptr = LLVMModuleCreateWithNameInContext(name.as_ptr(), self.as_raw());
24            Owning::from_raw(ptr)
25        }
26    }
27}
28
29impl OpaqueClone for LLVMModule {
30    unsafe fn clone_raw(ptr: *mut Self) -> *mut Self {
31        unsafe { LLVMCloneModule(ptr) }
32    }
33}
34
35impl OpaqueDrop for LLVMModule {
36    unsafe fn drop_raw(ptr: *mut Self) {
37        unsafe { LLVMDisposeModule(ptr) }
38    }
39}
40
41impl<'c> Module<'c> {
42    pub fn get_identifier(&self) -> &[u8] {
43        unsafe {
44            let mut len = 0;
45            let ptr = LLVMGetModuleIdentifier(self.as_raw(), &mut len);
46            std::slice::from_raw_parts(ptr as _, len)
47        }
48    }
49
50    pub fn set_identifier(&self, ident: &[u8]) {
51        unsafe { LLVMSetModuleIdentifier(self.as_raw(), ident.as_ptr() as _, ident.len()) }
52    }
53
54    pub fn get_source_file_name(&self) -> &[u8] {
55        unsafe {
56            let mut len = 0;
57            let ptr = LLVMGetSourceFileName(self.as_raw(), &mut len);
58            std::slice::from_raw_parts(ptr as _, len)
59        }
60    }
61
62    pub fn set_source_file_name(&self, ident: &[u8]) {
63        unsafe { LLVMSetSourceFileName(self.as_raw(), ident.as_ptr() as _, ident.len()) }
64    }
65
66    pub fn get_data_layout_str(&self) -> &CStr {
67        unsafe { CStr::from_ptr(LLVMGetDataLayoutStr(self.as_raw())) }
68    }
69
70    pub fn set_data_layout_str(&self, data_layout_str: &CStr) {
71        unsafe { LLVMSetDataLayout(self.as_raw(), data_layout_str.as_ptr()) }
72    }
73
74    pub fn get_target(&self) -> &CStr {
75        unsafe { CStr::from_ptr(LLVMGetTarget(self.as_raw())) }
76    }
77
78    pub fn set_target(&self, triple: &CStr) {
79        unsafe { LLVMSetTarget(self.as_raw(), triple.as_ptr()) }
80    }
81
82    pub fn copy_flags_metadata(&self) -> ModuleFlagsMetadata {
83        unsafe {
84            let mut len = 0;
85            let ptr = LLVMCopyModuleFlagsMetadata(self.as_raw(), &mut len);
86            ModuleFlagsMetadata::from_raw(ptr, len)
87        }
88    }
89}
90
91impl<'m> Drop for ModuleFlagsMetadata<'m> {
92    fn drop(&mut self) {
93        unsafe { LLVMDisposeModuleFlagsMetadata(self.as_raw()) }
94    }
95}
96
97impl<'m> ModuleFlagsMetadata<'m> {
98    pub fn get_flag_behavior(&self, index: u32) -> LLVMModuleFlagBehavior {
99        assert!((index as usize) < self.len);
100        unsafe { LLVMModuleFlagEntriesGetFlagBehavior(self.as_raw() as _, index) }
101    }
102
103    pub fn get_key(&self, index: u32) -> &[u8] {
104        assert!((index as usize) < self.len);
105        unsafe {
106            let mut len = 0;
107            let ptr = LLVMModuleFlagEntriesGetKey(self.as_raw() as _, index, &mut len);
108            std::slice::from_raw_parts(ptr as _, len)
109        }
110    }
111
112    pub fn get_metadata(&self, index: u32) -> &Metadata {
113        assert!((index as usize) < self.len);
114        unsafe { Metadata::from_raw(LLVMModuleFlagEntriesGetMetadata(self.as_raw() as _, index)) }
115    }
116}
117
118impl<'c> Module<'c> {
119    pub fn get_flag(&self, key: &[u8]) -> &Metadata {
120        unsafe {
121            Metadata::from_raw(LLVMGetModuleFlag(
122                self.as_raw(),
123                key.as_ptr() as _,
124                key.len(),
125            ))
126        }
127    }
128
129    pub fn add_flag(&self, behavior: LLVMModuleFlagBehavior, key: &[u8], val: &Metadata) {
130        unsafe {
131            LLVMAddModuleFlag(
132                self.as_raw(),
133                behavior,
134                key.as_ptr() as _,
135                key.len(),
136                val.as_raw(),
137            )
138        }
139    }
140
141    pub fn dump(&self) {
142        unsafe { LLVMDumpModule(self.as_raw()) }
143    }
144
145    pub fn print_to_file(&self, filename: &CStr) -> Result<(), Message> {
146        unsafe {
147            let mut error = null_mut();
148            if LLVMPrintModuleToFile(self.as_raw(), filename.as_ptr(), &mut error) != 0 {
149                Err(Message::from_raw(error))
150            } else {
151                Ok(())
152            }
153        }
154    }
155
156    pub fn print_to_string(&self) -> Message {
157        unsafe { Message::from_raw(LLVMPrintModuleToString(self.as_raw())) }
158    }
159
160    pub fn get_inline_asm_raw(&self) -> *const [u8] {
161        unsafe {
162            let mut len = 0;
163            let ptr = LLVMGetModuleInlineAsm(self.as_raw(), &mut len);
164            std::ptr::slice_from_raw_parts(ptr as _, len)
165        }
166    }
167
168    pub fn get_inline_asm(&self) -> Vec<u8> {
169        unsafe { Vec::from(&*self.get_inline_asm_raw()) }
170    }
171
172    pub fn set_inline_asm(&self, asm: &[u8]) {
173        unsafe { LLVMSetModuleInlineAsm2(self.as_raw(), asm.as_ptr() as _, asm.len()) }
174    }
175
176    pub fn append_inline_asm(&self, asm: &[u8]) {
177        unsafe { LLVMAppendModuleInlineAsm(self.as_raw(), asm.as_ptr() as _, asm.len()) }
178    }
179}
180
181impl<T: TypeTag> Type<T> {
182    pub fn get_inline_asm(
183        &self,
184        asm_string: &[u8],
185        constraints: &[u8],
186        has_side_effects: bool,
187        is_align_stack: bool,
188        dialect: LLVMInlineAsmDialect,
189        can_throw: bool,
190    ) -> &Value<T> {
191        unsafe {
192            Value::from_raw(LLVMGetInlineAsm(
193                self.as_raw(),
194                asm_string.as_ptr() as _,
195                asm_string.len(),
196                constraints.as_ptr() as _,
197                constraints.len(),
198                has_side_effects as _,
199                is_align_stack as _,
200                dialect,
201                can_throw as _,
202            ))
203        }
204    }
205}
206
207impl<T: TypeTag> Value<T> {
208    pub fn get_inline_asm_constrain_string(&self) -> &[u8] {
209        unsafe {
210            let mut len = 0;
211            let ptr = LLVMGetInlineAsmConstraintString(self.as_raw(), &mut len);
212            std::slice::from_raw_parts(ptr as _, len)
213        }
214    }
215
216    pub fn get_inline_asm_dialect(&self) -> LLVMInlineAsmDialect {
217        unsafe { LLVMGetInlineAsmDialect(self.as_raw()) }
218    }
219
220    pub fn get_inline_asm_function_type(&self) -> &Type<T> {
221        unsafe { Type::from_raw(LLVMGetInlineAsmFunctionType(self.as_raw())) }
222    }
223
224    pub fn get_inline_asm_has_side_effects(&self) -> bool {
225        unsafe { LLVMGetInlineAsmHasSideEffects(self.as_raw()) != 0 }
226    }
227
228    pub fn get_inline_asm_needs_aligned_stack(&self) -> bool {
229        unsafe { LLVMGetInlineAsmNeedsAlignedStack(self.as_raw()) != 0 }
230    }
231
232    pub fn get_inline_asm_can_unwind(&self) -> bool {
233        unsafe { LLVMGetInlineAsmCanUnwind(self.as_raw()) != 0 }
234    }
235}
236
237impl<'c> Module<'c> {
238    /// Obtain the context to which this module is associated.
239    pub fn context(&self) -> &'c Context {
240        unsafe { Context::from_raw(LLVMGetModuleContext(self.as_raw())) }
241    }
242
243    pub fn get_first_named_metadata(&self) -> &NamedMDNode {
244        unsafe { NamedMDNode::from_raw(LLVMGetFirstNamedMetadata(self.as_raw())) }
245    }
246
247    pub fn get_last_named_metadata(&self) -> &NamedMDNode {
248        unsafe { NamedMDNode::from_raw(LLVMGetLastNamedMetadata(self.as_raw())) }
249    }
250}
251
252impl NamedMDNode {
253    pub fn get_next(&self) -> &NamedMDNode {
254        unsafe { NamedMDNode::from_raw(LLVMGetNextNamedMetadata(self.as_raw())) }
255    }
256
257    pub fn get_previous(&self) -> &NamedMDNode {
258        unsafe { NamedMDNode::from_raw(LLVMGetPreviousNamedMetadata(self.as_raw())) }
259    }
260}
261
262impl<'c> Module<'c> {
263    pub fn get_named_metadata(&self, name: &[u8]) -> &NamedMDNode {
264        unsafe {
265            NamedMDNode::from_raw(LLVMGetNamedMetadata(
266                self.as_raw(),
267                name.as_ptr() as _,
268                name.len(),
269            ))
270        }
271    }
272
273    pub fn get_or_insert_named_metadata(&self, name: &[u8]) -> &NamedMDNode {
274        unsafe {
275            NamedMDNode::from_raw(LLVMGetOrInsertNamedMetadata(
276                self.as_raw(),
277                name.as_ptr() as _,
278                name.len(),
279            ))
280        }
281    }
282}
283
284impl NamedMDNode {
285    pub fn get_name(&self) -> &[u8] {
286        unsafe {
287            let mut len = 0;
288            let ptr = LLVMGetNamedMetadataName(self.as_raw(), &mut len);
289            std::slice::from_raw_parts(ptr as _, len)
290        }
291    }
292}
293
294impl<'c> Module<'c> {
295    pub fn get_named_metadata_num_operands(&self, name: &CStr) -> u32 {
296        unsafe { LLVMGetNamedMetadataNumOperands(self.as_raw(), name.as_ptr()) }
297    }
298
299    pub fn get_named_metadata_operands<'s>(
300        &self,
301        name: &CStr,
302        slice: &'s mut [Option<&'c Value<metadata>>],
303    ) -> &'s mut [&'c Value<metadata>] {
304        assert_eq!(
305            slice.len(),
306            self.get_named_metadata_num_operands(name) as usize
307        );
308        unsafe {
309            LLVMGetNamedMetadataOperands(self.as_raw(), name.as_ptr(), slice.as_mut_ptr() as _);
310            std::mem::transmute(slice)
311        }
312    }
313
314    pub fn add_named_metadata_operand(&self, name: &CStr, val: &Value<metadata>) {
315        unsafe { LLVMAddNamedMetadataOperand(self.as_raw(), name.as_ptr(), val.as_raw()) }
316    }
317}
318
319impl<T: TypeTag> Value<T> {
320    pub fn get_debug_loc_director(&self) -> &[u8] {
321        unsafe {
322            let mut len = 0;
323            let ptr = LLVMGetDebugLocDirectory(self.as_raw(), &mut len);
324            std::slice::from_raw_parts(ptr as _, len as _)
325        }
326    }
327
328    pub fn get_debug_loc_filename(&self) -> &[u8] {
329        unsafe {
330            let mut len = 0;
331            let ptr = LLVMGetDebugLocFilename(self.as_raw(), &mut len);
332            std::slice::from_raw_parts(ptr as _, len as _)
333        }
334    }
335
336    pub fn get_debug_loc_line(&self) -> u32 {
337        unsafe { LLVMGetDebugLocLine(self.as_raw()) }
338    }
339
340    pub fn get_debug_loc_column(&self) -> u32 {
341        unsafe { LLVMGetDebugLocColumn(self.as_raw()) }
342    }
343}
344
345impl<'c> Module<'c> {
346    /// Add a function to a module under a specified name.
347    pub fn add_function<T: FunTypeTag>(&self, name: &CStr, ty: &'c Type<T>) -> &'c Function<T> {
348        unsafe { Function::from_raw(LLVMAddFunction(self.as_raw(), name.as_ptr(), ty.as_raw())) }
349    }
350
351    /// Obtain a Function value from a Module by its name.
352    pub fn get_named_function<T: FunTypeTag>(&self, name: &CStr) -> &'c Function<T> {
353        unsafe {
354            Function::<fun_any>::from_raw(LLVMGetNamedFunction(self.as_raw(), name.as_ptr())).cast()
355        }
356    }
357
358    pub fn get_first_function(&self) -> &'c Function<fun_any> {
359        unsafe { Function::from_raw(LLVMGetFirstFunction(self.as_raw())) }
360    }
361
362    pub fn get_last_function(&self) -> &'c Function<fun_any> {
363        unsafe { Function::from_raw(LLVMGetLastFunction(self.as_raw())) }
364    }
365}
366
367impl<T: FunTypeTag> Function<T> {
368    pub fn get_next_function(&self) -> &Function<fun_any> {
369        unsafe { Function::from_raw(LLVMGetNextFunction(self.as_raw())) }
370    }
371
372    pub fn get_previous_function(&self) -> &Function<fun_any> {
373        unsafe { Function::from_raw(LLVMGetPreviousFunction(self.as_raw())) }
374    }
375}