feat: abstract value for IR
This commit is contained in:
@@ -2,15 +2,16 @@
|
|||||||
|
|
||||||
#include "codegen/codegen.hpp"
|
#include "codegen/codegen.hpp"
|
||||||
#include "ir/slot.hpp"
|
#include "ir/slot.hpp"
|
||||||
|
#include "ir/value.hpp"
|
||||||
|
|
||||||
class StackFasmX86_64Generator : public CodeGenerator
|
class StackFasmX86_64Generator : public CodeGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~StackFasmX86_64Generator() override = default;
|
~StackFasmX86_64Generator() override = default;
|
||||||
private:
|
private:
|
||||||
StringView GetTempAddr(IR::Tmp reg)
|
StringView GetTempAddr(IR::Value reg)
|
||||||
{
|
{
|
||||||
return std::move((StringBuilder() << 't' << reg).view());
|
return std::move((StringBuilder() << reg.Format()).view());
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView GetSlotAddr(const IR::IRSlot& slot)
|
StringView GetSlotAddr(const IR::IRSlot& slot)
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "prelude/string.hpp"
|
#include "prelude/string.hpp"
|
||||||
#include "ir/slot.hpp"
|
|
||||||
#include "parser/ast.hpp"
|
#include "parser/ast.hpp"
|
||||||
|
#include "ir/slot.hpp"
|
||||||
#include "ir/allocator.hpp"
|
#include "ir/allocator.hpp"
|
||||||
|
#include "ir/value.hpp"
|
||||||
|
|
||||||
namespace IR
|
namespace IR
|
||||||
{
|
{
|
||||||
@@ -23,11 +24,6 @@ enum class OpType
|
|||||||
#define OP_TYPE(x) \
|
#define OP_TYPE(x) \
|
||||||
OpType GetType() const override { return OpType::x; }
|
OpType GetType() const override { return OpType::x; }
|
||||||
|
|
||||||
using Tmp = int;
|
|
||||||
|
|
||||||
using TmpView = View<Tmp>;
|
|
||||||
using TmpBuilder = Builder<Tmp>;
|
|
||||||
|
|
||||||
class Op
|
class Op
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -43,13 +39,13 @@ using OpBuilder = Builder<Op*>;
|
|||||||
class Valued
|
class Valued
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Valued(Tmp dest)
|
Valued(Value dest)
|
||||||
: m_dest(dest) {}
|
: m_dest(dest) {}
|
||||||
~Valued() = default;
|
~Valued() = default;
|
||||||
public:
|
public:
|
||||||
Tmp result() const { return m_dest; }
|
Value result() const { return m_dest; }
|
||||||
private:
|
private:
|
||||||
Tmp m_dest;
|
Value m_dest;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExternOp : public Op
|
class ExternOp : public Op
|
||||||
@@ -100,14 +96,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
StringView m_name;
|
StringView m_name;
|
||||||
OpView m_ops;
|
OpView m_ops;
|
||||||
View<Tmp> m_slots;
|
ValueView m_slots;
|
||||||
View<StringView> m_params;
|
View<StringView> m_params;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoadConstOp : public Op, public Valued
|
class LoadConstOp : public Op, public Valued
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LoadConstOp(Tmp dest, long value)
|
LoadConstOp(Value dest, long value)
|
||||||
: Valued(dest), m_value(value) {}
|
: Valued(dest), m_value(value) {}
|
||||||
~LoadConstOp() {}
|
~LoadConstOp() {}
|
||||||
|
|
||||||
@@ -117,7 +113,7 @@ public:
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << 't' << result() << " = LOAD_CONST " << m_value;
|
sb << result().Format() << " = LOAD_CONST " << m_value;
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -129,7 +125,7 @@ private:
|
|||||||
class LoadOp : public Op, public Valued
|
class LoadOp : public Op, public Valued
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LoadOp(Tmp dest, StringView addr)
|
LoadOp(Value dest, StringView addr)
|
||||||
: Valued(dest), m_addr(addr) {}
|
: Valued(dest), m_addr(addr) {}
|
||||||
~LoadOp() {}
|
~LoadOp() {}
|
||||||
|
|
||||||
@@ -139,7 +135,7 @@ public:
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << 't' << result() << " = LOAD \"" << m_addr.c_str() << "\"";
|
sb << result().Format() << " = LOAD \"" << m_addr.c_str() << "\"";
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -151,7 +147,7 @@ private:
|
|||||||
class StoreOp : public Op
|
class StoreOp : public Op
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StoreOp(StringView addr, Tmp src)
|
StoreOp(StringView addr, Value src)
|
||||||
: m_addr(addr), m_src(src) {}
|
: m_addr(addr), m_src(src) {}
|
||||||
~StoreOp() {}
|
~StoreOp() {}
|
||||||
|
|
||||||
@@ -161,21 +157,21 @@ public:
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << "STORE \"" << m_addr.c_str() << "\", t" << m_src;
|
sb << "STORE \"" << m_addr.c_str() << "\", " << m_src.Format();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
const StringView& addr() const { return m_addr; }
|
const StringView& addr() const { return m_addr; }
|
||||||
Tmp src() const { return m_src; }
|
Value src() const { return m_src; }
|
||||||
private:
|
private:
|
||||||
StringView m_addr;
|
StringView m_addr;
|
||||||
Tmp m_src;
|
Value m_src;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AddOp : public Op, public Valued
|
class AddOp : public Op, public Valued
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AddOp(Tmp dest, Tmp lhs, Tmp rhs)
|
AddOp(Value dest, Value lhs, Value rhs)
|
||||||
: Valued(dest), m_lhs(lhs), m_rhs(rhs) {}
|
: Valued(dest), m_lhs(lhs), m_rhs(rhs) {}
|
||||||
~AddOp() {}
|
~AddOp() {}
|
||||||
|
|
||||||
@@ -185,21 +181,21 @@ public:
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << 't' << result() << " = ADD " << m_lhs << ", " << m_rhs;
|
sb << result().Format() << " = ADD " << m_lhs.Format() << ", " << m_rhs.Format();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Tmp lhs() const { return m_lhs; }
|
Value lhs() const { return m_lhs; }
|
||||||
Tmp rhs() const { return m_rhs; }
|
Value rhs() const { return m_rhs; }
|
||||||
private:
|
private:
|
||||||
Tmp m_lhs;
|
Value m_lhs;
|
||||||
Tmp m_rhs;
|
Value m_rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CallOp : public Op, public Valued
|
class CallOp : public Op, public Valued
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CallOp(Tmp dest, StringView callee, TmpView args)
|
CallOp(Value dest, StringView callee, ValueView args)
|
||||||
: Valued(dest), m_callee(callee), m_args(args) {}
|
: Valued(dest), m_callee(callee), m_args(args) {}
|
||||||
~CallOp() {}
|
~CallOp() {}
|
||||||
|
|
||||||
@@ -211,18 +207,18 @@ public:
|
|||||||
for (size_t i = 0; i < m_args.size; ++i)
|
for (size_t i = 0; i < m_args.size; ++i)
|
||||||
{
|
{
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << "PARAM t" << m_args.data[i] << '\n';
|
sb << "PARAM " << m_args.data[i].Format() << '\n';
|
||||||
}
|
}
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << 't' << result() << " = CALL " << m_callee.c_str();
|
sb << result().Format() << " = CALL " << m_callee.c_str();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
const StringView& callee() const { return m_callee; }
|
const StringView& callee() const { return m_callee; }
|
||||||
const TmpView& args() const { return m_args; }
|
const ValueView& args() const { return m_args; }
|
||||||
private:
|
private:
|
||||||
StringView m_callee;
|
StringView m_callee;
|
||||||
TmpView m_args;
|
ValueView m_args;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IRBuilder
|
class IRBuilder
|
||||||
@@ -232,14 +228,14 @@ public:
|
|||||||
: m_root(root) {}
|
: m_root(root) {}
|
||||||
public:
|
public:
|
||||||
// TODO: support other literals
|
// TODO: support other literals
|
||||||
Tmp ParseIntLiteral(const IntLiteralNode* literal)
|
Value ParseIntLiteral(const IntLiteralNode* literal)
|
||||||
{
|
{
|
||||||
auto dst = AllocateRegister();
|
auto dst = AllocateRegister();
|
||||||
m_ops.Push(new LoadConstOp(dst, literal->integer()));
|
m_ops.Push(new LoadConstOp(dst, literal->integer()));
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tmp ParseVariable(const VariableNode* var)
|
Value ParseVariable(const VariableNode* var)
|
||||||
{
|
{
|
||||||
// auto dst = AllocateRegister();
|
// auto dst = AllocateRegister();
|
||||||
// m_ops.Push(new LoadOp(dst, var->name()));
|
// m_ops.Push(new LoadOp(dst, var->name()));
|
||||||
@@ -251,10 +247,10 @@ public:
|
|||||||
return m_locals[var->name()];
|
return m_locals[var->name()];
|
||||||
}
|
}
|
||||||
|
|
||||||
Tmp ParseFnCall(const FnCallNode* fn)
|
Value ParseFnCall(const FnCallNode* fn)
|
||||||
{
|
{
|
||||||
// TODO: support multiple args
|
// TODO: support multiple args
|
||||||
auto argRegs = TmpBuilder();
|
auto argRegs = ValueBuilder();
|
||||||
if (fn->arg() != nullptr)
|
if (fn->arg() != nullptr)
|
||||||
{
|
{
|
||||||
auto arg = ParseExpression(fn->arg());
|
auto arg = ParseExpression(fn->arg());
|
||||||
@@ -265,7 +261,7 @@ public:
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tmp ParseFactor(const Node* factor)
|
Value ParseFactor(const Node* factor)
|
||||||
{
|
{
|
||||||
switch(factor->GetType())
|
switch(factor->GetType())
|
||||||
{
|
{
|
||||||
@@ -276,10 +272,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(0 && "unreachable");
|
assert(0 && "unreachable");
|
||||||
return Tmp();
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tmp ParseExpression(const Node* expression)
|
Value ParseExpression(const Node* expression)
|
||||||
{
|
{
|
||||||
if (expression->GetType() == NodeType::Expression)
|
if (expression->GetType() == NodeType::Expression)
|
||||||
{
|
{
|
||||||
@@ -343,17 +339,17 @@ public:
|
|||||||
// TODO: think about safety (copying m_ops.data before giving)
|
// TODO: think about safety (copying m_ops.data before giving)
|
||||||
OpView ops() const { return OpView(m_ops.data, m_ops.size); }
|
OpView ops() const { return OpView(m_ops.data, m_ops.size); }
|
||||||
private:
|
private:
|
||||||
Tmp AllocateRegister()
|
Value AllocateRegister()
|
||||||
{
|
{
|
||||||
return m_tmp_counter++;
|
return Value(m_value_counter++);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
OpBuilder m_ops;
|
OpBuilder m_ops;
|
||||||
const Node* m_root = nullptr;
|
const Node* m_root = nullptr;
|
||||||
|
|
||||||
unsigned int m_tmp_counter = 0;
|
unsigned int m_value_counter = 0;
|
||||||
|
|
||||||
std::unordered_map<StringView, Tmp> m_locals;
|
std::unordered_map<StringView, Value> m_locals;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace IR
|
} // namespace IR
|
||||||
|
|||||||
26
include/ir/value.hpp
Normal file
26
include/ir/value.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "prelude/string.hpp"
|
||||||
|
|
||||||
|
namespace IR
|
||||||
|
{
|
||||||
|
|
||||||
|
class Value
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Value(unsigned int id) : m_id(id) {}
|
||||||
|
Value() : m_id(0) {}
|
||||||
|
public:
|
||||||
|
StringView Format() const
|
||||||
|
{
|
||||||
|
auto sb = StringBuilder();
|
||||||
|
sb.AppendFormat("%%%d", m_id);
|
||||||
|
return sb.view();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
unsigned int m_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ValueView = View<Value>;
|
||||||
|
using ValueBuilder = Builder<Value>;
|
||||||
|
|
||||||
|
} // namespace IR
|
||||||
Reference in New Issue
Block a user