Skip to content
Snippets Groups Projects
main.rs 2.75 KiB
extern crate clap;

use clap::Parser;

mod codegen;
mod dynconst;
mod env;
mod intrinsics;
mod parser;
mod locs;
mod semant;
mod ssa;
mod types;

use codegen::*;

use std::path::Path;

extern crate hercules_ir;

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
    src_file: String,
    #[clap(short, long)]
    verify: bool,
    #[clap(long = "verify-all")]
    verify_all: bool,
    #[arg(short, long = "x-dot")]
    x_dot: bool,
    #[arg(short, long, value_name = "OUTPUT")]
    output: Option<String>,
}

macro_rules! add_verified_pass {
    ($pm:ident, $args:ident, $pass:ident) => {
        $pm.add_pass(hercules_opt::pass::Pass::$pass);
        if $args.verify || $args.verify_all {
            $pm.add_pass(hercules_opt::pass::Pass::Verify);
        }
    };
}
macro_rules! add_pass {
    ($pm:ident, $args:ident, $pass:ident) => {
        $pm.add_pass(hercules_opt::pass::Pass::$pass);
        if $args.verify_all {
            $pm.add_pass(hercules_opt::pass::Pass::Verify);
        }
    };
}

fn main() {
    let args = Cli::parse();
    let src_file = args.src_file.clone();
    let prg = semant::parse_and_analyze(args.src_file);
    match prg {
        Ok(prg) => {
            let module = codegen_program(prg);

            let mut pm = hercules_opt::pass::PassManager::new(module);
            if args.verify || args.verify_all {
                pm.add_pass(hercules_opt::pass::Pass::Verify);
            }
            add_verified_pass!(pm, args, PhiElim);
            if args.x_dot {
                pm.add_pass(hercules_opt::pass::Pass::Xdot(true));
            }
            add_pass!(pm, args, CCP);
            add_pass!(pm, args, DCE);
            add_pass!(pm, args, GVN);
            add_pass!(pm, args, DCE);
            add_pass!(pm, args, SROA);
            if args.x_dot {
                pm.add_pass(hercules_opt::pass::Pass::Xdot(true));
            }
            add_pass!(pm, args, Forkify);
            add_pass!(pm, args, ForkGuardElim);
            add_verified_pass!(pm, args, DCE);
            if args.x_dot {
                pm.add_pass(hercules_opt::pass::Pass::Xdot(true));
            }
            
            let src_file_path = Path::new(&src_file);
            let module_name = String::from(src_file_path.file_stem().unwrap().to_str().unwrap());
            let output_folder = match args.output {
                Some(output_folder) => output_folder,
                None => String::from(src_file_path.parent().unwrap().to_str().unwrap())
            };
            pm.add_pass(hercules_opt::pass::Pass::Codegen(output_folder, module_name));
            
            let _ = pm.run_passes();
        }
        Err(errs) => {
            for err in errs {
                eprintln!("{}", err);
            }
        }
    }
}