mod masm;
mod mast;
use midenc_hir::{
self as hir,
pass::{RewritePass, RewriteSet},
};
use midenc_session::{diagnostics::Report, Session};
pub use self::{masm::MasmArtifact, mast::MastArtifact};
use crate::{intrinsics, ConvertHirToMasm, Program};
pub type CompilerResult<T> = Result<T, Report>;
pub struct MasmCompiler<'a> {
session: &'a Session,
analyses: hir::pass::AnalysisManager,
}
impl<'a> MasmCompiler<'a> {
pub fn new(session: &'a Session) -> Self {
Self {
session,
analyses: hir::pass::AnalysisManager::new(),
}
}
pub fn compile(&mut self, mut input: Box<hir::Program>) -> CompilerResult<MasmArtifact> {
use midenc_hir::pass::ConversionPass;
let mut rewrites = default_rewrites([], self.session);
let modules = input.modules_mut().take();
for mut module in modules.into_iter() {
rewrites.apply(&mut module, &mut self.analyses, self.session)?;
input.modules_mut().insert(module);
}
let mut convert_to_masm = ConvertHirToMasm::<hir::Program>::default();
let mut artifact = convert_to_masm.convert(input, &mut self.analyses, self.session)?;
artifact.insert(Box::new(
intrinsics::load("intrinsics::mem", &self.session.source_manager)
.expect("undefined intrinsics module"),
));
artifact.insert(Box::new(
intrinsics::load("intrinsics::i32", &self.session.source_manager)
.expect("undefined intrinsics module"),
));
artifact.insert(Box::new(
intrinsics::load("intrinsics::i64", &self.session.source_manager)
.expect("undefined intrinsics module"),
));
Ok(artifact)
}
pub fn compile_module(&mut self, input: Box<hir::Module>) -> CompilerResult<Box<Program>> {
assert!(input.entrypoint().is_some(), "cannot compile a program without an entrypoint");
let program =
hir::ProgramBuilder::new(&self.session.diagnostics).with_module(input)?.link()?;
match self.compile(program)? {
MasmArtifact::Executable(program) => Ok(program),
_ => unreachable!("expected compiler to produce an executable, got a library"),
}
}
pub fn compile_modules<I: IntoIterator<Item = Box<hir::Module>>>(
&mut self,
input: I,
) -> CompilerResult<Box<Program>> {
let mut builder = hir::ProgramBuilder::new(&self.session.diagnostics);
for module in input.into_iter() {
builder.add_module(module)?;
}
let program = builder.link()?;
assert!(program.has_entrypoint(), "cannot compile a program without an entrypoint");
match self.compile(program)? {
MasmArtifact::Executable(program) => Ok(program),
_ => unreachable!("expected compiler to produce an executable, got a library"),
}
}
}
pub fn default_rewrites<P>(registered: P, session: &Session) -> RewriteSet<hir::Module>
where
P: IntoIterator<Item = Box<dyn RewritePass<Entity = hir::Module>>>,
<P as IntoIterator>::IntoIter: ExactSizeIterator,
{
use midenc_hir::pass::ModuleRewritePassAdapter;
let registered = registered.into_iter();
let mut rewrites = RewriteSet::default();
if registered.len() == 0 {
if session.should_codegen() {
let fn_rewrites = default_function_rewrites(session);
for rewrite in fn_rewrites {
rewrites.push(ModuleRewritePassAdapter::new(rewrite));
}
}
} else {
rewrites.extend(registered);
}
rewrites
}
pub fn default_function_rewrites(session: &Session) -> RewriteSet<hir::Function> {
use midenc_hir_transform as transforms;
let mut rewrites = RewriteSet::default();
if session.should_codegen() {
rewrites.push(transforms::SplitCriticalEdges);
rewrites.push(transforms::Treeify);
rewrites.push(transforms::InlineBlocks);
rewrites.push(transforms::ApplySpills);
}
rewrites
}