Browse Source

holy rewrite

Nicolas Winkler 5 năm trước cách đây
mục cha
commit
cc1895de2d
3 tập tin đã thay đổi với 56 bổ sung26 xóa
  1. 1 0
      src/main.rs
  2. 51 22
      src/optimize.rs
  3. 4 4
      src/transpile_c.rs

+ 1 - 0
src/main.rs

@@ -39,6 +39,7 @@ fn main() -> io::Result<()> {
     if let Ok(mut insts) = insts {
         let mut lin_loop_optimizer = optimize::LinOptimizer::new();
         lin_loop_optimizer.visit_instructions(&mut insts);
+        std::mem::replace(&mut insts, lin_loop_optimizer.instructions);
         
         for ref inst in &insts {
             //println!("{}\n", inst.to_string());

+ 51 - 22
src/optimize.rs

@@ -132,51 +132,66 @@ impl<'a> ir::MutVisitor for DfgOptimizer<'a> {
 
 
 pub struct LinOptimizer {
-    offset: i64
+    offset: i64,
+    pub instructions: Vec<Instruction>
 }
 
 impl LinOptimizer {
     pub fn new() -> Self {
         LinOptimizer {
-            offset: 0
+            offset: 0,
+            instructions: Vec::new()
         }
     }
 }
 
 impl ir::MutVisitor for LinOptimizer {
-    type Ret = ();
+    type Ret = Option<Instruction>;
 
-    fn visit_instructions(&mut self, instr: &mut Vec<Instruction>) {
-        for inst in instr {
+    fn visit_instructions(&mut self, instrs: &mut Vec<Instruction>) {
+        for inst in instrs {
             self.walk_instruction(inst);
         }
     }
 
-    fn visit_add(&mut self, add: &mut Instruction) {
-        if let Instruction::Add{ offset, value: _value } = add {
-            *offset += self.offset;
+    fn visit_add(&mut self, add: &mut Instruction) -> Self::Ret {
+        if let Instruction::Add{ offset, value } = add {
+            self.instructions.push(Instruction::Add{ offset: *offset + self.offset, value: *value });
         }
+        None
     }
 
-    fn visit_set(&mut self, set: &mut Instruction) {
-        if let Instruction::Set{ offset, value: _value } = set {
-            *offset += self.offset;
+    fn visit_set(&mut self, set: &mut Instruction) -> Self::Ret {
+        if let Instruction::Set{ offset, value } = set {
+            self.instructions.push(Instruction::Set{ offset: *offset + self.offset, value: *value });
         }
+        None
     }
 
-    fn visit_linear_loop(&mut self, lloop: &mut Instruction) {
+    fn visit_linear_loop(&mut self, lloop: &mut Instruction) -> Self::Ret {
+        self.instructions.push(std::mem::replace(lloop, Instruction::Nop));
+        None
     }
 
-    fn visit_move_ptr(&mut self, move_ptr: &mut Instruction) {
+    fn visit_move_ptr(&mut self, move_ptr: &mut Instruction) -> Self::Ret {
         if let Instruction::MovePtr(offset) = move_ptr {
             self.offset += *offset;
         }
+        None
     }
 
-    fn visit_loop(&mut self, l: &mut Instruction) {
+    fn visit_loop(&mut self, l: &mut Instruction) -> Self::Ret {
         if let Instruction::Loop(instrs) = l {
             let mut increments: BTreeMap<i64, i64> = BTreeMap::new();
             let mut dirty = false;
+
+            // pointer movement to be added in case this loop cannot be linearized
+            let offset_before = self.offset;
+            self.offset = 0;
+
+            let mut swap: Vec<Instruction> = Vec::new();
+            std::mem::swap(&mut self.instructions, &mut swap);
+
             for inst in instrs {
                 self.walk_instruction(inst);
                 if !dirty {
@@ -190,38 +205,52 @@ impl ir::MutVisitor for LinOptimizer {
                         },
                         _ => {
                             dirty = true;
-                            break;
                         }
                     }
                 }
             }
+            if self.offset != 0 {
+                self.instructions.push(Instruction::MovePtr(self.offset));
+                self.offset = 0;
+            }
+            std::mem::swap(&mut self.instructions, &mut swap);
 
             if !dirty && increments.len() == 1 {
+                self.offset = offset_before;
                 if let Some(&v) = increments.get(&0) {
                     if v % 2 != 0 {
                         // cases like [-]
                         // also [---]
-                        std::mem::replace(l, Instruction::Set{ offset: self.offset, value: 0 });
+                        self.instructions.push(Instruction::Set{ offset: self.offset, value: 0 });
                     }
                 }
             }
             else if !dirty && increments.get(&0) == Some(&-1) {
-                std::mem::replace(l, Instruction::LinearLoop{ offset: self.offset, factors: increments });
+                self.offset = offset_before;
+                self.instructions.push(Instruction::LinearLoop{ offset: self.offset, factors: increments });
+            }
+            else {
+                if offset_before != 0 {
+                    self.instructions.push(Instruction::MovePtr(offset_before));
+                }
+                self.instructions.push(Instruction::Loop(swap));
             }
-
             // set cell at offset 0 to 0
         }
+        None
     }
 
-    fn visit_read(&mut self, read: &'_ mut Instruction) {
+    fn visit_read(&mut self, read: &mut Instruction) -> Self::Ret {
         if let Instruction::Read(offset) = read {
-            *offset += self.offset;
+            self.instructions.push(Instruction::Read(*offset + self.offset));
         }
+        None
     }
 
-    fn visit_write(&mut self, write: &'_ mut Instruction) {
+    fn visit_write(&mut self, write: &'_ mut Instruction) -> Self::Ret {
         if let Instruction::Write(offset) = write {
-            *offset += self.offset;
+            self.instructions.push(Instruction::Write(*offset + self.offset));
         }
+        None
     }
 }

+ 4 - 4
src/transpile_c.rs

@@ -71,16 +71,16 @@ impl ir::ConstVisitor for CTranspiler {
                 if factor == 0 {
                 }
                 else if factor == 1 {
-                    self.code_buf.add_line(&format!("buffer[{}] += buffer[0];", glob_offset + offset));
+                    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[0];", glob_offset + offset));
+                    self.code_buf.add_line(&format!("buffer[{}] -= buffer[{}];", glob_offset + offset, glob_offset));
                 }
                 else {
-                    self.code_buf.add_line(&format!("buffer[{}] += {} * buffer[0];", glob_offset + offset, factor));
+                    self.code_buf.add_line(&format!("buffer[{}] += {} * buffer[{}];", glob_offset + offset, factor, glob_offset));
                 }
             }
-            self.code_buf.add_line("buffer[0] = 0;");
+            self.code_buf.add_line(&format!("buffer[{}] = 0;", glob_offset));
         }
     }