// Copyright 2021 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include #include #include #include "shader_recompiler/exception.h" #include "shader_recompiler/frontend/ir/opcodes.h" namespace Shader::IR { namespace { struct OpcodeMeta { std::string_view name; Type type; std::array arg_types; }; using enum Type; constexpr std::array META_TABLE{ #define OPCODE(name_token, type_token, ...) \ OpcodeMeta{ \ .name{#name_token}, \ .type{type_token}, \ .arg_types{__VA_ARGS__}, \ }, #include "opcodes.inc" #undef OPCODE }; void ValidateOpcode(Opcode op) { const size_t raw{static_cast(op)}; if (raw >= META_TABLE.size()) { throw InvalidArgument("Invalid opcode with raw value {}", raw); } } } // Anonymous namespace Type TypeOf(Opcode op) { ValidateOpcode(op); return META_TABLE[static_cast(op)].type; } size_t NumArgsOf(Opcode op) { ValidateOpcode(op); const auto& arg_types{META_TABLE[static_cast(op)].arg_types}; const auto distance{std::distance(arg_types.begin(), std::ranges::find(arg_types, Type::Void))}; return static_cast(distance); } Type ArgTypeOf(Opcode op, size_t arg_index) { ValidateOpcode(op); const auto& arg_types{META_TABLE[static_cast(op)].arg_types}; if (arg_index >= arg_types.size() || arg_types[arg_index] == Type::Void) { throw InvalidArgument("Out of bounds argument"); } return arg_types[arg_index]; } std::string_view NameOf(Opcode op) { ValidateOpcode(op); return META_TABLE[static_cast(op)].name; } } // namespace Shader::IR