|  | @@ -1,23 +1,32 @@
 | 
	
		
			
				|  |  |  use std::i64;
 | 
	
		
			
				|  |  | -use super::ir;
 | 
	
		
			
				|  |  | +use super::{ir, optimize};
 | 
	
		
			
				|  |  |  use std::io::{Write, Read};
 | 
	
		
			
				|  |  |  use std::mem;
 | 
	
		
			
				|  |  | -use super::ir::{MutVisitor, Instruction};
 | 
	
		
			
				|  |  | +use super::ir::{ConstVisitor, Instruction};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #[cfg(target_os = "windows")]
 | 
	
		
			
				|  |  |  use winapi::um::memoryapi::VirtualAlloc;
 | 
	
		
			
				|  |  |  #[cfg(target_os = "windows")]
 | 
	
		
			
				|  |  |  use winapi::um::winnt::{MEM_COMMIT, PAGE_EXECUTE_READWRITE};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  use dynasmrt::{DynasmApi, DynasmLabelApi};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -pub fn compile(mut instrs: Vec<ir::Instruction>) -> Vec<u8> {
 | 
	
		
			
				|  |  | +pub enum Storation {
 | 
	
		
			
				|  |  | +    Register(&'static str),
 | 
	
		
			
				|  |  | +    Stack(i64),
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub fn compile_cfg<'a>(cfg: Vec<optimize::DfInstr<'a>>) -> Box<fn (*mut u8) -> ()> {
 | 
	
		
			
				|  |  | +    Box::new(|_| {})
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub fn compile(instrs: &Vec<ir::Instruction>) -> Vec<u8> {
 | 
	
		
			
				|  |  |      let mut cg = CodeGenerator::new();
 | 
	
		
			
				|  |  |      cg.initialize();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      let entry = cg.buffer.offset();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    cg.visit_instructions(&mut instrs);
 | 
	
		
			
				|  |  | +    cg.visit_instructions(instrs);
 | 
	
		
			
				|  |  |      cg.buffer.commit();
 | 
	
		
			
				|  |  |      cg.finalize();
 | 
	
		
			
				|  |  |      let buf = cg.buffer.finalize().unwrap();
 | 
	
	
		
			
				|  | @@ -30,10 +39,10 @@ pub fn compile(mut instrs: Vec<ir::Instruction>) -> Vec<u8> {
 | 
	
		
			
				|  |  |          mem::transmute(buf.ptr(entry))
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let mut data: Vec<u8> = Vec::with_capacity(100000);
 | 
	
		
			
				|  |  | +    //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]>()));
 | 
	
		
			
				|  |  | +        function(std::alloc::alloc_zeroed(std::alloc::Layout::new::<[u8; 100000]>()));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      //cg.into_vec()
 | 
	
	
		
			
				|  | @@ -80,37 +89,37 @@ impl CodeGenerator {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -impl ir::MutVisitor for CodeGenerator {
 | 
	
		
			
				|  |  | +impl ir::ConstVisitor for CodeGenerator {
 | 
	
		
			
				|  |  |      type Ret = ();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_nop(&mut self, nop: &mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_nop(&mut self, nop: &Instruction) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_add(&mut self, add: &'_ mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_add(&mut self, add: &'_ Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Add{ offset, value } = add {
 | 
	
		
			
				|  |  |              dynasm!(self.buffer
 | 
	
		
			
				|  |  | -                ; add BYTE [rdi + rsi + *offset as i32], *value as i8
 | 
	
		
			
				|  |  | +                ; add BYTE [rdi + *offset as i32], *value as i8
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_set(&mut self, set: &'_ mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_set(&mut self, set: &'_ Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Set{ offset, value } = set {
 | 
	
		
			
				|  |  |              dynasm!(self.buffer
 | 
	
		
			
				|  |  | -                ; mov BYTE [rdi + rsi + *offset as i32], *value as i8
 | 
	
		
			
				|  |  | +                ; mov BYTE [rdi + *offset as i32], *value as i8
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_linear_loop(&mut self, l: &mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_linear_loop(&mut self, l: &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]
 | 
	
		
			
				|  |  | +                    ; mov cl, BYTE [rdi]
 | 
	
		
			
				|  |  |                  );
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            for (&offset, &mut factor) in factors {
 | 
	
		
			
				|  |  | +            for (&offset, &factor) in factors {
 | 
	
		
			
				|  |  |                  if offset == 0 {
 | 
	
		
			
				|  |  |                      continue;
 | 
	
		
			
				|  |  |                  }
 | 
	
	
		
			
				|  | @@ -119,71 +128,69 @@ impl ir::MutVisitor for CodeGenerator {
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  else if factor == 1 {
 | 
	
		
			
				|  |  |                      dynasm!(self.buffer
 | 
	
		
			
				|  |  | -                        ; add BYTE [rdi + rsi + offset as i32], cl
 | 
	
		
			
				|  |  | +                        ; add BYTE [rdi + offset as i32], cl
 | 
	
		
			
				|  |  |                      );
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  else if factor == -1 {
 | 
	
		
			
				|  |  |                      dynasm!(self.buffer
 | 
	
		
			
				|  |  | -                        ; sub BYTE [rdi + rsi + offset as i32], cl
 | 
	
		
			
				|  |  | +                        ; sub BYTE [rdi + 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
 | 
	
		
			
				|  |  | +                        ; add BYTE [rdi + 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
 | 
	
		
			
				|  |  | +                        ; sub BYTE [rdi + offset as i32], bl
 | 
	
		
			
				|  |  |                      );
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  else {
 | 
	
		
			
				|  |  |                      dynasm!(self.buffer
 | 
	
		
			
				|  |  |                          ; mov al, factor as i8
 | 
	
		
			
				|  |  |                          ; mul cl
 | 
	
		
			
				|  |  | -                        ; add BYTE [rdi + rsi + offset as i32], al
 | 
	
		
			
				|  |  | +                        ; add BYTE [rdi + offset as i32], al
 | 
	
		
			
				|  |  |                      );
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              dynasm!(self.buffer
 | 
	
		
			
				|  |  | -                ; mov BYTE [rdi + rsi], 0
 | 
	
		
			
				|  |  | +                ; mov BYTE [rdi], 0
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_move_ptr(&mut self, mp: &'_ mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_move_ptr(&mut self, mp: &Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::MovePtr(offset) = mp {
 | 
	
		
			
				|  |  |              dynasm!(self.buffer
 | 
	
		
			
				|  |  | -                ; add rsi, DWORD *offset as i32
 | 
	
		
			
				|  |  | +                ; lea rdi, [rdi + *offset as i32]
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_loop(&mut self, l: &mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_loop(&mut self, l: &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
 | 
	
		
			
				|  |  | +                ; cmp BYTE [rdi], 0
 | 
	
		
			
				|  |  |                  ; jz => end
 | 
	
		
			
				|  |  |                  ; => begin
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |              self.visit_instructions(insts);
 | 
	
		
			
				|  |  |              dynasm!(self.buffer
 | 
	
		
			
				|  |  | -                ; mov al, BYTE [rdi + rsi]
 | 
	
		
			
				|  |  | -                ; test al, al
 | 
	
		
			
				|  |  | +                ; cmp BYTE [rdi], 0
 | 
	
		
			
				|  |  |                  ; jnz => begin
 | 
	
		
			
				|  |  |                  ; => end
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    fn visit_read(&mut self, r: &mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_read(&mut self, r: &Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Read(offset) = r {
 | 
	
		
			
				|  |  |              dynasm!(self.buffer
 | 
	
		
			
				|  |  |                  ; push rdi
 | 
	
	
		
			
				|  | @@ -194,18 +201,18 @@ impl ir::MutVisitor for CodeGenerator {
 | 
	
		
			
				|  |  |                  ; add rsp, 24
 | 
	
		
			
				|  |  |                  ; pop rsi
 | 
	
		
			
				|  |  |                  ; pop rdi
 | 
	
		
			
				|  |  | -                ; mov BYTE [rdi + rsi + *offset as i32], al
 | 
	
		
			
				|  |  | +                ; mov BYTE [rdi + *offset as i32], al
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_write(&mut self, w: &mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_write(&mut self, w: &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 dil, BYTE [rdi + *offset as i32]
 | 
	
		
			
				|  |  |                  ; mov rax, QWORD putbyte as _
 | 
	
		
			
				|  |  |                  ; call rax
 | 
	
		
			
				|  |  |                  ; add rsp, 24
 |