questionable refactoring

This commit is contained in:
2025-03-23 18:40:07 -04:00
parent c766d34b6a
commit 0614d48fcc
14 changed files with 240 additions and 79 deletions

View File

@@ -1,6 +1,5 @@
use crate::{
compiler::program::{Addr, Instr, SymTable},
ir::Symbol,
compiler::program::{Addr, Instr, SymTable}, ir::Symbol, util::LabeledFmt
};
use super::*;
@@ -169,14 +168,29 @@ impl LinkerInstruction {
}
}
// this is not even remotely worth it but technically it doesn't use the heap I think xdddddddddd
impl<R: std::fmt::Debug, S: std::fmt::Debug> std::fmt::Debug for LinkerInstruction<R, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_label(f, &|f, s| write!(f, "{s:?}"))
}
}
pub struct DebugInstr<'a, R, S, L: Fn(&mut std::fmt::Formatter<'_>, &S) -> std::fmt::Result> {
instr: &'a LinkerInstruction<R, S>,
label: &'a L,
}
impl<R: std::fmt::Debug, S: std::fmt::Debug> LabeledFmt<S> for LinkerInstruction<R, S> {
fn fmt_label(&self, f: &mut std::fmt::Formatter<'_>, label: &dyn crate::util::Labeler<S>) -> std::fmt::Result {
match self {
Self::ECall => write!(f, "ecall"),
Self::EBreak => write!(f, "ebreak"),
Self::Li { dest, imm } => write!(f, "li {dest:?}, {imm:?}"),
Self::Mv { dest, src } => write!(f, "mv {dest:?}, {src:?}"),
Self::La { dest, src } => write!(f, "la {dest:?}, {src:?}"),
Self::La { dest, src } => {
write!(f, "la {dest:?}, @")?;
label(f, src)
},
Self::Load {
width,
dest,
@@ -207,8 +221,14 @@ impl<R: std::fmt::Debug, S: std::fmt::Debug> std::fmt::Debug for LinkerInstructi
imm,
} => write!(f, "{}i {dest:?}, {src:?}, {imm}", opstr(*op, *funct)),
Self::Jal { dest, offset } => write!(f, "jal {dest:?}, {offset:?}"),
Self::Call(s) => write!(f, "call {s:?}"),
Self::J(s) => write!(f, "j {s:?}"),
Self::Call(s) => {
write!(f, "call ")?;
label(f, s)
}
Self::J(s) => {
write!(f, "j ")?;
label(f, s)
}
Self::Ret => write!(f, "ret"),
}
}

View File

@@ -1,7 +1,7 @@
use std::collections::HashMap;
use crate::{
compiler::{arch::riscv::Reg, create_program, Addr},
compiler::{arch::riscv::Reg, debug::DebugInfo, UnlinkedProgram},
ir::{
arch::riscv64::{RV64Instruction as AI, RegRef},
IRLInstruction as IRI, IRLProgram, Len, Size,
@@ -47,9 +47,10 @@ fn mov_mem(
}
}
pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
pub fn compile(program: &IRLProgram) -> UnlinkedProgram<LI> {
let mut fns = Vec::new();
let mut data = Vec::new();
let mut dbg = DebugInfo::new(program.labels().to_vec());
for (sym, d) in program.ro_data() {
data.push((d.clone(), *sym));
}
@@ -83,7 +84,9 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
v.push(LI::sd(ra, stack_ra, sp));
}
}
let mut irli = Vec::new();
for i in &f.instructions {
irli.push((v.len(), format!("{i:?}")));
match i {
IRI::Mv { dest, src } => todo!(),
IRI::Ref { dest, src } => todo!(),
@@ -212,6 +215,7 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
}
}
}
dbg.push_fn(irli);
if has_stack {
if let Some(stack_ra) = stack_ra {
v.push(LI::ld(ra, stack_ra, sp));
@@ -221,5 +225,10 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
v.push(LI::Ret);
fns.push((v, *sym));
}
create_program(fns, data, Some(program.entry()), &program)
UnlinkedProgram {
fns: fns.into_iter().map(|(v, s, ..)| (v, s)).collect(),
ro_data: data,
start: Some(program.entry()),
dbg,
}
}

23
src/compiler/debug.rs Normal file
View File

@@ -0,0 +1,23 @@
use crate::ir::Symbol;
pub struct DebugInfo {
pub sym_labels: Vec<Option<String>>,
pub ir_lower: Vec<Vec<(usize, String)>>,
}
impl DebugInfo {
pub fn new(sym_labels: Vec<Option<String>>) -> Self {
Self {
ir_lower: Vec::new(),
sym_labels,
}
}
pub fn push_fn(&mut self, instrs: Vec<(usize, String)>) {
self.ir_lower.push(instrs);
}
pub fn sym_label(&self, s: Symbol) -> Option<&String> {
self.sym_labels[*s].as_ref()
}
}

View File

