215 lines
5.4 KiB
C++
215 lines
5.4 KiB
C++
#pragma once
|
|
#include "prelude/string.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 << "extern " << 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. inherit the OpValued class instead)
|
|
class FnOp : public Op
|
|
{
|
|
public:
|
|
FnOp(StringView name, const View<StringView> ¶ms, 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> ¶ms() const { return m_params; }
|
|
|
|
private:
|
|
StringView m_name;
|
|
View<StringView> m_params;
|
|
Block m_body;
|
|
};
|
|
|
|
// Allocate slot on the stack for variable
|
|
// with the size of destination value,
|
|
// aka (dest.GetSize() will be used)
|
|
class AllocateOp : public OpValued
|
|
{
|
|
public:
|
|
AllocateOp(ValueHandle *dest, const ValueHandle::Type *typ)
|
|
: OpValued(dest), m_typ(new ValueHandle::Type(typ)) {}
|
|
~AllocateOp() {}
|
|
|
|
OP_TYPE(ALLOCATE)
|
|
|
|
public:
|
|
StringView Format(int indent) const override
|
|
{
|
|
StringBuilder sb;
|
|
sb.AppendIndent(indent);
|
|
sb << result()->Format() << " = allocate " << m_typ->Format();
|
|
return sb.view();
|
|
}
|
|
|
|
private:
|
|
ValueHandle::Type *m_typ;
|
|
};
|
|
|
|
class LoadOp : public OpValued
|
|
{
|
|
public:
|
|
LoadOp(ValueHandle *dest, Pointer *ptr)
|
|
: OpValued(dest), m_ptr(ptr) {}
|
|
~LoadOp() {}
|
|
|
|
OP_TYPE(LOAD)
|
|
public:
|
|
StringView Format(int indent) const override
|
|
{
|
|
StringBuilder sb;
|
|
sb.AppendIndent(indent);
|
|
sb << result()->Format() << " = load " << m_ptr->Format();
|
|
return sb.view();
|
|
}
|
|
|
|
private:
|
|
Pointer* m_ptr;
|
|
};
|
|
|
|
class StoreOp : public Op
|
|
{
|
|
public:
|
|
StoreOp(ValueHandle *src, Pointer *dst)
|
|
: m_dst(dst), m_src(src) {}
|
|
~StoreOp() {}
|
|
|
|
OP_TYPE(STORE)
|
|
public:
|
|
StringView Format(int indent) const override
|
|
{
|
|
StringBuilder sb;
|
|
sb.AppendIndent(indent);
|
|
sb << "store " << src()->Format() << ", " << dst()->Format();
|
|
return sb.view();
|
|
}
|
|
|
|
public:
|
|
const Pointer *dst() const { return m_dst; }
|
|
const ValueHandle *src() const { return m_src; }
|
|
|
|
private:
|
|
Pointer *m_dst;
|
|
ValueHandle *m_src;
|
|
};
|
|
|
|
class MathOp : public OpValued
|
|
{
|
|
public:
|
|
MathOp(ValueHandle *dest, ValueHandle *lhs, ValueHandle *rhs, OpType typ)
|
|
: OpValued(dest), m_lhs(lhs), m_rhs(rhs), m_typ(typ) {}
|
|
~MathOp() {}
|
|
|
|
OpType GetType() const override { return m_typ; }
|
|
|
|
private:
|
|
StringView FormatOperation() const
|
|
{
|
|
switch (m_typ)
|
|
{
|
|
case OpType::ADD:
|
|
return StringView("add");
|
|
case OpType::MUL:
|
|
return StringView("mul");
|
|
case OpType::SUB:
|
|
return StringView("sub");
|
|
case OpType::DIV:
|
|
return StringView("div");
|
|
default: break;
|
|
}
|
|
|
|
assert(false && "unreachable");
|
|
}
|
|
|
|
public:
|
|
StringView Format(int indent) const override
|
|
{
|
|
StringBuilder sb;
|
|
sb.AppendIndent(indent);
|
|
sb << result()->Format() << " = " << FormatOperation() << " " << m_lhs->Format() << ", " << m_rhs->Format();
|
|
return sb.view();
|
|
}
|
|
|
|
public:
|
|
ValueHandle *lhs() const { return m_lhs; }
|
|
ValueHandle *rhs() const { return m_rhs; }
|
|
|
|
private:
|
|
ValueHandle *m_lhs;
|
|
ValueHandle *m_rhs;
|
|
OpType m_typ;
|
|
};
|
|
|
|
class CallOp : public OpValued
|
|
{
|
|
public:
|
|
CallOp(ValueHandle *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
|