Commit b00ae3ce authored by zygzagZ's avatar zygzagZ

Most works, strings don't

parent 459ffddf
...@@ -45,7 +45,7 @@ Quadruple.o : src/codeGen/Quadruple.cpp src/codeGen/Quadruple.h src/Info.h src/I ...@@ -45,7 +45,7 @@ Quadruple.o : src/codeGen/Quadruple.cpp src/codeGen/Quadruple.h src/Info.h src/I
Variable.o : src/codeGen/Variable.cpp src/codeGen/Quadruple.h src/Info.h src/InfoList.h src/Absyn.h Variable.o : src/codeGen/Variable.cpp src/codeGen/Quadruple.h src/Info.h src/InfoList.h src/Absyn.h
${CC} ${CCFLAGS} -c src/codeGen/Variable.cpp ${CC} ${CCFLAGS} -c src/codeGen/Variable.cpp
BasicBlock.o : src/codeGen/BasicBlock.cpp src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/codeGen/Variable.h src/Info.h src/InfoList.h src/Absyn.h BasicBlock.o : src/codeGen/BasicBlock.cpp src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/codeGen/Variable.h src/Info.h src/InfoList.h src/Absyn.h src/Compiler.h
${CC} ${CCFLAGS} -c src/codeGen/BasicBlock.cpp ${CC} ${CCFLAGS} -c src/codeGen/BasicBlock.cpp
QuadrupleGenerator.o : src/codeGen/QuadrupleGenerator.cpp src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/Info.h src/InfoList.h src/Absyn.h src/codeGen/Variable.h src/Compiler.h src/codeGen/QuadrupleGenerator.h QuadrupleGenerator.o : src/codeGen/QuadrupleGenerator.cpp src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/Info.h src/InfoList.h src/Absyn.h src/codeGen/Variable.h src/Compiler.h src/codeGen/QuadrupleGenerator.h
......
hello: hello:
.string "Hello\n" .string "Hello\n"
.globl main .globl main
.globl printStr .globl printString
.globl printInt .globl printInt
.globl readInt .globl readInt
.globl readStr .globl readString
.globl error .globl error
.globl exit .globl exit
.globl _start .globl _start
...@@ -22,7 +22,7 @@ main: ...@@ -22,7 +22,7 @@ main:
pushl %ebp pushl %ebp
movl %esp, %ebp movl %esp, %ebp
pushl $hello pushl $hello
call printStr call printString
movl $0, %eax movl $0, %eax
leave leave
ret ret
......
...@@ -8,11 +8,11 @@ int printInt(int a) { ...@@ -8,11 +8,11 @@ int printInt(int a) {
printf("%d\n", a); printf("%d\n", a);
} }
int printStr(const char *c) { int printString(const char *c) {
printf("%s\n", c); printf("%s\n", c);
} }
char * readStr() { char * readString() {
char *line = NULL; char *line = NULL;
size_t len = 0; size_t len = 0;
getline(&line, &len, stdin); getline(&line, &len, stdin);
...@@ -47,7 +47,7 @@ void error() { ...@@ -47,7 +47,7 @@ void error() {
} }
char* __latte_mem_init(size_t size, void* virtTab) { char* __latte_mem_init(size_t size, void* virtTab) {
char *buf = calloc(len, size); char *buf = calloc(1, size);
if (!buf) error(); if (!buf) error();
*((void**)buf) = virtTab; *((void**)buf) = virtTab;
return buf; return buf;
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <iostream> #include <iostream>
#include <cassert> #include <cassert>
#define COMMENT "//"
extern std::filesystem::path binaryPath; extern std::filesystem::path binaryPath;
const std::string Compiler::extension = "s"; const std::string Compiler::extension = "s";
void Compiler::externalCommand(std::filesystem::path lat) { void Compiler::externalCommand(std::filesystem::path lat) {
...@@ -26,7 +28,7 @@ void Compiler::externalCommand(std::filesystem::path lat) { ...@@ -26,7 +28,7 @@ void Compiler::externalCommand(std::filesystem::path lat) {
string Compiler::compile(Visitable *v) { string Compiler::compile(Visitable *v) {
buf << buf <<
".globl _start\n" ".globl _start\n"
".globl exit\n" ".globl exit\n"
"_start:\n" "_start:\n"
" pushl %ebp\n" " pushl %ebp\n"
" movl %esp, %ebp\n" " movl %esp, %ebp\n"
...@@ -63,20 +65,15 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) { ...@@ -63,20 +65,15 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
RegisterAllocator regGen((quadEnv)); RegisterAllocator regGen((quadEnv));
regGen.allocate(); regGen.allocate();
} catch(const ParseError &e) { } catch(const ParseError &e) {
printFunction(quadEnv); printFunction(quadEnv, f);
throw ParseError(buf.str() + e.what()); throw ParseError(buf.str() + e.what());
} }
printFunction(quadEnv); printFunction(quadEnv, f);
swap(buf, asmGen); swap(buf, asmGen);
// for (auto &b : quadEnv.blocks) {
// for (auto &q : b->quads) {
// q->generateAsm(*this);
// }
// }
uint localsCount = temps.size() + localInfos.size(); uint localsCount = temps.size() + localInfos.size();
for (auto i : calleeSavedRegisters) for (auto i : Register::calleeSaved)
append("PUSH", Register(i)); append("PUSH", i);
buf << buf <<
"\tpush %ebp\n" "\tpush %ebp\n"
"\tmov %esp, %ebp\n"; "\tmov %esp, %ebp\n";
...@@ -85,11 +82,11 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) { ...@@ -85,11 +82,11 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
} }
buf << asmGen.str(); buf << asmGen.str();
buf << "\"" << exitLabel->label << "\":\n" << buf << "\"" << exitLabel->label << "\":\n" <<
"MOVL %ebp, %esp\n" "\tMOVL %ebp, %esp\n"
"POP %ebp\n"; "\tPOP %ebp\n";
for (auto i : calleeSavedRegisters) for (auto i = Register::calleeSaved.rbegin(); i != Register::calleeSaved.rend(); i++)
append("POP", Register(i)); append("POP", *i);
buf << "RET\n"; buf << "\tRET\n";
for (auto &t : temps) t->localOffset = 0; for (auto &t : temps) t->localOffset = 0;
for (auto &v : localInfos) v->localOffset = 0; for (auto &v : localInfos) v->localOffset = 0;
...@@ -97,33 +94,34 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) { ...@@ -97,33 +94,34 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
localInfos.clear(); localInfos.clear();
} }
void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) { void Compiler::printFunction(QuadrupleGenerator::Result quadEnv, const FunctionInfoPtr& f) {
int blkNo = 0; int blkNo = 0;
buf << COMMENT "\x1b[32;1mFunction " << mangleFunctionName(f) << "\x1b[0m" << endl;
for (const auto& b : quadEnv.blocks) { for (const auto& b : quadEnv.blocks) {
cout << "----------------------------------------------------------------------------\n"; buf << COMMENT "----------------------------------------------------------------------------\n";
cout << "blok " << blkNo << " " << b->getName() << endl; buf << COMMENT "blok " << blkNo << " " << b->getName() << endl;
/*cout << "in: "; /*buf << "in: ";
for (auto in : b->in) { for (auto in : b->in) {
cout << in->getName() << " "; buf << in->getName() << " ";
} }
cout << "\nouts: "; buf << "\nouts: ";
for (auto out : b->out) { for (auto buf : b->buf) {
cout << out->getName() << " "; buf << buf->getName() << " ";
} }
cout << "\n";*/ buf << "\n";*/
if (!b->flow.in.empty()) { if (!b->flow.in.empty()) {
cout << "in: "; buf << COMMENT "in: ";
for (const auto& v : b->flow.in) { for (const auto& v : b->flow.in) {
cout << v->name << ", "; buf << v->name << ", ";
} }
cout << "\n----------\n"; buf << "\n" COMMENT "----------\n";
} }
if (!b->flow.def.empty()) { if (!b->flow.def.empty()) {
cout << "def: "; buf << COMMENT "def: ";
for (const auto& v : b->flow.def) { for (const auto& v : b->flow.def) {
cout << v->name << ", "; buf << v->name << ", ";
} }
cout << "\n----------\n"; buf << "\n" COMMENT "----------\n";
} }
for (const auto& q : b->quads) { for (const auto& q : b->quads) {
auto ret = q->toString(); auto ret = q->toString();
...@@ -134,49 +132,52 @@ void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) { ...@@ -134,49 +132,52 @@ void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) {
if (c == '\t') len += 8 - (len % 8); if (c == '\t') len += 8 - (len % 8);
} }
for (; len < 70; len++) ret += ' '; for (; len < 70; len++) ret += ' ';
cout << ret << " alive: "; buf << COMMENT << ret << " alive: ";
for (auto var : q->aliveAfter) for (const auto &var : q->aliveAfter)
cout << var->name << " "; buf << var->name << " ";
cout << endl; buf << endl;
cout << "\x1b[37;1m";
stringstream asmStr; stringstream asmStr;
swap(asmStr, buf); swap(asmStr, buf);
q->generateAsm(*this); q->generateAsm(*this);
swap(asmStr, buf); swap(asmStr, buf);
buf << asmStr.str();
cout << asmStr.str(); if (!asmStr.str().empty()) {
cout << "\x1b[0m"; buf << COMMENT "\x1b[37;1m\n"
<< asmStr.str()
<< COMMENT "\x1b[0m\n";
}
} }
} }
if (!b->flow.use.empty()) { if (!b->flow.use.empty()) {
cout << "----------\nuse: "; buf << COMMENT "----------\n" COMMENT "use: ";
for (const auto &v : b->flow.use) { for (const auto &v : b->flow.use) {
cout << v->name << ", "; buf << v->name << ", ";
} }
cout << "\n"; buf << "\n";
} }
if (!b->flow.out.empty()) { if (!b->flow.out.empty()) {
cout << "----------\nout: "; buf << COMMENT "----------\n" COMMENT "out: ";
for (const auto &v : b->flow.out) { for (const auto &v : b->flow.out) {
cout << v->name << ", "; buf << v->name << ", ";
} }
cout << "\n"; buf << "\n";
} }
blkNo++; blkNo++;
} }
generateStandardReturn();
} }
const char* const Compiler::regs[6] = {"eax", "ebx", "ecx", "edx", "edi", "esi"}; const char* const Register::names[9] = {"eax", "ebx", "ecx", "edx", "edi", "esi", "ebp", "esp", "eip"};
const int Compiler::callerSavedRegisters[2] = {2, 3}; const vector<Register> Register::all = {0, 1, 2, 3, 4, 5, 6, 7, 8};
const int Compiler::calleeSavedRegisters[3] = {1, 4, 5}; const vector<Register> Register::callerSaved = {2, 3};
const vector<Register> Register::calleeSaved = {1, 4, 5};
const vector<Register> Register::assignable = {1,4,5,2,3}; // ecx and edx least used
string Compiler::getRef(VariablePtr &v) { string Compiler::getRef(const VariablePtr &v) {
if (v->registerColor == -1) { if (v->constExpr) {
if (v->constExpr) { return "$" + to_string(v->val);
return "$" + to_string(v->val); }
} if (v->registerColor == 0) {
if (!v->localOffset) { if (!v->localOffset) {
if (v->info) { if (v->info) {
if (!v->info->localOffset) { if (!v->info->localOffset) {
...@@ -218,7 +219,6 @@ void Compiler::generateQReturn(QReturn &q) { ...@@ -218,7 +219,6 @@ void Compiler::generateQReturn(QReturn &q) {
} }
void Compiler::generateQCall(QCall &q) { void Compiler::generateQCall(QCall &q) {
// return Quadruple::generateAsm();
if (q.self) { if (q.self) {
throw runtime_error("Class call unimplemented!"); throw runtime_error("Class call unimplemented!");
} }
...@@ -228,18 +228,19 @@ void Compiler::generateQCall(QCall &q) { ...@@ -228,18 +228,19 @@ void Compiler::generateQCall(QCall &q) {
} }
auto popRegs = registersToSave(q); auto popRegs = registersToSave(q);
for (auto r = popRegs.rbegin(); r != popRegs.rend(); r++) { for (auto r = popRegs.rbegin(); r != popRegs.rend(); r++) {
append("POPL", *r); if (*r != Register(q.loc))
append("POPL", *r);
} }
if (q.aliveAfter.count(q.loc)) { if (q.aliveAfter.count(q.loc)) {
moveTo(0, q.loc); append("MOVL", "%eax", getRef(q.loc));
} }
} }
void Compiler::generateQParam(QParam &q) { void Compiler::generateQParam(QParam &q) {
// return Quadruple::generateAsm(); // return Quadruple::generateAsm();
auto reg = Register(q.param);
if (q.num < 0) { if (q.num < 0) {
auto offset = 4 * q.num; auto reg = Register(q.param);
auto offset = 4 * (q.num - Register::calleeSaved.size() - 1); // push regs + ebp
if (reg == 0) { if (reg == 0) {
q.param->localOffset = offset; q.param->localOffset = offset;
} else { } else {
...@@ -249,21 +250,84 @@ void Compiler::generateQParam(QParam &q) { ...@@ -249,21 +250,84 @@ void Compiler::generateQParam(QParam &q) {
if (q.num == 1 && q.call) { if (q.num == 1 && q.call) {
// first argument, need to save registers // first argument, need to save registers
for (auto r : registersToSave(*q.call)) { for (auto r : registersToSave(*q.call)) {
append("PUSHL", r); if (r != Register(q.call->loc))
append("PUSHL", r);
} }
} }
append("PUSHL", getRef(q.param)); append("PUSHL", getRef(q.param));
} }
} }
void Compiler::generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap) {
vector<Register> regMap(Register::all.size(), 0);
// save to memory
for (const auto &phiVars : varMap) {
const auto &loc = phiVars.first, &val = phiVars.second;
auto ri = Register(loc), rj = Register(val);
if (loc->constExpr) continue;
if (ri == 0 || val->constExpr) { // we need to do do memory stores now
if (ri == 0 && rj == 0 && !val->constExpr) {
assert(loc->info == val->info);
} else {
append("MOVL", getRef(val), getRef(loc));
}
continue;
}
auto &r = regMap[(int)ri];
assert(r == 0 || r == rj);
r = rj;
}
// remap registers
for (uint x = 1; x < regMap.size(); x++) {
auto ri = Register(x);
auto &rj = regMap[x];
if (rj == 0 || ri == rj) continue;
int riUses = 0, rjUses = 0;
for (auto r : regMap) {
if (r == ri) riUses++;
if (r == rj) rjUses++;
}
if (riUses) {
append("XCHG", ri, rj);
for (auto &r : regMap) {
if (r == ri) r = rj;
else if (r == rj) r = ri;
}
} else {
append("MOVL", rj, ri);
rj = ri;
}
}
// load from memory
for (const auto &phiVars : varMap) {
const auto &i = phiVars.first, &j = phiVars.second;
auto ri = Register(i), rj = Register(j);
if (ri != 0 && rj == 0) {
append("MOVL", getRef(j), ri);
}
}
}
void Compiler::generateQJump(QJump &q) { void Compiler::generateQJump(QJump &q) {
// return Quadruple::generateAsm(); auto thisBlock = q.block;
auto tgBlock = q.target->block;
const auto &map = tgBlock->getPhiMapping(thisBlock);
generatePhiXCHG(map);
append("JMP", getBlockLabelText(q.target)); append("JMP", getBlockLabelText(q.target));
} }
void Compiler::generateQJumpCond(QJumpCond &q) { void Compiler::generateQJumpCond(QJumpCond &q) {
auto thisBlock = q.block;
auto tgBlock = q.target->block;
const auto &map = tgBlock->getPhiMapping(thisBlock);
for (const auto &phiVars : map) {
// if (Register(phiVars.first) != Register(phiVars.second)) {
throw runtime_error("Unimplemented phi CondJump register XCHG");
// }
}
auto op = q.op; auto op = q.op;
if (q.left) { if (q.left) { // 2 args
assert(!q.left->constExpr || !q.right->constExpr); assert(!q.left->constExpr || !q.right->constExpr);
auto regL = Register(q.left), regR = Register(q.right); auto regL = Register(q.left), regR = Register(q.right);
auto locL = getRef(q.left); auto locL = getRef(q.left);
...@@ -275,11 +339,11 @@ void Compiler::generateQJumpCond(QJumpCond &q) { ...@@ -275,11 +339,11 @@ void Compiler::generateQJumpCond(QJumpCond &q) {
// left is in register but right is not - swap operands // left is in register but right is not - swap operands
// as right needs to be a register // as right needs to be a register
swap(locL, locR); swap(locL, locR);
if (op.kind() == Op::CMP && op != Op::EQ && op != Op::NEQ) assert (op.kind() == Op::CMP);
op = op.neg(); op = op.rot(); // we swapped operands
} }
append("CMP", locL, locR); append("CMP", locL, locR);
} else { } else { // 1 arg
if (q.right->constExpr) { if (q.right->constExpr) {
if ((op == Op::Not) ^ q.right->val) { if ((op == Op::Not) ^ q.right->val) {
generateQJump(q); generateQJump(q);
...@@ -290,6 +354,8 @@ void Compiler::generateQJumpCond(QJumpCond &q) { ...@@ -290,6 +354,8 @@ void Compiler::generateQJumpCond(QJumpCond &q) {
append("CMP", tg, tg); append("CMP", tg, tg);
} }
if (op.kind() != Op::CMP && op.kind() != Op::UNARY) throw runtime_error("Unexpected operator in compare"); if (op.kind() != Op::CMP && op.kind() != Op::UNARY) throw runtime_error("Unexpected operator in compare");
if (op.kind() == Op::CMP)
op = op.rot(); // compare has different syntax in AT&T
string operand = getOpName(op); string operand = getOpName(op);
// getOpName returns SETZ, SETNE, SET*, replace it to JMP // getOpName returns SETZ, SETNE, SET*, replace it to JMP
operand.replace(0,3, "J"); operand.replace(0,3, "J");
...@@ -302,7 +368,7 @@ void Compiler::generateQJumpCond(QJumpCond &q) { ...@@ -302,7 +368,7 @@ void Compiler::generateQJumpCond(QJumpCond &q) {
} }
void Compiler::generateQAssign(QAssign &q) { void Compiler::generateQAssign(QAssign &q) {
if (!q.aliveAfter.count(q.loc)) return; if (!q.aliveAfter.count(q.loc) || q.loc->constExpr) return;
Register tg(q.loc); Register tg(q.loc);
if (q.args.size() == 1) { if (q.args.size() == 1) {
auto &arg = q.args[0]; auto &arg = q.args[0];
...@@ -338,14 +404,25 @@ void Compiler::generateQAssign(QAssign &q) { ...@@ -338,14 +404,25 @@ void Compiler::generateQAssign(QAssign &q) {
auto &i = q.args[0], &j = q.args[1]; auto &i = q.args[0], &j = q.args[1];
if (q.op == Op::Div || q.op == Op::Mod) { if (q.op == Op::Div || q.op == Op::Mod) {
auto edx = Register("edx"); auto edx = Register("edx");
bool edxAlive = false;
for (auto &alive : q.aliveAfter) auto alives = to_set(aliveAfter(q, Register::assignable));
if (Register(alive) == edx) {
edxAlive = true; bool edxAlive = alives.count(edx);
}
bool backupEdx = edx != tg && edx != Register(i) && (edx == Register(j) || edxAlive); bool backupEdx = edx != tg && edx != Register(i) && (edx == Register(j) || edxAlive);
if (backupEdx) append("MOVL", edx, "-4(%esp)"); if (backupEdx) append("MOVL", edx, "-4(%esp)");
auto jLoc = edx != Register(j) ? getRef(j) : "-4(%esp)"; string jLoc = Register(j) != edx ? getRef(j) : "-4(%esp)";
if (j->constExpr) {
auto free = to_set(Register::assignable) - alives;
if (!free.empty()) {
auto reg = *free.begin();
append("MOVL", jLoc, reg);
jLoc = reg;
} else {
append("MOVL", jLoc, "-8(%esp)");
jLoc = "-8(%esp)";
}
}
moveTo(i, 0); moveTo(i, 0);
append("CLTD"); // edx lost append("CLTD"); // edx lost
append("IDIVL", jLoc); append("IDIVL", jLoc);
...@@ -386,3 +463,14 @@ void Compiler::generateQAssign(QAssign &q) { ...@@ -386,3 +463,14 @@ void Compiler::generateQAssign(QAssign &q) {
void Compiler::generateQLabel(QLabel &q) { void Compiler::generateQLabel(QLabel &q) {
buf << "\"" << q.label << "\":" << endl; buf << "\"" << q.label << "\":" << endl;
} }
void Compiler::generateQPhi(QPhi &q) {
}
void Compiler::generateQBlockEnd(QBlockEnd &q) {
auto thisBlock = q.block;
auto tgBlock = q.next;
const auto &map = tgBlock->getPhiMapping(thisBlock);
generatePhiXCHG(map);
}
...@@ -14,6 +14,34 @@ ...@@ -14,6 +14,34 @@
#include "codeGen/QuadrupleGenerator.h" #include "codeGen/QuadrupleGenerator.h"
#include <unordered_set> #include <unordered_set>
class Register {
public:
Register(string n) {
for (auto &reg : names) {
if (n == reg) {
i = &reg - names;
return;
}
}
throw runtime_error("Invalid register name");
};
Register(int n) : i(n) { }
Register(const VariablePtr &v) : i(v->registerColor) { }
int i;
operator string() const { return string("%") + names[i]; }
explicit operator int() const { return i; }
bool operator==(const Register &other) const { return i == other.i; }
bool operator!=(const Register &other) const { return i != other.i; }
bool operator<(const Register &other) const { return i < other.i; }
// static const Register &eax, &ebx, &ecx, &edx, &edi, &esi, &ebp, &esp;
static const char* const names[9];
static const vector<Register> all;
static const vector<Register> callerSaved;
static const vector<Register> calleeSaved;
static const vector<Register> assignable;
};
using Op = Quadruple::Op; using Op = Quadruple::Op;
class Compiler { class Compiler {
public: public:
...@@ -38,6 +66,8 @@ public: ...@@ -38,6 +66,8 @@ public:
void generateQJump(QJump &q); void generateQJump(QJump &q);
void generateQAssign(QAssign &q); void generateQAssign(QAssign &q);
void generateQLabel(QLabel &q); void generateQLabel(QLabel &q);
void generateQPhi(QPhi &q);
void generateQBlockEnd(QBlockEnd &q);
static std::string mangleFunctionName(const FunctionInfoPtr& f) { static std::string mangleFunctionName(const FunctionInfoPtr& f) {
if (auto c = f->klass.lock()) { if (auto c = f->klass.lock()) {
...@@ -55,32 +85,10 @@ private: ...@@ -55,32 +85,10 @@ private:
unordered_set<VarInfoPtr> localInfos; unordered_set<VarInfoPtr> localInfos;
void compileFunction(const FunctionInfoPtr& f); void compileFunction(const FunctionInfoPtr& f);
void printFunction(QuadrupleGenerator::Result quadEnv); void printFunction(QuadrupleGenerator::Result quadEnv, const FunctionInfoPtr& f);
class Register {
public:
Register(string n) : name(n) {
for (auto reg : Compiler::regs) {
if (name == reg) {
return;
}
}
throw runtime_error("Invalid register name");
};
Register(int n) { name = Compiler::regs[n]; }
Register(const VariablePtr &v) { name = Compiler::regs[v->registerColor + 1]; }
string name;
operator string() { return "%" + name; }
bool operator==(const Register &other) const { return name == other.name; }
bool operator!=(const Register &other) const { return name != other.name; }
};
string getRef(VariablePtr &v); string getRef(const VariablePtr &v);
void generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap);
static const char* const regs[6];
static const int callerSavedRegisters[2];
static const int calleeSavedRegisters[3];
static string getOpName(Quadruple::Op op) { static string getOpName(Quadruple::Op op) {
switch(op.op) { switch(op.op) {
...@@ -89,8 +97,8 @@ private: ...@@ -89,8 +97,8 @@ private:
case Op::Mul: return "IMULL"; case Op::Mul: return "IMULL";
case Op::Div: case Op::Div:
case Op::Mod: throw runtime_error("Impossible to handle division with default"); case Op::Mod: throw runtime_error("Impossible to handle division with default");
case Op::Not: return "SETZ"; case Op::Not: return "SETNZ";
case Op::Copy: return "SETNZ"; case Op::Copy: return "SETZ";
case Op::LT: return "SETL"; case Op::LT: return "SETL";
case Op::LE: return "SETLE"; case Op::LE: return "SETLE";
case Op::EQ: return "SETZ"; case Op::EQ: return "SETZ";
...@@ -164,27 +172,30 @@ private: ...@@ -164,27 +172,30 @@ private:
append("JMP", "\"" + exitLabel->label + "\""); append("JMP", "\"" + exitLabel->label + "\"");
} }
vector<Register> registersToSave(QCall &q) { static vector<Register> aliveAfter(Quadruple &q, const vector<Register> &vec) {
const int noRegs = sizeof(callerSavedRegisters) / sizeof(*callerSavedRegisters); const uint noRegs = vec.size();
bool saved[noRegs]; bool used[noRegs];
int notSaved = noRegs; int notUsed = noRegs;
for (auto &i : saved) i = false; for (auto &i : used) i = false;
for (auto &live : q.aliveAfter) { for (auto &live : q.aliveAfter) {
for (int i = 0; i < noRegs; i++) { for (uint i = 0; i < noRegs; i++) {
int r = callerSavedRegisters[i]; const Register &r = vec[i];
if (!saved[i] && Register(live) == Register(r)) { if (!used[i] && Register(live) == r) {
saved[i] = true; used[i] = true;
--notSaved; --notUsed;
} }
} }
if (notSaved == 0) break; if (notUsed == 0) break;
} }
vector<Register> ret; vector<Register> ret;
for (int i = 0; i < noRegs; i++) { for (uint i = 0; i < noRegs; i++) {
if (saved[i]) ret.emplace_back(callerSavedRegisters[i]); if (used[i]) ret.emplace_back(vec[i]);
} }
return ret; return ret;
} }
static vector<Register> registersToSave(QCall &q) {
return aliveAfter(q, Register::callerSaved);
}
}; };
#endif #endif
...@@ -81,8 +81,8 @@ int main(int argc, char ** argv) ...@@ -81,8 +81,8 @@ int main(int argc, char ** argv)
typeCheck.check(parse_tree); typeCheck.check(parse_tree);
std::string out = compiler.compile(parse_tree); std::string out = compiler.compile(parse_tree);
printf("%s\n", out.data());
if (!filename) { if (!filename) {
printf("%s\n", out.data());
return 0; return 0;
} }
......
#include "BasicBlock.h" #include "BasicBlock.h"
#include "Quadruple.h" #include "Quadruple.h"
#include "../Compiler.h"
void BasicBlock::finishQuads() { void BasicBlock::finishQuads() {
if (!afterInit.empty()) { if (!afterInit.empty()) {
...@@ -10,6 +11,7 @@ void BasicBlock::finishQuads() { ...@@ -10,6 +11,7 @@ void BasicBlock::finishQuads() {
} }
for (const auto& q : afterInit) { for (const auto& q : afterInit) {
assert(q->block.get() == this);
quads.push_back(q); quads.push_back(q);
} }
afterInit.clear(); afterInit.clear();
...@@ -17,7 +19,16 @@ void BasicBlock::finishQuads() { ...@@ -17,7 +19,16 @@ void BasicBlock::finishQuads() {
auto self = this->shared_from_this(); auto self = this->shared_from_this();
for (const auto& q : quads) { for (const auto& q : quads) {
q->block = self;
q->useVariables(); q->useVariables();
} }
} }
const map<VariablePtr, VariablePtr>& BasicBlock::getPhiMapping(const BasicBlockPtr &b) const {
assert(phi);
for (uint i = 0; i < in.size(); i++) {
if (in[i] == b) {
return phi->phi[i];
}
}
throw runtime_error("BasicBlock::getPhiMapping: In block not found");
}
\ No newline at end of file
...@@ -13,7 +13,7 @@ using namespace std; ...@@ -13,7 +13,7 @@ using namespace std;
class BasicBlock : public std::enable_shared_from_this<BasicBlock> { class BasicBlock : public std::enable_shared_from_this<BasicBlock> {
public: public:
BasicBlock() { BasicBlock() : std::enable_shared_from_this<BasicBlock>() {
phi = make_shared<QPhi>(); phi = make_shared<QPhi>();
flow.b = this; flow.b = this;
quads.emplace_back(phi); quads.emplace_back(phi);
...@@ -23,6 +23,7 @@ public: ...@@ -23,6 +23,7 @@ public:
vector<BasicBlockPtr> in, out; vector<BasicBlockPtr> in, out;
shared_ptr<QPhi> phi; shared_ptr<QPhi> phi;
void append(const BasicBlockPtr& after) { void append(const BasicBlockPtr& after) {
assert(after);
out.push_back(after); out.push_back(after);
after->in.push_back(shared_from_this()); after->in.push_back(shared_from_this());
after->phi->phi.emplace_back(); after->phi->phi.emplace_back();
...@@ -78,6 +79,8 @@ public: ...@@ -78,6 +79,8 @@ public:
} }
}; };
FlowAnalysisData flow; FlowAnalysisData flow;
const map<VariablePtr, VariablePtr>& getPhiMapping(const BasicBlockPtr &b) const;
}; };
......
...@@ -28,12 +28,12 @@ public: ...@@ -28,12 +28,12 @@ public:
template<typename T> template<typename T>
class Graph { class Graph {
public: public:
struct Result { void add(const T &i) {
int color; if (evaluated) throw runtime_error("Add to evaluated graph");
bool spilled; vertices[i];
}; }
void add(T &i, T &j) { void add(const T &i, const T &j) {
if (evaluated) throw runtime_error("Add to evaluated graph"); if (evaluated) throw runtime_error("Add to evaluated graph");
vertices[i]; vertices[i];
vertices[j]; vertices[j];
...@@ -41,7 +41,7 @@ public: ...@@ -41,7 +41,7 @@ public:
edgesSet.emplace(j, i); edgesSet.emplace(j, i);
} }
void addAssign(T &i, T &j) { void addAssign(const T &i, const T &j) {
if (evaluated) throw runtime_error("Add to evaluated graph"); if (evaluated) throw runtime_error("Add to evaluated graph");
assignsSet.emplace(i, j); assignsSet.emplace(i, j);
vertices[i]; vertices[i];
...@@ -70,13 +70,6 @@ public: ...@@ -70,13 +70,6 @@ public:
return color[c]; return color[c];
} }
Result get(T x) {
if (!evaluated) throw runtime_error("Query of unevaluated graph");
if (!vertices.count(x)) throw runtime_error("Query of non-graph vertex");
int c = vertices[x];
return Result(color[c], spilled(c));
}
void eval(int colors) { void eval(int colors) {
if (evaluated) throw runtime_error("Try of re-evaluating graph"); if (evaluated) throw runtime_error("Try of re-evaluating graph");
evaluated = true; evaluated = true;
......
...@@ -40,3 +40,11 @@ void QAssign::generateAsm(Compiler &c) { ...@@ -40,3 +40,11 @@ void QAssign::generateAsm(Compiler &c) {
void QLabel::generateAsm(Compiler &c) { void QLabel::generateAsm(Compiler &c) {
c.generateQLabel(*this); c.generateQLabel(*this);
} }
void QPhi::generateAsm(Compiler &c) {
c.generateQPhi(*this);
}
void QBlockEnd::generateAsm(Compiler &c) {
c.generateQBlockEnd(*this);
}
...@@ -10,20 +10,20 @@ using namespace std; ...@@ -10,20 +10,20 @@ using namespace std;
class Compiler; class Compiler;
static const std::string opNames[] = { "_U", "!", "", "-", "_UE", static const std::string opNames[] = { "_U", "!", "", "-", "_UE",
"_B", "+", "-", "*", "/", "%", "&", "|", "^", "_BE", "_B", "+", "-", "*", "/", "%", "&", "|", "++", "_BE",
"_C", "<", ">=", "<=", ">", "==", "!=", "_CE"}; "_C", "<", ">=", "<=", ">", "_CR", "_CQ", "==", "!=", "_CE"};
class Quadruple : public enable_shared_from_this<Quadruple> { class Quadruple : public enable_shared_from_this<Quadruple> {
public: public:
class Op { class Op {
public: public:
enum OpType { enum OpType {
UNARY, UNARY, // 0
Not, Copy, Neg, UNARY_END, Not, Copy, Neg, UNARY_END, // 4
BINARY, BINARY, // 5
Plus, Minus, Mul, Div, Mod, And, Or, Xor, BINARY_END, Plus, Minus, Mul, Div, Mod, And, Or, Concat, BINARY_END, // 14
CMP, CMP, // 15
LT, GE, LE, GT, EQ, NEQ, CMP_END LT, GE, LE, GT, CMP_ROT_END, CMP_EQ, EQ, NEQ, CMP_END
}; };
OpType op; OpType op;
...@@ -38,6 +38,15 @@ public: ...@@ -38,6 +38,15 @@ public:
throw runtime_error("Invalid argument to Op::neg()"); throw runtime_error("Invalid argument to Op::neg()");
}; };
Op rot() const {
if (kind() != CMP) throw runtime_error("Invalid argument to Op::rot()");
if (op < CMP_ROT_END) {
// LT => GT, GE => LE, LE => GE, GT => LT
return OpType((int)op ^ 3);
}
return op;
}
static OpType kind(OpType op) { static OpType kind(OpType op) {
if (op <= UNARY_END) return UNARY; if (op <= UNARY_END) return UNARY;
if (op <= BINARY_END) return BINARY; if (op <= BINARY_END) return BINARY;
...@@ -65,7 +74,7 @@ public: ...@@ -65,7 +74,7 @@ public:
virtual void useVariables() { virtual void useVariables() {
auto self = shared_from_this(); auto self = shared_from_this();
for (const auto& v : vars()) { for (const auto& v : vars()) {
if (v) v->uses.emplace_back(self); if (v && !v->constExpr) v->uses.emplace_back(self);
} }
for (const auto& v : definitions()) { for (const auto& v : definitions()) {
if (v) v->writes.emplace_back(self); if (v) v->writes.emplace_back(self);
...@@ -84,7 +93,7 @@ public: ...@@ -84,7 +93,7 @@ public:
std::string toString() const override { return Quadruple::toString() + "\t" + (loc ? (loc->name + " := ") : ""); } std::string toString() const override { return Quadruple::toString() + "\t" + (loc ? (loc->name + " := ") : ""); }
vector<VariablePtr> definitions() const override { vector<VariablePtr> definitions() const override {
auto ret = Quadruple::definitions(); auto ret = Quadruple::definitions();
if (loc && !loc->constExpr) ret.emplace_back(loc); if (loc) ret.emplace_back(loc);
return ret; return ret;
}; };
}; };
...@@ -216,6 +225,7 @@ public: ...@@ -216,6 +225,7 @@ public:
if (self) ret.emplace_back(self); if (self) ret.emplace_back(self);
return ret; return ret;
} }
void generateAsm(Compiler &c) override; void generateAsm(Compiler &c) override;
}; };
...@@ -366,7 +376,19 @@ public: ...@@ -366,7 +376,19 @@ public:
} }
return ret; return ret;
} }
void generateAsm(Compiler &c) override;
};
class QBlockEnd : public Quadruple {
public:
QBlockEnd(BasicBlockPtr b) : next(std::move(b)) {};
QBlockEnd() : next(nullptr) {};
BasicBlockPtr next;
std::string toString() const override {
return Quadruple::toString() + "phi_xchg";
}
void generateAsm(Compiler &c) override;
}; };
......
...@@ -72,7 +72,7 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f ...@@ -72,7 +72,7 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
return ret; return ret;
} }
BasicBlockPtr QuadrupleGenerator::flushBasicBlock() { BasicBlockPtr QuadrupleGenerator::flushBasicBlock(bool append) {
auto ret = block; auto ret = block;
if (block) { if (block) {
blocks.emplace_back(block); blocks.emplace_back(block);
...@@ -81,6 +81,14 @@ BasicBlockPtr QuadrupleGenerator::flushBasicBlock() { ...@@ -81,6 +81,14 @@ BasicBlockPtr QuadrupleGenerator::flushBasicBlock() {
newBlock(); newBlock();
if (append) {
auto be = make_shared<QBlockEnd>(block);
be->lineno = lineno;
be->block = ret;
ret->quads.emplace_back(be);
ret->append(block);
}
return ret; return ret;
} }
...@@ -197,8 +205,9 @@ void QuadrupleGenerator::visitERel(ERel *p) { ...@@ -197,8 +205,9 @@ void QuadrupleGenerator::visitERel(ERel *p) {
else if (op == Op::GT) else if (op == Op::GT)
lastVar->val = l->val > r->val; lastVar->val = l->val > r->val;
addQuad<QAssign>(lastVar, l, op, r); addQuad<QAssign>(lastVar, l, op, r);
} else {
addLastVarCondJump(l, op, r);
} }
addLastVarCondJump(l, op, r);
} }
void QuadrupleGenerator::visitEAnd(EAnd *p) { void QuadrupleGenerator::visitEAnd(EAnd *p) {
...@@ -370,10 +379,11 @@ void QuadrupleGenerator::visitEApp(EApp *p) { ...@@ -370,10 +379,11 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
throw ParseError("Unimplemented EApp instantiation (neither EClsMmbr nor EVar", p); throw ParseError("Unimplemented EApp instantiation (neither EClsMmbr nor EVar", p);
} }
auto call = make_shared<QCall>(lastVar, info, p->listexpr_->size(), self); auto ret = alloc();
auto call = make_shared<QCall>(ret, info, p->listexpr_->size(), self);
int i = 0; int i = 0;
for (auto param : *p->listexpr_) { for (auto param = p->listexpr_->rbegin(); param != p->listexpr_->rend(); param++) {
auto var = evalExpr(param); auto var = evalExpr(*param);
addQuad<QParam>(var, ++i, call); addQuad<QParam>(var, ++i, call);
} }
...@@ -381,7 +391,7 @@ void QuadrupleGenerator::visitEApp(EApp *p) { ...@@ -381,7 +391,7 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
addQuad<QParam>(self, 0, call); addQuad<QParam>(self, 0, call);
} }
lastVar = alloc(); lastVar = ret;
addQuad(call); addQuad(call);
Bool b; Bool b;
...@@ -420,13 +430,19 @@ void QuadrupleGenerator::visitInit(Init *p) { ...@@ -420,13 +430,19 @@ void QuadrupleGenerator::visitInit(Init *p) {
auto info = p->pident_->var.lock(); auto info = p->pident_->var.lock();
assert(info); assert(info);
auto var = evalExpr(p->expr_); auto var = evalExpr(p->expr_);
addQuad<QAssign>(alloc(info), Op::Copy, var); auto loc = alloc(info);
addQuad<QAssign>(loc, Op::Copy, var);
if ((loc->constExpr = var->constExpr))
loc->val = var->val;
} }
void QuadrupleGenerator::visitNoInit(Init *p) { void QuadrupleGenerator::visitNoInit(Init *p) {
auto info = p->pident_->var.lock(); auto info = p->pident_->var.lock();
assert(info); assert(info);
addQuad<QAssign>(alloc(info), Op::Copy, alloc(0)); auto loc = alloc(info);
addQuad<QAssign>(loc, Op::Copy, alloc(0));
loc->constExpr = true;
loc->val = 0;
} }
void QuadrupleGenerator::assign(Expr* lval, VariablePtr val) { void QuadrupleGenerator::assign(Expr* lval, VariablePtr val) {
...@@ -497,7 +513,16 @@ void QuadrupleGenerator::compileCond(Expr *expr_, Stmt *stmt_1, Stmt *stmt_2) { ...@@ -497,7 +513,16 @@ void QuadrupleGenerator::compileCond(Expr *expr_, Stmt *stmt_1, Stmt *stmt_2) {
auto after = make_shared<QLabel>("end_else"); auto after = make_shared<QLabel>("end_else");
auto ifBranch = make_shared<QLabel>("if_true"); auto ifBranch = make_shared<QLabel>("if_true");
evalJump(expr_, ifBranch, elseBranch); auto condVar = evalJump(expr_, ifBranch, elseBranch);
if (condVar->constExpr) {
assert(!dynamic_pointer_cast<QJump>(lastQuad));
if (condVar->val) {
stmt_1->accept(this);
} else {
stmt_2->accept(this);
}
return;
}
auto beforeBlock = flushBasicBlock(); // possible jump -> else auto beforeBlock = flushBasicBlock(); // possible jump -> else
auto envIf = captureEnv(), envElse = envIf; auto envIf = captureEnv(), envElse = envIf;
...@@ -515,14 +540,13 @@ void QuadrupleGenerator::compileCond(Expr *expr_, Stmt *stmt_1, Stmt *stmt_2) { ...@@ -515,14 +540,13 @@ void QuadrupleGenerator::compileCond(Expr *expr_, Stmt *stmt_1, Stmt *stmt_2) {
stmt_2->accept(this); stmt_2->accept(this);
} }
auto stmtElseLastBlock = flushBasicBlock(); // jump <- cond auto stmtElseLastBlock = flushBasicBlock(true); // jump <- cond
envElse.capture(); envElse.capture();
addQuad(after); addQuad(after);
beforeBlock->append(stmtIfFirstBlock); beforeBlock->append(stmtIfFirstBlock);
beforeBlock->append(stmtElseFirstBlock); beforeBlock->append(stmtElseFirstBlock);
stmtIfLastBlock->append(block); stmtIfLastBlock->append(block);
stmtElseLastBlock->append(block);
merge2Envs(&envIf, stmtIfLastBlock, &envElse, stmtElseLastBlock); merge2Envs(&envIf, stmtIfLastBlock, &envElse, stmtElseLastBlock);
} }
...@@ -569,8 +593,8 @@ void QuadrupleGenerator::visitWhile(While *expr) { ...@@ -569,8 +593,8 @@ void QuadrupleGenerator::visitWhile(While *expr) {
expr->stmt_->accept(this); expr->stmt_->accept(this);
auto loopLastBlock = flushBasicBlock(); // jump <- cond auto loopLastBlock = flushBasicBlock(true); // jump <- cond
auto condBlock = block; auto condFirstBlock = block;
addQuad(cond); addQuad(cond);
// env2 contains changed hooks // env2 contains changed hooks
...@@ -578,9 +602,7 @@ void QuadrupleGenerator::visitWhile(While *expr) { ...@@ -578,9 +602,7 @@ void QuadrupleGenerator::visitWhile(While *expr) {
// restore env1 pre-hook variables // restore env1 pre-hook variables
env1.revert(); env1.revert();
beforeBlock->append(condBlock); beforeBlock->append(condFirstBlock);
condBlock->append(loopFirstBlock);
loopLastBlock->append(condBlock);
for (const auto& p : env2.changes) { for (const auto& p : env2.changes) {
auto info = p.first; auto info = p.first;
...@@ -591,22 +613,20 @@ void QuadrupleGenerator::visitWhile(While *expr) { ...@@ -591,22 +613,20 @@ void QuadrupleGenerator::visitWhile(While *expr) {
// save hooks if used // save hooks if used
info->loc = hooked; info->loc = hooked;
// transition from pre-hook to hooked var [before -> cond] // transition from pre-hook to hooked var [before -> cond]
condBlock->addPhi(beforeBlock, hooked, orig); condFirstBlock->addPhi(beforeBlock, hooked, orig);
// transition from hooked var // transition from hooked var
condBlock->addPhi(loopLastBlock, hooked, looped); condFirstBlock->addPhi(loopLastBlock, hooked, looped);
// loopLastBlock doesn't need phi, it has only one incoming block // loopLastBlock doesn't need phi, it has only one incoming block
} }
// expr uses pre-hook variables iff unused in loop // expr uses pre-hook variables iff unused in loop
auto var = evalExpr(expr->expr_); auto var = evalJump(expr->expr_, loop, nullptr);
auto condLastBlock = flushBasicBlock(true); // jump -> loop
addQuad<QJumpCond>(loop, Op::Copy, var); condLastBlock->append(loopFirstBlock);
flushBasicBlock(); // jump -> loop
// next block is ready to use updated variables // next block is ready to use updated variables
condBlock->append(block);
} }
void QuadrupleGenerator::visitSExp(SExp *p) { void QuadrupleGenerator::visitSExp(SExp *p) {
......
...@@ -85,8 +85,8 @@ private: ...@@ -85,8 +85,8 @@ private:
return v; return v;
} }
template<typename T, typename... Args> QuadruplePtr addQuad(Args... args) { template<typename T, typename... Args> shared_ptr<T> addQuad(Args... args) {
return addQuad(make_shared<T>(args...)); return static_pointer_cast<T>(addQuad(make_shared<T>(args...)));
} }
QuadruplePtr addQuad(QuadruplePtr quad) { QuadruplePtr addQuad(QuadruplePtr quad) {
...@@ -115,17 +115,20 @@ private: ...@@ -115,17 +115,20 @@ private:
QuadruplePtr lastQuad; QuadruplePtr lastQuad;
BasicBlockPtr newBlock() { BasicBlockPtr newBlock() {
return block = make_shared<BasicBlock>(); block = make_shared<BasicBlock>();
block->phi->block = block;
return block;
} }
void flushLastQuad() { void flushLastQuad() {
if (lastQuad) { if (lastQuad) {
block->quads.emplace_back(lastQuad); block->quads.emplace_back(lastQuad);
lastQuad->block = block;
lastQuad = nullptr; lastQuad = nullptr;
} }
} }
BasicBlockPtr flushBasicBlock(); BasicBlockPtr flushBasicBlock(bool append = false);
void visitPlus(Plus *p) override { op = Quadruple::Op::Plus; } void visitPlus(Plus *p) override { op = Quadruple::Op::Plus; }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "BasicBlock.h" #include "BasicBlock.h"
#include "setOverloads.h" #include "setOverloads.h"
#include <fstream> #include <fstream>
#include "../Compiler.h"
void RegisterAllocator::analyseLive() { void RegisterAllocator::analyseLive() {
for (const auto& v : vars) { for (const auto& v : vars) {
...@@ -9,6 +10,7 @@ void RegisterAllocator::analyseLive() { ...@@ -9,6 +10,7 @@ void RegisterAllocator::analyseLive() {
for (const auto& q : v->writes) { for (const auto& q : v->writes) {
q->block->flow.addDef(v); q->block->flow.addDef(v);
} }
if (v->constExpr) continue;
for (const auto& q : v->uses) { for (const auto& q : v->uses) {
q->block->flow.addUse(v); q->block->flow.addUse(v);
} }
...@@ -64,65 +66,57 @@ void printGraph(const Graph<std::string> &graph, const std::string& filename) { ...@@ -64,65 +66,57 @@ void printGraph(const Graph<std::string> &graph, const std::string& filename) {
} }
void RegisterAllocator::buildGraph() { void RegisterAllocator::buildGraph() {
bool anyAlive = false;
for (const auto& b : blocks) { for (const auto& b : blocks) {
set<VariablePtr> alive = b->flow.in; set<VariablePtr> alive = b->flow.in;
for (const auto& q : b->quads) { for (const auto& q : b->quads) {
if (auto assign = dynamic_pointer_cast<QAssign>(q)) {
if (assign->op == Quadruple::Op::Copy && !assign->args[0]->constExpr) {
graph.addAssign(assign->loc, assign->args[0]);
g2.addAssign(assign->loc->name, assign->args[0]->name);
}
}
alive += to_set(q->definitions()); alive += to_set(q->definitions());
vector<VariablePtr> dead; vector<VariablePtr> dead;
for (const auto& var : alive) { for (const auto& var : alive) {
// this quad is the last quad that uses var // this quad is the last quad that uses var
if ((var->uses.empty() || var->uses.back() == q) && !b->flow.out.contains(var)) { auto noMoreUses = var->uses.empty() || var->uses.back() == q;
if ((noMoreUses && !b->flow.out.count(var))) {
dead.emplace_back(var); dead.emplace_back(var);
} }
} }
alive -= to_set(dead); alive -= to_set(dead);
q->aliveAfter = alive; q->aliveAfter = alive;
anyAlive |= alive.size() >= 1; for (auto i = alive.begin(); i != alive.end(); i++) {
for (auto i : alive) { graph.add(*i);
for (auto j : alive) { auto j = i;
if (i != j) { for (++j; j != alive.end(); ++j) {
graph.add(i, j); graph.add(*i, *j);
g2.add(i->name, j->name); }
}
if (auto assign = dynamic_pointer_cast<QAssign>(q)) {
if (assign->op == Quadruple::Op::Copy && !assign->loc->constExpr && alive.count(assign->loc)) {
graph.addAssign(assign->loc, assign->args[0]);
}
} else if (auto phi = dynamic_pointer_cast<QPhi>(q)) {
for (const auto &phiBlock : phi->phi) {
for (const auto &phiVars : phiBlock) {
if (alive.count(phiVars.first)) {
graph.addAssign(phiVars.first, phiVars.second);
}
} }
} }
} }
} }
} }
if (!anyAlive) return; graph.eval(Register::assignable.size());
graph.eval(5); int spills = 0;
g2.eval(5);
int gNumSpill = 0, g2NumSpill = 0;
for (auto &v : graph.getAllocation()) { for (auto &v : graph.getAllocation()) {
v.first->registerColor = v.second;
if (v.second == -1) { if (v.second == -1) {
gNumSpill++; v.first->registerColor = 0;
spills++;
} else { } else {
v.first->name += "-r" + to_string(v.second + 2); auto regNo = (int)Register::assignable[v.second];
v.first->registerColor = regNo;
v.first->name += "-r" + to_string(regNo + 1);
} }
} }
for (auto &v : g2.getAllocation()) { if (!graph.isChordal()) {
if (v.second == -1) // printGraph(graph, "./mygraph");
g2NumSpill++; throw ParseError("allocation: graph not chordal!");
}
cout << "allocation: VPtr eval spills: " << gNumSpill << " vs strings spills: " << g2NumSpill << endl;
if (!g2.isChordal()) {
printGraph(graph, "./mygraph");
printGraph(g2, "./myg2");
if (graph.isChordal()) {
throw ParseError("allocation: g2 not chordal, tho g1 is chordal!");
}
throw ParseError("allocation: none graph chordal!");
} else {
if (!graph.isChordal()) {
throw ParseError("allocation: g1 not chordal, tho g2 is chordal!");
}
} }
} }
......
...@@ -7,12 +7,6 @@ ...@@ -7,12 +7,6 @@
#include "QuadrupleGenerator.h" #include "QuadrupleGenerator.h"
#include "Graph.h" #include "Graph.h"
class Register : public std::enable_shared_from_this<Register> {
bool available;
set<VariablePtr> contains;
std::string name;
};
class RegisterAllocator { class RegisterAllocator {
public: public:
RegisterAllocator(const QuadrupleGenerator::Result &r) : blocks(r.blocks), vars(r.vars) {} RegisterAllocator(const QuadrupleGenerator::Result &r) : blocks(r.blocks), vars(r.vars) {}
...@@ -31,7 +25,6 @@ public: ...@@ -31,7 +25,6 @@ public:
void buildGraph(); void buildGraph();
private: private:
Graph<VariablePtr> graph; Graph<VariablePtr> graph;
Graph<std::string> g2;
void analyseLive(); void analyseLive();
vector<BasicBlockPtr> blocks; vector<BasicBlockPtr> blocks;
vector<VariablePtr> vars; vector<VariablePtr> vars;
......
...@@ -18,7 +18,7 @@ public: ...@@ -18,7 +18,7 @@ public:
bool constExpr{false}; bool constExpr{false};
int val{0}; int val{0};
std::string name; std::string name;
int registerColor = -1; int registerColor = 0;
vector<QuadruplePtr> uses; vector<QuadruplePtr> uses;
vector<QuadruplePtr> writes; vector<QuadruplePtr> writes;
......
class A {
int x;
}
int main() {
A a = new A;
A b = a;
a.x++;
a.x = a.x+1;
a.x = 123;
if (a.x == 123 || 123*456 < -1) {
b.x = 456;
} else {
a.x = 123;
b = a;
}
int[] arr = new int[10];
for (int i : arr) {
i = 10;
}
return a.x;
}
int write_to_local() {
int a;
a = 123;
return a;
}
class A {
int x;
}
int main() {
A a = new A;
A b = a;
a.x++;
a.x = a.x+1;
a.x = 123;
if (a.x == 123 || 123*456 < -1) {
b.x = 456;
} else {
a.x = 123;
b = a;
}
int[] arr = new int[10];
int i = 0;
while (i < 10) {
i++;
i = 10;
}
if (true) {
b.x = 456;
a = b;
}
return a.x;
}
int write_to_local() {
int a;
a = 123;
return a;
}
int t() {
if (true) {
return 0;
}
}
int main() {
int a = 2;
while (a < 10) {
a = a + 1;
a = a + 2;
}
return 0;
}
int test(int a, int b, int c, int d, int e, int f, int g, int h) {
return a+b+c+d+e+f+g+h;
}
int main() {
return test(1,2,3,4,5,6,7,8);
}
\ No newline at end of file
int main() {
int a = 2;
a = 3;
while (a < 10) {
if (false) {
a = a + 1;
} else {
if (true) {
a = 100;
}
}
}
return 0;
}
int main() {
int a = 1;
int b = 2;
int c = 3;
while (a < 10) {
if (true) {
a = 10;
} else {
while (b < 2) {
if (c == 3) {
c = 4;
} else {
c = 23;
}
a = a + 1;
}
}
}
return 0;
}
int test(int a, int b, int c) {
{
int e, a = 1, b = 2, c = 3, d = 4, f = 5, g = 6;
if (a + b == 3 && e+f == f) {
printInt(a+b);
printInt(c-d);
printInt(e/f);
printInt(g%a);
} else if (!(b==c) || false) {
printInt(2);
}
}
return a+b+c;
}
int main() {
int e, a = 1, b = 2, c = 3, d = 4, f = 5, g = 6;
if (a + b == 3 && e+f == f) {
printInt(a+b);
printInt(c-d);
printInt(e/f);
printInt(g%a);
} else if (!(b==c) || false) {
printInt(2);
}
test(d,f,g);
return 0;
}
int z() {
return 1;
}
int a() {
return z();
}
int main() {
{
int e, a = 1, b = 2, c = 3, d = 4, f = 5, g = 6;
while (e < 10) {
a++;
b++;
c++;
d++;
e++;
f++;
g++;
}
printInt(a);
printInt(b);
printInt(c);
printInt(d);
printInt(e);
printInt(f);
printInt(g);
}
printInt(ifac2f(1, 10));
return a();
}
int ifac2f(int l, int h) {
if (l == h)
return l;
if (l > h)
return 1;
int m;
m = (l + h) / 2;
return ifac2f(l,m) * ifac2f(m+1,h);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment