summaryrefslogblamecommitdiffstats
path: root/src/shader_recompiler/ir_opt/verification_pass.cpp
blob: 32b56eb57c1601708fed1afc18974cd30ef5feee (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13












                                                           


                                                         



                                                   






                                                                                           




             
                                                        
                                         







                                                   




                                                 
                                                                                        



         


                                                     


                                   
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#include <map>

#include "shader_recompiler/exception.h"
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/microinstruction.h"
#include "shader_recompiler/ir_opt/passes.h"

namespace Shader::Optimization {

static void ValidateTypes(const IR::Function& function) {
    for (const auto& block : function.blocks) {
        for (const IR::Inst& inst : *block) {
            if (inst.Opcode() == IR::Opcode::Phi) {
                // Skip validation on phi nodes
                continue;
            }
            const size_t num_args{inst.NumArgs()};
            for (size_t i = 0; i < num_args; ++i) {
                const IR::Type t1{inst.Arg(i).Type()};
                const IR::Type t2{IR::ArgTypeOf(inst.Opcode(), i)};
                if (!IR::AreTypesCompatible(t1, t2)) {
                    throw LogicError("Invalid types in block:\n{}", IR::DumpBlock(*block));
                }
            }
        }
    }
}

static void ValidateUses(const IR::Function& function) {
    std::map<IR::Inst*, int> actual_uses;
    for (const auto& block : function.blocks) {
        for (const IR::Inst& inst : *block) {
            const size_t num_args{inst.NumArgs()};
            for (size_t i = 0; i < num_args; ++i) {
                const IR::Value arg{inst.Arg(i)};
                if (!arg.IsImmediate()) {
                    ++actual_uses[arg.Inst()];
                }
            }
        }
    }
    for (const auto [inst, uses] : actual_uses) {
        if (inst->UseCount() != uses) {
            throw LogicError("Invalid uses in block:" /*, IR::DumpFunction(function)*/);
        }
    }
}

void VerificationPass(const IR::Function& function) {
    ValidateTypes(function);
    ValidateUses(function);
}

} // namespace Shader::Optimization