shader: Always initialize up reference in structure control flow
Fixes ubsan issue.
This commit is contained in:
		| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user