|
@@ -0,0 +1,218 @@
|
|
|
|
+use std::i64;
|
|
|
|
+use super::ir;
|
|
|
|
+use std::io::{Write, Read};
|
|
|
|
+use std::mem;
|
|
|
|
+use super::ir::{MutVisitor, Instruction};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+use dynasmrt::{DynasmApi, DynasmLabelApi};
|
|
|
|
+
|
|
|
|
+pub fn compile(mut instrs: Vec<ir::Instruction>) -> Vec<u8> {
|
|
|
|
+ /*let mut ops = dynasmrt::x64::Assembler::new().unwrap();
|
|
|
|
+ let string = "Hello World!";
|
|
|
|
+
|
|
|
|
+ dynasm!(ops
|
|
|
|
+ ; ->hello:
|
|
|
|
+ ; .bytes string.as_bytes()
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ let hello = ops.offset();
|
|
|
|
+ dynasm!(ops
|
|
|
|
+ ; lea rcx, [->hello]
|
|
|
|
+ ; xor edx, edx
|
|
|
|
+ ; mov dl, BYTE string.len() as _
|
|
|
|
+ ; sub rsp, BYTE 0x28
|
|
|
|
+ ; call rax
|
|
|
|
+ ; add rsp, BYTE 0x28
|
|
|
|
+ ; ret
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ let buf = ops.finalize().unwrap();
|
|
|
|
+ buf.to_vec()
|
|
|
|
+ */
|
|
|
|
+ let mut cg = CodeGenerator::new();
|
|
|
|
+ cg.initialize();
|
|
|
|
+
|
|
|
|
+ let entry = cg.buffer.offset();
|
|
|
|
+
|
|
|
|
+ cg.visit_instructions(&mut instrs);
|
|
|
|
+ cg.finalize();
|
|
|
|
+ let buf = cg.buffer.finalize().unwrap();
|
|
|
|
+
|
|
|
|
+ let ret = buf.to_vec();
|
|
|
|
+ //println!("{:02x?}", ret);
|
|
|
|
+
|
|
|
|
+ let function: extern "C" fn(memory: *mut u8) -> bool = unsafe {
|
|
|
|
+ mem::transmute(buf.ptr(entry))
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ let mut data: Vec<u8> = Vec::with_capacity(100000);
|
|
|
|
+ unsafe {
|
|
|
|
+ //function(&mut *data.into_boxed_slice().as_mut_ptr() as *mut u8);
|
|
|
|
+ function(std::alloc::alloc_zeroed(std::alloc::Layout::new::<[u8; 1000]>()));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //cg.into_vec()
|
|
|
|
+ ret
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+pub struct CodeGenerator {
|
|
|
|
+ pub buffer: dynasmrt::x64::Assembler
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl CodeGenerator {
|
|
|
|
+ pub fn new() -> Self {
|
|
|
|
+ CodeGenerator {
|
|
|
|
+ buffer: dynasmrt::x64::Assembler::new().unwrap()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn initialize(&mut self) {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; xor rsi, rsi
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn finalize(&mut self) {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; ret
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl ir::MutVisitor for CodeGenerator {
|
|
|
|
+ type Ret = ();
|
|
|
|
+
|
|
|
|
+ fn visit_add(&mut self, add: &'_ mut Instruction) {
|
|
|
|
+ if let Instruction::Add{ offset, value } = add {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; add [rdi + rsi + *offset as i32], BYTE *value as i8
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn visit_move_ptr(&mut self, mp: &'_ mut Instruction) {
|
|
|
|
+ if let Instruction::MovePtr(offset) = mp {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; add rsi, DWORD *offset as i32
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn visit_loop(&mut self, l: &mut Instruction) {
|
|
|
|
+ if let Instruction::Loop(insts) = l {
|
|
|
|
+ let begin = self.buffer.new_dynamic_label();
|
|
|
|
+ let end = self.buffer.new_dynamic_label();
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; mov al, BYTE [rdi + rsi]
|
|
|
|
+ ; test al, al
|
|
|
|
+ ; jz => end
|
|
|
|
+ ; => begin
|
|
|
|
+ );
|
|
|
|
+ self.visit_instructions(insts);
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; mov al, BYTE [rdi + rsi]
|
|
|
|
+ ; test al, al
|
|
|
|
+ ; jnz => begin
|
|
|
|
+ ; => end
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn visit_linear_loop(&mut self, l: &mut Instruction) {
|
|
|
|
+ if let Instruction::LinearLoop(factors) = l {
|
|
|
|
+ if factors.len() > 1 ||
|
|
|
|
+ factors.len() >= 1 && !factors.contains_key(&0) {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; mov cl, BYTE [rdi + rsi]
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ for (&offset, &mut factor) in factors {
|
|
|
|
+ if offset == 0 {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if factor == 0 {
|
|
|
|
+ }
|
|
|
|
+ else if factor == 1 {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; add BYTE [rdi + rsi + offset as i32], cl
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ else if factor == -1 {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; sub BYTE [rdi + rsi + offset as i32], cl
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ else if factor.count_ones() == 1 {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; mov bl, cl
|
|
|
|
+ ; shl bl, factor.trailing_zeros() as i8
|
|
|
|
+ ; add BYTE [rdi + rsi + offset as i32], bl
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ else if (-factor).count_ones() == 1 {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; mov bl, cl
|
|
|
|
+ ; shl bl, factor.trailing_zeros() as i8
|
|
|
|
+ ; sub BYTE [rdi + rsi + offset as i32], bl
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; mov al, factor as i8
|
|
|
|
+ ; mul cl
|
|
|
|
+ ; add BYTE [rdi + rsi + offset as i32], al
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; mov BYTE [rdi + rsi], 0
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn visit_write(&mut self, w: &mut Instruction) {
|
|
|
|
+ if let Instruction::Write(offset) = w {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; push rdi
|
|
|
|
+ ; push rsi
|
|
|
|
+ ; sub rsp, 24
|
|
|
|
+ ; mov dil, BYTE [rdi + rsi + *offset as i32]
|
|
|
|
+ ; mov rax, QWORD putbyte as _
|
|
|
|
+ ; call rax
|
|
|
|
+ ; add rsp, 24
|
|
|
|
+ ; pop rsi
|
|
|
|
+ ; pop rdi
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn visit_read(&mut self, r: &mut Instruction) {
|
|
|
|
+ if let Instruction::Read(offset) = r {
|
|
|
|
+ dynasm!(self.buffer
|
|
|
|
+ ; push rdi
|
|
|
|
+ ; push rsi
|
|
|
|
+ ; sub rsp, 24
|
|
|
|
+ ; mov rax, QWORD readbyte as _
|
|
|
|
+ ; call rax
|
|
|
|
+ ; add rsp, 24
|
|
|
|
+ ; pop rsi
|
|
|
|
+ ; pop rdi
|
|
|
|
+ ; mov BYTE [rdi + rsi + *offset as i32], al
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+extern "C" fn putbyte(chr: u8) {
|
|
|
|
+ //print!("{:?}", chr as char);
|
|
|
|
+ std::io::stdout().write(&[chr]);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+extern "C" fn readbyte() -> u8 {
|
|
|
|
+ let mut byte: u8 = 0;
|
|
|
|
+ //std::io::stdin().read(&mut [byte]).unwrap();
|
|
|
|
+ std::io::stdin().bytes().next().unwrap_or(Ok(0)).unwrap_or(0)
|
|
|
|
+}
|
|
|
|
+
|