summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp67
1 files changed, 36 insertions, 31 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
index ebe5c2654..c1e0646e6 100644
--- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
@@ -101,22 +101,24 @@ struct Statement : ListBaseHook {
: children{std::move(children_)}, cond{cond_}, up{up_}, type{StatementType::Loop} {}
Statement(Break, Statement* cond_, Statement* up_)
: cond{cond_}, up{up_}, type{StatementType::Break} {}
- Statement(Return) : type{StatementType::Return} {}
- Statement(Kill) : type{StatementType::Kill} {}
- Statement(Unreachable) : type{StatementType::Unreachable} {}
+ Statement(Return, Statement* up_) : up{up_}, type{StatementType::Return} {}
+ Statement(Kill, Statement* up_) : up{up_}, type{StatementType::Kill} {}
+ Statement(Unreachable, Statement* up_) : up{up_}, type{StatementType::Unreachable} {}
Statement(FunctionTag) : children{}, type{StatementType::Function} {}
- Statement(Identity, IR::Condition cond_) : guest_cond{cond_}, type{StatementType::Identity} {}
- Statement(Not, Statement* op_) : op{op_}, type{StatementType::Not} {}
- Statement(Or, Statement* op_a_, Statement* op_b_)
- : op_a{op_a_}, op_b{op_b_}, type{StatementType::Or} {}
+ Statement(Identity, IR::Condition cond_, Statement* up_)
+ : guest_cond{cond_}, up{up_}, type{StatementType::Identity} {}
+ Statement(Not, Statement* op_, Statement* up_) : op{op_}, up{up_}, type{StatementType::Not} {}
+ Statement(Or, Statement* op_a_, Statement* op_b_, Statement* up_)
+ : op_a{op_a_}, op_b{op_b_}, up{up_}, type{StatementType::Or} {}
Statement(SetVariable, u32 id_, Statement* op_, Statement* up_)
: op{op_}, id{id_}, up{up_}, type{StatementType::SetVariable} {}
- Statement(SetIndirectBranchVariable, IR::Reg branch_reg_, s32 branch_offset_)
+ Statement(SetIndirectBranchVariable, IR::Reg branch_reg_, s32 branch_offset_, Statement* up_)
: branch_offset{branch_offset_},
- branch_reg{branch_reg_}, type{StatementType::SetIndirectBranchVariable} {}
- Statement(Variable, u32 id_) : id{id_}, type{StatementType::Variable} {}
- Statement(IndirectBranchCond, u32 location_)
- : location{location_}, type{StatementType::IndirectBranchCond} {}
+ branch_reg{branch_reg_}, up{up_}, type{StatementType::SetIndirectBranchVariable} {}
+ Statement(Variable, u32 id_, Statement* up_)
+ : id{id_}, up{up_}, type{StatementType::Variable} {}
+ Statement(IndirectBranchCond, u32 location_, Statement* up_)
+ : location{location_}, up{up_}, type{StatementType::IndirectBranchCond} {}
~Statement() {
if (HasChildren(type)) {
@@ -385,7 +387,7 @@ private:
void BuildTree(Flow::CFG& cfg, Flow::Function& function, u32& label_id,
std::vector<Node>& gotos, Node function_insert_point,
std::optional<Node> return_label) {
- Statement* const false_stmt{pool.Create(Identity{}, IR::Condition{false})};
+ Statement* const false_stmt{pool.Create(Identity{}, IR::Condition{false}, &root_stmt)};
Tree& root{root_stmt.children};
std::unordered_map<Flow::Block*, Node> local_labels;
local_labels.reserve(function.blocks.size());
@@ -411,7 +413,8 @@ private:
switch (block.end_class) {
case Flow::EndClass::Branch: {
- Statement* const always_cond{pool.Create(Identity{}, IR::Condition{true})};
+ Statement* const always_cond{
+ pool.Create(Identity{}, IR::Condition{true}, &root_stmt)};
if (block.cond == IR::Condition{true}) {
const Node true_label{local_labels.at(block.branch_true)};
gotos.push_back(
@@ -423,7 +426,7 @@ private:
} else {
const Node true_label{local_labels.at(block.branch_true)};
const Node false_label{local_labels.at(block.branch_false)};
- Statement* const true_cond{pool.Create(Identity{}, block.cond)};
+ Statement* const true_cond{pool.Create(Identity{}, block.cond, &root_stmt)};
gotos.push_back(
root.insert(ip, *pool.Create(Goto{}, true_cond, true_label, &root_stmt)));
gotos.push_back(root.insert(
@@ -433,14 +436,15 @@ private:
}
case Flow::EndClass::IndirectBranch:
root.insert(ip, *pool.Create(SetIndirectBranchVariable{}, block.branch_reg,
- block.branch_offset));
+ block.branch_offset, &root_stmt));
for (const Flow::IndirectBranch& indirect : block.indirect_branches) {
const Node indirect_label{local_labels.at(indirect.block)};
- Statement* cond{pool.Create(IndirectBranchCond{}, indirect.address)};
+ Statement* cond{
+ pool.Create(IndirectBranchCond{}, indirect.address, &root_stmt)};
Statement* goto_stmt{pool.Create(Goto{}, cond, indirect_label, &root_stmt)};
gotos.push_back(root.insert(ip, *goto_stmt));
}
- root.insert(ip, *pool.Create(Unreachable{}));
+ root.insert(ip, *pool.Create(Unreachable{}, &root_stmt));
break;
case Flow::EndClass::Call: {
Flow::Function& call{cfg.Functions()[block.function_call]};
@@ -449,16 +453,16 @@ private:
break;
}
case Flow::EndClass::Exit:
- root.insert(ip, *pool.Create(Return{}));
+ root.insert(ip, *pool.Create(Return{}, &root_stmt));
break;
case Flow::EndClass::Return: {
- Statement* const always_cond{pool.Create(Identity{}, block.cond)};
+ Statement* const always_cond{pool.Create(Identity{}, block.cond, &root_stmt)};
auto goto_stmt{pool.Create(Goto{}, always_cond, return_label.value(), &root_stmt)};
gotos.push_back(root.insert(ip, *goto_stmt));
break;
}
case Flow::EndClass::Kill:
- root.insert(ip, *pool.Create(Kill{}));
+ root.insert(ip, *pool.Create(Kill{}, &root_stmt));
break;
}
}
@@ -474,7 +478,7 @@ private:
Tree& body{goto_stmt->up->children};
Tree if_body;
if_body.splice(if_body.begin(), body, std::next(goto_stmt), label_stmt);
- Statement* const cond{pool.Create(Not{}, goto_stmt->cond)};
+ Statement* const cond{pool.Create(Not{}, goto_stmt->cond, &root_stmt)};
Statement* const if_stmt{pool.Create(If{}, cond, std::move(if_body), goto_stmt->up)};
UpdateTreeUp(if_stmt);
body.insert(goto_stmt, *if_stmt);
@@ -516,8 +520,8 @@ private:
Tree if_body;
if_body.splice(if_body.begin(), body, std::next(goto_stmt), label_nested_stmt);
- Statement* const variable{pool.Create(Variable{}, label_id)};
- Statement* const neg_var{pool.Create(Not{}, variable)};
+ Statement* const variable{pool.Create(Variable{}, label_id, &root_stmt)};
+ Statement* const neg_var{pool.Create(Not{}, variable, &root_stmt)};
if (!if_body.empty()) {
Statement* const if_stmt{pool.Create(If{}, neg_var, std::move(if_body), parent)};
UpdateTreeUp(if_stmt);
@@ -528,7 +532,8 @@ private:
switch (label_nested_stmt->type) {
case StatementType::If:
// Update nested if condition
- label_nested_stmt->cond = pool.Create(Or{}, variable, label_nested_stmt->cond);
+ label_nested_stmt->cond =
+ pool.Create(Or{}, variable, label_nested_stmt->cond, &root_stmt);
break;
case StatementType::Loop:
break;
@@ -550,7 +555,7 @@ private:
Tree loop_body;
loop_body.splice(loop_body.begin(), body, label_nested_stmt, goto_stmt);
SanitizeNoBreaks(loop_body);
- Statement* const variable{pool.Create(Variable{}, label_id)};
+ Statement* const variable{pool.Create(Variable{}, label_id, &root_stmt)};
Statement* const loop_stmt{pool.Create(Loop{}, variable, std::move(loop_body), parent)};
UpdateTreeUp(loop_stmt);
body.insert(goto_stmt, *loop_stmt);
@@ -577,15 +582,15 @@ private:
Tree if_body;
if_body.splice(if_body.begin(), body, std::next(goto_stmt), body.end());
if_body.pop_front();
- Statement* const cond{pool.Create(Variable{}, label_id)};
- Statement* const neg_cond{pool.Create(Not{}, cond)};
+ Statement* const cond{pool.Create(Variable{}, label_id, &root_stmt)};
+ Statement* const neg_cond{pool.Create(Not{}, cond, &root_stmt)};
Statement* const if_stmt{pool.Create(If{}, neg_cond, std::move(if_body), &*parent)};
UpdateTreeUp(if_stmt);
body.insert(goto_stmt, *if_stmt);
body.erase(goto_stmt);
- Statement* const new_cond{pool.Create(Variable{}, label_id)};
+ Statement* const new_cond{pool.Create(Variable{}, label_id, &root_stmt)};
Statement* const new_goto{pool.Create(Goto{}, new_cond, goto_stmt->label, parent->up)};
Tree& parent_tree{parent->up->children};
return parent_tree.insert(std::next(parent), *new_goto);
@@ -597,14 +602,14 @@ private:
const u32 label_id{goto_stmt->label->id};
Statement* const goto_cond{goto_stmt->cond};
Statement* const set_goto_var{pool.Create(SetVariable{}, label_id, goto_cond, parent)};
- Statement* const cond{pool.Create(Variable{}, label_id)};
+ Statement* const cond{pool.Create(Variable{}, label_id, &root_stmt)};
Statement* const break_stmt{pool.Create(Break{}, cond, parent)};
body.insert(goto_stmt, *set_goto_var);
body.insert(goto_stmt, *break_stmt);
body.erase(goto_stmt);
const Node loop{Tree::s_iterator_to(*goto_stmt->up)};
- Statement* const new_goto_cond{pool.Create(Variable{}, label_id)};
+ Statement* const new_goto_cond{pool.Create(Variable{}, label_id, &root_stmt)};
Statement* const new_goto{pool.Create(Goto{}, new_goto_cond, goto_stmt->label, loop->up)};
Tree& parent_tree{loop->up->children};
return parent_tree.insert(std::next(loop), *new_goto);