Переглянути джерело

Merge branch 'master' of https://gitlab.com/nicolaswinkler/zombie

Nicolas Winkler 5 роки тому
батько
коміт
c7783128cb
6 змінених файлів з 56 додано та 31 видалено
  1. 1 1
      examples/99bottles.bf
  2. 1 1
      examples/factor.bf
  3. 19 1
      src/compile.rs
  4. 1 0
      src/main.rs
  5. 2 2
      src/optimize.rs
  6. 32 26
      src/transpile_c.rs

+ 1 - 1
examples/99bottles.bf

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

+ 1 - 1
examples/factor.bf

@@ -192,4 +192,4 @@
 
 [>>>>>>>>>>]<<<<<<<<<<[+>[>>>>>>>>>+>]<-<<<<<<<<<<]-
 [>++++++++++++++++++++++++++++++++++++++++++++++++.<<<<<<<<<<<]
-++++++++++.
+++++++++++.

+ 19 - 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
-                    ; mov cl, BYTE [rdi + *glob_offset as i32]
+                    ; movzx ecx, BYTE [rdi]
                 );
             }
             for (&offset, &factor) in factors {
@@ -138,6 +138,24 @@ impl ir::ConstVisitor for CodeGenerator {
                         ; sub BYTE [rdi + absoff as i32], cl
                     );
                 }
+                else if factor == 3 {
+                    dynasm!(self.buffer
+                        ; lea ebx, [rcx + rcx * 2]
+                        ; mov [rdi + offset as i32], bl
+                    );
+                }
+                else if factor == 5 {
+                    dynasm!(self.buffer
+                        ; lea ebx, [rcx + rcx * 4]
+                        ; mov [rdi + offset as i32], bl
+                    );
+                }
+                else if factor == 9 {
+                    dynasm!(self.buffer
+                        ; lea ebx, [rcx + rcx * 8]
+                        ; mov [rdi + offset as i32], bl
+                    );
+                }
                 else if factor.count_ones() == 1 {
                     dynasm!(self.buffer
                         ; mov bl, cl

+ 1 - 0
src/main.rs

@@ -19,6 +19,7 @@ pub mod parser;
 pub mod interpret;
 pub mod optimize;
 pub mod compile;
+pub mod formatter;
 pub mod transpile_c;
 
 use crate::ir::MutVisitor;

+ 2 - 2
src/optimize.rs

@@ -164,10 +164,10 @@ impl ir::MutVisitor for LinOptimizer {
         }
     }
 
-    fn visit_linear_loop(&mut self, lloop: &'_ mut Instruction) {
+    fn visit_linear_loop(&mut self, lloop: &mut Instruction) {
     }
 
-    fn visit_move_ptr(&mut self, move_ptr: &'_ mut Instruction) {
+    fn visit_move_ptr(&mut self, move_ptr: &mut Instruction) {
         if let Instruction::MovePtr(offset) = move_ptr {
             self.offset += *offset;
         }

+ 32 - 26
src/transpile_c.rs

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