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