Commit 46d82364 authored by zygzagZ's avatar zygzagZ

Tests 1-17 work

parent 22f00483
...@@ -274,7 +274,7 @@ void Compiler::generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap) { ...@@ -274,7 +274,7 @@ void Compiler::generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap) {
const auto &loc = phiVars.first, &val = phiVars.second; const auto &loc = phiVars.first, &val = phiVars.second;
auto ri = Register(loc), rj = Register(val); auto ri = Register(loc), rj = Register(val);
if (loc->constExpr) continue; if (loc->constExpr) continue;
if (ri == 0 || val->constExpr) { // we need to do do memory stores now if (ri == 0) { // we need to do do memory stores now
if (ri == 0 && rj == 0 && !val->constExpr) { if (ri == 0 && rj == 0 && !val->constExpr) {
assert(loc->info == val->info); assert(loc->info == val->info);
} else { } else {
...@@ -311,7 +311,7 @@ void Compiler::generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap) { ...@@ -311,7 +311,7 @@ void Compiler::generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap) {
for (const auto &phiVars : varMap) { for (const auto &phiVars : varMap) {
const auto &i = phiVars.first, &j = phiVars.second; const auto &i = phiVars.first, &j = phiVars.second;
auto ri = Register(i), rj = Register(j); auto ri = Register(i), rj = Register(j);
if (ri != 0 && rj == 0) { if (ri != 0 && (rj == 0 || j->constExpr)) {
append("MOVL", getRef(j), ri); append("MOVL", getRef(j), ri);
} }
} }
...@@ -326,32 +326,39 @@ void Compiler::generateQJump(QJump &q) { ...@@ -326,32 +326,39 @@ void Compiler::generateQJump(QJump &q) {
append("JMP", getBlockLabelText(q.target)); append("JMP", getBlockLabelText(q.target));
} }
Op Compiler::generateCmp(const VariablePtr& l, Op op, const VariablePtr &r) {
auto regL = Register(l), regR = Register(r);
auto locL = getRef(l);
auto locR = getRef(r);
if (regL == 0 && regR == 0) {
append("MOVL", locR, regR);
locR = regR;
} else if (regL != 0 && regR == 0) {
// left is in register but right is not - swap operands
// as right needs to be a register
swap(locL, locR);
assert (op.kind() == Op::CMP);
op = op.rot(); // we swapped operands
}
append("CMP", locL, locR);
if (op.kind() == Op::CMP)
op = op.rot(); // compare has different syntax in AT&T
return op;
}
void Compiler::generateQJumpCond(QJumpCond &q) { void Compiler::generateQJumpCond(QJumpCond &q) {
auto thisBlock = q.block; auto thisBlock = q.block;
auto tgBlock = q.target->block; auto tgBlock = q.target->block;
const auto &map = tgBlock->getPhiMapping(thisBlock); const auto &map = tgBlock->getPhiMapping(thisBlock);
for (const auto &phiVars : map) { for (const auto &phiVars : map) {
// if (Register(phiVars.first) != Register(phiVars.second)) { // if (Register(phiVars.first) != Register(phiVars.second)) {
throw runtime_error("Unimplemented phi CondJump register XCHG"); buf << ("// Unimplemented phi CondJump register XCHG\n");
// } // }
} }
auto op = q.op; auto op = q.op;
if (q.left) { // 2 args 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); op = generateCmp(q.left, op, q.right);
auto locL = getRef(q.left);
auto locR = getRef(q.right);
if (regL == 0 && regR == 0) {
append("MOVL", locR, regR);
locR = regR;
} else if (regL != 0 && regR == 0) {
// left is in register but right is not - swap operands
// as right needs to be a register
swap(locL, locR);
assert (op.kind() == Op::CMP);
op = op.rot(); // we swapped operands
}
append("CMP", locL, locR);
} else { // 1 arg } 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) {
...@@ -360,11 +367,10 @@ void Compiler::generateQJumpCond(QJumpCond &q) { ...@@ -360,11 +367,10 @@ void Compiler::generateQJumpCond(QJumpCond &q) {
return; return;
} }
auto tg = moveToAnyRegister(q.right); auto tg = moveToAnyRegister(q.right);
append("CMP", tg, tg); append("TEST", tg, tg);
op = op.neg();
} }
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");
...@@ -441,14 +447,17 @@ void Compiler::generateQAssign(QAssign &q) { ...@@ -441,14 +447,17 @@ void Compiler::generateQAssign(QAssign &q) {
if (backupEdx && edxAlive) append("MOVL", "-4(%esp)", edx); if (backupEdx && edxAlive) append("MOVL", "-4(%esp)", edx);
return; return;
} else if (q.op.kind() == Op::CMP) { } else if (q.op.kind() == Op::CMP) {
auto loc = getRef(i); auto op = generateCmp(i, q.op, j);
if (Register(i) == 0 && Register(j) == 0) { if ((int) tg < 4) { // eax - edx
moveTo(i, 0); append("MOVL", "$0", tg);
loc = "%eax"; string s = "%AL";
s[1] = ((string)tg)[2];
append(op, s);
} else {
append("MOVL", "$0", "%EAX");
append(op, "%AL");
append("MOVL", "%EAX", tg);
} }
append("CMPL", loc, getRef(j));
append(q.op, tg);
} else { } else {
assert(q.op.kind() == Op::BINARY); assert(q.op.kind() == Op::BINARY);
bool swapped = false; bool swapped = false;
......
...@@ -69,6 +69,8 @@ public: ...@@ -69,6 +69,8 @@ public:
void generateQPhi(QPhi &q); void generateQPhi(QPhi &q);
void generateQBlockEnd(QBlockEnd &q); void generateQBlockEnd(QBlockEnd &q);
Op generateCmp(const VariablePtr& l, Op op, const VariablePtr &r);
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()) {
return c->name + "::" + f->name; return c->name + "::" + f->name;
......
...@@ -58,11 +58,11 @@ public: ...@@ -58,11 +58,11 @@ public:
InfoList<ClassInfo> classes; InfoList<ClassInfo> classes;
InfoList<FunctionInfo> functions; InfoList<FunctionInfo> functions;
weak_ptr<Binding> parent; shared_ptr<Binding> parent;
Binding(BindingPtr parent = nullptr); Binding(BindingPtr parent = nullptr);
virtual ~Binding() {}; virtual ~Binding() {};
BindingPtr getParent() { return parent.lock(); }; BindingPtr getParent() { return parent; };
}; };
class ClassInfo : public VarInfo, public Binding class ClassInfo : public VarInfo, public Binding
...@@ -72,7 +72,7 @@ public: ...@@ -72,7 +72,7 @@ public:
ClassInfo(PIdent *ident, BindingPtr parent = nullptr); ClassInfo(PIdent *ident, BindingPtr parent = nullptr);
virtual string kind() const { return "class"; } virtual string kind() const { return "class"; }
ClassInfoPtr getClassParent() { return dynamic_pointer_cast<ClassInfo>(parent.lock()); }; ClassInfoPtr getClassParent() { return dynamic_pointer_cast<ClassInfo>(parent); };
size_t calculateSize(); size_t calculateSize();
size_t size, functionCount; size_t size, functionCount;
}; };
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define ZAD2_QUAD_H #define ZAD2_QUAD_H
#include <string> #include <string>
#include <utility> #include <utility>
#include <cassert>
#include "../Info.h" #include "../Info.h"
#include "Variable.h" #include "Variable.h"
...@@ -112,8 +113,12 @@ public: ...@@ -112,8 +113,12 @@ public:
Op op; Op op;
vector<VariablePtr> args; vector<VariablePtr> args;
QAssign(VariablePtr loc, Op op, vector<VariablePtr> list) : QWriteVar(std::move(loc)), op(op), args(std::move(list)) {}; QAssign(VariablePtr loc, Op op, const vector<VariablePtr>& list) : QWriteVar(std::move(loc)), op(op) {
QAssign(VariablePtr loc, VariablePtr l, Op op, VariablePtr r) : QWriteVar(std::move(loc)), op(op), args({std::move(l), std::move(r)}) {}; for (const auto& i : list)
if (i)
args.emplace_back(i);
};
QAssign(VariablePtr loc, VariablePtr l, Op op, VariablePtr r) : QAssign(std::move(loc), op, {std::move(l), std::move(r)}) { };
QAssign(VariablePtr loc, Op op, VariablePtr x) : QWriteVar(std::move(loc)), op(op), args({std::move(x)}) {}; QAssign(VariablePtr loc, Op op, VariablePtr x) : QWriteVar(std::move(loc)), op(op), args({std::move(x)}) {};
std::string toString() const override { std::string toString() const override {
......
...@@ -102,7 +102,12 @@ VariableLayout QuadrupleGenerator::captureEnv() { ...@@ -102,7 +102,12 @@ VariableLayout QuadrupleGenerator::captureEnv() {
/// expressions /// expressions
void QuadrupleGenerator::visitEVar(EVar *p) { void QuadrupleGenerator::visitEVar(EVar *p) {
lastVar = alloc(p->pident_->var.lock()); auto var = p->pident_->var.lock();
lastVar = alloc(var);
Bool b;
if (var->type->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar);
}
} }
void QuadrupleGenerator::visitELitInt(ELitInt *p) { void QuadrupleGenerator::visitELitInt(ELitInt *p) {
...@@ -111,12 +116,12 @@ void QuadrupleGenerator::visitELitInt(ELitInt *p) { ...@@ -111,12 +116,12 @@ void QuadrupleGenerator::visitELitInt(ELitInt *p) {
void QuadrupleGenerator::visitELitTrue(ELitTrue *p) { void QuadrupleGenerator::visitELitTrue(ELitTrue *p) {
lastVar = alloc(1); lastVar = alloc(1);
if (labelTrue) addQuad<QJump>(labelTrue); // if (labelTrue) addQuad<QJump>(labelTrue);
} }
void QuadrupleGenerator::visitELitFalse(ELitFalse *p) { void QuadrupleGenerator::visitELitFalse(ELitFalse *p) {
lastVar = alloc(0); lastVar = alloc(0);
if (labelFalse) addQuad<QJump>(labelFalse); // if (labelFalse) addQuad<QJump>(labelFalse);
} }
void QuadrupleGenerator::visitEString(EString *p) { void QuadrupleGenerator::visitEString(EString *p) {
...@@ -131,26 +136,22 @@ void QuadrupleGenerator::visitNullCast(NullCast *p) { ...@@ -131,26 +136,22 @@ void QuadrupleGenerator::visitNullCast(NullCast *p) {
void QuadrupleGenerator::visitNeg(Neg *p) { void QuadrupleGenerator::visitNeg(Neg *p) {
auto var = evalExpr(p->expr_); auto var = evalExpr(p->expr_);
lastVar = alloc(); lastVar = alloc(var);
addQuad<QAssign>(lastVar, Op::Neg, var); addQuad<QAssign>(lastVar, Op::Neg, var);
if ((lastVar->constExpr = var->constExpr)) { lastVar->val = -var->val;
lastVar->val = -var->val;
}
} }
void QuadrupleGenerator::visitNot(Not *p) { void QuadrupleGenerator::visitNot(Not *p) {
auto var = evalJump(p->expr_, labelFalse, labelTrue); auto var = evalJump(p->expr_, labelFalse, labelTrue);
lastVar = alloc(); lastVar = alloc(var);
addQuad<QAssign>(lastVar, Op::Not, var); addQuad<QAssign>(lastVar, Op::Not, var);
if ((lastVar->constExpr = var->constExpr)) { lastVar->val = !var->val;
lastVar->val = !var->val;
}
} }
void QuadrupleGenerator::visitEMul(EMul *p) { void QuadrupleGenerator::visitEMul(EMul *p) {
auto l = evalExpr(p->expr_1); auto l = evalExpr(p->expr_1);
auto r = evalExpr(p->expr_2); auto r = evalExpr(p->expr_2);
lastVar = alloc(); lastVar = alloc(l);
p->mulop_->accept(this); p->mulop_->accept(this);
addQuad<QAssign>(lastVar, l, op, r); addQuad<QAssign>(lastVar, l, op, r);
if ((lastVar->constExpr = l->constExpr && r->constExpr)) { if ((lastVar->constExpr = l->constExpr && r->constExpr)) {
...@@ -168,7 +169,7 @@ void QuadrupleGenerator::visitEMul(EMul *p) { ...@@ -168,7 +169,7 @@ void QuadrupleGenerator::visitEMul(EMul *p) {
void QuadrupleGenerator::visitEAdd(EAdd *p) { void QuadrupleGenerator::visitEAdd(EAdd *p) {
auto l = evalExpr(p->expr_1); auto l = evalExpr(p->expr_1);
auto r = evalExpr(p->expr_2); auto r = evalExpr(p->expr_2);
lastVar = alloc(); lastVar = alloc(l);
p->addop_->accept(this); p->addop_->accept(this);
Str s; Str s;
if (p->type->isEqual(&s)) { if (p->type->isEqual(&s)) {
...@@ -176,6 +177,7 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) { ...@@ -176,6 +177,7 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) {
addQuad<QParam>(r, 1, call); addQuad<QParam>(r, 1, call);
addQuad<QParam>(l, 2, call); addQuad<QParam>(l, 2, call);
addQuad(call); addQuad(call);
lastVar->constExpr = false;
return; return;
} }
...@@ -191,7 +193,7 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) { ...@@ -191,7 +193,7 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) {
void QuadrupleGenerator::visitERel(ERel *p) { void QuadrupleGenerator::visitERel(ERel *p) {
auto l = evalExpr(p->expr_1); auto l = evalExpr(p->expr_1);
auto r = evalExpr(p->expr_2); auto r = evalExpr(p->expr_2);
lastVar = alloc(); lastVar = alloc(l);
p->relop_->accept(this); p->relop_->accept(this);
if ((lastVar->constExpr = l->constExpr && r->constExpr)) { if ((lastVar->constExpr = l->constExpr && r->constExpr)) {
if (op == Op::LT) if (op == Op::LT)
...@@ -381,7 +383,7 @@ void QuadrupleGenerator::visitEApp(EApp *p) { ...@@ -381,7 +383,7 @@ 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 ret = alloc(); auto ret = alloc(funType->type_->clone());
auto call = make_shared<QCall>(ret, info, p->listexpr_->size(), self); auto call = make_shared<QCall>(ret, info, p->listexpr_->size(), self);
int i = 0; int i = 0;
for (auto param = p->listexpr_->rbegin(); param != p->listexpr_->rend(); param++) { for (auto param = p->listexpr_->rbegin(); param != p->listexpr_->rend(); param++) {
......
...@@ -101,7 +101,8 @@ private: ...@@ -101,7 +101,8 @@ private:
void addLastVarCondJump(const VariablePtr& l, Quadruple::Op op, const VariablePtr& r) { void addLastVarCondJump(const VariablePtr& l, Quadruple::Op op, const VariablePtr& r) {
if (labelTrue && labelFalse) { if (labelTrue && labelFalse) {
addQuad<QJumpCond>(labelTrue, l, op, r); addQuad<QJumpCond>(labelTrue, l, op, r);
addQuad<QAssign>(lastVar, l, op, r); // testy jump assign
// addQuad<QAssign>(lastVar, l, op, r);
addQuad<QJump>(labelFalse); addQuad<QJump>(labelFalse);
return; return;
} else if (labelTrue) { } else if (labelTrue) {
...@@ -110,7 +111,10 @@ private: ...@@ -110,7 +111,10 @@ private:
} else if (labelFalse) { } else if (labelFalse) {
addQuad<QJumpCond>(labelFalse, l, op.neg(), r); addQuad<QJumpCond>(labelFalse, l, op.neg(), r);
lastVar = alloc(1); lastVar = alloc(1);
} else return; } else {
// testy jump assign
// return;
}
addQuad<QAssign>(lastVar, l, op, r); addQuad<QAssign>(lastVar, l, op, r);
} }
......
...@@ -6,11 +6,10 @@ ...@@ -6,11 +6,10 @@
void RegisterAllocator::analyseLive() { void RegisterAllocator::analyseLive() {
for (const auto& v : vars) { for (const auto& v : vars) {
if (!v->info) continue;
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; if (/*!v->info ||*/ 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);
} }
...@@ -70,11 +69,12 @@ void RegisterAllocator::buildGraph() { ...@@ -70,11 +69,12 @@ void RegisterAllocator::buildGraph() {
set<VariablePtr> alive = b->flow.in; set<VariablePtr> alive = b->flow.in;
for (const auto& q : b->quads) { for (const auto& q : b->quads) {
alive += to_set(q->definitions()); alive += to_set(q->definitions());
for (const auto& al : alive) assert(al);
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
auto noMoreUses = var->uses.empty() || var->uses.back() == q; auto noMoreUses = var->uses.empty() || var->uses.back() == q;
if ((noMoreUses && !b->flow.out.count(var))) { if ((noMoreUses && !b->flow.out.count(var)) || var->constExpr) {
dead.emplace_back(var); dead.emplace_back(var);
} }
} }
...@@ -89,12 +89,16 @@ void RegisterAllocator::buildGraph() { ...@@ -89,12 +89,16 @@ void RegisterAllocator::buildGraph() {
} }
if (auto assign = dynamic_pointer_cast<QAssign>(q)) { if (auto assign = dynamic_pointer_cast<QAssign>(q)) {
if (assign->op == Quadruple::Op::Copy && !assign->loc->constExpr && alive.count(assign->loc)) { if (assign->op == Quadruple::Op::Copy && !assign->loc->constExpr && alive.count(assign->loc)) {
assert(assign->loc);
assert(assign->args[0]);
graph.addAssign(assign->loc, assign->args[0]); graph.addAssign(assign->loc, assign->args[0]);
} }
} else if (auto phi = dynamic_pointer_cast<QPhi>(q)) { } else if (auto phi = dynamic_pointer_cast<QPhi>(q)) {
for (const auto &phiBlock : phi->phi) { for (const auto &phiBlock : phi->phi) {
for (const auto &phiVars : phiBlock) { for (const auto &phiVars : phiBlock) {
if (alive.count(phiVars.first)) { if (alive.count(phiVars.first)) {
assert(phiVars.first);
assert(phiVars.second);
graph.addAssign(phiVars.first, phiVars.second); graph.addAssign(phiVars.first, phiVars.second);
} }
} }
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
class Variable : std::enable_shared_from_this<Variable> { class Variable : std::enable_shared_from_this<Variable> {
public: public:
Variable() = default; Variable() = default;
explicit Variable(const VariablePtr &v) : info(v->info), type(v->type), constExpr(v->constExpr), val(v->val) {};
explicit Variable(TypePtr t) : type(std::move(t)) {};
explicit Variable(Type *t) : type(t) {};
explicit Variable(VarInfoPtr i) : info(std::move(i)), type(info->type) {}; explicit Variable(VarInfoPtr i) : info(std::move(i)), type(info->type) {};
explicit Variable(int constVal) : type(new Int), constExpr(true), val(constVal) {}; explicit Variable(int constVal) : type(new Int), constExpr(true), val(constVal) {};
explicit Variable(std::string symbolName) : name(std::move(symbolName)) {}; explicit Variable(std::string symbolName) : name(std::move(symbolName)) {};
......
...@@ -3,7 +3,7 @@ t=0 ...@@ -3,7 +3,7 @@ t=0
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
NONE='\033[0m' NONE='\033[0m'
BIN="./latc_x86"
function red { function red {
echo -e "${RED}$@${NONE}" echo -e "${RED}$@${NONE}"
} }
...@@ -13,27 +13,32 @@ function green { ...@@ -13,27 +13,32 @@ function green {
make -j8 && for i in lat/lattests/good/*.lat; do make -j8 && for i in lat/lattests/good/*.lat; do
t=$((t+1)) t=$((t+1))
(./latc "$i" &>/dev/null); ($BIN "$i" &>/dev/null);
if ! [ $? -eq 0 ]; then if ! [ $? -eq 0 ]; then
red "FAIL $i"; red "FAIL $i";
./latc "$i" $BIN "$i"
exit 1; exit 1;
fi fi
if ! diff <( ${i%.*} ) "${i%.*}.output"; then
red "ERROR $i"
exit 1
fi
done && green good OK && for i in lat/lattests/bad/*.lat; do done && green good OK && for i in lat/lattests/bad/*.lat; do
t=$((t+1)) t=$((t+1))
(./latc "$i" &>/dev/null); ($BIN "$i" &>/dev/null);
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
red "FAIL $i"; red "FAIL $i";
./latc "$i" $BIN "$i"
exit 1; exit 1;
fi fi
done && green "OK: $t tests passed!" && for ext in `ls lat/lattests/extensions`; do done && green "OK: $t tests passed!" && for ext in `ls lat/lattests/extensions`; do
ok=1 ok=1
for i in lat/lattests/extensions/$ext/*.lat; do for i in lat/lattests/extensions/$ext/*.lat; do
(./latc "$i" &>/dev/null); ($BIN "$i" &>/dev/null);
if ! [ $? -eq 0 ]; then if ! [ $? -eq 0 ]; then
red "$ext fails on $i"; red "$ext fails on $i";
./latc "$i" $BIN "$i"
ok=0; ok=0;
break; break;
fi fi
......
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