1use std::ffi::c_void;
2use std::fmt;
3
4use crate::{FuncItemRef, ImportResolver, MirContext, ffi};
5
6pub struct MirGenContext {
8 ctx: MirContext,
9 #[cfg(feature = "gen-debug")]
10 debug_file: std::cell::Cell<Option<crate::mem_file::MemoryFile>>,
11}
12
13impl fmt::Debug for MirGenContext {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 f.debug_struct("MirGenContext")
16 .field("ctx", &self.ctx)
17 .finish_non_exhaustive()
18 }
19}
20
21impl MirGenContext {
22 pub fn new(ctx: MirContext) -> Self {
24 unsafe { ffi::MIR_gen_init(ctx.ctx.as_ptr()) };
25 Self {
26 ctx,
27 #[cfg(feature = "gen-debug")]
28 debug_file: std::cell::Cell::new(None),
29 }
30 }
31
32 pub fn set_opt_level(&self, level: u32) {
38 unsafe { ffi::MIR_gen_set_optimize_level(self.ctx.ctx.as_ptr(), level) };
39 }
40
41 #[cfg(feature = "gen-debug")]
45 pub fn enable_debug(&self, level: libc::c_int) {
46 let file = crate::mem_file::MemoryFile::new();
47 unsafe {
48 ffi::MIR_gen_set_debug_level(self.ctx.ctx.as_ptr(), level);
49 ffi::MIR_gen_set_debug_file(self.ctx.ctx.as_ptr(), file.file());
50 }
51 self.debug_file.set(Some(file));
52 }
53
54 #[cfg(feature = "gen-debug")]
63 pub fn get_debug_output(&self) -> String {
64 let file = self.debug_file.take().expect("debug is not enabled");
65 let s = file.get_data_string();
66 self.debug_file.set(Some(file));
67 s
68 }
69
70 pub fn link_modules_for_codegen(&self) {
76 unsafe { self.link_modules_raw(Some(ffi::MIR_set_gen_interface), None) }
77 }
78
79 pub unsafe fn link_modules_for_codegen_with_resolver(&self, resolver: &ImportResolver) {
90 unsafe { self.link_modules_raw(Some(ffi::MIR_set_gen_interface), Some(resolver)) }
91 }
92
93 pub fn codegen_func(&self, func: FuncItemRef<'_>) -> *mut c_void {
98 unsafe { ffi::MIR_gen(self.ctx.ctx.as_ptr(), func.as_raw()) }
99 }
100}
101
102impl Drop for MirGenContext {
103 fn drop(&mut self) {
104 #[cfg(feature = "gen-debug")]
105 {
106 if self.debug_file.get_mut().is_some() {
107 unsafe {
108 ffi::MIR_gen_set_debug_file(self.ctx.ctx.as_ptr(), std::ptr::null_mut());
109 }
110 }
111 }
112 unsafe { ffi::MIR_gen_finish(self.ctx.ctx.as_ptr()) };
113 }
114}
115
116impl std::ops::Deref for MirGenContext {
117 type Target = MirContext;
118
119 fn deref(&self) -> &Self::Target {
120 &self.ctx
121 }
122}