diff options
| author | 2021-04-22 18:34:34 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:29 -0400 | |
| commit | 0c7230a606ae705a28c8a14590808d6bfd3656cf (patch) | |
| tree | 8b798882305a203b21a76d35448e5f0939e83dc0 /src/shader_recompiler/ir_opt/verification_pass.cpp | |
| parent | shader: Fix forward referencing identity instructions when inserting phi (diff) | |
| download | yuzu-0c7230a606ae705a28c8a14590808d6bfd3656cf.tar.gz yuzu-0c7230a606ae705a28c8a14590808d6bfd3656cf.tar.xz yuzu-0c7230a606ae705a28c8a14590808d6bfd3656cf.zip | |
shader: Add more strict validation the pass
Diffstat (limited to 'src/shader_recompiler/ir_opt/verification_pass.cpp')
| -rw-r--r-- | src/shader_recompiler/ir_opt/verification_pass.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/shader_recompiler/ir_opt/verification_pass.cpp b/src/shader_recompiler/ir_opt/verification_pass.cpp index 62bf5f8ff..207355ecc 100644 --- a/src/shader_recompiler/ir_opt/verification_pass.cpp +++ b/src/shader_recompiler/ir_opt/verification_pass.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <map> | 5 | #include <map> |
| 6 | #include <set> | ||
| 6 | 7 | ||
| 7 | #include "shader_recompiler/exception.h" | 8 | #include "shader_recompiler/exception.h" |
| 8 | #include "shader_recompiler/frontend/ir/basic_block.h" | 9 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| @@ -50,9 +51,50 @@ static void ValidateUses(const IR::Program& program) { | |||
| 50 | } | 51 | } |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 54 | static void ValidateForwardDeclarations(const IR::Program& program) { | ||
| 55 | std::set<const IR::Inst*> definitions; | ||
| 56 | for (const IR::Block* const block : program.blocks) { | ||
| 57 | for (const IR::Inst& inst : *block) { | ||
| 58 | definitions.emplace(&inst); | ||
| 59 | if (inst.GetOpcode() == IR::Opcode::Phi) { | ||
| 60 | // Phi nodes can have forward declarations | ||
| 61 | continue; | ||
| 62 | } | ||
| 63 | const size_t num_args{inst.NumArgs()}; | ||
| 64 | for (size_t arg = 0; arg < num_args; ++arg) { | ||
| 65 | if (inst.Arg(arg).IsImmediate()) { | ||
| 66 | continue; | ||
| 67 | } | ||
| 68 | if (!definitions.contains(inst.Arg(arg).Inst())) { | ||
| 69 | fmt::print("{}\n", IR::DumpBlock(*block)); | ||
| 70 | throw LogicError("Forward declaration in block: {}", IR::DumpBlock(*block)); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | static void ValidatePhiNodes(const IR::Program& program) { | ||
| 78 | for (const IR::Block* const block : program.blocks) { | ||
| 79 | bool no_more_phis{false}; | ||
| 80 | for (const IR::Inst& inst : *block) { | ||
| 81 | if (inst.GetOpcode() == IR::Opcode::Phi) { | ||
| 82 | if (no_more_phis) { | ||
| 83 | fmt::print("{}\n", IR::DumpBlock(*block)); | ||
| 84 | throw LogicError("Interleaved phi nodes: {}", IR::DumpBlock(*block)); | ||
| 85 | } | ||
| 86 | } else { | ||
| 87 | no_more_phis = true; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 53 | void VerificationPass(const IR::Program& program) { | 93 | void VerificationPass(const IR::Program& program) { |
| 54 | ValidateTypes(program); | 94 | ValidateTypes(program); |
| 55 | ValidateUses(program); | 95 | ValidateUses(program); |
| 96 | ValidateForwardDeclarations(program); | ||
| 97 | ValidatePhiNodes(program); | ||
| 56 | } | 98 | } |
| 57 | 99 | ||
| 58 | } // namespace Shader::Optimization | 100 | } // namespace Shader::Optimization |