Pārlūkot izejas kodu

started with implementation of new optimizations

Nicolas Winkler 6 gadi atpakaļ
vecāks
revīzija
a0007e7163
6 mainītis faili ar 103 papildinājumiem un 30 dzēšanām
  1. BIN
      src/.main.rs.swp
  2. 16 25
      src/compile.rs
  3. 5 0
      src/interpret.rs
  4. 12 0
      src/ir.rs
  5. 1 1
      src/main.rs
  6. 69 4
      src/optimize.rs

BIN
src/.main.rs.swp


+ 16 - 25
src/compile.rs

@@ -4,34 +4,14 @@ use std::io::{Write, Read};
 use std::mem;
 use super::ir::{MutVisitor, 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> {
-    /*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();
 
@@ -40,14 +20,14 @@ pub fn compile(mut instrs: Vec<ir::Instruction>) -> Vec<u8> {
     cg.visit_instructions(&mut instrs);
     cg.buffer.commit();
     cg.finalize();
-    //let buf = cg.buffer.finalize().unwrap();
+    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(cg.get_callable())
-        mem::transmute(cg.buffer.finalize().unwrap().ptr(entry))
+        mem::transmute(buf.ptr(entry))
     };
 
     let mut data: Vec<u8> = Vec::with_capacity(100000);
@@ -103,10 +83,21 @@ impl CodeGenerator {
 impl ir::MutVisitor for CodeGenerator {
     type Ret = ();
 
+    fn visit_nop(&mut self, nop: &mut Instruction) {
+    }
+
     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
+                ; add BYTE [rdi + rsi + *offset as i32], *value as i8
+            );
+        }
+    }
+
+    fn visit_set(&mut self, set: &'_ mut Instruction) {
+        if let Instruction::Set{ offset, value } = set {
+            dynasm!(self.buffer
+                ; mov BYTE [rdi + rsi + *offset as i32], *value as i8
             );
         }
     }

+ 5 - 0
src/interpret.rs

@@ -22,10 +22,15 @@ fn run_instrs(instructions: &Vec<Instruction>, data: &mut Data) {
     let len = data.memory.len();
     for inst in instructions {
         match inst {
+            Instruction::Nop => {},
             Instruction::Add{ offset, value } => {
                 let cell = &mut data.memory[(data.ptr + offset) as usize % len];
                 *cell = cell.wrapping_add(*value as u8);
             },
+            Instruction::Set{ offset, value } => {
+                let cell = &mut data.memory[(data.ptr + offset) as usize % len];
+                *cell = *value as u8;
+            },
             Instruction::MovePtr(offset) => {
                 data.ptr = data.ptr.wrapping_add(*offset);
             },

+ 12 - 0
src/ir.rs

@@ -2,7 +2,9 @@ use std::collections::BTreeMap;
 
 #[derive(Debug)]
 pub enum Instruction {
+    Nop,
     Add{ offset: i64, value: i64 },
+    Set{ offset: i64, value: i64 },
     LinearLoop(BTreeMap<i64, i64>),
     MovePtr(i64),
     Loop(Vec<Instruction>),
@@ -21,10 +23,18 @@ pub trait MutVisitor {
         }
     }
 
+    fn visit_nop(&mut self, nop: &mut Instruction) -> Self::Ret {
+        Self::Ret::default()
+    }
+
     fn visit_add(&mut self, add: &mut Instruction) -> Self::Ret {
         Self::Ret::default()
     }
 
+    fn visit_set(&mut self, add: &mut Instruction) -> Self::Ret {
+        Self::Ret::default()
+    }
+
     fn visit_linear_loop(&mut self, lloop: &mut Instruction) -> Self::Ret {
         Self::Ret::default()
     }
@@ -51,7 +61,9 @@ pub trait MutVisitor {
     fn walk_instruction(&mut self, inst: &mut Instruction) -> Self::Ret {
         use self::Instruction::*;
         match inst {
+            Nop => self.visit_nop(inst),
             Add {offset: _, value: _} => self.visit_add(inst),
+            Set {offset: _, value: _} => self.visit_set(inst),
             LinearLoop (_) => self.visit_linear_loop(inst),
             MovePtr(_) => self.visit_move_ptr(inst),
             Loop(_) => self.visit_loop(inst),

+ 1 - 1
src/main.rs

@@ -31,7 +31,7 @@ fn main() -> io::Result<()> {
 
     let insts = parser::parse(&buffer);
     if let Ok(mut insts) = insts {
-        let mut lin_loop_optimizer = optimize::LoopLinearizer;
+        let mut lin_loop_optimizer = optimize::Optimizer::new();
         //println!("code: {:#?}", insts);
         lin_loop_optimizer.visit_instructions(&mut insts);
         //println!("code: {:#?}", insts);

+ 69 - 4
src/optimize.rs

@@ -3,19 +3,82 @@ use std::collections::BTreeMap;
 use super::ir;
 use super::ir::Instruction;
 
+enum CellState {
+    Value(i64),
+    Added(i64)
+}
+
+struct TapeState {
+    pub cell_states: BTreeMap<i64, CellState>
+}
 
-pub struct LoopLinearizer;
+pub struct Optimizer {
+    state: TapeState
+}
 
-impl ir::MutVisitor for LoopLinearizer {
+impl TapeState {
+    fn add(&mut self, offset: i64, value: i64) {
+        let cell_state = self.cell_states.get_mut(&offset);
+        if let Some(cell) = cell_state {
+            let new_cell = match cell {
+                CellState::Value(val) => CellState::Value(*val + value),
+                CellState::Added(val) => CellState::Added(*val + value)
+            };
+            std::mem::replace(cell, new_cell);
+        }
+        else {
+            self.cell_states.insert(offset, CellState::Added(value));
+        }
+    }
+
+    fn set(&mut self, offset: i64, value: i64) {
+        let cell_state = self.cell_states.get_mut(&offset);
+        if let Some(cell) = cell_state {
+            std::mem::replace(cell, CellState::Value(value));
+        }
+        else {
+            self.cell_states.insert(offset, CellState::Value(value));
+        }
+    }
+
+    fn get(&self, offset: i64) -> Option<&CellState> {
+        self.cell_states.get(&offset)
+    }
+}
+
+impl Optimizer {
+    pub fn new() -> Self {
+        Optimizer {
+            state: TapeState {
+                cell_states: BTreeMap::new()
+            }
+        }
+    }
+}
+
+impl ir::MutVisitor for Optimizer {
     type Ret = ();
 
-    fn visit_instructions(&mut self, instr: &'_ mut Vec<Instruction>) {
+    fn visit_instructions(&mut self, instr: &mut Vec<Instruction>) {
         for inst in instr {
             self.walk_instruction(inst);
         }
     }
 
-    fn visit_add(&mut self, add: &'_ mut Instruction) {
+    fn visit_add(&mut self, add: &mut Instruction) {
+        if let Instruction::Add{ offset, value } = add {
+            let cell_state = self.state.get(*offset);
+            if let Some(CellState::Value(v)) = cell_state {
+                self.state.add(*offset, *value);
+                //std::mem::replace(add, Instruction::Set{ offset: *offset, value: *value + v });
+            }
+            else {
+                self.state.add(*offset, *value);
+            }
+        }
+    }
+
+    fn visit_set(&mut self, set: &mut Instruction) {
     }
 
     fn visit_linear_loop(&mut self, lloop: &'_ mut Instruction) {
@@ -49,6 +112,8 @@ impl ir::MutVisitor for LoopLinearizer {
             if !dirty && increments.get(&0) == Some(&-1) {
                 std::mem::replace(l, Instruction::LinearLoop(increments));
             }
+            // set cell at offset 0 to 0
+            self.state.set(0, 0);
         }
     }