feat: first prototype of optimizers + alloca optimizer
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include "parser/nodes.hpp"
|
||||
#include "prelude/string.hpp"
|
||||
#include "parser/ast.hpp"
|
||||
#include "ir/value.hpp"
|
||||
#include "ir/ops.hpp"
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace IR
|
||||
{
|
||||
auto value = ParseExpression(varDecl->value());
|
||||
// TODO: gather type information from var decl signature, aka local <int> v = 0;
|
||||
auto dst = AllocateNamed<Pointer>();
|
||||
auto dst = AllocateNamed<Pointer>(value->GetType());
|
||||
m_ops->Push(new AllocateOp(dst, value->GetType()));
|
||||
m_ops->Push(new StoreOp(value, reinterpret_cast<Pointer *>(dst)));
|
||||
m_locals.insert(std::make_pair(varDecl->name(), reinterpret_cast<Pointer *>(dst)));
|
||||
@@ -34,14 +34,14 @@ namespace IR
|
||||
|
||||
ValueHandle *ParseVariable(const VariableNode *var)
|
||||
{
|
||||
// auto dst = AllocateValue();
|
||||
// m_ops->Push(new LoadOp(dst, var->name()));
|
||||
if (m_locals.find(var->name()) == m_locals.end())
|
||||
{
|
||||
// TODO: throw proper error
|
||||
assert(0 && "ERROR: variable does not exist");
|
||||
}
|
||||
return reinterpret_cast<ValueHandle *>(m_locals[var->name()]);
|
||||
auto dst = AllocateNamed<Instruction>(m_locals[var->name()]->GetValueType());
|
||||
m_ops->Push(new LoadOp(dst, m_locals[var->name()]));
|
||||
return reinterpret_cast<ValueHandle *>(dst);
|
||||
}
|
||||
|
||||
ValueHandle *ParseFnCall(const FnCallNode *fn)
|
||||
@@ -54,7 +54,7 @@ namespace IR
|
||||
argRegs.Push(arg);
|
||||
}
|
||||
// TODO: gather return type of the function
|
||||
auto dst = AllocateUnnamed<Void>();
|
||||
auto dst = VoidValue();
|
||||
m_ops->Push(new CallOp(dst, fn->name(), argRegs.view()));
|
||||
return dst;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ namespace IR
|
||||
}
|
||||
|
||||
assert(0 && "unreachable");
|
||||
return reinterpret_cast<ValueHandle *>(new Void(0));
|
||||
return reinterpret_cast<ValueHandle *>(new Void());
|
||||
}
|
||||
|
||||
ValueHandle *ParseExpression(const Node *expression)
|
||||
@@ -187,12 +187,18 @@ namespace IR
|
||||
return new V(ValueHandle::kNoId, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
ValueHandle *VoidValue()
|
||||
{
|
||||
return new Void();
|
||||
}
|
||||
|
||||
private:
|
||||
const Node *m_root = nullptr;
|
||||
|
||||
OpBuilder *m_ops = nullptr;
|
||||
unsigned int m_value_counter = 0;
|
||||
unsigned int m_block_counter = 0;
|
||||
|
||||
std::unordered_map<StringView, Pointer *> m_locals;
|
||||
|
||||
Builder<OpBuilder *> m_containers;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "prelude/string.hpp"
|
||||
#include "parser/nodes.hpp"
|
||||
#include "ir/value.hpp"
|
||||
#include "ir/op.hpp"
|
||||
#include "ir/block.hpp"
|
||||
@@ -21,7 +20,7 @@ namespace IR
|
||||
{
|
||||
StringBuilder sb;
|
||||
sb.AppendIndent(indent);
|
||||
sb << "EXTRN " << m_symbol.c_str();
|
||||
sb << "extern " << m_symbol.c_str();
|
||||
return sb.view();
|
||||
}
|
||||
|
||||
@@ -46,7 +45,7 @@ namespace IR
|
||||
{
|
||||
StringBuilder sb;
|
||||
sb.AppendIndent(indent);
|
||||
sb << "LABEL " << m_name.c_str() << ':' << '\n';
|
||||
sb << "label " << m_name.c_str() << ':' << '\n';
|
||||
sb << m_body.Format(indent);
|
||||
return sb.view();
|
||||
}
|
||||
@@ -79,7 +78,7 @@ namespace IR
|
||||
{
|
||||
StringBuilder sb;
|
||||
sb.AppendIndent(indent);
|
||||
sb << result()->Format() << " = ALLOCATE " << m_typ->Format();
|
||||
sb << result()->Format() << " = allocate " << m_typ->Format();
|
||||
return sb.view();
|
||||
}
|
||||
|
||||
@@ -90,8 +89,8 @@ namespace IR
|
||||
class LoadOp : public OpValued
|
||||
{
|
||||
public:
|
||||
LoadOp(ValueHandle *dest, StringView addr)
|
||||
: OpValued(dest), m_addr(addr) {}
|
||||
LoadOp(ValueHandle *dest, Pointer *ptr)
|
||||
: OpValued(dest), m_ptr(ptr) {}
|
||||
~LoadOp() {}
|
||||
|
||||
OP_TYPE(LOAD)
|
||||
@@ -100,15 +99,12 @@ namespace IR
|
||||
{
|
||||
StringBuilder sb;
|
||||
sb.AppendIndent(indent);
|
||||
sb << result()->Format() << " = LOAD \"" << m_addr.c_str() << "\"";
|
||||
sb << result()->Format() << " = load " << m_ptr->Format();
|
||||
return sb.view();
|
||||
}
|
||||
|
||||
public:
|
||||
const StringView &addr() const { return m_addr; }
|
||||
|
||||
private:
|
||||
StringView m_addr;
|
||||
Pointer* m_ptr;
|
||||
};
|
||||
|
||||
class StoreOp : public Op
|
||||
@@ -124,7 +120,7 @@ namespace IR
|
||||
{
|
||||
StringBuilder sb;
|
||||
sb.AppendIndent(indent);
|
||||
sb << "STORE " << src()->Format() << ", " << dst()->Format();
|
||||
sb << "store " << src()->Format() << ", " << dst()->Format();
|
||||
return sb.view();
|
||||
}
|
||||
|
||||
@@ -152,13 +148,14 @@ namespace IR
|
||||
switch (m_typ)
|
||||
{
|
||||
case OpType::ADD:
|
||||
return StringView("ADD");
|
||||
return StringView("add");
|
||||
case OpType::MUL:
|
||||
return StringView("MUL");
|
||||
return StringView("mul");
|
||||
case OpType::SUB:
|
||||
return StringView("SUB");
|
||||
return StringView("sub");
|
||||
case OpType::DIV:
|
||||
return StringView("DIV");
|
||||
return StringView("div");
|
||||
default: break;
|
||||
}
|
||||
|
||||
assert(false && "unreachable");
|
||||
@@ -198,10 +195,10 @@ namespace IR
|
||||
for (size_t i = 0; i < m_args.size; ++i)
|
||||
{
|
||||
sb.AppendIndent(indent);
|
||||
sb << "PARAM " << m_args.data[i]->Format() << '\n';
|
||||
sb << "param " << m_args.data[i]->Format() << '\n';
|
||||
}
|
||||
sb.AppendIndent(indent);
|
||||
sb << result()->Format() << " = CALL " << m_callee.c_str();
|
||||
sb << result()->Format() << " = call " << m_callee.c_str();
|
||||
return sb.view();
|
||||
}
|
||||
|
||||
|
||||
34
include/ir/optimize.hpp
Normal file
34
include/ir/optimize.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "ir/op.hpp"
|
||||
#include "prelude/linkedlist.hpp"
|
||||
|
||||
namespace IR {
|
||||
|
||||
class Optimizer
|
||||
{
|
||||
public:
|
||||
virtual bool Apply(DoubleLinkedList<Op*>& ops) = 0;
|
||||
};
|
||||
|
||||
class AllocOptimizer : public Optimizer
|
||||
{
|
||||
public:
|
||||
bool Apply(DoubleLinkedList<Op*>& ops) override
|
||||
{
|
||||
for (ListNode<Op*>* cur = ops.Begin(); cur != nullptr; )
|
||||
{
|
||||
auto op = cur->value;
|
||||
if (op->GetType() == OpType::ALLOCATE)
|
||||
{
|
||||
auto tmp = cur;
|
||||
cur = cur->next;
|
||||
ops.SpliceFront(tmp);
|
||||
} else {
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include "prelude/string.hpp"
|
||||
|
||||
namespace IR
|
||||
@@ -104,8 +105,8 @@ namespace IR
|
||||
class Pointer : public ValueHandle
|
||||
{
|
||||
public:
|
||||
Pointer(unsigned int id)
|
||||
: ValueHandle(id)
|
||||
Pointer(unsigned int id, const Type* value_typ)
|
||||
: ValueHandle(id), m_value_typ(new Type(value_typ))
|
||||
{
|
||||
m_type = new Type{Type::Kind::Ptr};
|
||||
}
|
||||
@@ -120,16 +121,19 @@ namespace IR
|
||||
return sb.view();
|
||||
}
|
||||
|
||||
public:
|
||||
const Type *GetValueType() const { return m_value_typ; }
|
||||
|
||||
private:
|
||||
Type *m_type;
|
||||
Type *m_value_typ;
|
||||
};
|
||||
|
||||
// TODO: Remove void value and use void type only
|
||||
class Void : public ValueHandle
|
||||
{
|
||||
public:
|
||||
Void(unsigned int id)
|
||||
: ValueHandle(id)
|
||||
Void()
|
||||
: ValueHandle()
|
||||
{
|
||||
m_type = new Type{Type::Kind::Void};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user