Nicolas Winkler 5 سال پیش
والد
کامیت
f6707c9440
6فایلهای تغییر یافته به همراه56 افزوده شده و 148 حذف شده
  1. 1 1
      examples/99bottles.bf
  2. 1 1
      src/compile.rs
  3. 9 0
      src/ir.rs
  4. 5 3
      src/main.rs
  5. 40 29
      src/optimize.rs
  6. 0 114
      src/transpile_c.rs

+ 1 - 1
examples/99bottles.bf

@@ -1,6 +1,6 @@
 # 99 bottles of beer in Brainf*ck
 # Copyright (C) 2008 Raphael Bois
-# 1671 brainf*ck instructions.
+# 1671 brainf*ck instructions
 # Published under GPL v2
 
 Initialization

+ 1 - 1
src/compile.rs

@@ -116,7 +116,7 @@ impl ir::ConstVisitor for CodeGenerator {
             if factors.len() > 1 ||
                 factors.len() >= 1 && !factors.contains_key(&0) {
                 dynasm!(self.buffer
-                    ; movzx ecx, BYTE [rdi]
+                    ; movzx ecx, BYTE [rdi + *glob_offset as i32]
                 );
             }
             for (&offset, &factor) in factors {

+ 9 - 0
src/ir.rs

@@ -2,13 +2,22 @@ use std::collections::BTreeMap;
 
 #[derive(Debug)]
 pub enum Instruction {
+    // No instruction
     Nop,
+    // Add a constnant value to the cell at a specific offset
     Add{ offset: i64, value: i64 },
+    // Set the cell at the specified offset to a constant value
     Set{ offset: i64, value: i64 },
+    // Add the value at offset to all cells specified by factors
+    // multiplied (factors indices are relative to offset)
     LinearLoop{ offset: i64, factors: BTreeMap<i64, i64> },
+    // Move the current cell pointer
     MovePtr(i64),
+    // A loop that is executed until the current cell is 0
     Loop(Vec<Instruction>),
+    // Read one input symbol into the current cell
     Read(i64),
+    // Print the current cell
     Write(i64)
 }
 

+ 5 - 3
src/main.rs

@@ -20,7 +20,9 @@ pub mod interpret;
 pub mod optimize;
 pub mod compile;
 pub mod formatter;
-pub mod transpile_c;
+pub mod trans;
+
+use trans::{c};
 
 use crate::ir::MutVisitor;
 
@@ -44,9 +46,9 @@ fn main() -> io::Result<()> {
         for ref inst in &insts {
             //println!("{}\n", inst.to_string());
         }
-        println!("{}", transpile_c::transpile_c(&insts));
+        //println!("{}", trans::java::transpile(&insts));
 
-        //let code = compile::compile(&insts);
+        let code = compile::compile(&insts);
     }
     else if let Err(msg) = insts {
         println!("error parsing: {}", msg);

+ 40 - 29
src/optimize.rs

@@ -5,25 +5,16 @@ use super::ir::Instruction;
 use typed_arena::Arena;
 
 pub struct DfgOptimizer<'a> {
-    dfg: DataflowGraph<'a>,
-    cell_states: BTreeMap<i64, DfgNode<'a>>,
-    cfg: Vec<DfInstr<'a>>,
-}
-
-struct DataflowGraph<'a> {
     arena: Arena<DfgNode<'a>>,
+    cell_states: BTreeMap<i64, &'a DfgNode<'a>>,
+    cfg: Vec<DfInstr<'a>>,
 }
 
-pub struct DfgNode<'a> {
-    storation: Option<compile::Storation>,
-    kind: DfgNodeKind<'a>,
-}
-
-pub enum DfgNodeKind<'a> {
-    Offset(i64),
-    ConstAdd(&'a DfgNode<'a>),
+pub enum DfgNode<'a> {
+    Cell(i64),
     Const(i64),
-    AddMultiplied(&'a DfgNode<'a>, i64, &'a DfgNode<'a>),
+    Add(&'a DfgNode<'a>, &'a DfgNode<'a>),
+    Multiply(&'a DfgNode<'a>, &'a DfgNode<'a>),
     Read(),
 }
 
@@ -33,16 +24,17 @@ pub enum DfInstr<'a> {
     Loop(i64, Vec<DfInstr<'a>>),
 }
 
