Added src/codegen/holeybytes.rs.
This commit is contained in:
parent
e3cdfec0d9
commit
137d9f5884
274
src/codegen/holeybytes.rs
Normal file
274
src/codegen/holeybytes.rs
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue