xlang/bootstrap/emit.cc

162 lines
5.1 KiB
C++
Raw Normal View History

#include <emit.hh>
2023-01-05 16:44:30 +00:00
#include <vector>
namespace xlang {
2023-01-05 18:52:27 +00:00
std::string EmitVisitor::tmp() {
last = "%t" + std::to_string(tmpcount++);
return last;
}
2023-01-05 16:44:30 +00:00
EmitVisitor::EmitVisitor(std::string_view outputfile) : output{outputfile} {}
std::any EmitVisitor::visitFile(xlangParser::FileContext *ctx) {
output << "data $printformat = { b \"%d\\n\", b 0 }" << std::endl;
visitChildren(ctx);
return {};
}
2023-01-05 16:44:30 +00:00
std::any EmitVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
output << std::endl
<< "export function w $" << ctx->Identifier()->getSymbol()->getText()
2023-01-05 16:44:30 +00:00
<< "(";
if (auto arg_list = ctx->argumentList()) {
for (const auto arg : arg_list->Identifier()) {
output << "w %_" << arg->getSymbol()->getText() << ", ";
}
}
output << ")" << std::endl << "{" << std::endl << "@start" << std::endl;
blockcount = 0;
visitChildren(ctx);
output << " ret 0" << std::endl;
output << "}" << std::endl;
return {};
}
2023-01-05 16:44:30 +00:00
std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
if (auto identifier = ctx->Identifier()) {
tmpcount = 0;
2023-01-05 18:37:22 +00:00
visitExpr(ctx->expr());
2023-01-05 18:52:27 +00:00
output << " %_" << identifier->getSymbol()->getText() << " = w copy "
<< last << std::endl;
2023-01-05 16:44:30 +00:00
return {};
}
if (ctx->If()) {
2023-01-05 17:30:43 +00:00
int block = blockcount++;
output << "@if" << block << "_expr" << std::endl;
2023-01-05 16:44:30 +00:00
tmpcount = 0;
visitExpr(ctx->expr());
2023-01-05 18:52:27 +00:00
output << " jnz " << last << ", @if" << block << "_then, @if" << block
<< "_else" << std::endl;
2023-01-05 17:30:43 +00:00
output << "@if" << block << "_then" << std::endl;
2023-01-05 16:44:30 +00:00
visitBlock(ctx->block(0));
2023-01-05 17:30:43 +00:00
output << " jmp @if" << block << "_end" << std::endl;
output << "@if" << block << "_else" << std::endl;
2023-01-05 16:44:30 +00:00
if (ctx->Else()) {
visitBlock(ctx->block(1));
}
2023-01-05 17:30:43 +00:00
output << "@if" << block << "_end" << std::endl;
2023-01-05 16:44:30 +00:00
return {};
}
if (ctx->While()) {
2023-01-05 17:30:43 +00:00
int block = blockcount++;
output << "@while" << block << "_expr" << std::endl;
2023-01-05 16:44:30 +00:00
tmpcount = 0;
visitExpr(ctx->expr());
2023-01-05 18:52:27 +00:00
output << " jnz " << last << ", @while" << block << "_body, @while"
<< block << "_end" << std::endl;
2023-01-05 17:30:43 +00:00
output << "@while" << block << "_body" << std::endl;
2023-01-05 16:44:30 +00:00
visitBlock(ctx->block(0));
2023-01-05 17:30:43 +00:00
output << " jmp @while" << block << "_expr" << std::endl;
output << "@while" << block << "_end" << std::endl;
2023-01-05 16:44:30 +00:00
return {};
}
if (ctx->Return()) {
tmpcount = 0;
2023-01-05 18:37:22 +00:00
visitExpr(ctx->expr());
2023-01-05 18:52:27 +00:00
output << " ret " << last << std::endl;
2023-01-05 16:44:30 +00:00
output << "@dead" << blockcount++ << std::endl;
return {};
}
if (ctx->Print()) {
2023-01-05 16:44:30 +00:00
tmpcount = 0;
2023-01-05 18:37:22 +00:00
visitExpr(ctx->expr());
2023-01-05 18:52:27 +00:00
output << " call $printf(l $printformat, ..., w " << last << ")"
2023-01-05 16:44:30 +00:00
<< std::endl;
return {};
}
// unreachable
return {};
}
2023-01-05 18:52:27 +00:00
#define OPERATOR(Operator, visitLeft, left, visitRight, right, ssa_op) \
if (ctx->Operator()) { \
visitLeft(ctx->left); \
std::string l = last; \
visitRight(ctx->right); \
std::string r = last; \
output << " " << tmp() << " = w " ssa_op " " << l << ", " << r \
<< std::endl; \
return {}; \
}
2023-01-05 16:44:30 +00:00
std::any EmitVisitor::visitExpr(xlangParser::ExprContext *ctx) {
OPERATOR(Less, visitSum, sum(0), visitSum, sum(1), "csltw");
OPERATOR(LessEqual, visitSum, sum(0), visitSum, sum(1), "cslew");
OPERATOR(Greater, visitSum, sum(0), visitSum, sum(1), "csgtw");
OPERATOR(GreaterEqual, visitSum, sum(0), visitSum, sum(1), "csgew");
OPERATOR(Equal, visitSum, sum(0), visitSum, sum(1), "ceqw");
OPERATOR(NotEqual, visitSum, sum(0), visitSum, sum(1), "cnew");
visitSum(ctx->sum(0));
return {};
}
std::any EmitVisitor::visitSum(xlangParser::SumContext *ctx) {
OPERATOR(Plus, visitSum, sum(), visitTerm, term(), "add");
OPERATOR(Minus, visitSum, sum(), visitTerm, term(), "sub");
visitTerm(ctx->term());
return {};
}
2023-01-05 16:44:30 +00:00
std::any EmitVisitor::visitTerm(xlangParser::TermContext *ctx) {
OPERATOR(Mul, visitTerm, term(), visitFactor, factor(), "mul");
OPERATOR(Div, visitTerm, term(), visitFactor, factor(), "div");
visitFactor(ctx->factor());
return {};
}
std::any EmitVisitor::visitFactor(xlangParser::FactorContext *ctx) {
if (auto integer = ctx->Integer()) {
2023-01-05 18:52:27 +00:00
last = integer->getSymbol()->getText();
2023-01-05 16:44:30 +00:00
return {};
}
if (auto identifier = ctx->Identifier()) {
if (ctx->LeftParen()) {
2023-01-05 18:52:27 +00:00
std::vector<std::string> args;
2023-01-05 16:44:30 +00:00
if (auto expr_list = ctx->exprList()) {
for (auto expr : expr_list->expr()) {
visitExpr(expr);
2023-01-06 02:56:33 +00:00
args.emplace_back(last);
2023-01-05 16:44:30 +00:00
}
}
2023-01-05 18:52:27 +00:00
output << " " << tmp() << " = w call $"
2023-01-05 16:44:30 +00:00
<< identifier->getSymbol()->getText() << "(";
for (auto arg : args) {
2023-01-05 18:52:27 +00:00
output << "w " << arg << ", ";
2023-01-05 16:44:30 +00:00
}
output << ")" << std::endl;
} else {
2023-01-05 18:52:27 +00:00
last = "%_" + identifier->getSymbol()->getText();
2023-01-05 16:44:30 +00:00
}
return {};
}
if (auto sum = ctx->sum()) {
visitSum(sum);
return {};
}
2023-01-05 16:44:30 +00:00
// unreachable
return {};
}
} // namespace xlang