Ver Fonte

yes jaa

Nicolas Winkler há 7 anos atrás
pai
commit
716c476b2b
7 ficheiros alterados com 167 adições e 34 exclusões
  1. 44 1
      src/.vscode/settings.json
  2. 90 8
      src/AssemblyGenerator.cpp
  3. 17 17
      src/AssemblyGenerator.h
  4. 7 1
      src/Optimizer.cpp
  5. 4 3
      src/Optimizer.h
  6. 3 2
      src/main.cpp
  7. 2 2
      src/makefile

+ 44 - 1
src/.vscode/settings.json

@@ -1,6 +1,49 @@
 {
     "files.associations": {
         "memory": "cpp",
-        "iostream": "cpp"
+        "iostream": "cpp",
+        "xiosbase": "cpp",
+        "xlocale": "cpp",
+        "algorithm": "cpp",
+        "cmath": "cpp",
+        "cstddef": "cpp",
+        "cstdint": "cpp",
+        "cstdio": "cpp",
+        "cstdlib": "cpp",
+        "cstring": "cpp",
+        "cwchar": "cpp",
+        "exception": "cpp",
+        "fstream": "cpp",
+        "initializer_list": "cpp",
+        "ios": "cpp",
+        "iosfwd": "cpp",
+        "istream": "cpp",
+        "limits": "cpp",
+        "list": "cpp",
+        "map": "cpp",
+        "new": "cpp",
+        "ostream": "cpp",
+        "stdexcept": "cpp",
+        "streambuf": "cpp",
+        "string": "cpp",
+        "system_error": "cpp",
+        "tuple": "cpp",
+        "type_traits": "cpp",
+        "typeinfo": "cpp",
+        "unordered_map": "cpp",
+        "utility": "cpp",
+        "vector": "cpp",
+        "xfacet": "cpp",
+        "xhash": "cpp",
+        "xlocinfo": "cpp",
+        "xlocnum": "cpp",
+        "xmemory": "cpp",
+        "xmemory0": "cpp",
+        "xstddef": "cpp",
+        "xstring": "cpp",
+        "xtr1common": "cpp",
+        "xtree": "cpp",
+        "xutility": "cpp",
+        "cinttypes": "cpp"
     }
 }

+ 90 - 8
src/AssemblyGenerator.cpp

@@ -1,37 +1,111 @@
 #include "AssemblyGenerator.h"
 
 using namespace zp;
+using namespace std;
 
 #include <iostream>
 
-void AssemblyGenerator::visitBlockInstruction(const BlockInstruction& bi)
+const char* AssemblyGenerator::pointerRegister = "rbx";
+const char* AssemblyGenerator::dataRegister = "r12";
+
+#ifdef _WIN32
+const char* AssemblyGenerator::argumentRegister1 = "rcx";
+const char* AssemblyGenerator::argumentRegister2 = "rdx";
+#else
+const char* AssemblyGenerator::argumentRegister1 = "rdi";
+const char* AssemblyGenerator::argumentRegister2 = "rsi";
+#endif
+
+
+AssemblyGenerator::AssemblyGenerator(std::ostream& out) :
+    out{ out }
+{
+    out << ".globl main" << endl;
+    out << "main:" << endl;
+    out << "subq $40, %rsp" << endl;
+    out << "movq $131072, %" << argumentRegister1 << endl;
+    out << "movq $1, %" << argumentRegister2 << endl;
+    out << "callq calloc" << endl;
+    out << "addq $65536, %rax" << endl;
+    out << "movq %rax, %" << dataRegister << endl;
+    out << "xorq %" << pointerRegister << ", %" << pointerRegister << endl;
+    out << endl;
+    out << "# begin of bf-program" << endl;
+    out << endl;
+}
+
+
+void AssemblyGenerator::finish(void)
+{
+    out << endl;
+    out << "# end of bf-program" << endl;
+    out << endl;
+    out << "movq %" << dataRegister << ", %" << argumentRegister1 << endl;
+    out << "callq free" << endl;
+    out << "xorq %rax, %rax" << endl;
+    out << "addq $40, %rsp" << endl;
+    out << "retq" << endl;
+}
+
+
+std::string AssemblyGenerator::generateLabel(void)
+{
+    return ".L" + std::to_string(labelcount++);
+}
+
+
+std::string AssemblyGenerator::generateOffset(const std::string& offset,
+    const std::string& base)
+{
+    return "(" + offset + ", " + base + ")";
+}
+
+
+std::string AssemblyGenerator::ptr(void)
+{
+    return generateOffset("%"s + pointerRegister, "%"s + dataRegister);
+}
+
+void AssemblyGenerator::visitBlockInstruction(const BlockInstruction&)
 {
-    bi.
 }
 
 
 void AssemblyGenerator::visitUnionBlockInstruction(const UnionBlockInstruction& ubi)
 {
-    std::cout << "UnionBlockInstruction" << std::endl;
     for (auto& a : ubi.content) {
         a->accept(*this);
     }
 }
 
 
