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