Commit 459ffddf authored by zygzagZ's avatar zygzagZ

Dopychanie kolanem

parent e694f348
......@@ -3,14 +3,14 @@ CCFLAGS=-g -W -Wall -O0 -std=c++2a -Wno-unused-parameter
.PHONY : clean distclean
all : latc
all : latc_x86
clean :
rm -f *.o latc Grammar.aux Grammar.log Grammar.pdf Grammar.dvi Grammar.ps Grammar
rm -f *.o latc_x86 Grammar.aux Grammar.log Grammar.pdf Grammar.dvi Grammar.ps Grammar
latc : Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o Skeleton.o ParseError.o Compiler.o Quadruple.o BasicBlock.o QuadrupleGenerator.o RegisterAllocator.o Latte.o
@echo "Linking latc..."
${CC} ${CCFLAGS} $^ -lstdc++fs -o latc
latc_x86 : Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o Skeleton.o ParseError.o Compiler.o Quadruple.o BasicBlock.o QuadrupleGenerator.o RegisterAllocator.o Latte.o
@echo "Linking latc_x86..."
${CC} ${CCFLAGS} $^ -lstdc++fs -o latc_x86
Absyn.o : src/Absyn.cpp src/Absyn.h
${CC} ${CCFLAGS} -c src/Absyn.cpp
......@@ -30,7 +30,7 @@ Skeleton.o : src/Skeleton.cpp src/Skeleton.h src/Absyn.h
TypeCheck.o : src/TypeCheck.cpp src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h
${CC} ${CCFLAGS} -c src/TypeCheck.cpp
Compiler.o : src/Compiler.cpp src/Compiler.h src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h src/codeGen/Quadruple.h src/codeGen/Variable.h src/codeGen/QuadrupleGenerator.h src/codeGen/RegisterAllocator.h src/codeGen/Graph.h
Compiler.o : src/Compiler.cpp src/Compiler.h src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h src/codeGen/Quadruple.h src/codeGen/Variable.h src/codeGen/QuadrupleGenerator.h src/codeGen/RegisterAllocator.h src/codeGen/Graph.h src/codeGen/BasicBlock.h
${CC} ${CCFLAGS} -c src/Compiler.cpp
Info.o : src/Info.cpp src/Info.h src/InfoList.h src/Absyn.h
......
This diff is collapsed.
......@@ -38,6 +38,13 @@ public:
void generateQJump(QJump &q);
void generateQAssign(QAssign &q);
void generateQLabel(QLabel &q);
static std::string mangleFunctionName(const FunctionInfoPtr& f) {
if (auto c = f->klass.lock()) {
return c->name + "::" + f->name;
}
return f->name;
}
private:
std::filesystem::path file;
std::stringstream buf;
......@@ -52,7 +59,14 @@ private:
class Register {
public:
Register(string n) : name(std::move(n)) {};
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;
......@@ -61,16 +75,12 @@ private:
bool operator!=(const Register &other) const { return name != other.name; }
};
static std::string mangleFunctionName(const FunctionInfoPtr& f) {
if (auto c = f->klass.lock()) {
return c->name + "::" + f->name;
}
return f->name;
}
string getRef(VariablePtr &v);
static const char* const regs[6];
static const int callerSavedRegisters[2];
static const int calleeSavedRegisters[3];
static string getOpName(Quadruple::Op op) {
switch(op.op) {
......@@ -79,10 +89,12 @@ private:
case Op::Mul: return "IMULL";
case Op::Div:
case Op::Mod: throw runtime_error("Impossible to handle division with default");
case Op::Not: return "SETZ";
case Op::Copy: return "SETNZ";
case Op::LT: return "SETL";
case Op::LE: return "SETLE";
case Op::EQ: return "SETE";
case Op::NEQ: return "SETNE";
case Op::EQ: return "SETZ";
case Op::NEQ: return "SETNZ";
case Op::GE: return "SETGE";
case Op::GT: return "SETG";
default: return "Op" + to_string(op.op) + "?";
......@@ -121,7 +133,57 @@ private:
}
void append(string cmd, string op1 = "", string op2 = "", string op3 = "") {
buf << "\t" << cmd << " " << op1 << " " << op2 << " " << op3 << endl;
append({cmd, op1, op2, op3});
}
void append(vector<string> ops) {
static const char* const delimiters = "\t ,,,,";
assert(ops.size() < 6);
while (ops.size() && ops.back().empty())
ops.pop_back();
buf << "\t";
for (uint i = 0; i < ops.size(); i++) {
buf << delimiters[i] << ops[i];
}
buf << endl;
}
string getBlockLabelText(const QuadruplePtr &q) {
return getBlockLabelText(q->block);
}
string getBlockLabelText(BasicBlockPtr &b) {
auto n = b->getName();
if (n.empty()) throw runtime_error("Attempt to get label text of unlabeled block");
return "\"" + n + "\"";
}
shared_ptr<QLabel> exitLabel;
void generateStandardReturn() {
append("JMP", "\"" + exitLabel->label + "\"");
}
vector<Register> registersToSave(QCall &q) {
const int noRegs = sizeof(callerSavedRegisters) / sizeof(*callerSavedRegisters);
bool saved[noRegs];
int notSaved = noRegs;
for (auto &i : saved) i = false;
for (auto &live : q.aliveAfter) {
for (int i = 0; i < noRegs; i++) {
int r = callerSavedRegisters[i];
if (!saved[i] && Register(live) == Register(r)) {
saved[i] = true;
--notSaved;
}
}
if (notSaved == 0) break;
}
vector<Register> ret;
for (int i = 0; i < noRegs; i++) {
if (saved[i]) ret.emplace_back(callerSavedRegisters[i]);
}
return ret;
}
};
......
......@@ -50,7 +50,7 @@ public:
void addPhi(const BasicBlockPtr& blk, const VariablePtr& local, VariablePtr remote) {
assert(blk && local && remote);
assert(local->info && !local->info->isInstanceVariable());
assert(!local->info || !local->info->isInstanceVariable());
auto &phiMap = findPhi(blk);
phiMap[local] = std::move(remote);
}
......
......@@ -9,9 +9,9 @@
using namespace std;
class Compiler;
static const std::string opNames[] = { "_U", "-", "!", "", "_UE",
static const std::string opNames[] = { "_U", "!", "", "-", "_UE",
"_B", "+", "-", "*", "/", "%", "&", "|", "^", "_BE",
"_C", "<", "<=", "==", "!=", ">=", ">", "_CE"};
"_C", "<", ">=", "<=", ">", "==", "!=", "_CE"};
class Quadruple : public enable_shared_from_this<Quadruple> {
public:
......@@ -19,22 +19,35 @@ public:
public:
enum OpType {
UNARY,
Neg, Not, Copy, UNARY_END,
Not, Copy, Neg, UNARY_END,
BINARY,
Plus, Minus, Mul, Div, Mod, And, Or, Xor, BINARY_END,
CMP,
LT, LE, EQ, NEQ, GE, GT, CMP_END
LT, GE, LE, GT, EQ, NEQ, CMP_END
};
OpType op;
Op(OpType op = UNARY) : op(op) {};
operator OpType() const { return op; };
Op neg() const {
if (op <= Op::Copy)
return OpType(UNARY + 1 + ((int)(op - UNARY - 1)^1));
if (op > Op::CMP)
return OpType(CMP + 1 + ((int)(op - CMP - 1)^1));
throw runtime_error("Invalid argument to Op::neg()");
};
static OpType kind(OpType op) {
if (op <= UNARY_END) return UNARY;
if (op <= BINARY_END) return BINARY;
return CMP;
};
OpType kind() const {
return Op::kind(*this);
};
static const std::string& name(OpType op) {
return opNames[op];
}
......@@ -71,7 +84,7 @@ public:
std::string toString() const override { return Quadruple::toString() + "\t" + (loc ? (loc->name + " := ") : ""); }
vector<VariablePtr> definitions() const override {
auto ret = Quadruple::definitions();
if (loc) ret.emplace_back(loc);
if (loc && !loc->constExpr) ret.emplace_back(loc);
return ret;
};
};
......@@ -147,13 +160,16 @@ public:
}
void generateAsm(Compiler &c) override;
};
class QCall;
class QParam : public Quadruple {
public:
VariablePtr param;
int num;
QParam(VariablePtr param, int num) : param(std::move(param)), num(num) {};
shared_ptr<QCall> call;
QParam(VariablePtr param, int num, shared_ptr<QCall> call = nullptr) : param(std::move(param)), num(num), call(std::move(call)) {};
std::string toString() const override {
if (num < 0) {
......
......@@ -46,10 +46,10 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
for (const auto& q : b->quads) {
q->index = index++;
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++);
auto old = l->label;
l->label = "." + to_string(label++) + "_" + Compiler::mangleFunctionName(f);
if (!old.empty())
l->label += "_" + old;
}
}
}
......@@ -109,10 +109,12 @@ void QuadrupleGenerator::visitELitInt(ELitInt *p) {
void QuadrupleGenerator::visitELitTrue(ELitTrue *p) {
lastVar = alloc(1);
if (labelTrue) addQuad<QJump>(labelTrue);
}
void QuadrupleGenerator::visitELitFalse(ELitFalse *p) {
lastVar = alloc(0);
if (labelFalse) addQuad<QJump>(labelFalse);
}
void QuadrupleGenerator::visitEString(EString *p) {
......@@ -128,12 +130,20 @@ void QuadrupleGenerator::visitNeg(Neg *p) {
auto var = evalExpr(p->expr_);
lastVar = alloc();
addQuad<QAssign>(lastVar, Op::Neg, var);
if ((lastVar->constExpr = var->constExpr)) {
lastVar->val = -var->val;
}
}
void QuadrupleGenerator::visitNot(Not *p) {
swap(labelTrue, labelFalse);
auto var = evalExpr(p->expr_);
swap(labelTrue, labelFalse);
lastVar = alloc();
addQuad<QAssign>(lastVar, Op::Not, var);
if ((lastVar->constExpr = var->constExpr)) {
lastVar->val = !var->val;
}
}
void QuadrupleGenerator::visitEMul(EMul *p) {
......@@ -142,6 +152,16 @@ void QuadrupleGenerator::visitEMul(EMul *p) {
lastVar = alloc();
p->mulop_->accept(this);
addQuad<QAssign>(lastVar, l, op, r);
if ((lastVar->constExpr = l->constExpr && r->constExpr)) {
if (op == Op::Mul)
lastVar->val = l->val * r->val;
else if (r->val == 0)
throw ParseError("Division by 0", p);
else if (op == Op::Div)
lastVar->val = l->val / r->val;
else if (op == Op::Mod)
lastVar->val = l->val % r->val;
}
}
void QuadrupleGenerator::visitEAdd(EAdd *p) {
......@@ -150,48 +170,120 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) {
lastVar = alloc();
p->addop_->accept(this);
addQuad<QAssign>(lastVar, l, op, r);
if ((lastVar->constExpr = l->constExpr && r->constExpr)) {
if (op == Op::Minus)
lastVar->val = l->val - r->val;
else if (op == Op::Plus)
lastVar->val = l->val + r->val;
}
}
void QuadrupleGenerator::visitERel(ERel *p) {
auto l = evalExpr(p->expr_1);
auto r = evalExpr(p->expr_2);
auto l = evalJump(p->expr_1, nullptr, nullptr);
auto r = evalJump(p->expr_2, nullptr, nullptr);
lastVar = alloc();
p->relop_->accept(this);
addQuad<QAssign>(lastVar, l, op, r);
if ((lastVar->constExpr = l->constExpr && r->constExpr)) {
if (op == Op::LT)
lastVar->val = l->val < r->val;
else if (op == Op::LE)
lastVar->val = l->val <= r->val;
else if (op == Op::EQ)
lastVar->val = l->val == r->val;
else if (op == Op::NEQ)
lastVar->val = l->val != r->val;
else if (op == Op::GE)
lastVar->val = l->val >= r->val;
else if (op == Op::GT)
lastVar->val = l->val > r->val;
addQuad<QAssign>(lastVar, l, op, r);
}
addLastVarCondJump(l, op, r);
}
void QuadrupleGenerator::visitEAnd(EAnd *p) {
auto l = evalExpr(p->expr_1);
auto labelLeft = make_shared<QLabel>("use_left");
auto labelAfter = make_shared<QLabel>("end_and");
addQuad<QJumpCond>(labelLeft, Op::Not, l);
auto r = evalExpr(p->expr_2);
lastVar = alloc();
addQuad<QAssign>(lastVar, Op::Copy, r);
addQuad<QJump>(labelAfter);
addQuad(labelLeft);
addQuad<QAssign>(lastVar, Op::Copy, alloc(0));
addQuad(labelAfter);
auto labelAfter = make_shared<QLabel>("and_else");
auto l = evalJump(p->expr_1, nullptr, labelFalse);
if (!l) return;
if (l->constExpr) {
lastVar = l->val ? evalJump(p->expr_2, labelTrue, labelFalse) : l;
// jest git skoczymy pozniej bo to constexpr
return;
} else {
auto leftValBlock = block;
auto llq = make_shared<QJumpCond>(labelFalse ? labelFalse : labelAfter, Op::Not, l);
addQuad(llq);
flushBasicBlock();
leftValBlock->append(block);
auto r = evalJump(p->expr_2, labelTrue, labelFalse);
if (!r || r->constExpr) {
assert(leftValBlock->quads.back() == llq);
leftValBlock->quads.pop_back();
// could merge basic blocks now, but why bother
if (r) {
lastVar = r->val ? l : r;
}
} else {
auto rightValBlock = block;
flushBasicBlock();
addQuad(labelAfter);
rightValBlock->append(block);
leftValBlock->append(block);
if (!labelTrue || !labelFalse) {
lastVar = alloc();
block->addPhi(rightValBlock, lastVar, r);
block->addPhi(leftValBlock, lastVar, l);
} else {
lastVar = nullptr;
}
}
}
}
void QuadrupleGenerator::visitEOr(EOr *p) {
auto l = evalExpr(p->expr_1);
auto labelLeft = make_shared<QLabel>("use_left");
auto labelAfter = make_shared<QLabel>("end_or");
addQuad<QJumpCond>(labelLeft, Op::Copy, l);
auto r = evalExpr(p->expr_2);
lastVar = alloc();
addQuad<QAssign>(lastVar, Op::Copy, r);
addQuad<QJump>(labelAfter);
addQuad(labelLeft);
addQuad<QAssign>(lastVar, Op::Copy, alloc(1));
addQuad(labelAfter);
auto labelAfter = make_shared<QLabel>("or_else");
auto l = evalJump(p->expr_1, labelTrue, nullptr);
if (!l) return;
if (l->constExpr) {
lastVar = l->val ? l : evalJump(p->expr_2, labelTrue, labelFalse);
// jest git skoczymy pozniej bo to constexpr
return;
} else {
auto leftValBlock = block;
auto llq = make_shared<QJumpCond>(labelTrue ? labelTrue : labelAfter, Op::Copy, l);
addQuad(llq);
flushBasicBlock();
leftValBlock->append(block);
auto r = evalExpr(p->expr_2);
if (!r) return;
if (r->constExpr) {
assert(leftValBlock->quads.back() == llq);
leftValBlock->quads.pop_back();
// could merge basic blocks now, but why bother
lastVar = r->val ? r : l;
} else {
auto rightValBlock = block;
flushBasicBlock();
addQuad(labelAfter);
rightValBlock->append(block);
leftValBlock->append(block);
if (!labelTrue || !labelFalse) {
lastVar = alloc();
block->addPhi(rightValBlock, lastVar, r);
block->addPhi(leftValBlock, lastVar, l);
} else {
lastVar = nullptr;
}
}
}
}
/// complex extensions
......@@ -219,6 +311,10 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
}
auto quad = make_shared<QAccess>(lastVar, lhs, index, 4, 0);
addQuad(quad);
Bool b;
if (type->type_->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar);
}
}
void QuadrupleGenerator::visitEClsMmbr(EClsMmbr *p) {
......@@ -240,6 +336,10 @@ void QuadrupleGenerator::visitEClsMmbr(EClsMmbr *p) {
auto quad = make_shared<QAccess>(lastVar, l, nullptr, 0, offset);
addQuad(quad);
}
Bool b;
if (var->type->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar);
}
}
void QuadrupleGenerator::visitEApp(EApp *p) {
......@@ -270,18 +370,24 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
throw ParseError("Unimplemented EApp instantiation (neither EClsMmbr nor EVar", p);
}
int i = 1;
auto call = make_shared<QCall>(lastVar, info, p->listexpr_->size(), self);
int i = 0;
for (auto param : *p->listexpr_) {
auto var = evalExpr(param);
addQuad<QParam>(var, i++);
addQuad<QParam>(var, ++i, call);
}
if (self) {
addQuad<QParam>(self, 0);
addQuad<QParam>(self, 0, call);
}
lastVar = alloc();
addQuad<QCall>(lastVar, info, i, self);
addQuad(call);
Bool b;
if (info->type->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar);
}
}
void QuadrupleGenerator::visitENewArray(ENewArray *p) {
......@@ -387,17 +493,16 @@ void QuadrupleGenerator::visitCondElse(CondElse *p) {
}
void QuadrupleGenerator::compileCond(Expr *expr_, Stmt *stmt_1, Stmt *stmt_2) {
// TODO: stmty nie składają się z jednego bloku tylko z wielu
auto elseBranch = make_shared<QLabel>("if_else");
auto after = make_shared<QLabel>("end_else");
auto ifBranch = make_shared<QLabel>("if_true");
auto var = evalExpr(expr_);
evalJump(expr_, ifBranch, elseBranch);
addQuad<QJumpCond>(elseBranch, Op::Not, var);
auto beforeBlock = flushBasicBlock(); // possible jump -> else
auto envIf = captureEnv(), envElse = envIf;
auto stmtIfFirstBlock = block;
addQuad<QLabel>("if_true");
addQuad(ifBranch);
stmt_1->accept(this);
addQuad<QJump>(after);
auto stmtIfLastBlock = flushBasicBlock(); // jump -> after
......
......@@ -30,6 +30,7 @@ private:
VariablePtr lastVar;
int lineno;
shared_ptr<Scope> scope;
shared_ptr<QLabel> labelTrue, labelFalse;
VariablePtr evalLVal(Visitable *expr) {
auto info = evalExpr(expr)->info;
......@@ -55,6 +56,17 @@ private:
return ret;
}
VariablePtr evalJump(Visitable *expr, shared_ptr<QLabel> tLabel, shared_ptr<QLabel> fLabel) {
if (!expr) throw runtime_error("No expr to eval");
lineno = expr->lineno;
swap(labelTrue, tLabel);
swap(labelFalse ,fLabel);
auto ret = evalExpr(expr);
swap(labelTrue, tLabel);
swap(labelFalse ,fLabel);
return ret;
}
VariablePtr alloc(const VarInfoPtr& info) {
if (info->loc) {
return info->loc;
......@@ -84,6 +96,22 @@ private:
return quad;
}
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);
addQuad<QJump>(labelFalse);
return;
} else if (labelTrue) {
addQuad<QJumpCond>(labelTrue, l, op, r);
lastVar = alloc(0);
} else if (labelFalse) {
addQuad<QJumpCond>(labelFalse, l, op.neg(), r);
lastVar = alloc(1);
} else return;
addQuad<QAssign>(lastVar, l, op, r);
}
QuadruplePtr lastQuad;
BasicBlockPtr newBlock() {
......
......@@ -104,7 +104,7 @@ void RegisterAllocator::buildGraph() {
if (v.second == -1) {
gNumSpill++;
} else {
v.first->name += "-r" + to_string(v.second);
v.first->name += "-r" + to_string(v.second + 2);
}
}
for (auto &v : g2.getAllocation()) {
......
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