mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
codegen
This commit is contained in:
parent
f321d0e9e1
commit
ee0b311261
12 changed files with 265 additions and 36 deletions
20
codegen/Cargo.toml
Normal file
20
codegen/Cargo.toml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "codegen"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
analysis = { path = "../analysis" }
|
||||
iced-x86 = { version = "1.18.0", default-features = false, features = [
|
||||
"encoder",
|
||||
"block_encoder",
|
||||
"op_code_info",
|
||||
"instr_info",
|
||||
"nasm", # for debugging output
|
||||
"code_asm",
|
||||
"std",
|
||||
] }
|
||||
object = { version = "0.31.1", features = ["write"] }
|
||||
parser = { path = "../parser" }
|
||||
72
codegen/src/lib.rs
Normal file
72
codegen/src/lib.rs
Normal 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(())
|
||||
}
|
||||
32
codegen/src/x86.rs
Normal file
32
codegen/src/x86.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use analysis::{ir::Func, LoweringCx};
|
||||
use iced_x86::{code_asm as x, IcedError};
|
||||
use parser::Span;
|
||||
|
||||
use crate::Result;
|
||||
|
||||
trait IcedErrExt {
|
||||
type T;
|
||||
fn sp(self, span: Span) -> Result<Self::T, analysis::Error>;
|
||||
}
|
||||
|
||||
impl<T> IcedErrExt for Result<T, IcedError> {
|
||||
type T = T;
|
||||
|
||||
fn sp(self, span: Span) -> Result<Self::T, analysis::Error> {
|
||||
self.map_err(|e| analysis::Error::new(e.to_string(), span))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_func<'cx>(_lcx: &LoweringCx<'cx>, func: &Func<'cx>) -> Result<Vec<u8>> {
|
||||
assert_eq!(func.arity, 0, "arguments??? in MY uwucc????");
|
||||
|
||||
let sp = func.def_span;
|
||||
let mut a = x::CodeAssembler::new(64).sp(sp)?;
|
||||
|
||||
a.xor(x::rax, x::rax).sp(sp)?;
|
||||
a.ret().sp(sp)?;
|
||||
|
||||
let code = a.assemble(0x4000).sp(sp)?;
|
||||
|
||||
Ok(code)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue