This commit is contained in:
nora 2023-05-24 20:24:19 +02:00
parent f321d0e9e1
commit ee0b311261
12 changed files with 265 additions and 36 deletions

72
codegen/src/lib.rs Normal file
View file

@ -0,0 +1,72 @@
mod x86;
use std::process::Stdio;
use analysis::{ir::Ir, LoweringCx};
use object::{
elf,
write::{Object, Symbol},
};
type Result<T, E = analysis::Error> = std::result::Result<T, E>;
pub fn generate<'cx>(lcx: &LoweringCx<'cx>, ir: &Ir<'cx>) -> Result<()> {
let mut obj = Object::new(
object::BinaryFormat::Elf,
object::Architecture::X86_64,
object::Endianness::Little,
);
let text = obj.add_section(Vec::new(), b".text".to_vec(), object::SectionKind::Text);
for (_def_id, func) in &ir.funcs {
let code = x86::generate_func(lcx, func)?;
let offset = obj.append_section_data(text, &code, 8);
let sym = Symbol {
name: func.name.as_str(|s| s.as_bytes().to_vec()),
value: offset,
size: code.len().try_into().unwrap(),
kind: object::SymbolKind::Text,
scope: object::SymbolScope::Linkage,
weak: false,
section: object::write::SymbolSection::Section(text),
flags: object::SymbolFlags::Elf {
st_info: ((elf::STB_GLOBAL) << 4) | (elf::STT_FUNC),
st_other: elf::STV_DEFAULT,
},
};
obj.add_symbol(sym);
}
let object_file = obj.write().map_err(|err| {
analysis::Error::new_without_span(format!("failed to create object file: {err}"))
})?;
std::fs::write("main.o", object_file).map_err(|err| {
analysis::Error::new_without_span(format!("failed to write object file main.o: {err}"))
})?;
let output = std::process::Command::new("cc")
.arg("main.o")
.stdout(Stdio::inherit())
.stdout(Stdio::inherit())
.output()
.map_err(|err| analysis::Error::new_without_span(format!("failed to spawn `cc`: {err}")))?;
if !output.status.success() {
return Err(analysis::Error::new_without_span(format!(
"linking with `cc` failed"
)));
} else {
std::fs::remove_file("main.o").map_err(|err| {
analysis::Error::new_without_span(format!(
"failed to remove temporary file main.o: {err}"
))
})?;
}
Ok(())
}