-void AssemblyGenerator::visitIOInstruction(const IOInstruction&)
+void AssemblyGenerator::visitIOInstruction(const IOInstruction& ioi)
 {
-    std::cout << "IOInstruction" << std::endl;
+    if (ioi.isRead) {
+        out << "callq getchar" << endl;
+        out << "movb %al, " << ptr() << endl;
+    }
+    else {
+        out << "movq " << ptr() << ", %" << argumentRegister1 << endl;
+        out << "andq $255, %" << argumentRegister1 << endl;
+        out << "callq putchar" << endl;
+    }
 }
 
 
-void AssemblyGenerator::visitSimpleBlockInstruction(const SimpleBlockInstruction&)
+void AssemblyGenerator::visitSimpleBlockInstruction(const SimpleBlockInstruction& sbi)
 {
-
+    for (const auto [index, value] : sbi.added) {
+        out << "addb $" << int(value) << ", " << index <<
+            ptr() << endl;
+    }
+    if (sbi.pointerMoved != 0)
+        out << "addq $" << sbi.pointerMoved << ", %" << pointerRegister << endl;
+    //out << "andq $65535, %" << pointerRegister << endl;
 }
 
 
-void AssemblyGenerator::visitLinearLoopInstruction(const LinearLoopInstruction&)
+void AssemblyGenerator::visitLinearLoopInstruction(const LinearLoopInstruction& lli)
 {
 
 }
@@ -39,5 +113,13 @@ void AssemblyGenerator::visitLinearLoopInstruction(const LinearLoopInstruction&)
 
 void AssemblyGenerator::visitLoopInstruction(const LoopInstruction& li)
 {
+    std::string label1 = generateLabel();
+    std::string label2 = generateLabel();
+    out << label1 << ":" << endl;
+    out << "movb " << ptr() << ", %al" << endl;
+    out << "testb %al, %al" << endl;
+    out << "jz " << label2 << endl;
     visitUnionBlockInstruction(li);
+    out << "jmp " << label1 << endl;
+    out << label2 << ":" << endl;
 }

+ 17 - 17
src/AssemblyGenerator.h

@@ -2,10 +2,13 @@
 #define ZP_ASSEMBLY_GENERATOR_H_
 
 #include "Optimizer.h"
+#include <iostream>
+#include <string>
 
 namespace zp
 {
     class X64AssemblyHolder;
+    class X64TextAssemblyHolder;
 
     class IRVisitor;
 
@@ -13,20 +16,6 @@ namespace zp
 }
 
 
