Added src/codegen/holeybytes.rs.

master
Goren Barak 2023-12-24 10:44:37 -05:00
parent e3cdfec0d9
commit 137d9f5884
1 changed files with 274 additions and 0 deletions

274
src/codegen/holeybytes.rs Normal file
View File

@ -0,0 +1,274 @@
use crate::parse::ast::*;
use skylang::temp;
use std::rc::Rc;
use std::collections::HashMap;
#[derive(Debug)]
pub struct HbCodegen {
pc: u32,
functions: HashMap<String, u32>,
globals: HashMap<String, u64>,
}
impl HbCodegen {
pub fn new() -> Self {
HbCodegen {
pc: 0,
functions: HashMap::new(),
globals: HashMap::new()
}
}
pub fn hb_codegen(&mut self, exprs: &Vec<Expr>) -> &[u8] {
let mut gen: Vec<u8> = Vec::new();
macro_rules! unwrap {
($item:expr) => {
ins!({ self.hb_codegen(&vec![Rc::unwrap_or_clone($item)]) });
};
(norc $item:expr) => {
ins!(*{ self.hb_codegen(&vec![$item]) });
}
}
macro_rules! ins {
($ins:expr) => {
let ins = $ins;
let new_pc = self.pc.wrapping_add(ins.len() as u32);
gen.extend_from_slice(&ins);
self.pc = new_pc;
};
($($ins:expr);+) => {
$(
let ins = { $ins };
let new_pc = self.pc.wrapping_add(ins.len() as u32);
gen.extend_from_slice(&ins);
self.pc = new_pc;
)+
}
}
// Iterate over expressions.
for expr in exprs.iter() {
// Use patern matching on `expr`.
match expr {
// If the expression is a math expression.
Expr::MathExpr(e) => {
unwrap!(e.right);
// st r1, r254, 0, 8; addi64 r254, r254, 8;
ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]);
unwrap!(e.left);
// st r1, r254, 0, 8; addi64 r254, r254, 8;
ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]);
match e.operator {
// If the operator is addition.
MathOperator::OP_ADD => {
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]);
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]);
// add64 r1, r32, r33
ins!([0x06, 1, 32, 33]);
},
// If the operator is multiplication.
MathOperator::OP_MULT => {
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]);
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]);
// mul64 r1, r33, r34
ins!([0x0e, 1, 33, 34]);
},
// If the operator is division.
MathOperator::OP_DIV => {
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]);
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]);
// fdiv64 r1, r33, r34
ins!([0x65, 1, 33, 34]);
},
// If the operators is subtraction.
MathOperator::OP_SUB => {
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]);
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]);
// sub64 r1, r33, r34
ins!([0x0a, 1, 33, 34]);
},
// If the operator is modulo.
MathOperator::OP_MOD => {
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]);
// addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8;
ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]);
// dirs64 r2, r1, r33, r34
}
}
},
// If the expression is a function call.
Expr::FunCall(e) => {
for (i, p) in e.params.iter().enumerate() {
match i {
0 => {
unwrap!(*p);
// cp r2, r1
ins!([0x46, 2, 1]);
},
1 => {
unwrap!(*p);
// cp r3, r1
ins!([0x46, 3, 1]);
},
2 => {
unwrap!(*p);
// cp r4, r1
ins!([0x46, 4, 1]);
},
3 => {
unwrap!(*p);
// cp r5, r1
ins!([0x46, 5, 1]);
},
4 => {
unwrap!(*p);
// cp r6, r1
ins!([0x46, 6, 1]);
},
5 => {
unwrap!(*p);
// cp r7, r1
ins!([0x46, 7, 1]);
},
6 => {
unwrap!(*p);
// cp r8, r1
ins!([0x46, 8, 1]);
},
7 => {
unwrap!(*p);
// cp r9, r1
ins!([0x46, 9, 1]);
},
8 => {
unwrap!(*p);
// cp r10, r1
ins!([0x46, 10, 1]);
},
9 => {
unwrap!(*p);
// cp r11, r1
ins!([0x46, 11, 1]);
},
_ => {
println!("More than ten parameters are currently not supported.");
std::process::exit(1);
}
}
}
ins!([0x53]; unsafe { std::mem::transmute::<u32, [u8; 4]>(self.pc.wrapping_sub(self.functions[e.name])) });
},
// Define a global variable.
Expr::GlobalDefinition(e) => {
// Define a 64-bit global variable.
println!("Global variables are currently unsupported.");
std::process::exit(1);
},
// Breakpoint.
Expr::Breakpoint => {
// Write the interrupt for a debugger breakpoint.
ins!([0]);
},
// Return something from a function.
Expr::Return(e) => {
// Do the operation that should later be returned.
println!("Returns are currently not supported, (i was too lazy to implement)");
std::process::exit(1);
},
// A function defenition.
Expr::FunDefinition(e) => {
self.functions.insert(e.name.to_owned(), self.pc);
ins!(&self.hb_codegen(&e.contents).to_vec());
},
Expr::If(e) => {
// Increment the temporary variable/function counter.
// Compare the left and right value.
unwrap!(e.left);
// st r1, r254, 0, 8; addi64 r254, r254, 8;
ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]);
unwrap!(e.right);
// st r1, r254, 0, 8; addi64 r254, r254, 8;
ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]);
let action = self.pc;
ins!(&self.hb_codegen(&e.action).to_vec());
// Check what the condition is.
match e.cond {
COND_OP::EQ => {
// If the compared values are equal to each other jump to the temporary function.
ins!([0x56]; unsafe { std::mem::transmute::<u32, [u8; 4]>(self.pc.wrapping_sub(action)) });
},
COND_OP::NE => {
// If the compared values are not equal to eachother jump to the temporary function.
ins!([0x57]; unsafe { std::mem::transmute::<u32, [u8; 4]>(self.pc.wrapping_sub(action)) });
}
}
},
Expr::Number(n) => {
ins!([0x4b, 1]; unsafe { ::core::mem::transmute::<u64, [u8; 8]>(*n) });
},
no => unsafe {
// Write some data I randomly typed to your memory because don't going around playing with something that I haven't implemented yet.
println!("{:?} is not. implemented. prepare to be destroyed >:-(", no);
let ptr = std::ptr::null_mut::<f64>();
::std::ptr::write(ptr, 124010240120401240.12410240124120401240);
},
}
}
&gen
}
}