Files
pl/include/ir/ops.hpp

184 lines
4.1 KiB
C++

#pragma once
#include "prelude/string.hpp"
#include "parser/nodes.hpp"
#include "ir/value.hpp"
#include "ir/op.hpp"
#include "ir/block.hpp"
namespace IR
{
class ExternOp : public Op
{
public:
ExternOp(StringView symbol)
: m_symbol(symbol) {}
~ExternOp() {}
OP_TYPE(EXTERN)
public:
StringView Format(int indent) const override
{
StringBuilder sb;
sb.AppendIndent(indent);
sb << "EXTRN " << m_symbol.c_str();
return sb.view();
}
public:
const StringView& symbol() const { return m_symbol; }
private:
StringView m_symbol;
};
// TODO: Make function return value (i.e. inhreit the OpValued class instead)
class FnOp : public Op
{
public:
FnOp(StringView name, const View<StringView>& params, Block&& block)
: m_name(name), m_params(params), m_body(block) {}
~FnOp() {}
OP_TYPE(FN)
public:
StringView Format(int indent) const override
{
StringBuilder sb;
sb.AppendIndent(indent);
sb << "LABEL " << m_name.c_str() << ':' << '\n';
sb << m_body.Format(indent);
return sb.view();
}
public:
const StringView& name() const { return m_name; }
const Block& body() const { return m_body; }
const View<StringView>& params() const { return m_params; }
private:
StringView m_name;
ValueView m_slots;
View<StringView> m_params;
Block m_body;
};
class LoadConstOp : public OpValued
{
public:
LoadConstOp(Value dest, long value)
: OpValued(dest), m_value(value) {}
~LoadConstOp() {}
OP_TYPE(LOAD_CONST)
public:
StringView Format(int indent) const override
{
StringBuilder sb;
sb.AppendIndent(indent);
sb << result().Format() << " = LOAD_CONST " << m_value;
return sb.view();
}
public:
long value() const { return m_value; }
private:
long m_value;
};
class LoadOp : public OpValued
{
public:
LoadOp(Value dest, StringView addr)
: OpValued(dest), m_addr(addr) {}
~LoadOp() {}
OP_TYPE(LOAD)
public:
StringView Format(int indent) const override
{
StringBuilder sb;
sb.AppendIndent(indent);
sb << result().Format() << " = LOAD \"" << m_addr.c_str() << "\"";
return sb.view();
}
public:
const StringView& addr() const { return m_addr; }
private:
StringView m_addr;
};
class StoreOp : public Op
{
public:
StoreOp(StringView addr, Value src)
: m_addr(addr), m_src(src) {}
~StoreOp() {}
OP_TYPE(STORE)
public:
StringView Format(int indent) const override
{
StringBuilder sb;
sb.AppendIndent(indent);
sb << "STORE \"" << m_addr.c_str() << "\", " << m_src.Format();
return sb.view();
}
public:
const StringView& addr() const { return m_addr; }
Value src() const { return m_src; }
private:
StringView m_addr;
Value m_src;
};
class AddOp : public OpValued
{
public:
AddOp(Value dest, Value lhs, Value rhs)
: OpValued(dest), m_lhs(lhs), m_rhs(rhs) {}
~AddOp() {}
OP_TYPE(ADD)
public:
StringView Format(int indent) const override
{
StringBuilder sb;
sb.AppendIndent(indent);
sb << result().Format() << " = ADD " << m_lhs.Format() << ", " << m_rhs.Format();
return sb.view();
}
public:
Value lhs() const { return m_lhs; }
Value rhs() const { return m_rhs; }
private:
Value m_lhs;
Value m_rhs;
};
class CallOp : public OpValued
{
public:
CallOp(Value dest, StringView callee, ValueView args)
: OpValued(dest), m_callee(callee), m_args(args) {}
~CallOp() {}
OP_TYPE(CALL)
public:
StringView Format(int indent) const override
{
StringBuilder sb;
for (size_t i = 0; i < m_args.size; ++i)
{
sb.AppendIndent(indent);
sb << "PARAM " << m_args.data[i].Format() << '\n';
}
sb.AppendIndent(indent);
sb << result().Format() << " = CALL " << m_callee.c_str();
return sb.view();
}
public:
const StringView& callee() const { return m_callee; }
const ValueView& args() const { return m_args; }
private:
StringView m_callee;
ValueView m_args;
};
} // namespace IR