diff --git a/src/common/mp.h b/src/common/mp.h index 6e38cba0..8f72df69 100644 --- a/src/common/mp.h +++ b/src/common/mp.h @@ -6,21 +6,64 @@ #pragma once +#include #include "common/common_types.h" namespace Dynarmic { namespace mp { -template -struct MemFnInfo; +/// Used to provide information about an arbitrary function. +template +struct FunctionInfo; -/// This struct provides information about a member function pointer. -template -struct MemFnInfo { - using class_type = T; - using return_type = ReturnT; +/** + * Partial specialization for function types. + * + * This is used as the supporting base for all other specializations. + */ +template +struct FunctionInfo +{ + using return_type = R; static constexpr size_t args_count = sizeof...(Args); + + template + struct Parameter + { + static_assert(args_count != 0 && ParameterIndex < args_count - 1, "Non-existent function parameter index"); + using type = std::tuple_element_t>; + }; }; +/// Partial specialization for function pointers +template +struct FunctionInfo : public FunctionInfo +{ +}; + +/// Partial specialization for member function pointers. +template +struct FunctionInfo : public FunctionInfo +{ + using class_type = C; +}; + +/** + * Helper template for retrieving the type of a function parameter. + * + * @tparam Function An arbitrary function type. + * @tparam ParameterIndex Zero-based index indicating which parameter to get the type of. + */ +template +using parameter_type_t = typename FunctionInfo::template Parameter::type; + +/** + * Helper template for retrieving the return type of a function. + * + * @tparam Function The function type to get the return type of. + */ +template +using return_type_t = typename FunctionInfo::return_type; + } // namespace mp } // namespace Dynarmic diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index 6e5d3eb4..264bd2cf 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -22,7 +22,7 @@ namespace Arm { template struct ArmMatcher { - using CallRetT = typename mp::MemFnInfo::return_type; + using CallRetT = mp::return_type_t; ArmMatcher(const char* const name, u32 mask, u32 expect, std::function fn) : name(name), mask(mask), expect(expect), fn(fn) {} diff --git a/src/frontend/decoder/decoder_detail.h b/src/frontend/decoder/decoder_detail.h index 76a53b0a..d5f4d0ca 100644 --- a/src/frontend/decoder/decoder_detail.h +++ b/src/frontend/decoder/decoder_detail.h @@ -127,8 +127,8 @@ public: */ template static auto GetMatcher(FnT fn, const char* const name, const char* const bitstring) { - using Visitor = typename mp::MemFnInfo::class_type; - constexpr size_t args_count = mp::MemFnInfo::args_count; + using Visitor = typename mp::FunctionInfo::class_type; + constexpr size_t args_count = mp::FunctionInfo::args_count; using Iota = std::make_index_sequence; const auto mask_and_expect = GetMaskAndExpect(bitstring); diff --git a/src/frontend/decoder/thumb16.h b/src/frontend/decoder/thumb16.h index 2a1689f6..4c32c24b 100644 --- a/src/frontend/decoder/thumb16.h +++ b/src/frontend/decoder/thumb16.h @@ -20,7 +20,7 @@ namespace Arm { template struct Thumb16Matcher { - using CallRetT = typename mp::MemFnInfo::return_type; + using CallRetT = mp::return_type_t; Thumb16Matcher(const char* const name, u16 mask, u16 expect, std::function fn) : name(name), mask(mask), expect(expect), fn(fn) {} diff --git a/src/frontend/decoder/thumb32.h b/src/frontend/decoder/thumb32.h index 49bc7a77..381d5c64 100644 --- a/src/frontend/decoder/thumb32.h +++ b/src/frontend/decoder/thumb32.h @@ -20,7 +20,7 @@ namespace Arm { template struct Thumb32Matcher { - using CallRetT = typename mp::MemFnInfo::return_type; + using CallRetT = mp::return_type_t; Thumb32Matcher(const char* const name, u32 mask, u32 expect, std::function fn) : name(name), mask(mask), expect(expect), fn(fn) {} diff --git a/src/frontend/decoder/vfp2.h b/src/frontend/decoder/vfp2.h index 7fe85a6f..d3aa110f 100644 --- a/src/frontend/decoder/vfp2.h +++ b/src/frontend/decoder/vfp2.h @@ -20,7 +20,7 @@ namespace Arm { template struct VFP2Matcher { - using CallRetT = typename mp::MemFnInfo::return_type; + using CallRetT = mp::return_type_t; VFP2Matcher(const char* const name, u32 mask, u32 expect, std::function fn) : name(name), mask(mask), expect(expect), fn(fn) {}