llvm_wrap/
module.rs

1//! A wrapper around a `LLVMModuleRef` for a specific context
2
3use super::*;
4use super::c_api::*;
5
6use llvm_sys::bit_writer::LLVMWriteBitcodeToFile;
7use std::path::Path;
8
9/// A wrapper around a `LLVMModuleRef` for a specific context
10pub struct Module {
11    pub(crate) module: Option<LLVMModuleRef>,
12}
13
14impl Module {
15    /// Add a function to the module
16    pub fn add_function<S>(&self, name: S, ty: Type) -> Value where S: AsRef<str> {
17        Value {
18            value: unsafe {
19                LLVMAddFunction(self.module.unwrap(), into_c(name).as_ptr(), ty.ty)
20            }
21        }
22    }
23
24    /// Add a global to the module
25    pub fn add_global<S>(&self, name: S, ty: Type) -> Value where S: AsRef<str> {
26        Value {
27            value: unsafe {
28                LLVMAddGlobal(self.module.unwrap(), ty.ty, into_c(name).as_ptr())
29            }
30        }
31    }
32
33    /// Get the function with the given name
34    pub fn get_function<S>(&self, name: S) -> Value where S: AsRef<str> {
35        Value {
36            value: unsafe {
37                LLVMGetNamedFunction(self.module.unwrap(), into_c(name).as_ptr())
38            }
39        }
40    }
41
42    /// Get the global with the given name
43    pub fn get_global<S>(&self, name: S) -> Value where S: AsRef<str> {
44        Value {
45            value: unsafe {
46                LLVMGetNamedGlobal(self.module.unwrap(), into_c(name).as_ptr())
47            }
48        }
49    }
50
51    /// Sets the target triple for this module
52    pub fn set_triple<S>(&self, triple: S) where S: AsRef<str> {
53        unsafe {
54            LLVMSetTarget(self.module.unwrap(), into_c(triple).as_ptr())
55        }
56    }
57
58    /// Sets the data layout for this module
59    pub fn set_data_layout(&self, data: &target::TargetData) {
60        unsafe {
61            LLVMSetDataLayout(self.module.unwrap(), into_c(data.to_string()).as_ptr())
62        }
63    }
64
65    /// Returns an iterator over all functions in the module
66    pub fn functions(&self) -> iter::Functions {
67        iter::Functions {
68            pointer: Value {
69                value: unsafe {
70                    LLVMGetFirstFunction(self.module.unwrap())
71                }
72            }
73        }
74    }
75
76    /// Returns an iterator over all globals in the module
77    pub fn globals(&self) -> iter::Globals {
78        iter::Globals {
79            pointer: Value {
80                value: unsafe {
81                    LLVMGetFirstGlobal(self.module.unwrap())
82                }
83            }
84        }
85    }
86
87    /// Dump the contents of the module to stderr
88    pub fn dump(&self) {
89        unsafe {
90            LLVMDumpModule(self.module.unwrap());
91        }
92    }
93
94    /// Write module IR to a file
95    pub fn write_llvm_ir<P>(&self, path: P) where P: AsRef<Path> {
96        unsafe {
97            if LLVMPrintModuleToFile(
98                self.module.unwrap(),
99                into_c(path.as_ref()
100                    .to_str()
101                    .expect("path could not be converted to string")
102                ).as_ptr(),
103                vec![into_c("could not output LLVM IR for module").as_ptr() as *mut i8].as_mut_ptr(),
104            ) != 0 {
105                panic!("failed to write LLVM IR to file");
106            }
107        }
108    }
109
110    /// Write module bitcode to a file
111    pub fn write_bitcode<P>(&self, path: P) where P: AsRef<Path> {
112        unsafe {
113            if LLVMWriteBitcodeToFile(
114                self.module.unwrap(),
115                into_c(path.as_ref()
116                    .to_str()
117                    .expect("path could not be converted to string")
118                ).as_ptr()
119            ) != 0 {
120                panic!("failed to write bitcode to file");
121            }
122        }
123    }
124
125    /// Returns the internal module reference
126    pub fn inner(&self) -> LLVMModuleRef {
127        self.module.unwrap()
128    }
129
130    /// Destroys the wrapper, returning the internal module reference
131    pub unsafe fn into_inner(mut self) -> LLVMModuleRef {
132        self.module.take().unwrap()
133    }
134}
135
136impl Deref for Module {
137    type Target = LLVMModuleRef;
138
139    fn deref(&self) -> &LLVMModuleRef {
140        self.module.as_ref().unwrap()
141    }
142}
143
144impl Drop for Module {
145    fn drop(&mut self) {
146        if let Some(module) = self.module {
147            unsafe {
148                LLVMDisposeModule(module);
149            }
150        }
151    }
152}
153
154impl Debug for Module {
155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156        write!(f, "Module")
157    }
158}