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 {
return false;
}
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;
}
}
......
......@@ -182,8 +182,8 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu
void Compiler::genVirtTables() {
for (const auto &c : scope->classes) {
if (!c->functionCount) continue;
buf << quoted(getVirtName(c)) << ":\n";
if (!c->functionCount) continue;
vector<string> names(c->functionCount, "");
auto p = c;
while (p) {
......@@ -241,7 +241,8 @@ string Compiler::getRef(const VariablePtr &v) {
}
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
auto saveRegs = registersToSave(q);
for (auto r : saveRegs) {
......@@ -255,11 +256,12 @@ void Compiler::generateQAlloc(QAlloc &q) {
append("PUSHL", "$" + quote(q.virtSymbol));
}
append("PUSHL", "$" + to_string(q.size));
if (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("ADDL", "$" + to_string(q.count ? 12 : 8), "%esp");
......@@ -273,12 +275,12 @@ void Compiler::generateQAlloc(QAlloc &q) {
void Compiler::generateQWrite(QWrite &q) {
// memory = extension
throw runtime_error("Memory write unimplemented!");
append("MOVL", getRef(q.val), getRef(q.loc));
}
void Compiler::generateQAccess(QAccess &q) {
// memory = extension
throw runtime_error("Memory access unimplemented!");
append("MOVL", getRef(q.access), getRef(q.loc));
}
void Compiler::generateQReturn(QReturn &q) {
......@@ -290,11 +292,18 @@ void Compiler::generateQReturn(QReturn &q) {
void Compiler::generateQCall(QCall &q) {
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) {
append("ADDL", "$" + to_string(q.params*4), "%esp");
append("ADDL", "$" + to_string(q.params*4 + (q.self ? 4 : 0)), "%esp");
}
auto popRegs = registersToSave(q);
for (auto r = popRegs.rbegin(); r != popRegs.rend(); r++) {
......@@ -307,8 +316,18 @@ void Compiler::generateQCall(QCall &q) {
}
void Compiler::generateQParam(QParam &q) {
// return Quadruple::generateAsm();
if (q.num < 0) {
if (q.call) {
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 offset = 4 * (q.num - Register::calleeSaved.size() - 1); // push regs + ebp
if (reg == 0) {
......@@ -317,15 +336,6 @@ void Compiler::generateQParam(QParam &q) {
} else {
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:
void genVirtTables();
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);
static string getOpName(Quadruple::Op op) {
......
......@@ -55,7 +55,7 @@ size_t ClassInfo::calculateSize() {
if (auto pv = parent->functions.find(f->name)) {
// verify types
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;
continue;
......
......@@ -43,11 +43,14 @@ public:
vector<VarInfoPtr> arguments;
weak_ptr<ClassInfo> klass;
weak_ptr<Binding> binding;
VarInfoPtr self;
FunctionInfo(FuncDef *expr, ClassInfoPtr klass = nullptr);
FunctionInfo(string name, TypePtr type) : VarInfo(name, type), block(nullptr) {};
// FunctionInfo(PIdent *ident, ClassInfoPtr klass = nullptr) : VarInfo(ident), block(NULL), klass(klass) {};
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)
BindingPtr binding = make_shared<Binding>(getParentBinding());
f->binding = binding;
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) {
......
......@@ -202,13 +202,13 @@ public:
vector<VariablePtr> vars() const override {
auto ret = Quadruple::vars();
if (param && num >= 0) ret.emplace_back(param);
if (param && call) ret.emplace_back(param);
return ret;
}
vector<VariablePtr> definitions() const override {
auto ret = Quadruple::definitions();
if (param && num < 0) ret.emplace_back(param);
if (param && !call) ret.emplace_back(param);
return ret;
};
void generateAsm(Compiler &c) override;
......
......@@ -17,6 +17,10 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
addQuad(make_shared<QParam>(var, -param));
param++;
}
if (VarInfoPtr self = f->self){
auto var = alloc(self);
addQuad(make_shared<QParam>(var, -param));
}
}
f->block->accept(this);
......@@ -104,6 +108,11 @@ VariableLayout QuadrupleGenerator::captureEnv() {
void QuadrupleGenerator::visitEVar(EVar *p) {
auto var = p->pident_->var.lock();
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;
if (var->type->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar);
......@@ -312,16 +321,16 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
}
if (type->type_->size() > 4) {
// calculate quantifier, we multiply index because size is larger than 4
auto q = alloc(type->type_->size() / 4);
// calculate var = index * quantifier
addQuad<QAssign>(lastVar, index, Op::Mul, q);
auto q = alloc(type->type_->size());
// allocate new lastVar, index is now calculated multiplied index
index = alloc();
swap(index, lastVar);
auto newIndex = alloc();
// 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;
if (type->type_->isEqual(&b)) {
addLastVarCondJump(nullptr, Op::Copy, lastVar);
......@@ -338,7 +347,7 @@ void QuadrupleGenerator::visitEClsMmbr(EClsMmbr *p) {
size_t offset = var->offset;
if (dynamic_cast<EIndexAcc*>(p->expr_)) {
// 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;
l->info = var;
lastVar = l;
......
......@@ -24,6 +24,8 @@ public:
std::string name;
int registerColor = 0;
bool isInstanceVariable() const { return info && info->isInstanceVariable(); }
vector<QuadruplePtr> uses;
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