Files
compiler-old/src/main.rs
T

111 lines
3.1 KiB
Rust

use std::{fs::read_to_string, path::PathBuf, process::exit};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use crate::frontend::parser::Parser;
use crate::frontend::sema::Sema;
use crate::middle::builder::MirBuilder;
use crate::middle::dce::eliminate_dead_code;
use crate::middle::fold::fold_constants;
use clap::Parser as ClapParser;
pub mod backend;
pub mod frontend;
pub mod middle;
use crate::backend::cranelift::CraneliftBackend;
#[derive(ClapParser)]
#[command(version, about, long_about = None)]
struct Cli {
/// The input source file to compile
input: String,
/// The output file path
#[arg(short, long)]
output: Option<String>,
/// Emit Cranelift IR instead of an object file
#[arg(long)]
emit_ir: bool,
}
fn main() {
let cli = Cli::parse();
let content = read_to_string(&cli.input).unwrap_or_else(|err| {
eprintln!("error: failed to read source file ({:?})", err);
exit(1);
});
let writer = StandardStream::stderr(ColorChoice::Always);
let config = term::Config::default();
let file = SimpleFile::new(&cli.input, &content);
let mut parser = Parser::new(&content);
let module = parser.parse_module();
if let Some(errors) = parser.errors() {
for error in errors {
let diagnostic = Diagnostic::error()
.with_message(error.message)
.with_label(Label::primary((), error.span));
term::emit_to_write_style(&mut writer.lock(), &config, &file, &diagnostic).unwrap();
}
exit(1);
}
let mut sema = Sema::new();
let typed_module = sema.analyze_module(&module);
if let Some(errors) = sema.errors() {
for error in errors {
let diagnostic = Diagnostic::error()
.with_message(error.message)
.with_label(Label::primary((), error.span));
term::emit_to_write_style(&mut writer.lock(), &config, &file, &diagnostic).unwrap();
}
exit(1);
}
let mut mir_module = MirBuilder::build(&typed_module);
fold_constants(&mut mir_module);
let warnings = eliminate_dead_code(&mut mir_module);
for warning in warnings {
let diagnostic = Diagnostic::warning()
.with_message(warning.message)
.with_label(Label::primary((), warning.span));
term::emit_to_write_style(&mut writer.lock(), &config, &file, &diagnostic).unwrap();
}
let backend = CraneliftBackend::new();
let (ir, obj_bytes) = backend.compile_module(&mir_module);
if cli.emit_ir {
println!("{}", ir);
} else {
let output_path = cli.output.unwrap_or_else(|| {
PathBuf::from(&cli.input)
.with_extension("o")
.to_string_lossy()
.into_owned()
});
std::fs::write(&output_path, obj_bytes).unwrap_or_else(|err| {
eprintln!("error: failed to write object file: {:?}", err);
exit(1);
});
println!("Generated object file: {}", output_path);
}
}