use std::fs::File;
use std::path::{Path, PathBuf};
use std::process::ExitCode;
use llvmkit_asmparser::ll_parser::Parser;
use llvmkit_asmparser::parse_error::ParseError;
use llvmkit_asmparser::read_to_owned;
use llvmkit_ir::Module;
use llvmkit_support::{SourceMap, Span};
fn main() -> ExitCode {
let Some(path) = std::env::args_os().nth(1).map(PathBuf::from) else {
eprintln!("usage: parse_file <path/to/file.ll>");
return ExitCode::from(2);
};
let bytes = match File::open(&path).and_then(read_to_owned) {
Ok(b) => b,
Err(e) => {
eprintln!("error: cannot read {}: {e}", path.display());
return ExitCode::from(1);
}
};
let module_name = path.file_stem().and_then(|s| s.to_str()).unwrap_or("input");
Module::with_new::<_, _, _>(module_name, |module| {
let parser = match Parser::new(&bytes, &module) {
Ok(p) => p,
Err(err) => {
report_error(&path, &bytes, &err);
return ExitCode::from(1);
}
};
match parser.parse_module() {
Ok(_parsed) => {
print!("{module}");
ExitCode::SUCCESS
}
Err(err) => {
report_error(&path, &bytes, &err);
ExitCode::from(1)
}
}
})
}
fn report_error(path: &Path, src: &[u8], err: &ParseError) {
let sm = SourceMap::new(src);
let span = err.loc().map(|l| l.span).unwrap_or(Span::new(0, 0));
let (line, col) = sm.line_col(span.start);
eprintln!("{path}:{line}:{col}: {err}", path = path.display());
if let Some(line_bytes) = sm.line_text(line) {
eprintln!(" | {}", String::from_utf8_lossy(line_bytes));
let underline_len = (span.end.saturating_sub(span.start) as usize).max(1);
eprintln!(
" | {pad}{caret}",
pad = " ".repeat((col - 1) as usize),
caret = "^".repeat(underline_len)
);
}
}