Commit e4d71bee authored by zygzagZ's avatar zygzagZ

WIP better memory access

parent aafb3bcc
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h>
int printInt(int a) { int printInt(int a) {
printf("%d\n", a); printf("%d\n", a);
...@@ -59,11 +60,13 @@ char* __latte_mem_init(size_t size, void* virtTab) { ...@@ -59,11 +60,13 @@ char* __latte_mem_init(size_t size, void* virtTab) {
} }
char* __latte_mem_init_array(int len, size_t size, void* virtTab) { char* __latte_mem_init_array(int len, size_t size, void* virtTab) {
if (len < 0) error(); if (len < 0) error();
char *buf = calloc(len, size); if (len > (SIZE_MAX-4)/size) error();
char *buf = calloc(1, 4 + len * size);
if (!buf) error(); if (!buf) error();
*((int*)buf) = len; // store length
if (virtTab) { if (virtTab) {
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
*((void**)(buf + i * size)) = virtTab; *((void**)(buf + 4 + i * size)) = virtTab;
} }
} }
return buf; return buf;
......
...@@ -137,6 +137,7 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu ...@@ -137,6 +137,7 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu
buf << "\n" COMMENT "----------\n"; buf << "\n" COMMENT "----------\n";
} }
for (const auto& q : b->quads) { for (const auto& q : b->quads) {
currentQuad = q;
auto ret = q->toString(); auto ret = q->toString();
if (!ret.empty()) { if (!ret.empty()) {
auto len = 0; auto len = 0;
...@@ -162,6 +163,7 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu ...@@ -162,6 +163,7 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu
} }
} }
} }
currentQuad = nullptr;
if (!b->flow.use.empty()) { if (!b->flow.use.empty()) {
buf << COMMENT "----------\n" COMMENT "use: "; buf << COMMENT "----------\n" COMMENT "use: ";
for (const auto &v : b->flow.use) { for (const auto &v : b->flow.use) {
...@@ -209,7 +211,7 @@ const char* const Register::names[9] = {"eax", "ebx", "ecx", "edx", "edi", "esi" ...@@ -209,7 +211,7 @@ const char* const Register::names[9] = {"eax", "ebx", "ecx", "edx", "edi", "esi"
const vector<Register> Register::all = {0, 1, 2, 3, 4, 5, 6, 7, 8}; const vector<Register> Register::all = {0, 1, 2, 3, 4, 5, 6, 7, 8};
const vector<Register> Register::callerSaved = {2, 3}; const vector<Register> Register::callerSaved = {2, 3};
const vector<Register> Register::calleeSaved = {1, 4, 5}; const vector<Register> Register::calleeSaved = {1, 4, 5};
const vector<Register> Register::assignable = {1,4,5,2,3}; // ecx and edx least used const vector<Register> Register::assignable = {1,5,4,2,3}; // ecx and edx least used
string Compiler::getRef(const VariablePtr &v) { string Compiler::getRef(const VariablePtr &v) {
if (v->constExpr) { if (v->constExpr) {
...@@ -274,13 +276,28 @@ void Compiler::generateQAlloc(QAlloc &q) { ...@@ -274,13 +276,28 @@ void Compiler::generateQAlloc(QAlloc &q) {
} }
void Compiler::generateQWrite(QWrite &q) { void Compiler::generateQWrite(QWrite &q) {
// memory = extension Register rl = lock(q.val, true);
append("MOVL", getRef(q.val), getRef(q.loc)); // out of all registers
// now i want to choose some that are free
// or temporarily push some not used in calculation of q.access nor q.loc
append("MOVL", rl, loadLoc(q.loc));
// and, if pushed, pop them back later
regMap.unlock();
} }
void Compiler::generateQAccess(QAccess &q) { void Compiler::generateQAccess(QAccess &q) {
// memory = extension // get register for q.loc, spilling one if necessary
append("MOVL", getRef(q.access), getRef(q.loc)); Register rl = lock(q.loc, false);
// out of all registers
// now i want to choose some that are free
// or temporarily push some not used in calculation of q.access nor q.loc
append("MOVL", loadLoc(q.access), rl);
if (Register(q.loc) == 0) {
append("MOVL", rl, getRef(q.loc));
}
// and, if pushed, pop them back later
regMap.unlock();
} }
void Compiler::generateQReturn(QReturn &q) { void Compiler::generateQReturn(QReturn &q) {
...@@ -568,3 +585,35 @@ void Compiler::generateQBlockEnd(QBlockEnd &q) { ...@@ -568,3 +585,35 @@ void Compiler::generateQBlockEnd(QBlockEnd &q) {
const auto &map = tgBlock->getPhiMapping(thisBlock); const auto &map = tgBlock->getPhiMapping(thisBlock);
generatePhiXCHG(map); generatePhiXCHG(map);
} }
string Compiler::loadLoc(const VariableLocation &loc) {
int offset = loc.offset;
Register rb = lock(loc.base, true);
if (loc.index) {
if (loc.index->constExpr) {
offset += loc.index->val * loc.multiplier;
} else {
Register ri = lock(loc.index, true);
auto ret = to_string(offset) + "(" + (string)rb + "," + (string)ri;
if (loc.multiplier != 1) ret += "," + to_string(loc.multiplier);
return ret + ")";
}
}
return to_string(offset) + "(" + (string)rb + ")";
}
void RegisterMap::backup(Register i) {
chk(i);
backups.emplace_back(i);
c->append("MOVL", i, "-" + to_string(backups.size()*4) + "(%esp)");
lock(i);
}
void RegisterMap::unlock() {
locks.clear();
for (size_t i = 0; i < backups.size(); i++) {
c->append("MOVL", "-" + to_string(i*4+4) + "(%esp)", backups[i]);
}
backups.clear();
}
...@@ -42,10 +42,85 @@ public: ...@@ -42,10 +42,85 @@ public:
static const vector<Register> assignable; static const vector<Register> assignable;
}; };
namespace {
vector<Register> aliveAfter(const Quadruple &q, const vector<Register> &vec) {
const uint noRegs = vec.size();
bool used[noRegs];
int notUsed = noRegs;
for (auto &i : used) i = false;
for (auto &live : q.aliveAfter) {
for (uint i = 0; i < noRegs; i++) {
const Register &r = vec[i];
if (!used[i] && Register(live) == r) {
used[i] = true;
--notUsed;
}
}
if (notUsed == 0) break;
}
vector<Register> ret;
for (uint i = 0; i < noRegs; i++) {
if (used[i]) ret.emplace_back(vec[i]);
}
return ret;
}
vector<Register> aliveAfter(const QuadruplePtr &q, const vector<Register> &vec) {
return aliveAfter(*q, vec);
}
}
class RegisterMap {
public:
RegisterMap(Compiler *c) : c(c) {};
Compiler *c;
set<Register> locks;
vector<Register> backups;
set<Register> available() const {
auto ret = to_set(Register::assignable);
ret.emplace(0);
ret -= to_set(locks);
return ret;
}
auto unused(const QuadruplePtr &q) const {
auto ret = to_set(::aliveAfter(q, Register::assignable));
ret.emplace(0);
ret -= to_set(locks);
return ret;
}
void lock(Register i) {
if (!locks.count(i))
locks.emplace(i);
}
Register borrow(const QuadruplePtr &q) {
for (auto i : unused(q)) {
lock(i);
return i;
}
for (auto i : available()) {
backup(i);
return i;
}
throw runtime_error("Unable to borrow register!");
}
void backup(Register i);
void unlock();
private:
void chk(Register i) const {
if (locks.count(i))
throw runtime_error("Register already locked!");
}
};
using Op = Quadruple::Op; using Op = Quadruple::Op;
class Compiler { class Compiler {
public: public:
Compiler(const std::string& f, shared_ptr<Scope> s) : file(f), buf(), scope(s), quadGen(std::move(s)) {}; Compiler(const std::string& f, shared_ptr<Scope> s) : file(f), buf(), scope(s), quadGen(std::move(s)), regMap(this) {};
static const std::string extension; static const std::string extension;
static void externalCommand(std::filesystem::path file); static void externalCommand(std::filesystem::path file);
...@@ -82,6 +157,8 @@ private: ...@@ -82,6 +157,8 @@ private:
std::stringstream buf; std::stringstream buf;
shared_ptr<Scope> scope; shared_ptr<Scope> scope;
QuadrupleGenerator quadGen; QuadrupleGenerator quadGen;
RegisterMap regMap;
QuadruplePtr currentQuad;
unordered_set<VariablePtr> temps; unordered_set<VariablePtr> temps;
unordered_set<VarInfoPtr> localInfos; unordered_set<VarInfoPtr> localInfos;
...@@ -91,21 +168,38 @@ private: ...@@ -91,21 +168,38 @@ private:
void genVirtTables(); void genVirtTables();
string getRef(const VariablePtr &v); string getRef(const VariablePtr &v);
string getRef(const VariableLocation &loc) { string loadLoc(const VariableLocation &loc);
int offset = loc.offset; void generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap);
if (loc.index) {
if (loc.index->constExpr) { string getBlockLabelText(const QuadruplePtr &q) {
offset += loc.index->val * loc.multiplier; return getBlockLabelText(q->block);
} else { }
auto ret = to_string(offset) + "(" + getRef(loc.base) + "," + getRef(loc.index);
if (loc.multiplier != 1) ret += "," + to_string(loc.multiplier); string getBlockLabelText(BasicBlockPtr &b) {
return ret + ")"; auto n = b->getName();
if (n.empty()) throw runtime_error("Attempt to get label text of unlabeled block");
return quote(n);
}
shared_ptr<QLabel> exitLabel;
void generateStandardReturn() {
append("JMP", quote(exitLabel->label));
}
Register lock(const VariablePtr &v, bool move = false) {
auto reg = Register(v);
if (reg == 0) {
reg = regMap.borrow(currentQuad);
if (move) {
append("MOVL", getRef(v), reg);
} }
} else {
regMap.lock(reg);
} }
return to_string(offset) + "(" + getRef(loc.base) + ")"; return reg;
} }
void generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap);
protected:
static string getOpName(Quadruple::Op op) { static string getOpName(Quadruple::Op op) {
switch(op.op) { switch(op.op) {
case Op::Plus: return "ADDL"; case Op::Plus: return "ADDL";
...@@ -172,46 +266,16 @@ private: ...@@ -172,46 +266,16 @@ private:
buf << endl; buf << endl;
} }
public:
string getBlockLabelText(const QuadruplePtr &q) { static vector<Register> aliveAfter(Quadruple &q, const vector<Register> &vec) {
return getBlockLabelText(q->block); return ::aliveAfter(q, vec);
} }
string getBlockLabelText(BasicBlockPtr &b) {
auto n = b->getName();
if (n.empty()) throw runtime_error("Attempt to get label text of unlabeled block");
return quote(n);
}
shared_ptr<QLabel> exitLabel;
void generateStandardReturn() {
append("JMP", quote(exitLabel->label));
}
static vector<Register> aliveAfter(Quadruple &q, const vector<Register> &vec) {
const uint noRegs = vec.size();
bool used[noRegs];
int notUsed = noRegs;
for (auto &i : used) i = false;
for (auto &live : q.aliveAfter) {
for (uint i = 0; i < noRegs; i++) {
const Register &r = vec[i];
if (!used[i] && Register(live) == r) {
used[i] = true;
--notUsed;
}
}
if (notUsed == 0) break;
}
vector<Register> ret;
for (uint i = 0; i < noRegs; i++) {
if (used[i]) ret.emplace_back(vec[i]);
}
return ret;
}
static vector<Register> registersToSave(Quadruple &q) { static vector<Register> registersToSave(Quadruple &q) {
return aliveAfter(q, Register::callerSaved); return aliveAfter(q, Register::callerSaved);
} }
friend class RegisterMap;
}; };
#endif #endif
...@@ -12,14 +12,15 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f ...@@ -12,14 +12,15 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
newBlock(); newBlock();
{ {
int param = 1; int param = 1;
for (const auto& arg : f->arguments) { if (VarInfoPtr self = f->self){
auto var = alloc(arg); auto var = alloc(self);
addQuad(make_shared<QParam>(var, -param)); addQuad(make_shared<QParam>(var, -param));
param++; param++;
} }
if (VarInfoPtr self = f->self){ for (const auto& arg : f->arguments) {
auto var = alloc(self); auto var = alloc(arg);
addQuad(make_shared<QParam>(var, -param)); addQuad(make_shared<QParam>(var, -param));
param++;
} }
} }
f->block->accept(this); f->block->accept(this);
...@@ -327,9 +328,9 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) { ...@@ -327,9 +328,9 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
auto newIndex = alloc(); auto newIndex = alloc();
// calculate var = index * quantifier // calculate var = index * quantifier
addQuad<QAssign>(newIndex, index, Op::Mul, q); addQuad<QAssign>(newIndex, index, Op::Mul, q);
addQuad<QAccess>(lastVar, lhs, newIndex, 1, 0); addQuad<QAccess>(lastVar, lhs, newIndex, 1, 4); // 4 accounts for table length entry
} else { } else {
addQuad<QAccess>(lastVar, lhs, index, type->type_->size(), 0); addQuad<QAccess>(lastVar, lhs, index, type->type_->size(), 4); // 4 accounts for table length entry
} }
Bool b; Bool b;
if (type->type_->isEqual(&b)) { if (type->type_->isEqual(&b)) {
......
...@@ -38,11 +38,17 @@ private: ...@@ -38,11 +38,17 @@ private:
shared_ptr<QLabel> labelTrue, labelFalse; shared_ptr<QLabel> labelTrue, labelFalse;
VariablePtr evalLVal(Visitable *expr) { VariablePtr evalLVal(Visitable *expr) {
auto info = evalExpr(expr)->info; auto ret = evalExpr(expr);
auto info = ret->info;
if (!info) { if (!info) {
throw ParseError("LValue expected", expr); if (!lastQuad || !dynamic_pointer_cast<QAccess>(lastQuad))
throw ParseError("LValue expected", expr);
else
return ret;
} else {
info->loc = nullptr;
} }
info->loc = nullptr;
return alloc(info); return alloc(info);
} }
......
...@@ -85,7 +85,8 @@ done && green "OK: $t bad+ tests passed!" && for ext in `ls lat/lattests/extensi ...@@ -85,7 +85,8 @@ done && green "OK: $t bad+ tests passed!" && for ext in `ls lat/lattests/extensi
if ! diff <( $VALGRIND timeout 2 ${i%.*} < "$inp" ) "${i%.*}.output"; then if ! diff <( $VALGRIND timeout 2 ${i%.*} < "$inp" ) "${i%.*}.output"; then
red "ERROR $i" red "ERROR $i"
exit 1 ok=0
break
fi fi
done done
if [ $ok -eq 1 ]; then if [ $ok -eq 1 ]; then
......
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