|
@@ -1,37 +1,111 @@
|
|
#include "AssemblyGenerator.h"
|
|
#include "AssemblyGenerator.h"
|
|
|
|
|
|
using namespace zp;
|
|
using namespace zp;
|
|
|
|
+using namespace std;
|
|
|
|
|
|
#include <iostream>
|
|
#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)
|
|
void AssemblyGenerator::visitUnionBlockInstruction(const UnionBlockInstruction& ubi)
|
|
{
|
|
{
|
|
- std::cout << "UnionBlockInstruction" << std::endl;
|
|
|
|
for (auto& a : ubi.content) {
|
|
for (auto& a : ubi.content) {
|
|
a->accept(*this);
|
|
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)
|
|
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);
|
|
visitUnionBlockInstruction(li);
|
|
|
|
+ out << "jmp " << label1 << endl;
|
|
|
|
+ out << label2 << ":" << endl;
|
|
}
|
|
}
|