Commit e694f348 authored by zygzagZ's avatar zygzagZ

WIP asm

parent bb0ba170
......@@ -65,6 +65,17 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
}
printFunction(quadEnv);
// for (auto &b : quadEnv.blocks) {
// for (auto &q : b->quads) {
// q->generateAsm(*this);
// }
// }
for (auto &t : temps) t->localOffset = 0;
for (auto &v : localInfos) v->localOffset = 0;
temps.clear();
localInfos.clear();
}
void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) {
......@@ -108,6 +119,7 @@ void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) {
for (auto var : q->aliveAfter)
buf << var->name << " ";
buf << endl;
q->generateAsm(*this);
}
}
if (!b->flow.use.empty()) {
......@@ -128,17 +140,25 @@ void Compiler::printFunction(QuadrupleGenerator::Result quadEnv) {
}
}
Compiler::regs = {"eax", "ebx", "ecx", "edx", "esi", "edi"};
const char* const Compiler::regs[6] = {"eax", "ebx", "ecx", "edx", "esi", "edi"};
string Compiler::getRef(VariablePtr &v) {
if (v->registerColor == -1) {
if (!v->localOffset) {
temps.emplace(v);
v->localOffset = 4 * temps.size();
if (v->info) {
if (!v->info->localOffset) {
localInfos.emplace(v->info);
v->info->localOffset = 4 * (temps.size() + localInfos.size());
}
v->localOffset = v->info->localOffset;
} else {
temps.emplace(v);
v->localOffset = 4 * (temps.size() + localInfos.size());
}
}
return to_string(v->localOffset) + "(ebp)";
return to_string(v->localOffset) + "(%ebp)";
} else {
return regs[v->registerColor+1];
return Register(v);
}
}
......@@ -174,32 +194,90 @@ void Compiler::generateQCall(QCall &q) {
void Compiler::generateQParam(QParam &q) {
// return Quadruple::generateAsm();
auto reg = Register(q.param);
if (q.num < 0) {
auto offset = 4 * q.num;
if (reg == 0) {
q.param->localOffset = offset;
} else {
append("MOVL", to_string(offset)+"(%ebp)");
}
} else {
append("PUSHL", getRef(q.param));
}
}
void Compiler::generateQJump(QJump &q) {
// return Quadruple::generateAsm();
// append("JMP", q.block.la)
}
void Compiler::generateQAssign(QAssign &q) {
string tg = regs[q.loc->registerColor + 1];
Register tg(q.loc);
if (q.args.size() == 1) {
auto &arg = q.args[0];
switch (q.op.op) {
case Op::Not: {
buf << ""
return;
auto reg = Register(arg);
if (reg == 0) {
// avoids extra MOV when arg is already in register
moveTo(arg, tg);
reg = tg;
}
append("TEST", reg, reg);
append("SETZ", tg);
break;
}
case Op::Copy: {
if (arg->constExpr) {
// TODO
} else {
moveTo(arg, tg);
}
break;
}
case Op::Neg: {
moveTo(arg, tg);
append("NEG", tg);
break;
}
default: throw runtime_error("Unexpected operand");
}
} else {
buf << "movl %" << tg << " ";
auto &i = q.args[0], &j = q.args[1];
buf << getRef(i) << endl;
buf << getOpName(q.op) << " %" << tg << " " << getRef(i) << endl;
if (q.op == Op::Div || q.op == Op::Mod) {
auto edx = Register("edx");
bool backupEdx = edx != tg && edx != Register(i);
if (backupEdx) append("MOVL", edx, "4(%esp)");
auto jLoc = edx != Register(j) ? getRef(j) : "4(%esp)";
moveTo(i, 0);
append("CLTD"); // edx lost
append("IDIVL", jLoc);
moveTo(q.op == Op::Mod ? edx : 0, getRef(q.loc));
// restore unnecessary if j was in edx and becomes dead and was NOT coalesced
if (backupEdx) append("MOVL", "4(%esp)", edx);
return;
} else if (q.op < Op::CMP) {
moveTo(i, tg);
append(q.op, getRef(i), tg);
} else {
auto loc = getRef(i);
if (Register(i) == 0 && Register(j) == 0) {
moveTo(i, 0);
loc = "%eax";
}
append("CMPL", loc, getRef(j));
append(q.op, tg);
}
}
if (tg == 0) {
append("MOVL", tg, getRef(q.loc));
}
}
void Compiler::generateQLabel(QLabel &q) {
// return Quadruple::generateAsm();
}
\ No newline at end of file
}
......@@ -50,6 +50,17 @@ private:
void compileFunction(const FunctionInfoPtr& f);
void printFunction(QuadrupleGenerator::Result quadEnv);
class Register {
public:
Register(string n) : name(std::move(n)) {};
Register(int n) { name = Compiler::regs[n]; }
Register(const VariablePtr &v) { name = Compiler::regs[v->registerColor + 1]; }
string name;
operator string() { return "%" + name; }
bool operator==(const Register &other) const { return name == other.name; }
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;
......@@ -59,24 +70,58 @@ private:
string getRef(VariablePtr &v);
static const char** regs;
static const char* const regs[6];
static string getOpName(Quadruple::Op op) {
switch(op.op) {
case Op::Plus: return "addl";
case Op::Minus: return "subl";
case Op::Mul: return "mull";
case Op::Div: return "divl";
case Op::Mod: return "divl";
default: return "";
case Op::Plus: return "ADDL";
case Op::Minus: return "SUBL";
case Op::Mul: return "IMULL";
case Op::Div:
case Op::Mod: throw runtime_error("Impossible to handle division with default");
case Op::LT: return "SETL";
case Op::LE: return "SETLE";
case Op::EQ: return "SETE";
case Op::NEQ: return "SETNE";
case Op::GE: return "SETGE";
case Op::GT: return "SETG";
default: return "Op" + to_string(op.op) + "?";
}
}
void moveTo(VariablePtr &v, Register tg) {
if (v->constExpr) {
append("MOVL", "$"+to_string(v->val), tg);
return;
}
auto reg = Register(v);
if (reg == 0) {
append("MOVL", getRef(v), tg);
} else if (reg != tg) {
append("MOVL", reg, tg);
}
}
void moveTo(Register reg, Register tg) {
if (reg != tg) {
append("MOVL", reg, tg);
}
}
Register moveToAnyRegister(VariablePtr &v) {
auto reg = Register(v);
if (reg == 0) {
append("MOVL", getRef(v), reg);
}
return reg;
}
void append(Quadruple::Op op, string op1, string op2 = "", string op3 = "") {
return append(getOpName(op), op1, op2, op3);
}
string moveToAnyRegister(VariablePtr &v) {
if (v->registerColor == -1) {
buf << "movl %eax " << getRef(v) << endl;
return "eax";
} else return regs[v->registerColor+1];
void append(string cmd, string op1 = "", string op2 = "", string op3 = "") {
buf << "\t" << cmd << " " << op1 << " " << op2 << " " << op3 << endl;
}
};
......
......@@ -13,26 +13,6 @@ using namespace std;
class BasicBlock : public std::enable_shared_from_this<BasicBlock> {
public:
struct FlowAnalysisData {
set<VariablePtr> in, out, def, use;
BasicBlock *b {};
void addUse(const VariablePtr& v) {
if (!def.contains(v)) use.emplace(v);
}
void addDef(const VariablePtr &v) {
def.emplace(v);
use.erase(v);
}
[[nodiscard]] set<VariablePtr> inForBlock(const BasicBlockPtr& q) const {
set<VariablePtr> ret;
for (const auto& var : b->findPhi(q)) {
ret.emplace(var.second);
}
return in + ret;
}
};
BasicBlock() {
phi = make_shared<QPhi>();
flow.b = this;
......@@ -42,7 +22,6 @@ public:
vector<QuadruplePtr> afterInit;
vector<BasicBlockPtr> in, out;
shared_ptr<QPhi> phi;
FlowAnalysisData flow;
void append(const BasicBlockPtr& after) {
out.push_back(after);
after->in.push_back(shared_from_this());
......@@ -77,6 +56,28 @@ public:
}
void finishQuads();
struct FlowAnalysisData {
set<VariablePtr> in, out, def, use;
BasicBlock *b {};
void addUse(const VariablePtr& v) {
if (!def.contains(v)) use.emplace(v);
}
void addDef(const VariablePtr &v) {
def.emplace(v);
use.erase(v);
}
[[nodiscard]] set<VariablePtr> inForBlock(const BasicBlockPtr& q) const {
set<VariablePtr> ret;
for (const auto& var : b->findPhi(q)) {
ret.emplace(var.second);
}
return in + ret;
}
};
FlowAnalysisData flow;
};
......
......@@ -69,7 +69,7 @@ void RegisterAllocator::buildGraph() {
set<VariablePtr> alive = b->flow.in;
for (const auto& q : b->quads) {
if (auto assign = dynamic_pointer_cast<QAssign>(q)) {
if (assign->op == Quadruple::Op::Copy) {
if (assign->op == Quadruple::Op::Copy && !assign->args[0]->constExpr) {
graph.addAssign(assign->loc, assign->args[0]);
g2.addAssign(assign->loc->name, assign->args[0]->name);
}
......
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