mp: Implement metaprogramming library
This commit is contained in:
parent
4ab029c114
commit
7360a2579b
15 changed files with 412 additions and 0 deletions
|
@ -33,6 +33,17 @@ add_library(dynarmic
|
|||
common/memory_pool.cpp
|
||||
common/memory_pool.h
|
||||
common/mp.h
|
||||
common/mp/append.h
|
||||
common/mp/bind.h
|
||||
common/mp/cartesian_product.h
|
||||
common/mp/concat.h
|
||||
common/mp/fapply.h
|
||||
common/mp/fmap.h
|
||||
common/mp/list.h
|
||||
common/mp/lut.h
|
||||
common/mp/to_tuple.h
|
||||
common/mp/vlift.h
|
||||
common/mp/vllift.h
|
||||
common/safe_ops.h
|
||||
common/scope_exit.h
|
||||
common/sm4.cpp
|
||||
|
|
27
src/common/mp/append.h
Normal file
27
src/common/mp/append.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class... L>
|
||||
struct append_impl;
|
||||
|
||||
template<template<class...> class LT, class... T1, class... T2>
|
||||
struct append_impl<LT<T1...>, T2...> {
|
||||
using type = LT<T1..., T2...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Append items T to list L
|
||||
template<class L, class... T>
|
||||
using append = typename detail::append_impl<L, T...>::type;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
18
src/common/mp/bind.h
Normal file
18
src/common/mp/bind.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
/// Binds the first sizeof...(A) arguments of metafunction F with arguments A
|
||||
template<template<class...> class F, class... A>
|
||||
struct bind {
|
||||
template<class... T>
|
||||
using type = F<A..., T...>;
|
||||
};
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
51
src/common/mp/cartesian_product.h
Normal file
51
src/common/mp/cartesian_product.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/mp/append.h"
|
||||
#include "common/mp/bind.h"
|
||||
#include "common/mp/concat.h"
|
||||
#include "common/mp/fmap.h"
|
||||
#include "common/mp/list.h"
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class... Ls>
|
||||
struct cartesian_product_impl{};
|
||||
|
||||
template<class RL>
|
||||
struct cartesian_product_impl<RL> {
|
||||
using type = RL;
|
||||
};
|
||||
|
||||
template<template<class...> class LT, class... RT, class... T1>
|
||||
struct cartesian_product_impl<LT<RT...>, LT<T1...>> {
|
||||
using type = concat<
|
||||
fmap<bind<append, RT>::template type, list<T1...>>...
|
||||
>;
|
||||
};
|
||||
|
||||
template<class RL, class L1, class L2, class... Ls>
|
||||
struct cartesian_product_impl<RL, L1, L2, Ls...> {
|
||||
using type = typename cartesian_product_impl<
|
||||
typename cartesian_product_impl<RL, L1>::type,
|
||||
L2,
|
||||
Ls...
|
||||
>::type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Produces the cartesian product of a set of lists
|
||||
/// For example:
|
||||
/// cartesian_product<list<A, B>, list<D, E>> == list<list<A, D>, list<A, E>, list<B, D>, list<B, E>
|
||||
template<typename L1, typename... Ls>
|
||||
using cartesian_product = typename detail::cartesian_product_impl<fmap<list, L1>, Ls...>::type;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
57
src/common/mp/concat.h
Normal file
57
src/common/mp/concat.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/mp/list.h"
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class... L>
|
||||
struct concat_impl;
|
||||
|
||||
template<>
|
||||
struct concat_impl<> {
|
||||
using type = list<>;
|
||||
};
|
||||
|
||||
template<class L>
|
||||
struct concat_impl<L> {
|
||||
using type = L;
|
||||
};
|
||||
|
||||
template<template<class...> class LT, class... T1, class... T2, class... Ls>
|
||||
struct concat_impl<LT<T1...>, LT<T2...>, Ls...> {
|
||||
using type = typename concat_impl<LT<T1..., T2...>, Ls...>::type;
|
||||
};
|
||||
|
||||
template<template<class...> class LT,
|
||||
class... T1, class... T2, class... T3, class... T4, class... T5, class... T6, class... T7, class... T8,
|
||||
class... T9, class... T10, class... T11, class... T12, class... T13, class... T14, class... T15, class... T16,
|
||||
class... Ls>
|
||||
struct concat_impl<
|
||||
LT<T1...>, LT<T2...>, LT<T3...>, LT<T4...>, LT<T5...>, LT<T6...>, LT<T7...>, LT<T8...>,
|
||||
LT<T9...>, LT<T10...>, LT<T11...>, LT<T12...>, LT<T13...>, LT<T14...>, LT<T15...>, LT<T16...>,
|
||||
Ls...>
|
||||
{
|
||||
using type = typename concat_impl<
|
||||
LT<
|
||||
T1..., T2..., T3..., T4..., T5..., T6..., T7..., T8...,
|
||||
T9..., T10..., T11..., T12..., T13..., T14..., T15..., T16...
|
||||
>,
|
||||
Ls...
|
||||
>::type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Concatenate lists together
|
||||
template<class... L>
|
||||
using concat = typename detail::concat_impl<L...>::type;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
27
src/common/mp/fapply.h
Normal file
27
src/common/mp/fapply.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<template<class...> class F, class L>
|
||||
struct fapply_impl;
|
||||
|
||||
template<template<class...> class F, template<class...> class LT, class... T>
|
||||
struct fapply_impl<F, LT<T...>> {
|
||||
using type = F<T...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Invokes metafunction F where the arguments are all the members of list L
|
||||
template<template<class...> class F, class L>
|
||||
using fapply = typename detail::fapply_impl<F, L>::type;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
27
src/common/mp/fmap.h
Normal file
27
src/common/mp/fmap.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<template<class...> class F, class L>
|
||||
struct fmap_impl;
|
||||
|
||||
template<template<class...> class F, template<class...> class LT, class... T>
|
||||
struct fmap_impl<F, LT<T...>> {
|
||||
using type = LT<F<T>...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Metafunction that applies each element of list L to metafunction F
|
||||
template<template<class...> class F, class L>
|
||||
using fmap = typename detail::fmap_impl<F, L>::type;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
51
src/common/mp/integer.h
Normal file
51
src/common/mp/integer.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t size>
|
||||
struct integer_of_size_impl{};
|
||||
|
||||
template<>
|
||||
struct integer_of_size_impl<8> {
|
||||
using unsigned_type = std::uint8_t;
|
||||
using signed_type = std::int8_t;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct integer_of_size_impl<16> {
|
||||
using unsigned_type = std::uint16_t;
|
||||
using signed_type = std::int16_t;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct integer_of_size_impl<32> {
|
||||
using unsigned_type = std::uint32_t;
|
||||
using signed_type = std::int32_t;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct integer_of_size_impl<64> {
|
||||
using unsigned_type = std::uint64_t;
|
||||
using signed_type = std::int64_t;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<std::size_t size>
|
||||
using unsigned_integer_of_size = typename detail::integer_of_size_impl<size>::unsigned_type;
|
||||
|
||||
template<std::size_t size>
|
||||
using signed_integer_of_size = typename detail::integer_of_size_impl<size>::signed_type;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
15
src/common/mp/list.h
Normal file
15
src/common/mp/list.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
/// Contains a list of types
|
||||
template<class... T>
|
||||
struct list {};
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
23
src/common/mp/lut.h
Normal file
23
src/common/mp/lut.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
|
||||
#include "common/mp/list.h"
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
template <typename KeyT, typename ValueT, typename Function, typename ...Values>
|
||||
inline auto GenerateLookupTableFromList(Function f, list<Values...>) {
|
||||
static const std::array<std::pair<KeyT, ValueT>, sizeof...(Values)> pair_array{f(Values{})...};
|
||||
return std::map<KeyT, ValueT>(pair_array.begin(), pair_array.end());
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
29
src/common/mp/to_tuple.h
Normal file
29
src/common/mp/to_tuple.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class L>
|
||||
struct to_tuple_impl;
|
||||
|
||||
template<template<class...> class LT, class... T>
|
||||
struct to_tuple_impl<LT<T...>> {
|
||||
static constexpr auto value = std::make_tuple(static_cast<typename T::value_type>(T::value)...);
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Metafunction that converts a list of metavalues to a tuple value.
|
||||
template<class L>
|
||||
constexpr auto to_tuple = detail::to_tuple_impl<L>::value;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
17
src/common/mp/vlift.h
Normal file
17
src/common/mp/vlift.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
/// Lifts a value into a type
|
||||
template<auto V>
|
||||
using vlift = std::integral_constant<decltype(V), V>;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
31
src/common/mp/vllift.h
Normal file
31
src/common/mp/vllift.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "common/mp/list.h"
|
||||
|
||||
namespace Dynarmic::Common::mp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class VL>
|
||||
struct vllift_impl{};
|
||||
|
||||
template<class T, T... values>
|
||||
struct vllift_impl<std::integer_sequence<T, values...>> {
|
||||
using type = list<std::integral_constant<T, values>...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Lifts values in value list VL to create a type list.
|
||||
template<class VL>
|
||||
using vllift = typename detail::vllift_impl<VL>::type;
|
||||
|
||||
} // namespace Dynarmic::Common::mp
|
|
@ -31,6 +31,7 @@ add_executable(dynarmic_tests
|
|||
A64/testenv.h
|
||||
fp/unpacked_tests.cpp
|
||||
main.cpp
|
||||
mp.cpp
|
||||
rand_int.h
|
||||
)
|
||||
|
||||
|
|
27
tests/mp.cpp
Normal file
27
tests/mp.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "common/mp/cartesian_product.h"
|
||||
|
||||
using namespace Dynarmic::Common::mp;
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
cartesian_product<list<int, bool>, list<double, float>, list<char, unsigned>>,
|
||||
list<
|
||||
list<int, double, char>,
|
||||
list<int, double, unsigned>,
|
||||
list<int, float, char>,
|
||||
list<int, float, unsigned>,
|
||||
list<bool, double, char>,
|
||||
list<bool, double, unsigned>,
|
||||
list<bool, float, char>,
|
||||
list<bool, float, unsigned>
|
||||
>
|
||||
>
|
||||
);
|
Loading…
Reference in a new issue