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 diagnostics::{miette, Diagnostic, Report, WrapErr},
18 OutputMode,
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 (dyn FnMut(CodegenOutput, Rc<Context>) -> CompilerResult<CodegenOutput>
89 + '_),
90 )
91 .next(AssembleStage);
92
93 let inputs = context.session().inputs.clone();
94 stages.run(inputs, context)
95}
96
97pub fn compile_to_optimized_hir(context: Rc<Context>) -> CompilerResult<LinkOutput> {
101 let mut stages = ParseStage.collect(LinkStage).next_optional(ApplyRewritesStage);
102
103 let inputs = context.session().inputs.clone();
104 stages.run(inputs, context)
105}
106
107pub fn compile_to_unoptimized_hir(context: Rc<Context>) -> CompilerResult<LinkOutput> {
111 let mut stages = ParseStage.collect(LinkStage);
112
113 let inputs = context.session().inputs.clone();
114 stages.run(inputs, context)
115}
116
117pub fn compile_link_output_to_masm(link_output: LinkOutput) -> CompilerResult<Artifact> {
121 let mut stages = CodegenStage.next(AssembleStage);
122
123 let context = link_output.component.borrow().as_operation().context_rc();
124 stages.run(link_output, context)
125}
126
127pub fn compile_link_output_to_masm_with_pre_assembly_stage<F>(
132 link_output: LinkOutput,
133 pre_assembly_stage: &mut F,
134) -> CompilerResult<Artifact>
135where
136 F: FnMut(CodegenOutput, Rc<Context>) -> CompilerResult<CodegenOutput>,
137{
138 let mut stages = CodegenStage
139 .next(
140 pre_assembly_stage
141 as &mut (dyn FnMut(CodegenOutput, Rc<Context>) -> CompilerResult<CodegenOutput>
142 + '_),
143 )
144 .next(AssembleStage);
145
146 let context = link_output.component.borrow().as_operation().context_rc();
147 stages.run(link_output, context)
148}
149
150fn compile_inputs(
151 inputs: Vec<midenc_session::InputFile>,
152 context: Rc<Context>,
153) -> CompilerResult<Artifact> {
154 let mut stages = ParseStage
155 .collect(LinkStage)
156 .next_optional(ApplyRewritesStage)
157 .next(CodegenStage)
158 .next(AssembleStage);
159
160 stages.run(inputs, context)
161}