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;
......
This diff is collapsed.
...@@ -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