questionable refactoring
This commit is contained in:
@@ -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"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
23
src/compiler/debug.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user