2023-01-04 22:32:55 +00:00
|
|
|
#include <emit.hh>
|
2023-01-05 16:44:30 +00:00
|
|
|
#include <vector>
|
2023-01-04 22:32:55 +00:00
|
|
|
|
|
|
|
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-04 22:32:55 +00:00
|
|
|
}
|
|
|
|
|
2023-01-05 16:44:30 +00:00
|
|
|
std::any EmitVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
|
2023-01-04 22:32:55 +00:00
|
|
|
output << std::endl
|
|
|
|
<< "export function w $" << ctx->Identifier()->getSymbol()->getText()
|
2023-01-05 16:44:30 +00:00
|
|
|
<< "(";
|
2023-01-06 17:46:45 +00:00
|
|
|
if (auto param_list = ctx->parameterList()) {
|
|
|
|
for (const auto param : param_list->Identifier()) {
|
|
|
|
output << "w %_" << param->getSymbol()->getText() << ", ";
|
2023-01-05 16:44:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
output << ")" << std::endl << "{" << std::endl << "@start" << std::endl;
|
|
|
|
blockcount = 0;
|
|
|
|
visitChildren(ctx);
|
|
|
|
output << " ret 0" << std::endl;
|
|
|
|
output << "}" << std::endl;
|
|
|
|
return {};
|
2023-01-04 22:32:55 +00:00
|
|
|
}
|
|
|
|
|
2023-01-05 16:44:30 +00:00
|
|
|
std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
|
|
|
|
if (auto identifier = ctx->Identifier()) {
|
|
|
|
tmpcount = 0;
|
2023-01-06 17:46:45 +00:00
|
|
|
visitValue(ctx->value());
|
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++;
|
2023-01-06 17:56:53 +00:00
|
|
|
|
2023-01-05 17:30:43 +00:00
|
|
|
output << "@if" << block << "_expr" << std::endl;
|
2023-01-05 16:44:30 +00:00
|
|
|
tmpcount = 0;
|
2023-01-06 16:44:57 +00:00
|
|
|
visitCondition(ctx->condition());
|
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++;
|
2023-01-06 17:56:53 +00:00
|
|
|
|
2023-01-05 17:30:43 +00:00
|
|
|
output << "@while" << block << "_expr" << std::endl;
|
2023-01-05 16:44:30 +00:00
|
|
|
tmpcount = 0;
|
2023-01-06 16:44:57 +00:00
|
|
|
visitCondition(ctx->condition());
|
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-06 17:46:45 +00:00
|
|
|
visitValue(ctx->value());
|
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 {};
|
|
|
|
}
|
2023-01-04 22:32:55 +00:00
|
|
|
if (ctx->Print()) {
|
2023-01-05 16:44:30 +00:00
|
|
|
tmpcount = 0;
|
2023-01-06 17:46:45 +00:00
|
|
|
visitValue(ctx->value());
|
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-04 22:32:55 +00:00
|
|
|
}
|
2023-01-05 16:44:30 +00:00
|
|
|
|
2023-01-06 16:44:57 +00:00
|
|
|
std::any EmitVisitor::visitCondition(xlangParser::ConditionContext *ctx) {
|
|
|
|
OPERATOR(And, visitCondition, condition(), visitBoolean, boolean(), "and");
|
|
|
|
OPERATOR(Or, visitCondition, condition(), visitBoolean, boolean(), "or");
|
|
|
|
OPERATOR(Xor, visitCondition, condition(), visitBoolean, boolean(), "xor");
|
|
|
|
visitBoolean(ctx->boolean());
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::any EmitVisitor::visitBoolean(xlangParser::BooleanContext *ctx) {
|
|
|
|
if (ctx->Not()) {
|
|
|
|
visitBoolean(ctx->boolean());
|
|
|
|
std::string b = last;
|
|
|
|
output << " " << tmp() << " = w xor 1, " << b << std::endl;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (ctx->True()) {
|
|
|
|
last = "1";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (ctx->False()) {
|
|
|
|
last = "0";
|
|
|
|
return {};
|
|
|
|
}
|
2023-01-06 17:56:53 +00:00
|
|
|
OPERATOR(Less, visitExpr, expr(0), visitExpr, expr(1), "csltw");
|
|
|
|
OPERATOR(LessEqual, visitExpr, expr(0), visitExpr, expr(1), "cslew");
|
|
|
|
OPERATOR(Greater, visitExpr, expr(0), visitExpr, expr(1), "csgtw");
|
|
|
|
OPERATOR(GreaterEqual, visitExpr, expr(0), visitExpr, expr(1), "csgew");
|
|
|
|
OPERATOR(Equal, visitExpr, expr(0), visitExpr, expr(1), "ceqw");
|
|
|
|
OPERATOR(NotEqual, visitExpr, expr(0), visitExpr, expr(1), "cnew");
|
2023-01-06 17:46:45 +00:00
|
|
|
visitChildren(ctx);
|
2023-01-05 16:44:30 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2023-01-06 16:44:57 +00:00
|
|
|
std::any EmitVisitor::visitExpr(xlangParser::ExprContext *ctx) {
|
|
|
|
OPERATOR(Plus, visitExpr, expr(), visitTerm, term(), "add");
|
|
|
|
OPERATOR(Minus, visitExpr, expr(), visitTerm, term(), "sub");
|
|
|
|
OPERATOR(BitAnd, visitExpr, expr(), visitTerm, term(), "and");
|
|
|
|
OPERATOR(BitOr, visitExpr, expr(), visitTerm, term(), "or");
|
|
|
|
OPERATOR(BitXor, visitExpr, expr(), visitTerm, term(), "xor");
|
|
|
|
OPERATOR(ShiftLeft, visitExpr, expr(), visitTerm, term(), "shl");
|
|
|
|
OPERATOR(ShiftRight, visitExpr, expr(), visitTerm, term(), "shr");
|
2023-01-05 16:44:30 +00:00
|
|
|
visitTerm(ctx->term());
|
|
|
|
return {};
|
2023-01-04 22:32:55 +00:00
|
|
|
}
|
|
|
|
|
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) {
|
2023-01-06 16:44:57 +00:00
|
|
|
if (ctx->Minus()) {
|
|
|
|
visitFactor(ctx->factor());
|
|
|
|
std::string f = last;
|
|
|
|
output << " " << tmp() << " = w neg " << f << std::endl;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (ctx->BitNot()) {
|
|
|
|
visitFactor(ctx->factor());
|
|
|
|
std::string f = last;
|
|
|
|
output << " " << tmp() << " = w xor -1, " << f << std::endl;
|
|
|
|
return {};
|
|
|
|
}
|
2023-01-04 22:32:55 +00:00
|
|
|
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 {};
|
|
|
|
}
|
2023-01-06 17:46:45 +00:00
|
|
|
visitChildren(ctx);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) {
|
|
|
|
auto name = ctx->Identifier()->getSymbol()->getText();
|
|
|
|
|
|
|
|
if (ctx->LeftParen()) {
|
|
|
|
std::vector<std::string> args;
|
2023-01-06 17:56:53 +00:00
|
|
|
|
2023-01-06 17:46:45 +00:00
|
|
|
if (auto arg_list = ctx->argumentList()) {
|
|
|
|
for (auto value : arg_list->value()) {
|
|
|
|
visitValue(value);
|
|
|
|
args.emplace_back(last);
|
2023-01-05 16:44:30 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-06 17:46:45 +00:00
|
|
|
output << " " << tmp() << " = w call $" << name << "(";
|
|
|
|
for (auto arg : args) {
|
|
|
|
output << "w " << arg << ", ";
|
|
|
|
}
|
|
|
|
output << ")" << std::endl;
|
|
|
|
} else {
|
|
|
|
last = "%_" + name;
|
2023-01-05 16:44:30 +00:00
|
|
|
}
|
|
|
|
return {};
|
2023-01-04 22:32:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace xlang
|