Commit 9b245472 authored by zygzagZ's avatar zygzagZ

quadcode względnie działa, brakuje flow zmiennych lokalnych między

blokami prostymi
parent 9f4bdacd
......@@ -196,6 +196,8 @@ public:
std::weak_ptr<FunctionInfo> function;
virtual Block *clone() const = 0;
std::shared_ptr<Binding> getBinding() const { return binding; };
};
class Stmt : public Visitable
......
......@@ -130,13 +130,13 @@ void Compiler::visitNullCast(NullCast *p) {
void Compiler::visitNeg(Neg *p) {
auto var = evalExpr(p->expr_);
lastVar = alloc();
quads.emplace_back(make_shared<QAssign>(lastVar, Op::Neg, var));
addQuad<QAssign>(lastVar, Op::Neg, var);
}
void Compiler::visitNot(Not *p) {
auto var = evalExpr(p->expr_);
lastVar = alloc();
quads.emplace_back(make_shared<QAssign>(lastVar, Op::Not, var));
addQuad<QAssign>(lastVar, Op::Not, var);
}
// binary ops
......@@ -146,7 +146,7 @@ void Compiler::visitEMul(EMul *p) {
auto r = evalExpr(p->expr_2);
lastVar = alloc();
p->mulop_->accept(this);
quads.emplace_back(make_shared<QAssign>(lastVar, l, op, r));
addQuad<QAssign>(lastVar, l, op, r);
}
void Compiler::visitEAdd(EAdd *p) {
......@@ -154,7 +154,7 @@ void Compiler::visitEAdd(EAdd *p) {
auto r = evalExpr(p->expr_2);
lastVar = alloc();
p->addop_->accept(this);
quads.emplace_back(make_shared<QAssign>(lastVar, l, op, r));
addQuad<QAssign>(lastVar, l, op, r);
}
......@@ -163,7 +163,7 @@ void Compiler::visitERel(ERel *p) {
auto r = evalExpr(p->expr_2);
lastVar = alloc();
p->relop_->accept(this);
quads.emplace_back(make_shared<QAssign>(lastVar, l, op, r));
addQuad<QAssign>(lastVar, l, op, r);
}
// lazy bools
......@@ -173,15 +173,15 @@ void Compiler::visitEAnd(EAnd *p) {
auto labelLeft = make_shared<QLabel>("use_left");
auto labelAfter = make_shared<QLabel>("end_and");
quads.emplace_back(make_shared<QJumpCond>(labelLeft, Op::Not, l));
addQuad<QJumpCond>(labelLeft, Op::Not, l);
auto r = evalExpr(p->expr_2);
lastVar = alloc();
quads.emplace_back(make_shared<QAssign>(lastVar, Op::Copy, r));
quads.emplace_back(make_shared<QJump>(labelAfter));
quads.emplace_back(labelLeft);
quads.emplace_back(make_shared<QAssign>(lastVar, Op::Copy, l));
quads.emplace_back(labelAfter);
addQuad<QAssign>(lastVar, Op::Copy, r);
addQuad<QJump>(labelAfter);
addQuad(labelLeft);
addQuad<QAssign>(lastVar, Op::Copy, l);
addQuad(labelAfter);
}
void Compiler::visitEOr(EOr *p) {
......@@ -189,16 +189,16 @@ void Compiler::visitEOr(EOr *p) {
auto labelLeft = make_shared<QLabel>("use_left");
auto labelAfter = make_shared<QLabel>("end_or");
quads.emplace_back(make_shared<QJumpCond>(labelLeft, Op::Copy, l));
addQuad<QJumpCond>(labelLeft, Op::Copy, l);
auto r = evalExpr(p->expr_2);
lastVar = alloc();
quads.emplace_back(make_shared<QAssign>(lastVar, Op::Copy, r));
quads.emplace_back(make_shared<QJump>(labelAfter));
quads.emplace_back(labelLeft);
quads.emplace_back(make_shared<QAssign>(lastVar, Op::Copy, l));
quads.emplace_back(labelAfter);
addQuad<QAssign>(lastVar, Op::Copy, r);
addQuad<QJump>(labelAfter);
addQuad(labelLeft);
addQuad<QAssign>(lastVar, Op::Copy, l);
addQuad(labelAfter);
}
// complex extensions
......@@ -218,14 +218,14 @@ void Compiler::visitEIndexAcc(EIndexAcc *p) {
// calculate quantifier, we multiply index because size is larger than 4
auto q = alloc(type->type_->size() / 4);
// calculate var = index * quantifier
quads.emplace_back(make_shared<QAssign>(lastVar, index, Op::Mul, q));
addQuad<QAssign>(lastVar, index, Op::Mul, q);
// allocate new lastVar, index is now calculated multiplied index
index = alloc();
swap(index, lastVar);
}
auto quad = make_shared<QAccess>(lastVar, lhs, index, 4, 0);
quads.emplace_back(quad);
addQuad(quad);
}
void Compiler::visitEClsMmbr(EClsMmbr *p) {
......@@ -234,18 +234,18 @@ void Compiler::visitEClsMmbr(EClsMmbr *p) {
assert(var);
// it cannot be function, as function might only be used in EApp and are handled directly there
assert(!var->toFunction());
// Array length calculation works because of arrayLengthVar that has offset 0
size_t offset = var->offset;
// TODO: Array length calculation
// if ()
if (dynamic_cast<EIndexAcc*>(p->expr_)) {
// opt if EIndexAcc is used inside visitEClsMmbr
auto access = dynamic_pointer_cast<QAccess>(quads.back());
access->offset += offset;
access->access.offset += offset;
l->info = var;
lastVar = l;
} else {
lastVar = alloc();
lastVar = alloc(var);
auto quad = make_shared<QAccess>(lastVar, l, alloc(0), 0, offset);
quads.emplace_back(quad);
addQuad(quad);
}
}
......@@ -280,15 +280,15 @@ void Compiler::visitEApp(EApp *p) {
int i = 1;
for (auto param : *p->listexpr_) {
auto var = evalExpr(param);
quads.emplace_back(make_shared<QParam>(var, i++));
addQuad<QParam>(var, i++);
}
if (self) {
quads.emplace_back(make_shared<QParam>(self, 0));
addQuad<QParam>(self, 0);
}
lastVar = alloc();
quads.emplace_back(make_shared<QCall>(lastVar, info, i, self));
addQuad<QCall>(lastVar, info, i, self);
}
void Compiler::visitENewArray(ENewArray *p) {
......@@ -303,7 +303,7 @@ void Compiler::visitENewArray(ENewArray *p) {
}
auto count = evalExpr(p->expr_);
lastVar = alloc();
quads.emplace_back(make_shared<QAlloc>(lastVar, size, virtSymbol, count));
addQuad<QAlloc>(lastVar, size, virtSymbol, count);
}
void Compiler::visitENewClass(ENewClass *p) {
......@@ -312,7 +312,7 @@ void Compiler::visitENewClass(ENewClass *p) {
size_t size = info->size;
std::string virtSymbol = getVirtName(info);
lastVar = alloc();
quads.emplace_back(make_shared<QAlloc>(lastVar, size, virtSymbol));
addQuad<QAlloc>(lastVar, size, virtSymbol);
}
/// statements
......@@ -321,35 +321,53 @@ void Compiler::visitInit(Init *p) {
auto info = p->pident_->var.lock();
assert(info);
auto var = evalExpr(p->expr_);
quads.emplace_back(make_shared<QAssign>(alloc(info), Op::Copy, var));
addQuad<QAssign>(alloc(info), Op::Copy, var);
}
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());
assert(quad);
auto loc = quad->access;
quads.pop_back();
addQuad<QWrite>(loc, val);
return;
} else {
// local variable - only assign
addQuad<QAssign>(dest, Op::Copy, val);
}
}
void Compiler::visitAss(Ass *p) {
auto dest = evalExpr(p->expr_1);
quads.emplace_back(make_shared<QAssign>(dest, Op::Copy, evalExpr(p->expr_2)));
auto val = evalExpr(p->expr_2);
assign(p->expr_1, val);
}
void Compiler::visitIncr(Incr *p) {
auto dest = evalExpr(p->expr_);
auto lhs = evalExpr(p->expr_);
quads.emplace_back(make_shared<QAssign>(dest, lhs, Op::Plus, alloc(1)));
auto tmp = alloc();
addQuad<QAssign>(tmp, lhs, Op::Plus, alloc(1));
assign(p->expr_, tmp);
}
void Compiler::visitDecr(Decr *p) {
auto dest = evalExpr(p->expr_);
auto lhs = evalExpr(p->expr_);
quads.emplace_back(make_shared<QAssign>(dest, lhs, Op::Minus, alloc(1)));
auto tmp = alloc();
addQuad<QAssign>(tmp, lhs, Op::Minus, alloc(1));
assign(p->expr_, tmp);
}
void Compiler::visitRet(Ret *p) {
auto var = evalExpr(p->expr_);
endBasicBlock();
quads.emplace_back(make_shared<QReturn>(var));
addQuad<QReturn>(var);
}
void Compiler::visitVRet(VRet *p) {
endBasicBlock();
quads.emplace_back(make_shared<QReturn>(nullptr));
addQuad<QReturn>(nullptr);
}
void Compiler::visitCond(Cond *p) {
......@@ -357,11 +375,11 @@ void Compiler::visitCond(Cond *p) {
auto after = make_shared<QLabel>("end_if");
endBasicBlock(); // possible jump -> after
quads.emplace_back(make_shared<QJumpCond>(after, Op::Not, var));
addQuad<QJumpCond>(after, Op::Not, var);
p->stmt_->accept(this);
endBasicBlock(); // possible jump <- cond
quads.emplace_back(after);
addQuad(after);
}
void Compiler::visitCondElse(CondElse *p) {
......@@ -371,36 +389,36 @@ void Compiler::visitCondElse(CondElse *p) {
auto var = evalExpr(p->expr_);
endBasicBlock(); // possible jump -> else
quads.emplace_back(make_shared<QJumpCond>(elseBranch, Op::Not, var));
addQuad<QJumpCond>(elseBranch, Op::Not, var);
p->stmt_1->accept(this);
endBasicBlock(); // jump -> after
quads.emplace_back(make_shared<QJump>(after));
addQuad<QJump>(after);
quads.emplace_back(elseBranch);
addQuad(elseBranch);
p->stmt_2->accept(this);
endBasicBlock(); // jump <- cond
quads.emplace_back(after);
addQuad(after);
}
void Compiler::visitWhile(While *p) {
auto cond = make_shared<QLabel>("cond");
endBasicBlock(); // jump <- loop -> cond
quads.emplace_back(make_shared<QJump>(cond));
addQuad<QJump>(cond);
// jump <- loop
auto loop = make_shared<QLabel>("loop");
quads.emplace_back(loop);
addQuad(loop);
p->stmt_->accept(this);
endBasicBlock(); // jump <- cond
quads.emplace_back(cond);
addQuad(cond);
auto var = evalExpr(p->expr_);
endBasicBlock(); // jump -> loop
quads.emplace_back(make_shared<QJumpCond>(loop, Op::Copy, var));
addQuad<QJumpCond>(loop, Op::Copy, var);
}
void Compiler::visitSExp(SExp *p) {
......
......@@ -31,11 +31,22 @@ private:
Quadruple::Op op;
VariablePtr lastVar;
int lineno;
void compileFunction(FunctionInfoPtr f);
VariablePtr evalLVal(Visitable *expr) {
auto info = evalExpr(expr)->info;
if (!info) {
throw ParseError("LValue expected", expr);
}
info->loc = nullptr;
return alloc(info);
}
VariablePtr evalExpr(Visitable *expr) {
if (!expr) throw runtime_error("No expr to eval");
lineno = expr->lineno;
lastVar = nullptr;
try {
expr->accept(this);
......@@ -60,7 +71,7 @@ private:
};
VariablePtr alloc(VarInfoPtr info) {
if (info->loc) {
if (info->loc && !info->isInstanceVariable()) {
return info->loc;
}
auto v = make_shared<Variable>(info);
......@@ -74,8 +85,23 @@ private:
return v;
}
template<typename T, typename... Args> QuadruplePtr addQuad(Args... args) {
auto quad = make_shared<T>(args...);
quad->lineno = lineno;
quads.emplace_back(quad);
return quad;
}
QuadruplePtr addQuad(QuadruplePtr quad) {
quad->lineno = lineno;
quads.emplace_back(quad);
return quad;
}
void endBasicBlock();
void assign(Expr* lval, VariablePtr val);
void visitEVar(EVar *p) override;
void visitEIndexAcc(EIndexAcc *p) override;
void visitEClsMmbr(EClsMmbr *p) override;
......
......@@ -26,7 +26,8 @@ public:
string name;
TypePtr type;
int lineLocation;
size_t offset;
size_t offset = 0;
bool isInstanceVariable() const { return offset; };
VariablePtr loc;
......
......@@ -117,7 +117,7 @@ void TypeCheck::visitClassFld(ClassFld *decl)
void TypeCheck::visitBlk(Blk *blk)
{
BindingPtr binding = blk->binding/*.lock()*/;
BindingPtr binding = blk->getBinding();
if (!binding) {
binding = make_shared<Binding>(scope->currentBinding);
blk->binding = binding;
......@@ -310,8 +310,9 @@ void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
if (!type) {
// it is an array and we ask for length
if (dynamic_pointer_cast<Array>(exprType)) {
if (e_cls_mmbr->pident_->string_ == "length") {
lastType = make_shared<Int>();
if (e_cls_mmbr->pident_->string_ == arrayLengthVar->name) {
e_cls_mmbr->pident_->var = arrayLengthVar;
lastType = arrayLengthVar->type;
return;
}
}
......@@ -558,6 +559,8 @@ void TypeCheck::setupEnv() {
scope->functions << error;
}
arrayLengthVar = make_shared<VarInfo>("length", make_shared<Int>());
}
void TypeCheck::check(Visitable *v)
......
......@@ -22,6 +22,8 @@ class TypeCheck : public Visitor
vector<pair<ClassInfoPtr, ClassDef*>> classDefs;
VarInfoPtr arrayLengthVar;
void checkFunction(FunctionInfoPtr f);
void checkReturnStatement(shared_ptr<Type> type, Stmt *stmt);
void checkFunctionRet();
......
......@@ -38,8 +38,10 @@ public:
}
};
int lineno;
virtual ~Quadruple() {};
virtual std::string toString() const = 0;
virtual std::string toString() const { return to_string(lineno) + "\t"; };
};
class QWriteVar : public Quadruple {
......@@ -47,13 +49,13 @@ public:
VariablePtr loc;
explicit QWriteVar(VariablePtr loc) : Quadruple(), loc(std::move(loc)) {};
std::string toString() const override { return loc ? ("\t" + loc->name + " := ") : "\t"; }
std::string toString() const override { return Quadruple::toString() + "\t" + (loc ? (loc->name + " := ") : ""); }
};
class QLabel : public Quadruple {
public:
string label;
std::string toString() const override { return "\"" + label + "\":"; }
std::string toString() const override { return Quadruple::toString() + "\"" + label + "\":"; }
QLabel(std::string comment) : label(comment) {}
};
......@@ -80,7 +82,7 @@ public:
explicit QJump(shared_ptr<QLabel> target) : target(std::move(target)) {};
std::string toString() const override {
return "\tjump " + target->label;
return Quadruple::toString() + "jump " + target->label;
}
};
......@@ -97,9 +99,9 @@ public:
std::string toString() const override {
if (!left)
return "\tjump \"" + target->label + "\" if " + Op::name(op) + " " + right->name;
return Quadruple::toString() + "jump \"" + target->label + "\" if " + Op::name(op) + " " + right->name;
else
return "\tjump \"" + target->label + "\" if " + left->name + " " + Op::name(op) + " " + right->name;
return Quadruple::toString() + "jump \"" + target->label + "\" if " + left->name + " " + Op::name(op) + " " + right->name;
}
};
......@@ -112,9 +114,9 @@ public:
std::string toString() const override {
if (num == 0) {
return "\tparam self " + param->name;
return Quadruple::toString() + "\tparam self " + param->name;
} else {
return "\tparam #" + to_string(num) + " <- " + param->name;
return Quadruple::toString() + "\tparam #" + to_string(num) + " <- " + param->name;
}
}
};
......@@ -143,9 +145,9 @@ public:
std::string toString() const override {
if (ret) {
return "\treturn " + ret->name;
return Quadruple::toString() + "\treturn " + ret->name;
} else {
return "\treturn";
return Quadruple::toString() + "\treturn";
}
}
};
......@@ -153,23 +155,31 @@ public:
class QAccess : public QWriteVar {
public:
QAccess(VariablePtr loc, VariablePtr base, VariablePtr index, int multiplier, int offset)
: QWriteVar(std::move(loc)), base(std::move(base)), index(std::move(index)), multiplier(multiplier), offset(offset)
: QWriteVar(std::move(loc)), access(std::move(base), std::move(index), multiplier, offset)
{};
// leal 8(,%eax,4), %eax # Arithmetic: multiply eax by 4 and add 8
// leal (%edx,%eax,2), %eax # Arithmetic: multiply eax by 2 and add edx
VariablePtr base;
VariablePtr index;
int multiplier;
int offset;
VariableLocation access;
bool lea = false;
std::string toString() const override {
auto ret = QWriteVar::toString() + "[" + base->name;
if (multiplier || !(index->constExpr || !index->val)) ret += " + " + to_string(multiplier) + "*" + index->name;
if (offset) ret += " + " + to_string(offset);
return ret + "]";
auto ret = QWriteVar::toString();
if (lea) ret += "&";
return ret + access.toString();
}
};
class QWrite : public Quadruple {
public:
QWrite(VariableLocation loc, VariablePtr val)
: Quadruple(), loc(std::move(loc)), val(std::move(val))
{};
VariableLocation loc;
VariablePtr val;
std::string toString() const override { return Quadruple::toString() + "\t" + loc.toString() + " := " + val->name; }
};
class QAlloc : public QWriteVar {
public:
size_t size;
......
......@@ -27,4 +27,23 @@ public:
// where in mem - id or offset
};
class VariableLocation {
public:
VariableLocation() = default;
VariableLocation(VariablePtr base, VariablePtr index, int multiplier, int offset)
: base(std::move(base)), index(std::move(index)), multiplier(multiplier), offset(offset)
{}
VariablePtr base;
VariablePtr index;
int multiplier;
int offset;
string toString() const {
std::string ret = "[" + base->name;
if (multiplier || !(index->constExpr || !index->val)) ret += " + " + to_string(multiplier) + "*" + index->name;
if (offset) ret += " + " + to_string(offset);
return ret + "]";
}
};
#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