-class X64AssemblyHolder
-{
-public:
-    enum class Register {
-        RAX, RBX, RCX, RDX,
-        RSI, RDI, RBP, RSP,
-        R8, R9, R10, R11, R12, R13, R14, R15
-    };
-
-    void mov(Register src, Register target) = 0;
-    void mov(uint64_t imm, Register target) = 0;
-};
-
-
 class zp::IRVisitor
 {
 public:
@@ -42,11 +31,22 @@ public:
 class zp::AssemblyGenerator :
     public IRVisitor
 {
-    X64AssemblyHolder& as;
+    std::ostream& out;
+
+    int labelcount = 0;
+    static const char* dataRegister;
+    static const char* pointerRegister;
+    static const char* argumentRegister1;
+    static const char* argumentRegister2;
 public:
 
-    inline AssemblyGenerator(X64AssemblyHolder& as) :
-        as{ as } {}
+    AssemblyGenerator(std::ostream& out);
+
+    void finish(void);
+
+    std::string generateLabel(void);
+    std::string generateOffset(const std::string& offset, const std::string& base);
+    std::string ptr(void);
 
     virtual void visitBlockInstruction(const BlockInstruction&);
     virtual void visitUnionBlockInstruction(const UnionBlockInstruction&);

+ 7 - 1
src/Optimizer.cpp

@@ -45,7 +45,6 @@ void LoopInstruction::accept(IRVisitor& v)
 
 unique_ptr<BlockInstruction> Optimizer::visitInstructionBlock(InstructionBlock& ib)
 {
-    std::cout << "InstructionBlock" << std::endl;
     unique_ptr<SimpleBlockInstruction> sbi = make_unique<SimpleBlockInstruction>();
     for (auto instr : ib.instructions) {
         switch(instr) {
@@ -56,15 +55,22 @@ unique_ptr<BlockInstruction> Optimizer::visitInstructionBlock(InstructionBlock&
                 sbi->pointerMoved++;
                 break;
             case Instruction::PLUS:
+                if (sbi->added.find(sbi->pointerMoved) == sbi->added.end())
+                    sbi->added[sbi->pointerMoved] = 0;
                 sbi->added[sbi->pointerMoved]++;
                 break;
             case Instruction::MINUS:
+                if (sbi->added.find(sbi->pointerMoved) == sbi->added.end())
+                    sbi->added[sbi->pointerMoved] = 0;
                 sbi->added[sbi->pointerMoved]--;
                 break;
             default:
                 break;
         }
     }
+    /*for (const auto [index, value] : sbi->added) {
+        std::cout << "we have: " << index << ", " << int(value) << std::endl;
+    }*/
     return sbi;
 }
 

+ 4 - 3
src/Optimizer.h

@@ -3,8 +3,9 @@
 
 #include "Parser.h"
 
-#include <unordered_map>
+#include <map>
 #include <memory>
+#include <cinttypes>
 
 namespace zp
 {
@@ -28,7 +29,7 @@ namespace zp
     class Optimizer;
 
     using Index = int;
-    using Cell = unsigned char;
+    using Cell = uint8_t;
 
 
     // forward declaration
@@ -81,7 +82,7 @@ struct zp::SimpleBlockInstruction :
     public BlockInstruction
 {
     Index pointerMoved;
-    std::unordered_map<Index, Cell> added;
+    std::map<Index, Cell> added;
     virtual void accept(IRVisitor& v);
 };
 

+ 3 - 2
src/main.cpp

@@ -9,6 +9,7 @@
 using namespace std;
 using zp::Parser;
 using zp::Optimizer;
+using zp::X64TextAssemblyHolder;
 using zp::AssemblyGenerator;
 
 
@@ -46,9 +47,9 @@ int main(int argc, char** argv)
     Optimizer optimizer;
     auto ir = ast->accept(optimizer);
 
-    AssemblyGenerator ag{};
+    AssemblyGenerator ag{ cout };
     ir->accept(ag);
-
+    ag.finish();
 
     if (filename != "") {
         dynamic_cast<ifstream*> (in)->close();

+ 2 - 2
src/makefile

@@ -1,6 +1,6 @@
 CXX         := g++
-CXXFLAGS    := -std=c++14 -Wall
-LNFLAGS     := -Lasmjit -lasmjit
+CXXFLAGS    := -std=c++17 -Wall
+LNFLAGS     := 
 SOURCES     := $(wildcard *.cpp)
 OBJECTS     := $(patsubst %.cpp, %.o, $(SOURCES))
 EXECUTABLE  := zombie