Commit 9234e433 authored by zygzagZ's avatar zygzagZ

WIP basic block graph (CFG)

parent 9b245472
......@@ -54,6 +54,7 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
buf << "\"" << name << "\":\n";
scope->currentFunction = f;
block = make_shared<BasicBlock>();
f->block->accept(this);
int id = 1;
......@@ -69,17 +70,25 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
id++;
}
flushBasicBlock();
block = nullptr;
int label = 1;
for (auto q : quads) {
if (auto l = dynamic_pointer_cast<QLabel>(q)) {
if (!l->label.empty())
l->label = to_string(label++) + "_" + l->label;
else
l->label = to_string(label++);
for (auto b : blocks) {
for (auto q : b->quads) {
if (auto l = dynamic_pointer_cast<QLabel>(q)) {
if (!l->label.empty())
l->label = to_string(label++) + "_" + l->label;
else
l->label = to_string(label++);
}
}
}
for (auto q : quads) {
buf << q->toString() << endl;
for (auto b : blocks) {
for (auto q : b->quads) {
buf << q->toString() << endl;
}
}
for (auto v : vars) {
......@@ -87,17 +96,74 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
v->info->loc = nullptr;
}
quads.clear();
scope->currentFunction = nullptr;
}
void Compiler::endBasicBlock() {
for (auto v : vars) {
/*
- kiedy przechodzę między blokami:
- pierwsze wejście w while/fora: ustawienie używanych wartości w pętli w zależności od ostatnich wartości przed pętlą
- dump przed wejściem w stmt fora, dump po sparsowaniu fora
- różnice ustawić w bloku przed i tak samo za nim
- if: przed ifem dump, za ifem dorobić else i ustawić diff
- ifelse: przed ifem dump, w środku dump, po elsie dump
- wszystkie poza zmienionymi w bloku ustawiamy na koniec bloku
wskazówki do implementacji:
- w momencie przypisywania do zmiennej lokalnej chcemy powiadomić najświeższy detektor zmian lokalnych
- po zakończeniu bloku detektor zmian odpowiednio poprzypisuje w pożądanych miejcach odpowiednie definicje
- po zakończeniu bloku detektor powiadomi kolejny z rzędu detektor o najnowszych instancjach zmienionych zmiennych
- detektor powinien działać ponad blokami prostymi
funkcje detektora:
- dodanie zmiennej VarInfoPtr do zbioru, przyporządkowanie jej najnowszej definicji (i zapamiętanie oryginalnej)
- umiejętność porównania dwóch zbiorów poprzez iterację
- każdy element który występuje tylko w jednym
- para jeśli el. występuje w obu zbiorach
implementacja detektora:
- map<VarInfoPtr, pair<orig, new>>
dalej: << i >> dla BB
porobić graf BB
złapać blocki i podumpować envy dookoła flow
dopisać sumę dumpów
*/
BasicBlockPtr Compiler::flushBasicBlock() {
for (const auto& v : vars) {
if (v->info) v->info->loc = nullptr;
}
auto ret = block;
if (block) {
blocks.emplace_back(block);
flushLastQuad();
}
block = make_shared<BasicBlock>();
return ret;
}
VariableLayout Compiler::captureEnv() {
VariableLayout ret;
BindingPtr b = scope->currentBinding;
while (b) {
for (const auto& info : b->variables) {
if (info->isInstanceVariable()) continue;
if (info->loc) {
ret.add(info);
}
}
b = b->getParent();
}
return ret;
}
/// expressions
void Compiler::visitEVar(EVar *p) {
......@@ -180,7 +246,7 @@ void Compiler::visitEAnd(EAnd *p) {
addQuad<QAssign>(lastVar, Op::Copy, r);
addQuad<QJump>(labelAfter);
addQuad(labelLeft);
addQuad<QAssign>(lastVar, Op::Copy, l);
addQuad<QAssign>(lastVar, Op::Copy, alloc(0));
addQuad(labelAfter);
}
......@@ -197,7 +263,7 @@ void Compiler::visitEOr(EOr *p) {
addQuad<QAssign>(lastVar, Op::Copy, r);
addQuad<QJump>(labelAfter);
addQuad(labelLeft);
addQuad<QAssign>(lastVar, Op::Copy, l);
addQuad<QAssign>(lastVar, Op::Copy, alloc(1));
addQuad(labelAfter);
}
......@@ -238,7 +304,7 @@ void Compiler::visitEClsMmbr(EClsMmbr *p) {
size_t offset = var->offset;
if (dynamic_cast<EIndexAcc*>(p->expr_)) {
// opt if EIndexAcc is used inside visitEClsMmbr
auto access = dynamic_pointer_cast<QAccess>(quads.back());
auto access = dynamic_pointer_cast<QAccess>(block->quads.back());
access->access.offset += offset;
l->info = var;
lastVar = l;
......@@ -328,12 +394,11 @@ void Compiler::assign(Expr* lval, VariablePtr val) {
auto dest = evalLVal(lval);
if (dest->info && dest->info->isInstanceVariable()) {
// instance variable, need to write it to memory
auto quad = dynamic_pointer_cast<QAccess>(quads.empty() ? nullptr : quads.back());
auto quad = dynamic_pointer_cast<QAccess>(lastQuad);
assert(quad);
auto loc = quad->access;
quads.pop_back();
block->quads.pop_back();
addQuad<QWrite>(loc, val);
return;
} else {
// local variable - only assign
addQuad<QAssign>(dest, Op::Copy, val);
......@@ -359,27 +424,33 @@ void Compiler::visitDecr(Decr *p) {
assign(p->expr_, tmp);
}
// flow control
void Compiler::visitRet(Ret *p) {
auto var = evalExpr(p->expr_);
endBasicBlock();
addQuad<QReturn>(var);
flushBasicBlock();
}
void Compiler::visitVRet(VRet *p) {
endBasicBlock();
addQuad<QReturn>(nullptr);
flushBasicBlock();
}
void Compiler::visitCond(Cond *p) {
auto var = evalExpr(p->expr_);
auto after = make_shared<QLabel>("end_if");
endBasicBlock(); // possible jump -> after
addQuad<QJumpCond>(after, Op::Not, var);
auto beforeBlock = flushBasicBlock(); // possible jump -> after
p->stmt_->accept(this);
endBasicBlock(); // possible jump <- cond
auto innerBlock = flushBasicBlock(); // possible jump <- cond
addQuad(after);
beforeBlock->append(innerBlock);
beforeBlock->append(block);
innerBlock->append(block);
}
void Compiler::visitCondElse(CondElse *p) {
......@@ -388,37 +459,46 @@ void Compiler::visitCondElse(CondElse *p) {
auto var = evalExpr(p->expr_);
endBasicBlock(); // possible jump -> else
addQuad<QJumpCond>(elseBranch, Op::Not, var);
auto beforeBlock = flushBasicBlock(); // possible jump -> else
p->stmt_1->accept(this);
endBasicBlock(); // jump -> after
addQuad<QJump>(after);
auto stmt1Block = flushBasicBlock(); // jump -> after
addQuad(elseBranch);
p->stmt_2->accept(this);
endBasicBlock(); // jump <- cond
auto stmt2Block = flushBasicBlock(); // jump <- cond
addQuad(after);
beforeBlock->append(stmt1Block);
beforeBlock->append(stmt2Block);
stmt1Block->append(block);
stmt2Block->append(block);
}
void Compiler::visitWhile(While *p) {
auto cond = make_shared<QLabel>("cond");
endBasicBlock(); // jump <- loop -> cond
addQuad<QJump>(cond);
auto beforeBlock = flushBasicBlock(); // jump <- loop -> cond
// jump <- loop
auto loop = make_shared<QLabel>("loop");
addQuad(loop);
p->stmt_->accept(this);
endBasicBlock(); // jump <- cond
auto stmtsBlock = flushBasicBlock(); // jump <- cond
addQuad(cond);
auto var = evalExpr(p->expr_);
endBasicBlock(); // jump -> loop
addQuad<QJumpCond>(loop, Op::Copy, var);
auto condBlock = flushBasicBlock(); // jump -> loop
beforeBlock->append(condBlock);
condBlock->append(stmtsBlock);
condBlock->append(block);
}
void Compiler::visitSExp(SExp *p) {
......@@ -431,3 +511,11 @@ void Compiler::visitForEach(ForEach *p) {
// TODO: implement
}
void Compiler::visitBlk(Blk *blk) {
scope->currentBinding = blk->getBinding();
Skeleton::visitBlk(blk);
scope->currentBinding = scope->currentBinding->getParent();
}
......@@ -11,7 +11,6 @@
#include "Info.h"
#include "codeGen/Quadruple.h"
#include "codeGen/BasicBlock.h"
using Op = Quadruple::Op;
class Compiler : public Skeleton
{
......@@ -27,8 +26,9 @@ private:
std::stringstream buf;
shared_ptr<Scope> scope;
vector<VariablePtr> vars;
vector<QuadruplePtr> quads;
vector<BasicBlockPtr> blocks;
Quadruple::Op op;
BasicBlockPtr block;
VariablePtr lastVar;
int lineno;
......@@ -59,26 +59,29 @@ private:
return ret;
};
std::string mangleFunctionName(FunctionInfoPtr f) const {
static std::string mangleFunctionName(const FunctionInfoPtr& f) {
if (auto c = f->klass.lock()) {
return c->name + "::" + f->name;
}
return f->name;
};
std::string getVirtName(ClassInfoPtr c) const {
static std::string getVirtName(const ClassInfoPtr& c) {
return c->name + ":virt_table";
};
VariablePtr alloc(VarInfoPtr info) {
if (info->loc && !info->isInstanceVariable()) {
VariablePtr alloc(const VarInfoPtr& info) {
if (info->loc) {
return info->loc;
}
auto v = make_shared<Variable>(info);
vars.emplace_back(v);
info->loc = v;
if (!info->isInstanceVariable()) {
info->loc = v;
}
return v;
}
template<typename... Args> VariablePtr alloc(Args... args) {
auto v = make_shared<Variable>(args...);
vars.emplace_back(v);
......@@ -86,22 +89,31 @@ private:
}
template<typename T, typename... Args> QuadruplePtr addQuad(Args... args) {
auto quad = make_shared<T>(args...);
quad->lineno = lineno;
quads.emplace_back(quad);
return quad;
return addQuad(make_shared<T>(args...));
}
QuadruplePtr addQuad(QuadruplePtr quad) {
quad->lineno = lineno;
quads.emplace_back(quad);
flushLastQuad();
lastQuad = quad;
return quad;
}
void endBasicBlock();
QuadruplePtr lastQuad;
void flushLastQuad() {
if (lastQuad) {
block->quads.emplace_back(lastQuad);
lastQuad = nullptr;
}
}
BasicBlockPtr flushBasicBlock();
void assign(Expr* lval, VariablePtr val);
VariableLayout captureEnv();
void visitEVar(EVar *p) override;
void visitEIndexAcc(EIndexAcc *p) override;
void visitEClsMmbr(EClsMmbr *p) override;
......@@ -123,6 +135,7 @@ private:
void visitBlk(Blk *p) override;
void visitInit(Init *p) override;
void visitAss(Ass *p) override;
void visitIncr(Incr *p) override;
......
......@@ -21,6 +21,7 @@ class Quadruple;
using QuadruplePtr = shared_ptr<Quadruple>;
class BasicBlock;
using BasicBlockPtr = shared_ptr<BasicBlock>;
class VariableLayout;
class Visitable;
class Program;
......
......@@ -6,12 +6,19 @@
#define ZAD2_BASICBLOCK_H
#include "../TypeDefs.h"
#include <vector>
#include <set>
using namespace std;
class BasicBlock {
class BasicBlock : public std::enable_shared_from_this<BasicBlock> {
public:
vector<QuadruplePtr> quads;
vector<BasicBlockPtr> in, out;
set<VarInfoPtr> modifications;
void append(const BasicBlockPtr& after) {
out.push_back(after);
after->in.push_back(shared_from_this());
}
};
......
......@@ -6,8 +6,10 @@
#define ZAD2_VARIABLE_H
#include <utility>
#include <map>
#include "../TypeDefs.h"
#include "../Info.h"
class Variable : std::enable_shared_from_this<Variable> {
public:
......@@ -46,4 +48,29 @@ public:
}
};
class VariableLayout {
map<VarInfoPtr, pair<VariablePtr, VariablePtr>> changes;
public:
void add(const VarInfoPtr& info) {
if (!changes.count(info)) {
changes[info] = {info->loc, nullptr};
}
}
void update() {
for (auto p : changes) {
p.second.second = p.first->loc;
}
}
void revert() {
for (auto p : changes) {
VarInfoPtr info = p.first;
info->loc = p.second.first;
}
}
};
#endif //ZAD2_VARIABLE_H
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