midenc_codegen_masm/compiler/
mod.rs1mod masm;
2mod mast;
3
4use midenc_hir::{
5 self as hir,
6 pass::{RewritePass, RewriteSet},
7};
8use midenc_session::{diagnostics::Report, Session};
9
10pub use self::{masm::MasmArtifact, mast::MastArtifact};
11use crate::{intrinsics, ConvertHirToMasm, Program};
12
13pub type CompilerResult<T> = Result<T, Report>;
14
15pub struct MasmCompiler<'a> {
25 session: &'a Session,
26 analyses: hir::pass::AnalysisManager,
27}
28impl<'a> MasmCompiler<'a> {
29 pub fn new(session: &'a Session) -> Self {
30 Self {
31 session,
32 analyses: hir::pass::AnalysisManager::new(),
33 }
34 }
35
36 pub fn compile(&mut self, mut input: Box<hir::Program>) -> CompilerResult<MasmArtifact> {
38 use midenc_hir::pass::ConversionPass;
39
40 let mut rewrites = default_rewrites([], self.session);
41
42 let modules = input.modules_mut().take();
43 for mut module in modules.into_iter() {
44 rewrites.apply(&mut module, &mut self.analyses, self.session)?;
45 input.modules_mut().insert(module);
46 }
47
48 let mut convert_to_masm = ConvertHirToMasm::<hir::Program>::default();
49 let mut artifact = convert_to_masm.convert(input, &mut self.analyses, self.session)?;
50
51 artifact.insert(Box::new(
53 intrinsics::load("intrinsics::mem", &self.session.source_manager)
54 .expect("undefined intrinsics module"),
55 ));
56 artifact.insert(Box::new(
57 intrinsics::load("intrinsics::i32", &self.session.source_manager)
58 .expect("undefined intrinsics module"),
59 ));
60 artifact.insert(Box::new(
61 intrinsics::load("intrinsics::i64", &self.session.source_manager)
62 .expect("undefined intrinsics module"),
63 ));
64
65 Ok(artifact)
66 }
67
68 pub fn compile_module(&mut self, input: Box<hir::Module>) -> CompilerResult<Box<Program>> {
74 assert!(input.entrypoint().is_some(), "cannot compile a program without an entrypoint");
75
76 let program =
77 hir::ProgramBuilder::new(&self.session.diagnostics).with_module(input)?.link()?;
78
79 match self.compile(program)? {
80 MasmArtifact::Executable(program) => Ok(program),
81 _ => unreachable!("expected compiler to produce an executable, got a library"),
82 }
83 }
84
85 pub fn compile_modules<I: IntoIterator<Item = Box<hir::Module>>>(
91 &mut self,
92 input: I,
93 ) -> CompilerResult<Box<Program>> {
94 let mut builder = hir::ProgramBuilder::new(&self.session.diagnostics);
95 for module in input.into_iter() {
96 builder.add_module(module)?;
97 }
98
99 let program = builder.link()?;
100
101 assert!(program.has_entrypoint(), "cannot compile a program without an entrypoint");
102
103 match self.compile(program)? {
104 MasmArtifact::Executable(program) => Ok(program),
105 _ => unreachable!("expected compiler to produce an executable, got a library"),
106 }
107 }
108}
109
110pub fn default_rewrites<P>(registered: P, session: &Session) -> RewriteSet<hir::Module>
111where
112 P: IntoIterator<Item = Box<dyn RewritePass<Entity = hir::Module>>>,
113 <P as IntoIterator>::IntoIter: ExactSizeIterator,
114{
115 use midenc_hir::pass::ModuleRewritePassAdapter;
116
117 let registered = registered.into_iter();
118
119 let mut rewrites = RewriteSet::default();
124 if registered.len() == 0 {
125 if session.should_codegen() {
126 let fn_rewrites = default_function_rewrites(session);
127 for rewrite in fn_rewrites {
128 rewrites.push(ModuleRewritePassAdapter::new(rewrite));
129 }
130 }
131 } else {
132 rewrites.extend(registered);
133 }
134
135 rewrites
136}
137
138pub fn default_function_rewrites(session: &Session) -> RewriteSet<hir::Function> {
139 use midenc_hir_transform as transforms;
140
141 let mut rewrites = RewriteSet::default();
146 if session.should_codegen() {
147 rewrites.push(transforms::SplitCriticalEdges);
148 rewrites.push(transforms::Treeify);
149 rewrites.push(transforms::InlineBlocks);
150 rewrites.push(transforms::ApplySpills);
151 }
152
153 rewrites
154}