1#![no_std]
2#![deny(warnings)]
3
4extern crate alloc;
5#[cfg(feature = "std")]
6extern crate std;
7
8mod compiler;
9mod stage;
10mod stages;
11
12use alloc::{rc::Rc, vec::Vec};
13
14pub use midenc_hir::Context;
15use midenc_hir::Op;
16use midenc_session::{
17 OutputMode,
18 diagnostics::{Diagnostic, Report, WrapErr, miette},
19};
20
21pub use self::{
22 compiler::Compiler,
23 stages::{CodegenOutput, LinkOutput},
24};
25use self::{stage::Stage, stages::*};
26
27pub type CompilerResult<T> = Result<T, Report>;
28
29#[derive(Debug, thiserror::Error, Diagnostic)]
31#[error("compilation was canceled by user")]
32#[diagnostic()]
33pub struct CompilerStopped;
34
35pub fn compile(context: Rc<Context>) -> CompilerResult<()> {
37 use midenc_hir::formatter::DisplayHex;
38
39 log::info!("starting compilation session");
40
41 midenc_codegen_masm::register_dialect_hooks(&context);
42
43 let session = context.session();
44 match compile_inputs(session.inputs.clone(), context.clone())? {
45 Artifact::Assembled(ref package) => {
46 log::info!(
47 "succesfully assembled mast package '{}' with digest {}",
48 package.name,
49 DisplayHex::new(&package.digest().as_bytes())
50 );
51 session
52 .emit(OutputMode::Text, package)
53 .map_err(Report::msg)
54 .wrap_err("failed to pretty print 'mast' artifact")?;
55 session
56 .emit(OutputMode::Binary, package)
57 .map_err(Report::msg)
58 .wrap_err("failed to serialize 'mast' artifact")
59 }
60 Artifact::Lowered(_) => {
61 log::debug!("no outputs requested by user: pipeline stopped before assembly");
62 Ok(())
63 }
64 }
65}
66
67pub fn compile_to_memory(context: Rc<Context>) -> CompilerResult<Artifact> {
69 let inputs = context.session().inputs.clone();
70 compile_inputs(inputs, context)
71}
72
73pub fn compile_to_memory_with_pre_assembly_stage<F>(
76 context: Rc<Context>,
77 pre_assembly_stage: &mut F,
78) -> CompilerResult<Artifact>
79where
80 F: FnMut(CodegenOutput, Rc<Context>) -> CompilerResult<CodegenOutput>,
81{
82 let mut stages = ParseStage
83 .collect(LinkStage)
84 .next_optional(ApplyRewritesStage)
85 .next(CodegenStage)
86 .next(
87 pre_assembly_stage
88 as &mut (
89 dyn FnMut(CodegenOutput, Rc<Context>) -> CompilerResult<CodegenOutput> + '_
90 ),
91 )
92 .next(AssembleStage);
93
94 let inputs = context.session().inputs.clone();
95 stages.run(inputs, context)
96}
97
98pub fn compile_to_optimized_hir(context: Rc<Context>) -> CompilerResult<LinkOutput> {
102 let mut stages = ParseStage.collect(LinkStage).next_optional(ApplyRewritesStage);
103
104 let inputs = context.session().inputs.clone();
105 stages.run(inputs, context)
106}
107
108pub fn compile_to_unoptimized_hir(context: Rc<Context>) -> CompilerResult<LinkOutput> {
112 let mut stages = ParseStage.collect(LinkStage);
113
114 let inputs = context.session().inputs.clone();
115 stages.run(inputs, context)
116}
117
118pub fn compile_link_output_to_masm(link_output: LinkOutput) -> CompilerResult<Artifact> {
122 let mut stages = CodegenStage.next(AssembleStage);
123
124 let context = link_output.component.borrow().as_operation().context_rc();
125 stages.run(link_output, context)
126}
127
128pub fn compile_link_output_to_masm_with_pre_assembly_stage<F>(
133 link_output: LinkOutput,
134 pre_assembly_stage: &mut F,
135) -> CompilerResult<Artifact>
136where
137 F: FnMut(CodegenOutput, Rc<Context>) -> CompilerResult<CodegenOutput>,
138{
139 let mut stages = CodegenStage
140 .next(
141 pre_assembly_stage
142 as &mut (
143 dyn FnMut(CodegenOutput, Rc<Context>) -> CompilerResult<CodegenOutput> + '_
144 ),
145 )
146 .next(AssembleStage);
147
148 let context = link_output.component.borrow().as_operation().context_rc();
149 stages.run(link_output, context)
150}
151
152fn compile_inputs(
153 inputs: Vec<midenc_session::InputFile>,
154 context: Rc<Context>,
155) -> CompilerResult<Artifact> {
156 let mut stages = ParseStage
157 .collect(LinkStage)
158 .next_optional(ApplyRewritesStage)
159 .next(CodegenStage)
160 .next(AssembleStage);
161
162 stages.run(inputs, context)
163}