Commit aafb3bcc authored by zygzagZ's avatar zygzagZ

WIP virtual classes

parent deb3fc4d
...@@ -2898,7 +2898,7 @@ bool Fun::isEqual(Type const *other, bool sub) const { ...@@ -2898,7 +2898,7 @@ bool Fun::isEqual(Type const *other, bool sub) const {
return false; return false;
} }
for (unsigned int i = 0; i < listtype_->size(); i++) { for (unsigned int i = 0; i < listtype_->size(); i++) {
if (!casted->listtype_->at(i)->isEqual(listtype_->at(i), true)) { if (!listtype_->at(i)->isEqual(casted->listtype_->at(i), true)) {
return false; return false;
} }
} }
......
...@@ -182,8 +182,8 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu ...@@ -182,8 +182,8 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu
void Compiler::genVirtTables() { void Compiler::genVirtTables() {
for (const auto &c : scope->classes) { for (const auto &c : scope->classes) {
if (!c->functionCount) continue;
buf << quoted(getVirtName(c)) << ":\n"; buf << quoted(getVirtName(c)) << ":\n";
if (!c->functionCount) continue;
vector<string> names(c->functionCount, ""); vector<string> names(c->functionCount, "");
auto p = c; auto p = c;
while (p) { while (p) {
...@@ -241,7 +241,8 @@ string Compiler::getRef(const VariablePtr &v) { ...@@ -241,7 +241,8 @@ string Compiler::getRef(const VariablePtr &v) {
} }
void Compiler::generateQAlloc(QAlloc &q) { void Compiler::generateQAlloc(QAlloc &q) {
if (!q.aliveAfter.count(q.loc)) { return; } if (!q.aliveAfter.count(q.loc) && !q.loc->isInstanceVariable()) { return; }
// jesli zaden nie rejestr to obliczyc adres do eax
// int len, size_t size, void* virtTab // int len, size_t size, void* virtTab
auto saveRegs = registersToSave(q); auto saveRegs = registersToSave(q);
for (auto r : saveRegs) { for (auto r : saveRegs) {
...@@ -255,11 +256,12 @@ void Compiler::generateQAlloc(QAlloc &q) { ...@@ -255,11 +256,12 @@ void Compiler::generateQAlloc(QAlloc &q) {
append("PUSHL", "$" + quote(q.virtSymbol)); append("PUSHL", "$" + quote(q.virtSymbol));
} }
append("PUSHL", "$" + to_string(q.size));
if (q.count) { if (q.count) {
append("PUSHL", getRef(q.count)); append("PUSHL", getRef(q.count));
} }
append("PUSHL", "$" + to_string(q.size));
append("CALL", q.count ? "__latte_mem_init_array" : "__latte_mem_init"); append("CALL", q.count ? "__latte_mem_init_array" : "__latte_mem_init");
append("ADDL", "$" + to_string(q.count ? 12 : 8), "%esp"); append("ADDL", "$" + to_string(q.count ? 12 : 8), "%esp");
...@@ -273,12 +275,12 @@ void Compiler::generateQAlloc(QAlloc &q) { ...@@ -273,12 +275,12 @@ void Compiler::generateQAlloc(QAlloc &q) {
void Compiler::generateQWrite(QWrite &q) { void Compiler::generateQWrite(QWrite &q) {
// memory = extension // memory = extension
throw runtime_error("Memory write unimplemented!"); append("MOVL", getRef(q.val), getRef(q.loc));
} }
void Compiler::generateQAccess(QAccess &q) { void Compiler::generateQAccess(QAccess &q) {
// memory = extension // memory = extension
throw runtime_error("Memory access unimplemented!"); append("MOVL", getRef(q.access), getRef(q.loc));
} }
void Compiler::generateQReturn(QReturn &q) { void Compiler::generateQReturn(QReturn &q) {
...@@ -290,11 +292,18 @@ void Compiler::generateQReturn(QReturn &q) { ...@@ -290,11 +292,18 @@ void Compiler::generateQReturn(QReturn &q) {
void Compiler::generateQCall(QCall &q) { void Compiler::generateQCall(QCall &q) {
if (q.self) { if (q.self) {
throw runtime_error("Class call unimplemented!"); auto tg = Register(q.self);
auto eax = Register(0);
if (tg == 0) {
append("MOVL", getRef(q.self), tg);
} }
append("MOVL", "(" + (string)tg + ")", eax); // eax := virt table's address
append("CALL", "*" + to_string(q.fn->offset * 4) + "(%eax)"); // get proper function from virt table
} else {
append("CALL", quote(mangleFunctionName(q.fn))); append("CALL", quote(mangleFunctionName(q.fn)));
}
if (q.params) { if (q.params) {
append("ADDL", "$" + to_string(q.params*4), "%esp"); append("ADDL", "$" + to_string(q.params*4 + (q.self ? 4 : 0)), "%esp");
} }
auto popRegs = registersToSave(q); auto popRegs = registersToSave(q);
for (auto r = popRegs.rbegin(); r != popRegs.rend(); r++) { for (auto r = popRegs.rbegin(); r != popRegs.rend(); r++) {
...@@ -307,8 +316,18 @@ void Compiler::generateQCall(QCall &q) { ...@@ -307,8 +316,18 @@ void Compiler::generateQCall(QCall &q) {
} }
void Compiler::generateQParam(QParam &q) { void Compiler::generateQParam(QParam &q) {
// return Quadruple::generateAsm(); if (q.call) {
if (q.num < 0) { assert(q.num >= 0);
if (q.num == 1) {
// first argument, need to save registers
for (auto r : registersToSave(*q.call)) {
if (r != Register(q.call->loc))
append("PUSHL", r);
}
}
append("PUSHL", getRef(q.param));
} else {
assert(q.num <= 0);
auto reg = Register(q.param); auto reg = Register(q.param);
auto offset = 4 * (q.num - Register::calleeSaved.size() - 1); // push regs + ebp auto offset = 4 * (q.num - Register::calleeSaved.size() - 1); // push regs + ebp
if (reg == 0) { if (reg == 0) {
...@@ -317,15 +336,6 @@ void Compiler::generateQParam(QParam &q) { ...@@ -317,15 +336,6 @@ void Compiler::generateQParam(QParam &q) {
} else { } else {
append("MOVL", to_string(-offset)+"(%ebp)", reg); append("MOVL", to_string(-offset)+"(%ebp)", reg);
} }
} else {
if (q.num == 1 && q.call) {
// first argument, need to save registers
for (auto r : registersToSave(*q.call)) {
if (r != Register(q.call->loc))
append("PUSHL", r);
}
}
append("PUSHL", getRef(q.param));
} }
} }
......
...@@ -91,6 +91,19 @@ private: ...@@ -91,6 +91,19 @@ private:
void genVirtTables(); void genVirtTables();
string getRef(const VariablePtr &v); string getRef(const VariablePtr &v);
string getRef(const VariableLocation &loc) {
int offset = loc.offset;
if (loc.index) {
if (loc.index->constExpr) {
offset += loc.index->val * loc.multiplier;
} else {
auto ret = to_string(offset) + "(" + getRef(loc.base) + "," + getRef(loc.index);
if (loc.multiplier != 1) ret += "," + to_string(loc.multiplier);
return ret + ")";
}
}
return to_string(offset) + "(" + getRef(loc.base) + ")";
}
void generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap); void generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap);
static string getOpName(Quadruple::Op op) { static string getOpName(Quadruple::Op op) {
......
...@@ -55,7 +55,7 @@ size_t ClassInfo::calculateSize() { ...@@ -55,7 +55,7 @@ size_t ClassInfo::calculateSize() {
if (auto pv = parent->functions.find(f->name)) { if (auto pv = parent->functions.find(f->name)) {
// verify types // verify types
if (!f->type->isEqual(pv->type, true)) { if (!f->type->isEqual(pv->type, true)) {
throw InvalidTypeError(*f->type, {pv->type}, f->ident); throw InvalidTypeError(*pv->type, {f->type}, f->ident);
} }
f->offset = pv->offset; f->offset = pv->offset;
continue; continue;
......
...@@ -43,11 +43,14 @@ public: ...@@ -43,11 +43,14 @@ public:
vector<VarInfoPtr> arguments; vector<VarInfoPtr> arguments;
weak_ptr<ClassInfo> klass; weak_ptr<ClassInfo> klass;
weak_ptr<Binding> binding; weak_ptr<Binding> binding;
VarInfoPtr self;
FunctionInfo(FuncDef *expr, ClassInfoPtr klass = nullptr); FunctionInfo(FuncDef *expr, ClassInfoPtr klass = nullptr);
FunctionInfo(string name, TypePtr type) : VarInfo(name, type), block(nullptr) {}; FunctionInfo(string name, TypePtr type) : VarInfo(name, type), block(nullptr) {};
// FunctionInfo(PIdent *ident, ClassInfoPtr klass = nullptr) : VarInfo(ident), block(NULL), klass(klass) {}; // FunctionInfo(PIdent *ident, ClassInfoPtr klass = nullptr) : VarInfo(ident), block(NULL), klass(klass) {};
virtual string kind() const { return "function"; } virtual string kind() const { return "function"; }
ClassInfoPtr getClass() const { return klass.lock(); }
BindingPtr getBinding() const { return binding.lock(); }
}; };
......
...@@ -661,7 +661,8 @@ void TypeCheck::checkFunction(FunctionInfoPtr f) ...@@ -661,7 +661,8 @@ void TypeCheck::checkFunction(FunctionInfoPtr f)
BindingPtr binding = make_shared<Binding>(getParentBinding()); BindingPtr binding = make_shared<Binding>(getParentBinding());
f->binding = binding; f->binding = binding;
if (scope->currentClass) { if (scope->currentClass) {
binding->variables << make_shared<VarInfo>("self", scope->currentClass->type); f->self = make_shared<VarInfo>("self", scope->currentClass->type);
binding->variables << f->self;
} }
for (auto arg : f->arguments) { for (auto arg : f->arguments) {
......
...@@ -202,13 +202,13 @@ public: ...@@ -202,13 +202,13 @@ public:
vector<VariablePtr> vars() const override { vector<VariablePtr> vars() const override {
auto ret = Quadruple::vars(); auto ret = Quadruple::vars();
if (param && num >= 0) ret.emplace_back(param); if (param && call) ret.emplace_back(param);
return ret; return ret;
} }
vector<VariablePtr> definitions() const override { vector<VariablePtr> definitions() const override {
auto ret = Quadruple::definitions(); auto ret = Quadruple::definitions();
if (param && num < 0) ret.emplace_back(param); if (param && !call) ret.emplace_back(param);
return ret; return ret;
}; };
void generateAsm(Compiler &c) override; void generateAsm(Compiler &c) override;
......
...@@ -17,6 +17,10 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f ...@@ -17,6 +17,10 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
addQuad(make_shared<QParam>(var, -param)); addQuad(make_shared<QParam>(var, -param));
param++; param++;
} }
if (VarInfoPtr self = f->self){
auto var = alloc(self);
addQuad(make_shared<QParam>(var, -param));
}
} }
f->block->accept(this); f->block->accept(this);
...@@ -104,6 +108,11 @@ VariableLayout QuadrupleGenerator::captureEnv() { ...@@ -104,6 +108,11 @@ VariableLayout QuadrupleGenerator::captureEnv() {
void QuadrupleGenerator::visitEVar(EVar *p) { void QuadrupleGenerator::visitEVar(EVar *p) {
auto var = p->pident_->var.lock(); auto var = p->pident_->var.lock();
lastVar = alloc(var); lastVar = alloc(var);
if (var->isInstanceVariable()) {
auto fn = scope->currentFunction;
auto self = fn->self;
addQuad<QAccess>(lastVar, alloc(self), nullptr, 0, (int)var->offset);
}
Bool b; Bool b;
if (var->type->isEqual(&b)) { if (var->type->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar); addLastVarCondJump(nullptr, Op::Copy, lastVar);
...@@ -312,16 +321,16 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) { ...@@ -312,16 +321,16 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
} }
if (type->type_->size() > 4) { if (type->type_->size() > 4) {
// calculate quantifier, we multiply index because size is larger than 4 // calculate quantifier, we multiply index because size is larger than 4
auto q = alloc(type->type_->size() / 4); auto q = alloc(type->type_->size());
// calculate var = index * quantifier
addQuad<QAssign>(lastVar, index, Op::Mul, q);
// allocate new lastVar, index is now calculated multiplied index
index = alloc(); auto newIndex = alloc();
swap(index, lastVar); // calculate var = index * quantifier
addQuad<QAssign>(newIndex, index, Op::Mul, q);
addQuad<QAccess>(lastVar, lhs, newIndex, 1, 0);
} else {
addQuad<QAccess>(lastVar, lhs, index, type->type_->size(), 0);
} }
auto quad = make_shared<QAccess>(lastVar, lhs, index, 4, 0);
addQuad(quad);
Bool b; Bool b;
if (type->type_->isEqual(&b)) { if (type->type_->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar); addLastVarCondJump(nullptr, Op::Copy, lastVar);
...@@ -338,7 +347,7 @@ void QuadrupleGenerator::visitEClsMmbr(EClsMmbr *p) { ...@@ -338,7 +347,7 @@ void QuadrupleGenerator::visitEClsMmbr(EClsMmbr *p) {
size_t offset = var->offset; size_t offset = var->offset;
if (dynamic_cast<EIndexAcc*>(p->expr_)) { if (dynamic_cast<EIndexAcc*>(p->expr_)) {
// opt if EIndexAcc is used inside visitEClsMmbr // opt if EIndexAcc is used inside visitEClsMmbr
auto access = dynamic_pointer_cast<QAccess>(block->quads.back()); auto access = dynamic_pointer_cast<QAccess>(lastQuad);
access->access.offset += offset; access->access.offset += offset;
l->info = var; l->info = var;
lastVar = l; lastVar = l;
......
...@@ -24,6 +24,8 @@ public: ...@@ -24,6 +24,8 @@ public:
std::string name; std::string name;
int registerColor = 0; int registerColor = 0;
bool isInstanceVariable() const { return info && info->isInstanceVariable(); }
vector<QuadruplePtr> uses; vector<QuadruplePtr> uses;
vector<QuadruplePtr> writes; vector<QuadruplePtr> writes;
......
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