-impl<'a> DfgNode<'a> {
-    pub fn new(kind: DfgNodeKind<'a>) -> Self {
-        DfgNode {
-            storation: None,
-            kind: kind
-        }
-    }
-}
 
 impl<'a> DfgOptimizer<'a> {
+    fn get_cell(&'a self, offset: i64) -> &'a DfgNode<'a> {
+        if let Some(cell) = self.cell_states.get(&offset) {
+            cell
+        }
+        else {
+            let off: &mut DfgNode<'a> = self.arena.alloc(DfgNode::Cell(offset));
+            off
+        }
+    }
 }
 
 impl<'a> ir::MutVisitor for DfgOptimizer<'a> {
@@ -56,14 +48,19 @@ impl<'a> ir::MutVisitor for DfgOptimizer<'a> {
 
     fn visit_add(&mut self, add: &mut Instruction) {
         if let Instruction::Add{ offset, value } = add {
-            let arena = &self.dfg.arena;
-            let load = RefCell::new(arena.alloc(DfgNode::new(DfgNodeKind::Offset(*offset))));
-            //let addition: &'a _ = arena.alloc(DfgNode::new(DfgNodeKind::ConstAdd(load)));
-            //self.cfg.push(DfInstr::WriteMem(*offset, addition));
+            /*let cell = self.get_cell(*offset);
+            let adder = self.arena.alloc(DfgNode::Const(*value));
+            let addition = self.arena.alloc(DfgNode::Add(cell, adder));
+            */
         }
     }
 
-    fn visit_set(&mut self, set: &mut Instruction) {
+    fn visit_set<'b>(&'b mut self, set: &mut Instruction) {
+        if let Instruction::Set{ offset, value } = set {
+            let arena: &'b _ = &self.arena;
+            let setter: &'b DfgNode<'a> = arena.alloc(DfgNode::Const(*value));
+            self.cell_states.insert(13, setter);
+        }
     }
 
     fn visit_linear_loop(&mut self, lloop: &'_ mut Instruction) {
@@ -111,6 +108,19 @@ impl<'a> ir::MutVisitor for DfgOptimizer<'a> {
 
 
 
+struct MemoryState {
+    cellStates: BTreeMap<i64, CellState>,
+    default_cell: CellState
+}
+
+enum CellState {
+    Unknown,
+    Const(i64),
+    OtherCell(usize),
+    Sum(usize, usize),
+    Prod(usize, usize),
+}
+
 
 
 
@@ -186,9 +196,10 @@ impl ir::MutVisitor for LinOptimizer {
             let mut dirty = false;
 
             // pointer movement to be added in case this loop cannot be linearized
+            // also copy the instruction list (essentially push the optimizer state on a stack
+            // for the loop)
             let offset_before = self.offset;
             self.offset = 0;
-
             let mut swap: Vec<Instruction> = Vec::new();
             std::mem::swap(&mut self.instructions, &mut swap);
 

+ 0 - 114
src/transpile_c.rs

@@ -1,114 +0,0 @@
-
-use super::{ir, optimize, formatter};
-
-use ir::Instruction;
-use ir::ConstVisitor;
-use formatter::Formatter;
-
-struct CTranspiler {
-    pub code_buf: Formatter
-}
-
-
-pub fn transpile_c(instrs: &Vec<ir::Instruction>) -> String {
-    let mut transpiler = CTranspiler::default();
-    transpiler.visit_instructions(instrs);
-    transpiler.finalize();
-    return transpiler.code_buf.get_code();
-}
-
-
-impl Default for CTranspiler {
-    fn default() -> Self {
-        let mut transpiler = CTranspiler{ code_buf: Formatter::new() };
-
-        transpiler.code_buf.add_line(r#"#include <stdio.h>
-#include <stdlib.h>
-
-
-int main() {
-    unsigned char* restrict buffer = (unsigned char*) calloc(2000000000, 1);
-    buffer += 1000000000;"#);
-        transpiler.code_buf.indent();
-        transpiler
-    }
-}
-
-impl CTranspiler {
-    pub fn finalize(&mut self) {
-        self.code_buf.unindent();
-        self.code_buf.add_line("}");
-    }
-}
-
-
-impl ir::ConstVisitor for CTranspiler {
-    type Ret = ();
-
-    fn visit_nop(&mut self, nop: &Instruction) {
-        self.code_buf.add_line("");
-    }
-
-    fn visit_add(&mut self, add: &'_ Instruction) {
-        if let Instruction::Add{ offset, value } = add {
-            self.code_buf.add_line(&format!("buffer[{}] += {};", offset, value));
-        }
-    }
-
-    fn visit_set(&mut self, set: &'_ Instruction) {
-        if let Instruction::Set{ offset, value } = set {
-            self.code_buf.add_line(&format!("buffer[{}] = {};", offset, value));
-        }
-    }
-
-    fn visit_linear_loop(&mut self, l: &Instruction) {
-        if let Instruction::LinearLoop{ offset: glob_offset, factors } = l {
-            for (&offset, &factor) in factors {
-                if offset == 0 {
-                    continue;
-                }
-
-                if factor == 0 {
-                }
-                else if factor == 1 {
-                    self.code_buf.add_line(&format!("buffer[{}] += buffer[{}];", glob_offset + offset, glob_offset));
-                }
-                else if factor == -1 {
-                    self.code_buf.add_line(&format!("buffer[{}] -= buffer[{}];", glob_offset + offset, glob_offset));
-                }
-                else {
-                    self.code_buf.add_line(&format!("buffer[{}] += {} * buffer[{}];", glob_offset + offset, factor, glob_offset));
-                }
-            }
-            self.code_buf.add_line(&format!("buffer[{}] = 0;", glob_offset));
-        }
-    }
-
-    fn visit_move_ptr(&mut self, mp: &'_ Instruction) {
-        if let Instruction::MovePtr(offset) = mp {
-            self.code_buf.add_line(&format!("buffer += {};", offset));
-        }
-    }
-
-    fn visit_loop(&mut self, l: &Instruction) {
-        if let Instruction::Loop(insts) = l {
-            self.code_buf.add_line("while(buffer[0]) {");
-            self.code_buf.indent();
-            self.visit_instructions(insts);
-            self.code_buf.unindent();
-            self.code_buf.add_line("}");
-        }
-    }
-    
-    fn visit_read(&mut self, r: &Instruction) {
-        if let Instruction::Read(offset) = r {
-            self.code_buf.add_line(&format!("buffer[{}] = getchar();", offset));
-        }
-    }
-
-    fn visit_write(&mut self, w: &Instruction) {
-        if let Instruction::Write(offset) = w {
-            self.code_buf.add_line(&format!("putchar(buffer[{}]);", offset));
-        }
-    }
-}