@@ -1,4 +1,4 @@
use super::program::Addr;
use super::{program::Addr, LinkedProgram};
#[repr(C)]
pub struct ELF64Header {
@@ -102,3 +102,9 @@ pub fn create(program: Vec<u8>, start_offset: Addr) -> Vec<u8> {
unsafe fn as_u8_slice<T: Sized>(p: &T) -> &[u8] {
core::slice::from_raw_parts((p as *const T) as *const u8, size_of::<T>())
}
impl LinkedProgram {
pub fn to_elf(self) -> Vec<u8> {
create(self.code, self.start.expect("no start found"))
}
}

View File

@@ -1,13 +1,14 @@
pub mod arch;
mod debug;
mod elf;
mod program;
mod target;
use arch::riscv;
pub use program::*;
use crate::ir::IRLProgram;
pub fn compile(program: IRLProgram) -> Vec<u8> {
let (compiled, start) = arch::riscv::compile(program);
elf::create(compiled, start.expect("no start method found"))
pub fn compile(program: &IRLProgram) -> UnlinkedProgram<riscv::LinkerInstruction> {
arch::riscv::compile(program)
}

View File

@@ -1,57 +1,63 @@
use std::collections::HashMap;
use crate::ir::{IRLProgram, Symbol};
use crate::{
ir::Symbol,
util::{Labelable, LabeledFmt, Labeler},
};
pub fn create_program<I: Instr>(
fns: Vec<(Vec<I>, Symbol)>,
ro_data: Vec<(Vec<u8>, Symbol)>,
start: Option<Symbol>,
program: &IRLProgram,
) -> (Vec<u8>, Option<Addr>) {
let mut data = Vec::new();
let mut sym_table = SymTable::new(fns.len() + ro_data.len());
let mut missing = HashMap::<Symbol, Vec<(Addr, I)>>::new();
for (val, id) in ro_data {
sym_table.insert(id, Addr(data.len() as u64));
data.extend(val);
}
data.resize(data.len() + (4 - data.len() % 4), 0);
for (fun, id) in fns {
sym_table.insert(id, Addr(data.len() as u64));
for i in fun {
let i_pos = Addr(data.len() as u64);
if let Some(sym) = i.push(&mut data, &sym_table, i_pos, false) {
if let Some(vec) = missing.get_mut(&sym) {
vec.push((i_pos, i));
} else {
missing.insert(sym, vec![(i_pos, i)]);
use super::debug::DebugInfo;
pub struct LinkedProgram {
pub code: Vec<u8>,
pub start: Option<Addr>,
}
pub struct UnlinkedProgram<I: Instr> {
pub fns: Vec<(Vec<I>, Symbol)>,
pub ro_data: Vec<(Vec<u8>, Symbol)>,
pub start: Option<Symbol>,
pub dbg: DebugInfo,
}
impl<I: Instr> UnlinkedProgram<I> {
pub fn link(self) -> LinkedProgram {
let mut data = Vec::new();
let mut sym_table = SymTable::new(self.fns.len() + self.ro_data.len());
let mut missing = HashMap::<Symbol, Vec<(Addr, I)>>::new();
for (val, id) in self.ro_data {
sym_table.insert(id, Addr(data.len() as u64));
data.extend(val);
}
data.resize(data.len() + (4 - data.len() % 4), 0);
for (fun, id) in self.fns {
sym_table.insert(id, Addr(data.len() as u64));
for i in fun {
let i_pos = Addr(data.len() as u64);
if let Some(sym) = i.push(&mut data, &sym_table, i_pos, false) {
if let Some(vec) = missing.get_mut(&sym) {
vec.push((i_pos, i));
} else {
missing.insert(sym, vec![(i_pos, i)]);
}
}
}
if let Some(vec) = missing.remove(&id) {
for (addr, i) in vec {
let mut replace = Vec::new();
i.push(&mut replace, &sym_table, addr, true);
let pos = addr.val() as usize;
data[pos..pos + replace.len()].copy_from_slice(&replace);
}
}
}
if let Some(vec) = missing.remove(&id) {
for (addr, i) in vec {
let mut replace = Vec::new();
i.push(&mut replace, &sym_table, addr, true);
let pos = addr.val() as usize;
data[pos..pos + replace.len()].copy_from_slice(&replace);
}
assert!(missing.is_empty());
LinkedProgram {
code: data,
start: self
.start
.map(|s| sym_table.get(s).expect("start symbol doesn't exist")),
}
}
for (s, f) in program.fns() {
println!(
"{}: {:?}",
f.name,
sym_table.get(*s).map(|a| {
let pos = a.0 + 0x1000 + 0x40 + 0x38;
format!("0x{:x}", pos)
})
);
}
assert!(missing.is_empty());
(
data,
start.map(|s| sym_table.get(s).expect("start symbol doesn't exist")),
)
}
pub trait Instr {
@@ -83,3 +89,31 @@ impl SymTable {
}
}
}
impl<I: Instr + Labelable<Symbol> + LabeledFmt<Symbol>> std::fmt::Debug for UnlinkedProgram<I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for ((v, s), irli) in self.fns.iter().zip(&self.dbg.ir_lower) {
writeln!(f, "{}:", self.dbg.sym_label(*s).unwrap())?;
let mut liter = irli.iter();
let mut cur = liter.next();
for (i, instr) in v.iter().enumerate() {
if let Some(c) = cur {
if i == c.0 {
writeln!(f, " {}:", c.1)?;
cur = liter.next();
}
}
writeln!(
f,
" {:?}",
instr.labeled(&|f: &mut std::fmt::Formatter, s: &Symbol| write!(
f,
"{}",
self.dbg.sym_label(*s).unwrap_or(&format!("{:?}", *s))
))
)?;
}
}
Ok(())
}
}