Commit 9f4bdacd authored by zygzagZ's avatar zygzagZ

WIP code generation

parent 0c32bb1e
CC=g++
CCFLAGS=-g -W -Wall -O0 -std=c++2a -Wno-unused-parameter
OBJS=Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o Skeleton.o ParseError.o Compiler.o Quadruple.o
OBJS=Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o Skeleton.o ParseError.o Compiler.o Quadruple.o BasicBlock.o
.PHONY : clean distclean
......@@ -32,7 +32,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
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
${CC} ${CCFLAGS} -c src/Compiler.cpp
Info.o : src/Info.cpp src/Info.h src/InfoList.h src/Absyn.h
......@@ -47,6 +47,9 @@ Quadruple.o : src/codeGen/Quadruple.cpp src/Info.h src/InfoList.h src/Absyn.h sr
Variable.o : src/codeGen/Quadruple.h src/codeGen/Variable.cpp src/Info.h src/InfoList.h src/Absyn.h
${CC} ${CCFLAGS} -c src/codeGen/Variable.cpp
BasicBlock.o : src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/codeGen/BasicBlock.cpp src/codeGen/Variable.h src/Info.h src/InfoList.h src/Absyn.h
${CC} ${CCFLAGS} -c src/codeGen/BasicBlock.cpp
Latte.o : src/Latte.cpp src/Parser.h src/Printer.h src/Absyn.h src/ParseError.h src/TypeCheck.h src/Compiler.h src/Info.h src/InfoList.h
${CC} ${CCFLAGS} -c src/Latte.cpp
......
......@@ -12,6 +12,8 @@ hello:
_start:
pushl %ebp
movl %esp, %ebp
# subl $8, %esp
andl $-16, %esp
call main
pushl %eax
call exit
......@@ -24,3 +26,6 @@ call printStr
movl $0, %eax
leave
ret
"fun test::label XD":
ret
......@@ -45,3 +45,21 @@ void error() {
puts("runtime error");
exit(1);
}
char* __latte_mem_init(size_t size, void* virtTab) {
char *buf = calloc(len, size);
if (!buf) error();
*((void**)buf) = virtTab;
return buf;
}
char* __latte_mem_init_array(int len, size_t size, void* virtTab) {
if (len < 0) error();
char *buf = calloc(len, size);
if (!buf) error();
if (virtTab) {
for (size_t i = 0; i < len; i++) {
*((void**)(buf + i * size)) = virtTab;
}
}
return buf;
}
......@@ -192,7 +192,7 @@ public:
class Block : public Visitable
{
public:
std::weak_ptr<Binding> binding;
std::shared_ptr<Binding> binding;
std::weak_ptr<FunctionInfo> function;
virtual Block *clone() const = 0;
......@@ -234,13 +234,14 @@ public:
bool isEqual(shared_ptr<T> f, bool sub = false) const { return isEqual((T*)&*f, sub); };
bool operator==(Type const & f) const { return isEqual(&f); }
bool operator!=(Type const & f) const { return !isEqual(&f); }
virtual size_t size() const = 0;
};
class Expr : public Visitable
{
public:
virtual Expr *clone() const = 0;
shared_ptr<Type> type;
};
class AddOp : public Visitable
......@@ -656,6 +657,7 @@ public:
return true;
return false;
}
size_t size() const override { return 4; };
};
class Str : public Type
......@@ -674,6 +676,7 @@ public:
return true;
return false;
}
size_t size() const override { return 4; };
};
class Bool : public Type
......@@ -693,6 +696,7 @@ public:
return true;
return false;
}
size_t size() const override { return 4; };
};
class Void : public Type
......@@ -712,6 +716,7 @@ public:
return true;
return false;
}
size_t size() const override { return 0; };
};
class Array : public Type
......@@ -733,6 +738,7 @@ public:
return type_->isEqual(casted->type_, sub);
return false;
}
size_t size() const { return 4; } // wskaźnik na stertę
};
class ClassT : public Type
......@@ -750,6 +756,7 @@ public:
void swap(ClassT &);
std::string printName() const { return pident_ ? ("class " + pident_->string_) : "class"; }
bool isEqual(Type const *other, bool sub = false) const;
size_t size() const override { return 4; };
};
class Fun : public Type
......@@ -768,6 +775,7 @@ public:
void swap(Fun &);
std::string printName() const;
bool isEqual(Type const *other, bool sub = false) const;
size_t size() const override { return 0; };
};
class EVar : public Expr
......
This diff is collapsed.
......@@ -9,7 +9,10 @@
#include "codeGen/Variable.h"
#include "ParseError.h"
#include "Info.h"
#include "codeGen/Quadruple.h"
#include "codeGen/BasicBlock.h"
using Op = Quadruple::Op;
class Compiler : public Skeleton
{
public:
......@@ -23,9 +26,14 @@ private:
std::filesystem::path file;
std::stringstream buf;
shared_ptr<Scope> scope;
vector<VariablePtr> vars;
vector<QuadruplePtr> quads;
Quadruple::Op op;
VariablePtr lastVar;
void compileFunction(FunctionInfoPtr f);
VariablePtr evalExpr(Visitable *expr) {
if (!expr) throw runtime_error("No expr to eval");
lastVar = nullptr;
......@@ -39,6 +47,80 @@ private:
lastVar = nullptr;
return ret;
};
std::string mangleFunctionName(FunctionInfoPtr f) const {
if (auto c = f->klass.lock()) {
return c->name + "::" + f->name;
}
return f->name;
};
std::string getVirtName(ClassInfoPtr c) const {
return c->name + ":virt_table";
};
VariablePtr alloc(VarInfoPtr info) {
if (info->loc) {
return info->loc;
}
auto v = make_shared<Variable>(info);
vars.emplace_back(v);
info->loc = v;
return v;
}
template<typename... Args> VariablePtr alloc(Args... args) {
auto v = make_shared<Variable>(args...);
vars.emplace_back(v);
return v;
}
void endBasicBlock();
void visitEVar(EVar *p) override;
void visitEIndexAcc(EIndexAcc *p) override;
void visitEClsMmbr(EClsMmbr *p) override;
void visitEApp(EApp *p) override;
void visitELitInt(ELitInt *p) override;
void visitELitTrue(ELitTrue *p) override;
void visitELitFalse(ELitFalse *p) override;
void visitEString(EString *p) override;
void visitENewArray(ENewArray *p) override;
void visitENewClass(ENewClass *p) override;
void visitNullCast(NullCast *p) override;
void visitNeg(Neg *p) override;
void visitNot(Not *p) override;
void visitEMul(EMul *p) override;
void visitEAdd(EAdd *p) override;
void visitERel(ERel *p) override;
void visitEAnd(EAnd *p) override;
void visitEOr(EOr *p) override;
void visitInit(Init *p) override;
void visitAss(Ass *p) override;
void visitIncr(Incr *p) override;
void visitDecr(Decr *p) override;
void visitRet(Ret *p) override;
void visitVRet(VRet *p) override;
void visitCond(Cond *p) override;
void visitCondElse(CondElse *p) override;
void visitWhile(While *p) override;
void visitSExp(SExp *p) override;
void visitForEach(ForEach *p) override;
void visitPlus(Plus *p) override { op = Op::Plus; };
void visitMinus(Minus *p) override { op = Op::Minus; };
void visitTimes(Times *p) override { op = Op::Mul; };
void visitDiv(Div *p) override { op = Op::Div; };
void visitMod(Mod *p) override { op = Op::Mod; };
void visitLTH(LTH *p) override { op = Op::LT; };
void visitLE(LE *p) override { op = Op::LE; };
void visitGTH(GTH *p) override { op = Op::GT; };
void visitGE(GE *p) override { op = Op::GE; };
void visitEQU(EQU *p) override { op = Op::EQ; };
void visitNE(NE *p) override { op = Op::NEQ; };
};
#endif
......@@ -24,14 +24,35 @@ Binding::Binding(shared_ptr<Binding> parent)
}
ClassInfo::ClassInfo(PIdent *ident, BindingPtr parent /*= nullptr*/)
: VarInfo(ident),
Binding(parent)
Binding(parent),
size(0), functionCount(0)
{
type = make_shared<ClassT>(ident->clone());
type->binding = parent;
}
size_t ClassInfo::calculateSize() {
if (size) return size;
size = 4; // pointer to virtual methods table
if (auto p = getParent()) { // parent already has virt pointer included
p->calculateSize();
size = p->size;
functionCount = p->functionCount;
}
for (const auto& var : variables) {
var->offset = size;
size += var->type->size();
}
for (auto f : functions) {
f->offset = functionCount++;
}
return size;
};
Scope::Scope()
......
......@@ -26,6 +26,9 @@ public:
string name;
TypePtr type;
int lineLocation;
size_t offset;
VariablePtr loc;
bool operator<(const VarInfo &other) const {
return name != other.name ? name < other.name : type < other.type;
......@@ -58,7 +61,7 @@ public:
Binding(BindingPtr parent = nullptr);
virtual ~Binding() {};
BindingPtr getParent() const { return parent.lock(); };
BindingPtr getParent() { return parent.lock(); };
};
class ClassInfo : public VarInfo, public Binding
......@@ -68,7 +71,9 @@ public:
ClassInfo(PIdent *ident, BindingPtr parent = nullptr);
virtual string kind() const { return "class"; }
ClassInfoPtr getParent() const { return dynamic_pointer_cast<ClassInfo>(parent.lock()); };
ClassInfoPtr getParent() { return dynamic_pointer_cast<ClassInfo>(parent.lock()); };
size_t calculateSize();
size_t size, functionCount;
};
......
......@@ -3,6 +3,7 @@
#include <stdexcept>
#include "Printer.h"
#include <climits>
#include <cassert>
void TypeCheck::visitClassDef(ClassDef *t) {
const string name = t->getName()->string_;
......@@ -116,7 +117,7 @@ void TypeCheck::visitClassFld(ClassFld *decl)
void TypeCheck::visitBlk(Blk *blk)
{
BindingPtr binding = blk->binding.lock();
BindingPtr binding = blk->binding/*.lock()*/;
if (!binding) {
binding = make_shared<Binding>(scope->currentBinding);
blk->binding = binding;
......@@ -317,13 +318,12 @@ void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
throw ParseError("Class expected", e_cls_mmbr->expr_);
}
ClassInfoPtr klass = scope->classes[type->pident_];
if (klass != type->pident_->var.lock()) {
throw ParseError("ej lol inny var");
}
assert(klass == type->pident_->var.lock());
VarInfoPtr var = klass->variables[e_cls_mmbr->pident_];
if (!var || var == scope->variables.local(e_cls_mmbr->pident_->string_)) {
throw UndefinedError(e_cls_mmbr->pident_);
}
e_cls_mmbr->pident_->var = var;
lastType = var->type;
}
......@@ -392,19 +392,11 @@ void TypeCheck::visitENewArray(ENewArray *e)
void TypeCheck::visitENewClass(ENewClass *e_new_class)
{
// e_new_class->pident_->accept(this);
lastType = evalExpr<ClassT>(e_new_class->pident_);
// if (!e_new_class->pident_->var.lock()) {
// }
// ClassInfoPtr klass = dynamic_pointer_cast<ClassInfo>(e_new_class->pident_->var.lock());
// if (!klass) {
// throw ParseError("Class expected", e_new_class->pident_);
// }
// auto ret = make_shared<ClassT>(e_new_class->pident_); // make type
// ret->binding = scope->currentBinding;
// lastType = ret;
e_new_class->pident_->accept(this);
if (!dynamic_pointer_cast<ClassT>(lastType)) {
ClassT expect;
throw InvalidTypeError(expect, {lastType}, e_new_class);
}
}
void TypeCheck::visitNullCast(NullCast *null_cast)
......
......@@ -29,7 +29,7 @@ class TypeCheck : public Visitor
void setupEnv();
template<typename T>
shared_ptr<T> evalExpr(Visitable *expr) {
shared_ptr<T> evalExpr(Expr *expr) {
if (!expr) throw runtime_error("No expr to eval");
lastType = nullptr;
try {
......@@ -42,11 +42,12 @@ class TypeCheck : public Visitor
T expect;
throw InvalidTypeError(expect, {lastType}, expr);
}
expr->type = lastType;
lastType = nullptr;
return ret;
};
shared_ptr<Type> evalExpr(Visitable *expr) {
shared_ptr<Type> evalExpr(Expr *expr) {
if (!expr) throw runtime_error("No expr to eval");
try {
expr->accept(this);
......@@ -54,9 +55,12 @@ class TypeCheck : public Visitor
throw ParseError(err, expr);
}
if (!lastType) throw ParseError("No expression type", expr);
auto ret = lastType;
if (auto fun = dynamic_pointer_cast<Fun>(lastType)) {
throw ParseError("Unexpected function access", expr);
}
expr->type = lastType;
lastType = nullptr;
return ret;
return expr->type;
};
public:
BindingPtr getParentBinding() const { return scope->currentClass ? static_pointer_cast<Binding>(scope->currentClass) : static_pointer_cast<Binding>(scope); }
......
......@@ -6,16 +6,21 @@
using namespace std;
class VarInfo;
class FunctionInfo;
class ClassInfo;
class Binding;
class Type;
using VarInfoPtr = shared_ptr<VarInfo>;
class FunctionInfo;
using FunctionInfoPtr = shared_ptr<FunctionInfo>;
class ClassInfo;
using ClassInfoPtr = shared_ptr<ClassInfo>;
class Binding;
using BindingPtr = shared_ptr<Binding>;
class Type;
using TypePtr = shared_ptr<Type>;
class Variable;
using VariablePtr = shared_ptr<Variable>;
class Quadruple;
using QuadruplePtr = shared_ptr<Quadruple>;
class BasicBlock;
using BasicBlockPtr = shared_ptr<BasicBlock>;
class Visitable;
class Program;
......
//
// Created by zygzagz on 03.01.2021.
//
#include "BasicBlock.h"
//
// Created by zygzagz on 03.01.2021.
//
#ifndef ZAD2_BASICBLOCK_H
#define ZAD2_BASICBLOCK_H
#include "../TypeDefs.h"
#include <vector>
using namespace std;
class BasicBlock {
vector<QuadruplePtr> quads;
vector<BasicBlockPtr> in, out;
};
#endif //ZAD2_BASICBLOCK_H
#ifndef ZAD2_QUAD_H
#define ZAD2_QUAD_H
#include <string>
#include <utility>
#include "../Info.h"
#include "Variable.h"
using namespace std;
class Quadruple {
public:
enum Op {
UNARY,
Neg,
Not,
BINARY,
Plus,
Minus,
Mul,
Div,
And,
Or,
Xor,
static const std::string opNames[] = { "_U", "-", "!", "", "_UE",
"_B", "+", "-", "*", "/", "%", "&", "|", "^", "_BE",
"_C", "<", "<=", "==", "!=", ">=", ">", "_CE"};
class Quadruple : std::enable_shared_from_this<Quadruple> {
public:
class Op {
public:
enum OpType {
UNARY,
Neg, Not, Copy, UNARY_END,
BINARY,
Plus, Minus, Mul, Div, Mod, And, Or, Xor, BINARY_END,
CMP,
LT, LE, EQ, NEQ, GE, GT, CMP_END
};
OpType op;
Op(OpType op = UNARY) : op(op) {};
operator OpType() const { return op; };
static OpType kind(OpType op) {
if (op <= UNARY_END) return UNARY;
if (op <= BINARY_END) return BINARY;
return CMP;
};
static const std::string& name(OpType op) {
return opNames[op];
}
};
string label;
virtual ~Quadruple() {};
virtual std::string toString() const = 0;
};
class QAssign : Quadruple {
class QWriteVar : public Quadruple {
public:
VariablePtr loc;
explicit QWriteVar(VariablePtr loc) : Quadruple(), loc(std::move(loc)) {};
std::string toString() const override { return loc ? ("\t" + loc->name + " := ") : "\t"; }
};
class QLabel : public Quadruple {
public:
string label;
std::string toString() const override { return "\"" + label + "\":"; }
QLabel(std::string comment) : label(comment) {}
};
class QAssign : public QWriteVar {
public:
Op op;
vector<VariablePtr> args;
VarInfoPtr varInfo;
QAssign(VariablePtr loc, Op op, vector<VariablePtr> list) : QWriteVar(std::move(loc)), op(op), args(std::move(list)) {};
QAssign(VariablePtr loc, VariablePtr l, Op op, VariablePtr r) : QWriteVar(std::move(loc)), op(op), args({std::move(l), std::move(r)}) {};
QAssign(VariablePtr loc, Op op, VariablePtr x) : QWriteVar(std::move(loc)), op(op), args({std::move(x)}) {};
std::string toString() const override {
if (args.size() == 1)
return QWriteVar::toString() + Op::name(op) + " " + args[0]->name;
else
return QWriteVar::toString() + args[0]->name + " " + Op::name(op) + " " + args[1]->name;
}
};
class QJump : public Quadruple {
public:
shared_ptr<QLabel> target;
explicit QJump(shared_ptr<QLabel> target) : target(std::move(target)) {};
std::string toString() const override {
return "\tjump " + target->label;
}
};
class QJumpCond : public QJump {
public:
VariablePtr left;
Op op;
VariablePtr right;
QJumpCond(shared_ptr<QLabel> to, VariablePtr left, Op op, VariablePtr right)
: QJump(std::move(to)), left(std::move(left)), op(op), right(std::move(right)) {};
QJumpCond(shared_ptr<QLabel> to, Op op, VariablePtr right)
: QJumpCond(std::move(to), nullptr, op, std::move(right)) {};
std::string toString() const override {
if (!left)
return "\tjump \"" + target->label + "\" if " + Op::name(op) + " " + right->name;
else
return "\tjump \"" + target->label + "\" if " + left->name + " " + Op::name(op) + " " + right->name;
}
};
class QParam : public Quadruple {
public:
VariablePtr param;
int num;
QParam(VariablePtr param, int num) : param(std::move(param)), num(num) {};
std::string toString() const override {
if (num == 0) {
return "\tparam self " + param->name;
} else {
return "\tparam #" + to_string(num) + " <- " + param->name;
}
}
};
class QCall : public QWriteVar {
public:
FunctionInfoPtr fn;
int params;
VariablePtr self;
QCall(VariablePtr loc, FunctionInfoPtr fn, int params, VariablePtr self)
: QWriteVar(std::move(loc)), fn(std::move(fn)), params(params), self(std::move(self)) {};
std::string toString() const override {
if (self) {
return QWriteVar::toString() + "call " + fn->name + " of " + self->name + " with " + to_string(params) + " params";
} else {
return QWriteVar::toString() + "call " + fn->name + " with " + to_string(params) + " params";
}
}
};
class QReturn : public Quadruple {
public:
VariablePtr ret;
explicit QReturn(VariablePtr ret) : ret(std::move(ret)) {};
std::string toString() const override {
if (ret) {
return "\treturn " + ret->name;
} else {
return "\treturn";
}
}
};
class QAccess : public QWriteVar {
public:
QAccess(VariablePtr loc, VariablePtr base, VariablePtr index, int multiplier, int offset)
: QWriteVar(std::move(loc)), base(std::move(base)), index(std::move(index)), multiplier(multiplier), offset(offset)
{};
// leal 8(,%eax,4), %eax # Arithmetic: multiply eax by 4 and add 8
// leal (%edx,%eax,2), %eax # Arithmetic: multiply eax by 2 and add edx
VariablePtr base;
VariablePtr index;
int multiplier;
int offset;
std::string toString() const override {
auto ret = QWriteVar::toString() + "[" + base->name;
if (multiplier || !(index->constExpr || !index->val)) ret += " + " + to_string(multiplier) + "*" + index->name;
if (offset) ret += " + " + to_string(offset);
return ret + "]";
}
};
class QAlloc : public QWriteVar {
public:
size_t size;
VariablePtr count;
std::string virtSymbol;
QAlloc(VariablePtr loc, size_t size, std::string virtSymbol, VariablePtr count = nullptr)
: QWriteVar(std::move(loc)), size(size), count(std::move(count)), virtSymbol(std::move(virtSymbol)) {};
std::string toString() const override {
std::string ret = QWriteVar::toString() + "alloc (" + to_string(size) + ")";
if (count) { ret += " [" + count->name + "]"; }
if (!virtSymbol.empty()) { ret += " " + virtSymbol; }
return ret;
}
};
......
......@@ -5,14 +5,26 @@
#ifndef ZAD2_VARIABLE_H
#define ZAD2_VARIABLE_H
#include <utility>
#include "../TypeDefs.h"
class Variable : std::enable_shared_from_this<Variable> {
public:
Variable() = default;
explicit Variable(VarInfoPtr info) : info(std::move(info)), constExpr(false), val(0) {};
explicit Variable(int constVal) : type(new Int), constExpr(true), val(constVal) {};
explicit Variable(std::string symbolName) {};
VarInfoPtr info;
TypePtr type;
bool constExpr;
int val;
std::string name;
// chcemy znać lokalizację w pamięci gdzie zapisać z powrotem i gdzie leży ogólnie
// lok. może nie być, jeśli to tymczasowa
// registers
// is mem?
// where in mem - id or offset
};
using VariablePtr = shared_ptr<Variable>;
#endif //ZAD2_VARIABLE_H
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