yuzu/src/video_core/shader/ast.cpp

181 lines
4.5 KiB
C++
Raw Normal View History

2019-06-27 06:39:40 +02:00
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <string>
#include "common/assert.h"
#include "common/common_types.h"
#include "video_core/shader/ast.h"
#include "video_core/shader/expr.h"
namespace VideoCommon::Shader {
class ExprPrinter final {
public:
ExprPrinter() = default;
void operator()(ExprAnd const& expr) {
inner += "( ";
std::visit(*this, *expr.operand1);
inner += " && ";
std::visit(*this, *expr.operand2);
inner += ')';
}
void operator()(ExprOr const& expr) {
inner += "( ";
std::visit(*this, *expr.operand1);
inner += " || ";
std::visit(*this, *expr.operand2);
inner += ')';
}
void operator()(ExprNot const& expr) {
inner += "!";
std::visit(*this, *expr.operand1);
}
void operator()(ExprPredicate const& expr) {
u32 pred = static_cast<u32>(expr.predicate);
if (pred > 7) {
inner += "!";
pred -= 8;
}
inner += "P" + std::to_string(pred);
}
void operator()(ExprCondCode const& expr) {
u32 cc = static_cast<u32>(expr.cc);
inner += "CC" + std::to_string(cc);
}
void operator()(ExprVar const& expr) {
inner += "V" + std::to_string(expr.var_index);
}
void operator()(ExprBoolean const& expr) {
inner += expr.value ? "true" : "false";
}
std::string& GetResult() {
return inner;
}
std::string inner{};
};
class ASTPrinter {
public:
ASTPrinter() = default;
void operator()(ASTProgram& ast) {
scope++;
inner += "program {\n";
for (ASTNode& node : ast.nodes) {
Visit(node);
}
inner += "}\n";
scope--;
}
void operator()(ASTIf& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
inner += Ident() + "if (" + expr_parser.GetResult() + ") {\n";
scope++;
for (auto& node : ast.then_nodes) {
Visit(node);
}
scope--;
if (ast.else_nodes.size() > 0) {
inner += Ident() + "} else {\n";
scope++;
for (auto& node : ast.else_nodes) {
Visit(node);
}
scope--;
} else {
inner += Ident() + "}\n";
}
}
void operator()(ASTBlockEncoded& ast) {
inner += Ident() + "Block(" + std::to_string(ast.start) + ", " + std::to_string(ast.end) +
");\n";
}
void operator()(ASTVarSet& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
inner +=
Ident() + "V" + std::to_string(ast.index) + " := " + expr_parser.GetResult() + ";\n";
}
void operator()(ASTLabel& ast) {
inner += "Label_" + std::to_string(ast.index) + ":\n";
}
void operator()(ASTGoto& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
inner += Ident() + "(" + expr_parser.GetResult() + ") -> goto Label_" +
std::to_string(ast.label) + ";\n";
}
void operator()(ASTDoWhile& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
inner += Ident() + "do {\n";
scope++;
for (auto& node : ast.loop_nodes) {
Visit(node);
}
scope--;
inner += Ident() + "} while (" + expr_parser.GetResult() + ")\n";
}
void operator()(ASTReturn& ast) {
ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition);
inner += Ident() + "(" + expr_parser.GetResult() + ") -> " +
(ast.kills ? "discard" : "exit") + ";\n";
}
std::string& Ident() {
if (memo_scope == scope) {
return tabs_memo;
}
tabs_memo = tabs.substr(0, scope * 2);
memo_scope = scope;
return tabs_memo;
}
void Visit(ASTNode& node) {
std::visit(*this, *node->GetInnerData());
}
std::string& GetResult() {
return inner;
}
private:
std::string inner{};
u32 scope{};
std::string tabs_memo{};
u32 memo_scope{};
static std::string tabs;
};
std::string ASTPrinter::tabs = " ";
std::string ASTManager::Print() {
ASTPrinter printer{};
printer.Visit(main_node);
return printer.GetResult();
}
} // namespace VideoCommon::Shader