You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
4.1 KiB
114 lines
4.1 KiB
use lalrpop_util::lalrpop_mod;
|
|
use rustc_hash::FxHashMap as HashMap;
|
|
use std::io::Result;
|
|
|
|
pub mod backend;
|
|
pub mod frontend;
|
|
pub mod utils;
|
|
|
|
//指定生成的代码的位置
|
|
lalrpop_mod!(#[allow(clippy::all)] pub sysy, "/frontend/lalrpop/sysy.rs");
|
|
|
|
/// 解析命令行参数
|
|
fn parse_arguments() -> HashMap<String, String> {
|
|
let mut args_map = HashMap::default();
|
|
let args: Vec<String> = std::env::args().collect();
|
|
let mut i = 0;
|
|
while i < args.len() {
|
|
let arg = args[i].as_str();
|
|
if arg == "-ast" {
|
|
args_map.insert(String::from("ast"), args[i + 1].to_string());
|
|
i += 1;
|
|
} else if arg == "-ir" {
|
|
args_map.insert(String::from("ir"), args[i + 1].to_string());
|
|
i += 1;
|
|
} else if arg == "-asm" {
|
|
args_map.insert(String::from("asm"), args[i + 1].to_string());
|
|
i += 1;
|
|
} else if arg == "-S" {
|
|
args_map.insert(String::from("S"), String::from("true"));
|
|
} else if arg == "-o" {
|
|
args_map.insert(String::from("o"), args[i + 1].to_string());
|
|
i += 1;
|
|
} else if arg == "-O1" {
|
|
args_map.insert(String::from("O1"), String::from("true"));
|
|
} else if arg == "-h" {
|
|
println!("[Compiler] Usage:");
|
|
println!("[Compiler] compiler [options] source_file");
|
|
println!("[Compiler] Options:");
|
|
println!("[Compiler] -ast <file> : Output the AST to a file");
|
|
println!("[Compiler] -ir <file> : Output the IR to a file");
|
|
println!(
|
|
"[Compiler] -asm <file> : Output the ASM to a file( Has higher priority than -S!!! )"
|
|
);
|
|
println!("[Compiler] -S : Output the ASM to stdout");
|
|
println!("[Compiler] -o <file> : Output the ASM to a file");
|
|
println!("[Compiler] -O1 : Enable optimization level 1");
|
|
std::process::exit(0);
|
|
} else {
|
|
args_map.insert(String::from("source"), arg.to_string());
|
|
}
|
|
i += 1;
|
|
}
|
|
args_map
|
|
}
|
|
|
|
/// 检查命令行参数
|
|
fn check_args(args: &HashMap<String, String>) {
|
|
let emit_s = if args.get("S").is_some() && args.get("S").unwrap() == "true" {
|
|
true
|
|
} else {
|
|
false
|
|
};
|
|
let source = args.get("source");
|
|
let output_file = args.get("o");
|
|
if source.is_none() {
|
|
panic!("Error: Source file `{}` not specified", source.unwrap());
|
|
}
|
|
if output_file.is_none() && emit_s {
|
|
panic!("Error: Output file not specified");
|
|
}
|
|
if !std::path::Path::new(source.unwrap()).exists() {
|
|
panic!("Error: Source file `{}` not found", source.unwrap());
|
|
}
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
// 参数解析与检查
|
|
let args = parse_arguments();
|
|
check_args(&args);
|
|
|
|
// 提取参数
|
|
let emit_ast = args.get("ast"); // 输出AST文件
|
|
let emit_ir = args.get("ir"); // 输出IR文件
|
|
let emit_asm = args.get("asm"); // 输出ASM文件
|
|
let emit_s = matches!(args.get("S"), Some(v) if v == "true"); // 适配比赛编译器选项要求,表示生成汇编代码
|
|
let _optimize = matches!(args.get("O1"), Some(v) if v == "true"); // 优化选项
|
|
let source = args.get("source"); // 源文件名
|
|
let output_file = args.get("o"); // 输出文件名
|
|
|
|
let src = std::fs::read_to_string(source.unwrap())?; // 读取源文件内容
|
|
|
|
let mut ast = sysy::CompUnitParser::new().parse(&src).unwrap();
|
|
if let Some(ast_file) = emit_ast {
|
|
std::fs::write(ast_file, format!("{:#?}", ast)).expect("Failed to write AST to file");
|
|
}
|
|
|
|
let mut ir = frontend::irgen(&mut ast, 8); // ARMV8架构
|
|
|
|
if let Some(ir_file) = emit_ir {
|
|
std::fs::write(ir_file, ir.get_ir_string()).expect("Failed to write IR to file");
|
|
}
|
|
|
|
let mir = backend::mirgen(&mut ir);
|
|
if emit_s || emit_asm.is_some() {
|
|
let mut asm_file = output_file;
|
|
if emit_asm.is_some() {
|
|
asm_file = emit_asm;
|
|
}
|
|
std::fs::write(asm_file.unwrap(), mir.get_asm()).expect("Failed to write ASM to file");
|
|
}
|
|
|
|
Ok(())
|
|
}
|