Merge pull request #2944 from lioncash/ast

video_core/shader: Minor changes
master
Fernando Sahmkow 2019-10-05 12:02:51 +07:00 committed by GitHub
commit 47ccfabe18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 166 additions and 152 deletions

@ -17,6 +17,7 @@ void ASTZipper::Init(const ASTNode new_first, const ASTNode parent) {
ASSERT(new_first->manager == nullptr); ASSERT(new_first->manager == nullptr);
first = new_first; first = new_first;
last = new_first; last = new_first;
ASTNode current = first; ASTNode current = first;
while (current) { while (current) {
current->manager = this; current->manager = this;
@ -92,7 +93,7 @@ void ASTZipper::InsertBefore(const ASTNode new_node, const ASTNode at_node) {
new_node->manager = this; new_node->manager = this;
} }
void ASTZipper::DetachTail(const ASTNode node) { void ASTZipper::DetachTail(ASTNode node) {
ASSERT(node->manager == this); ASSERT(node->manager == this);
if (node == first) { if (node == first) {
first.reset(); first.reset();
@ -103,7 +104,8 @@ void ASTZipper::DetachTail(const ASTNode node) {
last = node->previous; last = node->previous;
last->next.reset(); last->next.reset();
node->previous.reset(); node->previous.reset();
ASTNode current = node;
ASTNode current = std::move(node);
while (current) { while (current) {
current->manager = nullptr; current->manager = nullptr;
current->parent.reset(); current->parent.reset();
@ -185,9 +187,7 @@ void ASTZipper::Remove(const ASTNode node) {
class ExprPrinter final { class ExprPrinter final {
public: public:
ExprPrinter() = default; void operator()(const ExprAnd& expr) {
void operator()(ExprAnd const& expr) {
inner += "( "; inner += "( ";
std::visit(*this, *expr.operand1); std::visit(*this, *expr.operand1);
inner += " && "; inner += " && ";
@ -195,7 +195,7 @@ public:
inner += ')'; inner += ')';
} }
void operator()(ExprOr const& expr) { void operator()(const ExprOr& expr) {
inner += "( "; inner += "( ";
std::visit(*this, *expr.operand1); std::visit(*this, *expr.operand1);
inner += " || "; inner += " || ";
@ -203,29 +203,29 @@ public:
inner += ')'; inner += ')';
} }
void operator()(ExprNot const& expr) { void operator()(const ExprNot& expr) {
inner += "!"; inner += "!";
std::visit(*this, *expr.operand1); std::visit(*this, *expr.operand1);
} }
void operator()(ExprPredicate const& expr) { void operator()(const ExprPredicate& expr) {
inner += "P" + std::to_string(expr.predicate); inner += "P" + std::to_string(expr.predicate);
} }
void operator()(ExprCondCode const& expr) { void operator()(const ExprCondCode& expr) {
u32 cc = static_cast<u32>(expr.cc); u32 cc = static_cast<u32>(expr.cc);
inner += "CC" + std::to_string(cc); inner += "CC" + std::to_string(cc);
} }
void operator()(ExprVar const& expr) { void operator()(const ExprVar& expr) {
inner += "V" + std::to_string(expr.var_index); inner += "V" + std::to_string(expr.var_index);
} }
void operator()(ExprBoolean const& expr) { void operator()(const ExprBoolean& expr) {
inner += expr.value ? "true" : "false"; inner += expr.value ? "true" : "false";
} }
std::string& GetResult() { const std::string& GetResult() const {
return inner; return inner;
} }
@ -234,9 +234,7 @@ public:
class ASTPrinter { class ASTPrinter {
public: public:
ASTPrinter() = default; void operator()(const ASTProgram& ast) {
void operator()(ASTProgram& ast) {
scope++; scope++;
inner += "program {\n"; inner += "program {\n";
ASTNode current = ast.nodes.GetFirst(); ASTNode current = ast.nodes.GetFirst();
@ -248,7 +246,7 @@ public:
scope--; scope--;
} }
void operator()(ASTIfThen& ast) { void operator()(const ASTIfThen& ast) {
ExprPrinter expr_parser{}; ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition); std::visit(expr_parser, *ast.condition);
inner += Ident() + "if (" + expr_parser.GetResult() + ") {\n"; inner += Ident() + "if (" + expr_parser.GetResult() + ") {\n";
@ -262,7 +260,7 @@ public:
inner += Ident() + "}\n"; inner += Ident() + "}\n";
} }
void operator()(ASTIfElse& ast) { void operator()(const ASTIfElse& ast) {
inner += Ident() + "else {\n"; inner += Ident() + "else {\n";
scope++; scope++;
ASTNode current = ast.nodes.GetFirst(); ASTNode current = ast.nodes.GetFirst();
@ -274,34 +272,34 @@ public:
inner += Ident() + "}\n"; inner += Ident() + "}\n";
} }
void operator()(ASTBlockEncoded& ast) { void operator()(const ASTBlockEncoded& ast) {
inner += Ident() + "Block(" + std::to_string(ast.start) + ", " + std::to_string(ast.end) + inner += Ident() + "Block(" + std::to_string(ast.start) + ", " + std::to_string(ast.end) +
");\n"; ");\n";
} }
void operator()(ASTBlockDecoded& ast) { void operator()(const ASTBlockDecoded& ast) {
inner += Ident() + "Block;\n"; inner += Ident() + "Block;\n";
} }
void operator()(ASTVarSet& ast) { void operator()(const ASTVarSet& ast) {
ExprPrinter expr_parser{}; ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition); std::visit(expr_parser, *ast.condition);
inner += inner +=
Ident() + "V" + std::to_string(ast.index) + " := " + expr_parser.GetResult() + ";\n"; Ident() + "V" + std::to_string(ast.index) + " := " + expr_parser.GetResult() + ";\n";
} }
void operator()(ASTLabel& ast) { void operator()(const ASTLabel& ast) {
inner += "Label_" + std::to_string(ast.index) + ":\n"; inner += "Label_" + std::to_string(ast.index) + ":\n";
} }
void operator()(ASTGoto& ast) { void operator()(const ASTGoto& ast) {
ExprPrinter expr_parser{}; ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition); std::visit(expr_parser, *ast.condition);
inner += Ident() + "(" + expr_parser.GetResult() + ") -> goto Label_" + inner += Ident() + "(" + expr_parser.GetResult() + ") -> goto Label_" +
std::to_string(ast.label) + ";\n"; std::to_string(ast.label) + ";\n";
} }
void operator()(ASTDoWhile& ast) { void operator()(const ASTDoWhile& ast) {
ExprPrinter expr_parser{}; ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition); std::visit(expr_parser, *ast.condition);
inner += Ident() + "do {\n"; inner += Ident() + "do {\n";
@ -315,14 +313,14 @@ public:
inner += Ident() + "} while (" + expr_parser.GetResult() + ");\n"; inner += Ident() + "} while (" + expr_parser.GetResult() + ");\n";
} }
void operator()(ASTReturn& ast) { void operator()(const ASTReturn& ast) {
ExprPrinter expr_parser{}; ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition); std::visit(expr_parser, *ast.condition);
inner += Ident() + "(" + expr_parser.GetResult() + ") -> " + inner += Ident() + "(" + expr_parser.GetResult() + ") -> " +
(ast.kills ? "discard" : "exit") + ";\n"; (ast.kills ? "discard" : "exit") + ";\n";
} }
void operator()(ASTBreak& ast) { void operator()(const ASTBreak& ast) {
ExprPrinter expr_parser{}; ExprPrinter expr_parser{};
std::visit(expr_parser, *ast.condition); std::visit(expr_parser, *ast.condition);
inner += Ident() + "(" + expr_parser.GetResult() + ") -> break;\n"; inner += Ident() + "(" + expr_parser.GetResult() + ") -> break;\n";
@ -341,7 +339,7 @@ public:
std::visit(*this, *node->GetInnerData()); std::visit(*this, *node->GetInnerData());
} }
std::string& GetResult() { const std::string& GetResult() const {
return inner; return inner;
} }
@ -352,11 +350,9 @@ private:
std::string tabs_memo{}; std::string tabs_memo{};
u32 memo_scope{}; u32 memo_scope{};
static std::string tabs; static constexpr std::string_view tabs{" "};
}; };
std::string ASTPrinter::tabs = " ";
std::string ASTManager::Print() { std::string ASTManager::Print() {
ASTPrinter printer{}; ASTPrinter printer{};
printer.Visit(main_node); printer.Visit(main_node);
@ -376,30 +372,6 @@ void ASTManager::Init() {
false_condition = MakeExpr<ExprBoolean>(false); false_condition = MakeExpr<ExprBoolean>(false);
} }
ASTManager::ASTManager(ASTManager&& other) noexcept
: labels_map(std::move(other.labels_map)), labels_count{other.labels_count},
gotos(std::move(other.gotos)), labels(std::move(other.labels)), variables{other.variables},
program{other.program}, main_node{other.main_node}, false_condition{other.false_condition},
disable_else_derivation{other.disable_else_derivation} {
other.main_node.reset();
}
ASTManager& ASTManager::operator=(ASTManager&& other) noexcept {
full_decompile = other.full_decompile;
labels_map = std::move(other.labels_map);
labels_count = other.labels_count;
gotos = std::move(other.gotos);
labels = std::move(other.labels);
variables = other.variables;
program = other.program;
main_node = other.main_node;
false_condition = other.false_condition;
disable_else_derivation = other.disable_else_derivation;
other.main_node.reset();
return *this;
}
void ASTManager::DeclareLabel(u32 address) { void ASTManager::DeclareLabel(u32 address) {
const auto pair = labels_map.emplace(address, labels_count); const auto pair = labels_map.emplace(address, labels_count);
if (pair.second) { if (pair.second) {
@ -417,19 +389,19 @@ void ASTManager::InsertLabel(u32 address) {
void ASTManager::InsertGoto(Expr condition, u32 address) { void ASTManager::InsertGoto(Expr condition, u32 address) {
const u32 index = labels_map[address]; const u32 index = labels_map[address];
const ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index); const ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, std::move(condition), index);
gotos.push_back(goto_node); gotos.push_back(goto_node);
program->nodes.PushBack(goto_node); program->nodes.PushBack(goto_node);
} }
void ASTManager::InsertBlock(u32 start_address, u32 end_address) { void ASTManager::InsertBlock(u32 start_address, u32 end_address) {
const ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address); ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address);
program->nodes.PushBack(block); program->nodes.PushBack(std::move(block));
} }
void ASTManager::InsertReturn(Expr condition, bool kills) { void ASTManager::InsertReturn(Expr condition, bool kills) {
const ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills); ASTNode node = ASTBase::Make<ASTReturn>(main_node, std::move(condition), kills);
program->nodes.PushBack(node); program->nodes.PushBack(std::move(node));
} }
// The decompile algorithm is based on // The decompile algorithm is based on
@ -496,10 +468,10 @@ void ASTManager::Decompile() {
} }
labels.clear(); labels.clear();
} else { } else {
auto it = labels.begin(); auto label_it = labels.begin();
while (it != labels.end()) { while (label_it != labels.end()) {
bool can_remove = true; bool can_remove = true;
ASTNode label = *it; ASTNode label = *label_it;
for (const ASTNode& goto_node : gotos) { for (const ASTNode& goto_node : gotos) {
const auto label_index = goto_node->GetGotoLabel(); const auto label_index = goto_node->GetGotoLabel();
if (!label_index) { if (!label_index) {
@ -543,11 +515,11 @@ bool ASTManager::IsBackwardsJump(ASTNode goto_node, ASTNode label_node) const {
return false; return false;
} }
bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) { bool ASTManager::IndirectlyRelated(const ASTNode& first, const ASTNode& second) const {
return !(first->GetParent() == second->GetParent() || DirectlyRelated(first, second)); return !(first->GetParent() == second->GetParent() || DirectlyRelated(first, second));
} }
bool ASTManager::DirectlyRelated(ASTNode first, ASTNode second) { bool ASTManager::DirectlyRelated(const ASTNode& first, const ASTNode& second) const {
if (first->GetParent() == second->GetParent()) { if (first->GetParent() == second->GetParent()) {
return false; return false;
} }
@ -577,7 +549,7 @@ bool ASTManager::DirectlyRelated(ASTNode first, ASTNode second) {
return min->GetParent() == max->GetParent(); return min->GetParent() == max->GetParent();
} }
void ASTManager::ShowCurrentState(std::string state) { void ASTManager::ShowCurrentState(std::string_view state) {
LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print()); LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print());
SanityCheck(); SanityCheck();
} }
@ -696,7 +668,7 @@ class ASTClearer {
public: public:
ASTClearer() = default; ASTClearer() = default;
void operator()(ASTProgram& ast) { void operator()(const ASTProgram& ast) {
ASTNode current = ast.nodes.GetFirst(); ASTNode current = ast.nodes.GetFirst();
while (current) { while (current) {
Visit(current); Visit(current);
@ -704,7 +676,7 @@ public:
} }
} }
void operator()(ASTIfThen& ast) { void operator()(const ASTIfThen& ast) {
ASTNode current = ast.nodes.GetFirst(); ASTNode current = ast.nodes.GetFirst();
while (current) { while (current) {
Visit(current); Visit(current);
@ -712,7 +684,7 @@ public:
} }
} }
void operator()(ASTIfElse& ast) { void operator()(const ASTIfElse& ast) {
ASTNode current = ast.nodes.GetFirst(); ASTNode current = ast.nodes.GetFirst();
while (current) { while (current) {
Visit(current); Visit(current);
@ -720,19 +692,19 @@ public:
} }
} }
void operator()(ASTBlockEncoded& ast) {} void operator()([[maybe_unused]] const ASTBlockEncoded& ast) {}
void operator()(ASTBlockDecoded& ast) { void operator()(ASTBlockDecoded& ast) {
ast.nodes.clear(); ast.nodes.clear();
} }
void operator()(ASTVarSet& ast) {} void operator()([[maybe_unused]] const ASTVarSet& ast) {}
void operator()(ASTLabel& ast) {} void operator()([[maybe_unused]] const ASTLabel& ast) {}
void operator()(ASTGoto& ast) {} void operator()([[maybe_unused]] const ASTGoto& ast) {}
void operator()(ASTDoWhile& ast) { void operator()(const ASTDoWhile& ast) {
ASTNode current = ast.nodes.GetFirst(); ASTNode current = ast.nodes.GetFirst();
while (current) { while (current) {
Visit(current); Visit(current);
@ -740,11 +712,11 @@ public:
} }
} }
void operator()(ASTReturn& ast) {} void operator()([[maybe_unused]] const ASTReturn& ast) {}
void operator()(ASTBreak& ast) {} void operator()([[maybe_unused]] const ASTBreak& ast) {}
void Visit(ASTNode& node) { void Visit(const ASTNode& node) {
std::visit(*this, *node->GetInnerData()); std::visit(*this, *node->GetInnerData());
node->Clear(); node->Clear();
} }

@ -18,17 +18,17 @@
namespace VideoCommon::Shader { namespace VideoCommon::Shader {
class ASTBase; class ASTBase;
class ASTProgram;
class ASTIfThen;
class ASTIfElse;
class ASTBlockEncoded;
class ASTBlockDecoded; class ASTBlockDecoded;
class ASTVarSet; class ASTBlockEncoded;
class ASTGoto;
class ASTLabel;
class ASTDoWhile;
class ASTReturn;
class ASTBreak; class ASTBreak;
class ASTDoWhile;
class ASTGoto;
class ASTIfElse;
class ASTIfThen;
class ASTLabel;
class ASTProgram;
class ASTReturn;
class ASTVarSet;
using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded, using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded,
ASTVarSet, ASTGoto, ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>; ASTVarSet, ASTGoto, ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>;
@ -48,11 +48,11 @@ public:
void Init(ASTNode first, ASTNode parent); void Init(ASTNode first, ASTNode parent);
ASTNode GetFirst() { ASTNode GetFirst() const {
return first; return first;
} }
ASTNode GetLast() { ASTNode GetLast() const {
return last; return last;
} }
@ -71,20 +71,18 @@ public:
class ASTProgram { class ASTProgram {
public: public:
explicit ASTProgram() = default;
ASTZipper nodes{}; ASTZipper nodes{};
}; };
class ASTIfThen { class ASTIfThen {
public: public:
explicit ASTIfThen(Expr condition) : condition(condition) {} explicit ASTIfThen(Expr condition) : condition{std::move(condition)} {}
Expr condition; Expr condition;
ASTZipper nodes{}; ASTZipper nodes{};
}; };
class ASTIfElse { class ASTIfElse {
public: public:
explicit ASTIfElse() = default;
ASTZipper nodes{}; ASTZipper nodes{};
}; };
@ -103,7 +101,7 @@ public:
class ASTVarSet { class ASTVarSet {
public: public:
explicit ASTVarSet(u32 index, Expr condition) : index{index}, condition{condition} {} explicit ASTVarSet(u32 index, Expr condition) : index{index}, condition{std::move(condition)} {}
u32 index; u32 index;
Expr condition; Expr condition;
}; };
@ -117,42 +115,45 @@ public:
class ASTGoto { class ASTGoto {
public: public:
explicit ASTGoto(Expr condition, u32 label) : condition{condition}, label{label} {} explicit ASTGoto(Expr condition, u32 label) : condition{std::move(condition)}, label{label} {}
Expr condition; Expr condition;
u32 label; u32 label;
}; };
class ASTDoWhile { class ASTDoWhile {
public: public:
explicit ASTDoWhile(Expr condition) : condition(condition) {} explicit ASTDoWhile(Expr condition) : condition{std::move(condition)} {}
Expr condition; Expr condition;
ASTZipper nodes{}; ASTZipper nodes{};
}; };
class ASTReturn { class ASTReturn {
public: public:
explicit ASTReturn(Expr condition, bool kills) : condition{condition}, kills{kills} {} explicit ASTReturn(Expr condition, bool kills)
: condition{std::move(condition)}, kills{kills} {}
Expr condition; Expr condition;
bool kills; bool kills;
}; };
class ASTBreak { class ASTBreak {
public: public:
explicit ASTBreak(Expr condition) : condition{condition} {} explicit ASTBreak(Expr condition) : condition{std::move(condition)} {}
Expr condition; Expr condition;
}; };
class ASTBase { class ASTBase {
public: public:
explicit ASTBase(ASTNode parent, ASTData data) : parent{parent}, data{data} {} explicit ASTBase(ASTNode parent, ASTData data)
: data{std::move(data)}, parent{std::move(parent)} {}
template <class U, class... Args> template <class U, class... Args>
static ASTNode Make(ASTNode parent, Args&&... args) { static ASTNode Make(ASTNode parent, Args&&... args) {
return std::make_shared<ASTBase>(parent, ASTData(U(std::forward<Args>(args)...))); return std::make_shared<ASTBase>(std::move(parent),
ASTData(U(std::forward<Args>(args)...)));
} }
void SetParent(ASTNode new_parent) { void SetParent(ASTNode new_parent) {
parent = new_parent; parent = std::move(new_parent);
} }
ASTNode& GetParent() { ASTNode& GetParent() {
@ -177,6 +178,10 @@ public:
return &data; return &data;
} }
const ASTData* GetInnerData() const {
return &data;
}
ASTNode GetNext() const { ASTNode GetNext() const {
return next; return next;
} }
@ -189,6 +194,10 @@ public:
return *manager; return *manager;
} }
const ASTZipper& GetManager() const {
return *manager;
}
std::optional<u32> GetGotoLabel() const { std::optional<u32> GetGotoLabel() const {
auto inner = std::get_if<ASTGoto>(&data); auto inner = std::get_if<ASTGoto>(&data);
if (inner) { if (inner) {
@ -239,7 +248,7 @@ public:
void SetGotoCondition(Expr new_condition) { void SetGotoCondition(Expr new_condition) {
auto inner = std::get_if<ASTGoto>(&data); auto inner = std::get_if<ASTGoto>(&data);
if (inner) { if (inner) {
inner->condition = new_condition; inner->condition = std::move(new_condition);
} }
} }
@ -304,8 +313,8 @@ public:
ASTManager(const ASTManager& o) = delete; ASTManager(const ASTManager& o) = delete;
ASTManager& operator=(const ASTManager& other) = delete; ASTManager& operator=(const ASTManager& other) = delete;
ASTManager(ASTManager&& other) noexcept; ASTManager(ASTManager&& other) noexcept = default;
ASTManager& operator=(ASTManager&& other) noexcept; ASTManager& operator=(ASTManager&& other) noexcept = default;
void Init(); void Init();
@ -323,7 +332,7 @@ public:
void Decompile(); void Decompile();
void ShowCurrentState(std::string state); void ShowCurrentState(std::string_view state);
void SanityCheck(); void SanityCheck();
@ -331,8 +340,9 @@ public:
bool IsFullyDecompiled() const { bool IsFullyDecompiled() const {
if (full_decompile) { if (full_decompile) {
return gotos.size() == 0; return gotos.empty();
} else { }
for (ASTNode goto_node : gotos) { for (ASTNode goto_node : gotos) {
auto label_index = goto_node->GetGotoLabel(); auto label_index = goto_node->GetGotoLabel();
if (!label_index) { if (!label_index) {
@ -345,7 +355,6 @@ public:
} }
return true; return true;
} }
}
ASTNode GetProgram() const { ASTNode GetProgram() const {
return main_node; return main_node;
@ -362,9 +371,9 @@ public:
private: private:
bool IsBackwardsJump(ASTNode goto_node, ASTNode label_node) const; bool IsBackwardsJump(ASTNode goto_node, ASTNode label_node) const;
bool IndirectlyRelated(ASTNode first, ASTNode second); bool IndirectlyRelated(const ASTNode& first, const ASTNode& second) const;
bool DirectlyRelated(ASTNode first, ASTNode second); bool DirectlyRelated(const ASTNode& first, const ASTNode& second) const;
void EncloseDoWhile(ASTNode goto_node, ASTNode label); void EncloseDoWhile(ASTNode goto_node, ASTNode label);

@ -479,7 +479,7 @@ std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
auto result_out = std::make_unique<ShaderCharacteristics>(); auto result_out = std::make_unique<ShaderCharacteristics>();
if (settings.depth == CompileDepth::BruteForce) { if (settings.depth == CompileDepth::BruteForce) {
result_out->settings.depth = CompileDepth::BruteForce; result_out->settings.depth = CompileDepth::BruteForce;
return std::move(result_out); return result_out;
} }
CFGRebuildState state{program_code, program_size, start_address}; CFGRebuildState state{program_code, program_size, start_address};
@ -490,7 +490,7 @@ std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
while (!state.inspect_queries.empty()) { while (!state.inspect_queries.empty()) {
if (!TryInspectAddress(state)) { if (!TryInspectAddress(state)) {
result_out->settings.depth = CompileDepth::BruteForce; result_out->settings.depth = CompileDepth::BruteForce;
return std::move(result_out); return result_out;
} }
} }
@ -530,14 +530,15 @@ std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
state.manager->ShowCurrentState("Of Shader"); state.manager->ShowCurrentState("Of Shader");
state.manager->Clear(); state.manager->Clear();
} else { } else {
auto result_out = std::make_unique<ShaderCharacteristics>(); auto characteristics = std::make_unique<ShaderCharacteristics>();
result_out->start = start_address; characteristics->start = start_address;
result_out->settings.depth = settings.depth; characteristics->settings.depth = settings.depth;
result_out->manager = std::move(manager); characteristics->manager = std::move(manager);
result_out->end = state.block_info.back().end + 1; characteristics->end = state.block_info.back().end + 1;
return std::move(result_out); return characteristics;
} }
} }
result_out->start = start_address; result_out->start = start_address;
result_out->settings.depth = result_out->settings.depth =
use_flow_stack ? CompileDepth::FlowStack : CompileDepth::NoFlowStack; use_flow_stack ? CompileDepth::FlowStack : CompileDepth::NoFlowStack;
@ -557,8 +558,9 @@ std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
} }
if (!use_flow_stack) { if (!use_flow_stack) {
result_out->labels = std::move(state.labels); result_out->labels = std::move(state.labels);
return std::move(result_out); return result_out;
} }
auto back = result_out->blocks.begin(); auto back = result_out->blocks.begin();
auto next = std::next(back); auto next = std::next(back);
while (next != result_out->blocks.end()) { while (next != result_out->blocks.end()) {
@ -570,6 +572,7 @@ std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
back = next; back = next;
++next; ++next;
} }
return std::move(result_out);
return result_out;
} }
} // namespace VideoCommon::Shader } // namespace VideoCommon::Shader

@ -2,40 +2,51 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once
#include <memory> #include <memory>
#include <variant> #include <variant>
#include "video_core/shader/expr.h" #include "video_core/shader/expr.h"
namespace VideoCommon::Shader { namespace VideoCommon::Shader {
namespace {
bool ExprIsBoolean(const Expr& expr) {
return std::holds_alternative<ExprBoolean>(*expr);
}
bool ExprBooleanGet(const Expr& expr) {
return std::get_if<ExprBoolean>(expr.get())->value;
}
} // Anonymous namespace
bool ExprAnd::operator==(const ExprAnd& b) const { bool ExprAnd::operator==(const ExprAnd& b) const {
return (*operand1 == *b.operand1) && (*operand2 == *b.operand2); return (*operand1 == *b.operand1) && (*operand2 == *b.operand2);
} }
bool ExprAnd::operator!=(const ExprAnd& b) const {
return !operator==(b);
}
bool ExprOr::operator==(const ExprOr& b) const { bool ExprOr::operator==(const ExprOr& b) const {
return (*operand1 == *b.operand1) && (*operand2 == *b.operand2); return (*operand1 == *b.operand1) && (*operand2 == *b.operand2);
} }
bool ExprOr::operator!=(const ExprOr& b) const {
return !operator==(b);
}
bool ExprNot::operator==(const ExprNot& b) const { bool ExprNot::operator==(const ExprNot& b) const {
return (*operand1 == *b.operand1); return *operand1 == *b.operand1;
} }
bool ExprIsBoolean(Expr expr) { bool ExprNot::operator!=(const ExprNot& b) const {
return std::holds_alternative<ExprBoolean>(*expr); return !operator==(b);
}
bool ExprBooleanGet(Expr expr) {
return std::get_if<ExprBoolean>(expr.get())->value;
} }
Expr MakeExprNot(Expr first) { Expr MakeExprNot(Expr first) {
if (std::holds_alternative<ExprNot>(*first)) { if (std::holds_alternative<ExprNot>(*first)) {
return std::get_if<ExprNot>(first.get())->operand1; return std::get_if<ExprNot>(first.get())->operand1;
} }
return MakeExpr<ExprNot>(first); return MakeExpr<ExprNot>(std::move(first));
} }
Expr MakeExprAnd(Expr first, Expr second) { Expr MakeExprAnd(Expr first, Expr second) {
@ -45,7 +56,7 @@ Expr MakeExprAnd(Expr first, Expr second) {
if (ExprIsBoolean(second)) { if (ExprIsBoolean(second)) {
return ExprBooleanGet(second) ? first : second; return ExprBooleanGet(second) ? first : second;
} }
return MakeExpr<ExprAnd>(first, second); return MakeExpr<ExprAnd>(std::move(first), std::move(second));
} }
Expr MakeExprOr(Expr first, Expr second) { Expr MakeExprOr(Expr first, Expr second) {
@ -55,14 +66,14 @@ Expr MakeExprOr(Expr first, Expr second) {
if (ExprIsBoolean(second)) { if (ExprIsBoolean(second)) {
return ExprBooleanGet(second) ? second : first; return ExprBooleanGet(second) ? second : first;
} }
return MakeExpr<ExprOr>(first, second); return MakeExpr<ExprOr>(std::move(first), std::move(second));
} }
bool ExprAreEqual(Expr first, Expr second) { bool ExprAreEqual(const Expr& first, const Expr& second) {
return (*first) == (*second); return (*first) == (*second);
} }
bool ExprAreOpposite(Expr first, Expr second) { bool ExprAreOpposite(const Expr& first, const Expr& second) {
if (std::holds_alternative<ExprNot>(*first)) { if (std::holds_alternative<ExprNot>(*first)) {
return ExprAreEqual(std::get_if<ExprNot>(first.get())->operand1, second); return ExprAreEqual(std::get_if<ExprNot>(first.get())->operand1, second);
} }
@ -72,7 +83,7 @@ bool ExprAreOpposite(Expr first, Expr second) {
return false; return false;
} }
bool ExprIsTrue(Expr first) { bool ExprIsTrue(const Expr& first) {
if (ExprIsBoolean(first)) { if (ExprIsBoolean(first)) {
return ExprBooleanGet(first); return ExprBooleanGet(first);
} }

@ -15,12 +15,12 @@ using Tegra::Shader::ConditionCode;
using Tegra::Shader::Pred; using Tegra::Shader::Pred;
class ExprAnd; class ExprAnd;
class ExprOr;
class ExprNot;
class ExprPredicate;
class ExprCondCode;
class ExprVar;
class ExprBoolean; class ExprBoolean;
class ExprCondCode;
class ExprNot;
class ExprOr;
class ExprPredicate;
class ExprVar;
using ExprData = using ExprData =
std::variant<ExprVar, ExprCondCode, ExprPredicate, ExprNot, ExprOr, ExprAnd, ExprBoolean>; std::variant<ExprVar, ExprCondCode, ExprPredicate, ExprNot, ExprOr, ExprAnd, ExprBoolean>;
@ -28,9 +28,10 @@ using Expr = std::shared_ptr<ExprData>;
class ExprAnd final { class ExprAnd final {
public: public:
explicit ExprAnd(Expr a, Expr b) : operand1{a}, operand2{b} {} explicit ExprAnd(Expr a, Expr b) : operand1{std::move(a)}, operand2{std::move(b)} {}
bool operator==(const ExprAnd& b) const; bool operator==(const ExprAnd& b) const;
bool operator!=(const ExprAnd& b) const;
Expr operand1; Expr operand1;
Expr operand2; Expr operand2;
@ -38,9 +39,10 @@ public:
class ExprOr final { class ExprOr final {
public: public:
explicit ExprOr(Expr a, Expr b) : operand1{a}, operand2{b} {} explicit ExprOr(Expr a, Expr b) : operand1{std::move(a)}, operand2{std::move(b)} {}
bool operator==(const ExprOr& b) const; bool operator==(const ExprOr& b) const;
bool operator!=(const ExprOr& b) const;
Expr operand1; Expr operand1;
Expr operand2; Expr operand2;
@ -48,9 +50,10 @@ public:
class ExprNot final { class ExprNot final {
public: public:
explicit ExprNot(Expr a) : operand1{a} {} explicit ExprNot(Expr a) : operand1{std::move(a)} {}
bool operator==(const ExprNot& b) const; bool operator==(const ExprNot& b) const;
bool operator!=(const ExprNot& b) const;
Expr operand1; Expr operand1;
}; };
@ -63,6 +66,10 @@ public:
return var_index == b.var_index; return var_index == b.var_index;
} }
bool operator!=(const ExprVar& b) const {
return !operator==(b);
}
u32 var_index; u32 var_index;
}; };
@ -74,6 +81,10 @@ public:
return predicate == b.predicate; return predicate == b.predicate;
} }
bool operator!=(const ExprPredicate& b) const {
return !operator==(b);
}
u32 predicate; u32 predicate;
}; };
@ -85,6 +96,10 @@ public:
return cc == b.cc; return cc == b.cc;
} }
bool operator!=(const ExprCondCode& b) const {
return !operator==(b);
}
ConditionCode cc; ConditionCode cc;
}; };
@ -96,6 +111,10 @@ public:
return value == b.value; return value == b.value;
} }
bool operator!=(const ExprBoolean& b) const {
return !operator==(b);
}
bool value; bool value;
}; };
@ -105,9 +124,9 @@ Expr MakeExpr(Args&&... args) {
return std::make_shared<ExprData>(T(std::forward<Args>(args)...)); return std::make_shared<ExprData>(T(std::forward<Args>(args)...));
} }
bool ExprAreEqual(Expr first, Expr second); bool ExprAreEqual(const Expr& first, const Expr& second);
bool ExprAreOpposite(Expr first, Expr second); bool ExprAreOpposite(const Expr& first, const Expr& second);
Expr MakeExprNot(Expr first); Expr MakeExprNot(Expr first);
@ -115,6 +134,6 @@ Expr MakeExprAnd(Expr first, Expr second);
Expr MakeExprOr(Expr first, Expr second); Expr MakeExprOr(Expr first, Expr second);
bool ExprIsTrue(Expr first); bool ExprIsTrue(const Expr& first);
} // namespace VideoCommon::Shader } // namespace VideoCommon::Shader