diff options
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp | 67 | 
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); | 
