llama/
module.rs

1use crate::*;
2
3/// Wraps LLVMModule
4pub struct Module<'a>(
5    pub(crate) NonNull<llvm::LLVMModule>,
6    pub(crate) std::sync::atomic::AtomicBool,
7    pub(crate) PhantomData<&'a ()>,
8);
9
10llvm_inner_impl!(Module<'a>, llvm::LLVMModule);
11
12impl<'a> Drop for Module<'a> {
13    fn drop(&mut self) {
14        if !self.1.load(std::sync::atomic::Ordering::Relaxed) {
15            return;
16        }
17
18        unsafe { llvm::core::LLVMDisposeModule(self.llvm()) }
19    }
20}
21
22impl<'a> Clone for Module<'a> {
23    fn clone(&self) -> Module<'a> {
24        let m = unsafe {
25            wrap_inner(llvm::core::LLVMCloneModule(self.llvm())).expect("Invalid module")
26        };
27        Module(m, std::sync::atomic::AtomicBool::new(true), PhantomData)
28    }
29}
30
31impl<'a> Module<'a> {
32    /// Create a new module
33    pub fn new(ctx: &Context<'a>, name: impl AsRef<str>) -> Result<Module<'a>, Error> {
34        let name = cstr!(name.as_ref());
35        let m = unsafe {
36            wrap_inner(llvm::core::LLVMModuleCreateWithNameInContext(
37                name.as_ptr(),
38                ctx.llvm(),
39            ))?
40        };
41        Ok(Module(
42            m,
43            std::sync::atomic::AtomicBool::new(true),
44            PhantomData,
45        ))
46    }
47
48    /// Get the associated context
49    pub fn context(&self) -> Result<Context<'a>, Error> {
50        let ctx = unsafe { wrap_inner(llvm::core::LLVMGetModuleContext(self.llvm()))? };
51        Ok(Context(ctx, false, PhantomData))
52    }
53
54    /// Get the module identifier
55    pub fn identifier(&self) -> Result<&str, Error> {
56        let mut size = 0usize;
57        unsafe {
58            let s = llvm::core::LLVMGetModuleIdentifier(self.llvm(), &mut size);
59            let s = std::slice::from_raw_parts(s as *const u8, size);
60            let s = std::str::from_utf8(s)?;
61            Ok(s)
62        }
63    }
64
65    /// Set the module source file name
66    pub fn set_source_file(&mut self, name: impl AsRef<str>) {
67        let len = name.as_ref().len();
68        let name = cstr!(name.as_ref());
69        unsafe { llvm::core::LLVMSetSourceFileName(self.llvm(), name.as_ptr(), len) }
70    }
71
72    /// Get the source file name
73    pub fn source_file(&self) -> Result<&str, Error> {
74        let mut size = 0;
75        unsafe {
76            let s = llvm::core::LLVMGetSourceFileName(self.llvm(), &mut size);
77            let s = std::slice::from_raw_parts(s as *const u8, size);
78            let s = std::str::from_utf8_unchecked(s);
79            Ok(s)
80        }
81    }
82
83    /// Set the module target string
84    pub fn set_target(&mut self, target: impl AsRef<str>) {
85        let target = cstr!(target.as_ref());
86        unsafe { llvm::core::LLVMSetTarget(self.llvm(), target.as_ptr()) }
87    }
88
89    /// Get the target string
90    pub fn target(&self) -> Result<&str, Error> {
91        unsafe {
92            let s = llvm::core::LLVMGetTarget(self.llvm());
93            let s = std::slice::from_raw_parts(s as *const u8, strlen(s));
94            let s = std::str::from_utf8_unchecked(s);
95            Ok(s)
96        }
97    }
98
99    /// Set the module data layout string
100    pub fn set_data_layout(&mut self, layout: impl AsRef<str>) {
101        let layout = cstr!(layout.as_ref());
102        unsafe { llvm::core::LLVMSetDataLayout(self.llvm(), layout.as_ptr()) }
103    }
104
105    /// Get data layout string
106    pub fn data_layout(&self) -> Result<&str, Error> {
107        unsafe {
108            let s = llvm::core::LLVMGetDataLayoutStr(self.llvm());
109            let s = std::slice::from_raw_parts(s as *const u8, strlen(s));
110            let s = std::str::from_utf8_unchecked(s);
111            Ok(s)
112        }
113    }
114
115    /// Set module inline assembly
116    pub fn set_inline_asm(&mut self, asm: impl AsRef<str>) {
117        let len = asm.as_ref().len();
118        let asm = cstr!(asm.as_ref());
119        unsafe { llvm::core::LLVMSetModuleInlineAsm2(self.llvm(), asm.as_ptr(), len) }
120    }
121
122    /// Append module inline assembly
123    pub fn append_inline_asm(&mut self, asm: impl AsRef<str>) {
124        let len = asm.as_ref().len();
125        let asm = cstr!(asm.as_ref());
126        unsafe { llvm::core::LLVMAppendModuleInlineAsm(self.llvm(), asm.as_ptr(), len) }
127    }
128
129    /// Get module inline assembly
130    pub fn inline_asm(&self) -> Result<&str, Error> {
131        let mut len = 0;
132        unsafe {
133            let s = llvm::core::LLVMGetModuleInlineAsm(self.llvm(), &mut len);
134            let s = std::slice::from_raw_parts(s as *const u8, len);
135            let s = std::str::from_utf8_unchecked(s);
136            Ok(s)
137        }
138    }
139
140    /// Verify the module, returning an error on failure
141    pub fn verify(&self) -> Result<(), Error> {
142        let mut message = std::ptr::null_mut();
143        let ok = unsafe {
144            llvm::analysis::LLVMVerifyModule(
145                self.llvm(),
146                llvm::analysis::LLVMVerifierFailureAction::LLVMReturnStatusAction,
147                &mut message,
148            ) == 0
149        };
150
151        let message = Message::from_raw(message);
152
153        if !ok {
154            return Err(Error::Message(message));
155        }
156
157        Ok(())
158    }
159
160    /// Define a new function without declaring a function body
161    pub fn define_function(&self, name: impl AsRef<str>, t: FuncType) -> Result<Func<'a>, Error> {
162        let name = cstr!(name.as_ref());
163        let value =
164            unsafe { llvm::core::LLVMAddFunction(self.llvm(), name.as_ptr(), t.as_ref().llvm()) };
165        let x = Value::from_inner(value)?;
166        Ok(Func(x))
167    }
168
169    /// Declare a new function with function body
170    pub fn declare_function<T: Into<Value<'a>>, F: FnOnce(Func<'a>) -> Result<T, Error>>(
171        &self,
172        builder: &Builder<'a>,
173        name: impl AsRef<str>,
174        ft: FuncType,
175        def: F,
176    ) -> Result<Func<'a>, Error> {
177        let f = self.define_function(name, ft)?;
178        builder.function_body(f, |_, _| def(f))?;
179        Ok(f)
180    }
181
182    /// Create a new global with an empty initializer
183    pub fn define_global(
184        &self,
185        name: impl AsRef<str>,
186        ty: impl AsRef<Type<'a>>,
187    ) -> Result<Value<'a>, Error> {
188        let name = cstr!(name.as_ref());
189        let value =
190            unsafe { llvm::core::LLVMAddGlobal(self.llvm(), ty.as_ref().llvm(), name.as_ptr()) };
191        Value::from_inner(value)
192    }
193
194    /// Define a new global in the given address space with an empty initializer
195    pub fn define_global_in_address_space(
196        &self,
197        name: impl AsRef<str>,
198        ty: impl AsRef<Type<'a>>,
199        addr: usize,
200    ) -> Result<Value<'a>, Error> {
201        let name = cstr!(name.as_ref());
202        let value = unsafe {
203            llvm::core::LLVMAddGlobalInAddressSpace(
204                self.llvm(),
205                ty.as_ref().llvm(),
206                name.as_ptr(),
207                addr as c_uint,
208            )
209        };
210        Value::from_inner(value)
211    }
212
213    /// Create a new global with the specified initializer
214    pub fn declare_global(
215        &self,
216        name: impl AsRef<str>,
217        t: impl AsRef<Value<'a>>,
218    ) -> Result<Value<'a>, Error> {
219        let name = cstr!(name.as_ref());
220        let ty = t.as_ref().type_of()?;
221        let value =
222            unsafe { llvm::core::LLVMAddGlobal(self.llvm(), ty.as_ref().llvm(), name.as_ptr()) };
223        unsafe {
224            llvm::core::LLVMSetInitializer(value, t.as_ref().llvm());
225        }
226        Value::from_inner(value)
227    }
228
229    /// Create a new global in the given address space with the specified initializer
230    pub fn declare_global_in_address_space(
231        &self,
232        name: impl AsRef<str>,
233        t: impl AsRef<Value<'a>>,
234        addr: usize,
235    ) -> Result<Value<'a>, Error> {
236        let name = cstr!(name.as_ref());
237        let ty = t.as_ref().type_of()?;
238        let value = unsafe {
239            llvm::core::LLVMAddGlobalInAddressSpace(
240                self.llvm(),
241                ty.llvm(),
242                name.as_ptr(),
243                addr as c_uint,
244            )
245        };
246        unsafe {
247            llvm::core::LLVMSetInitializer(value, t.as_ref().llvm());
248        }
249        Value::from_inner(value)
250    }
251
252    /// Get a function by name
253    pub fn function(&self, name: impl AsRef<str>) -> Result<Func<'a>, Error> {
254        let name = cstr!(name.as_ref());
255        let value = unsafe { llvm::core::LLVMGetNamedFunction(self.llvm(), name.as_ptr()) };
256        Ok(Func(Value::from_inner(value)?))
257    }
258
259    /// Get a global value by name
260    pub fn global(&self, name: impl AsRef<str>) -> Result<Value<'a>, Error> {
261        let name = cstr!(name.as_ref());
262        let value = unsafe { llvm::core::LLVMGetNamedGlobal(self.llvm(), name.as_ptr()) };
263        Value::from_inner(value)
264    }
265
266    /// Get the first global
267    pub fn first_global(&self) -> Result<Value<'a>, Error> {
268        let value = unsafe { llvm::core::LLVMGetFirstGlobal(self.llvm()) };
269        Value::from_inner(value)
270    }
271
272    /// Get the last global
273    pub fn last_global(&self) -> Result<Value<'a>, Error> {
274        let value = unsafe { llvm::core::LLVMGetLastGlobal(self.llvm()) };
275        Value::from_inner(value)
276    }
277
278    /// Get the next global
279    pub fn next_global(&self, global: impl AsRef<Value<'a>>) -> Result<Value<'a>, Error> {
280        let value = unsafe { llvm::core::LLVMGetNextGlobal(global.as_ref().llvm()) };
281        Value::from_inner(value)
282    }
283
284    /// Get the first function
285    pub fn first_function(&self) -> Result<Func<'a>, Error> {
286        let value = unsafe { llvm::core::LLVMGetFirstFunction(self.llvm()) };
287        Ok(Func(Value::from_inner(value)?))
288    }
289
290    /// Get the last function
291    pub fn last_function(&self) -> Result<Func<'a>, Error> {
292        let value = unsafe { llvm::core::LLVMGetLastFunction(self.llvm()) };
293        Ok(Func(Value::from_inner(value)?))
294    }
295
296    /// Create a new module from existing IR
297    pub fn parse_ir(ctx: &Context, mem_buf: &MemoryBuffer) -> Result<Module<'a>, Error> {
298        let mut module = std::ptr::null_mut();
299        let mut message = std::ptr::null_mut();
300        let ok = unsafe {
301            llvm::ir_reader::LLVMParseIRInContext(
302                ctx.llvm(),
303                mem_buf.llvm(),
304                &mut module,
305                &mut message,
306            ) == 1
307        };
308
309        let message = Message::from_raw(message);
310
311        if !ok {
312            return Err(Error::Message(message));
313        }
314
315        let module = wrap_inner(module)?;
316
317        Ok(Module(
318            module,
319            std::sync::atomic::AtomicBool::new(true),
320            PhantomData,
321        ))
322    }
323
324    /// Create a new module from existing bitcode
325    pub fn parse_bitcode(ctx: &Context, mem_buf: &MemoryBuffer) -> Option<Module<'a>> {
326        let mut module = std::ptr::null_mut();
327        let ok = unsafe {
328            llvm::bit_reader::LLVMParseBitcodeInContext2(ctx.llvm(), mem_buf.llvm(), &mut module)
329                == 1
330        };
331
332        if !ok {
333            return None;
334        }
335
336        let module = match wrap_inner(module) {
337            Ok(m) => m,
338            Err(_) => return None,
339        };
340
341        Some(Module(
342            module,
343            std::sync::atomic::AtomicBool::new(true),
344            PhantomData,
345        ))
346    }
347
348    /// Write module bitcode to file
349    pub fn write_bitcode_to_file(&self, path: impl AsRef<std::path::Path>) -> Result<bool, Error> {
350        let path = match path.as_ref().to_str() {
351            Some(p) => cstr!(p),
352            None => return Err(Error::InvalidPath),
353        };
354
355        let r =
356            unsafe { llvm::bit_writer::LLVMWriteBitcodeToFile(self.llvm(), path.as_ptr()) == 0 };
357
358        Ok(r)
359    }
360
361    /// Write module bitcode to in-memory buffer
362    pub fn write_bitcode_to_memory_buffer(&self) -> Result<MemoryBuffer, Error> {
363        let mem = unsafe { llvm::bit_writer::LLVMWriteBitcodeToMemoryBuffer(self.llvm()) };
364        MemoryBuffer::from_raw(mem)
365    }
366
367    /// Link another module into `self`
368    pub fn link(&self, other: &Module) -> bool {
369        unsafe {
370            let other = llvm::core::LLVMCloneModule(other.llvm());
371            llvm::linker::LLVMLinkModules2(self.llvm(), other) == 1
372        }
373    }
374
375    /// Set WASM32 target/data layout
376    pub fn set_wasm32(&mut self) {
377        self.set_target("wasm32");
378        self.set_data_layout("p:32:32:32");
379    }
380
381    /// Set target data
382    pub fn set_target_data(&mut self, target: &TargetData) {
383        unsafe { llvm::target::LLVMSetModuleDataLayout(self.llvm(), target.llvm()) }
384    }
385
386    /// Get target data
387    pub fn target_data(&self) -> Result<TargetData, Error> {
388        let x = unsafe { llvm::target::LLVMGetModuleDataLayout(self.llvm()) };
389        TargetData::from_inner(x)
390    }
391}
392
393impl<'a> std::fmt::Display for Module<'a> {
394    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
395        let message =
396            unsafe { Message::from_raw(llvm::core::LLVMPrintModuleToString(self.llvm())) };
397        write!(fmt, "{}", message.as_ref())
398    }
399}