1use crate::*;
2
3pub 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pub fn set_wasm32(&mut self) {
377 self.set_target("wasm32");
378 self.set_data_layout("p:32:32:32");
379 }
380
381 pub fn set_target_data(&mut self, target: &TargetData) {
383 unsafe { llvm::target::LLVMSetModuleDataLayout(self.llvm(), target.llvm()) }
384 }
385
386 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}