12namespace native::detail {
13 template<
class List>
struct abi_entries;
14 template<>
struct abi_entries<::native::isa_list<>> {
15 using isa_type=::native::isa<>;
16 static constexpr std::array<isa_type,0> requirements{};
18 template<
auto First,
auto... E>
struct abi_entries<::native::isa_list<First,E...>> {
19 using isa_type=std::remove_cv_t<
decltype(::native::detail::abi_match<First,0>::required_features)>;
20 static constexpr std::array<isa_type,1+
sizeof...(E)> requirements{
21 ::native::detail::abi_match<First,0>::required_features,
22 ::native::detail::abi_match<E,0>::required_features...};
25 template<
class... Lists>
struct refinement_isa {
using type=::native::isa<>; };
26 template<
class First,
class... Rest>
struct refinement_isa<First,Rest...> {
27 using type=std::conditional_t<abi_entries<First>::requirements.empty(),
28 typename refinement_isa<Rest...>
::type,
typename abi_entries<First>::isa_type>;
31 template<
class... Lists>
struct abi_refinement {
32 static_assert(
sizeof...(Lists)>0);
33 using isa_type=
typename refinement_isa<Lists...>
::type;
34 static_assert(((abi_entries<Lists>::requirements.empty() ||
35 std::same_as<isa_type,
typename abi_entries<Lists>::isa_type>) && ...),
36 "ABI refinement requires one architecture family");
37 static constexpr std::size_t dimensions=
sizeof...(Lists);
38 static constexpr std::size_t capacity=(std::size_t{1} * ... * abi_entries<Lists>::requirements.size());
40 isa_type requirements{};
41 std::array<int,dimensions> choices{};
45 std::array<cell,capacity> records{};
49 template<std::
size_t K>
static consteval auto choices() {
50 constexpr std::array radices{abi_entries<Lists>::requirements.size()...};
51 std::array<int,dimensions> result{};
54 for(std::size_t i=dimensions;i>0;--i) {
55 result[i-1]=int(remaining%radices[i-1]);
56 remaining/=radices[i-1];
60 template<std::size_t K,std::size_t... I>
61 static consteval cell candidate(std::index_sequence<I...>) {
62 constexpr auto selected=choices<K>();
64 (isa_type{} & ... & abi_entries<Lists>::requirements[selected[I]]));
65 constexpr auto A=requirements;
66 constexpr bool possible=((::native::abi_lookup<A,Lists>::matched &&
67 ::native::abi_lookup<A,Lists>::index==selected[I]) && ...);
68 return {requirements,selected,possible};
70 template<std::size_t... K>
static consteval table enumerate(std::index_sequence<K...>) {
72 auto append=[&](cell value) {
73 if(value.possible) result.records[result.size++]=value;
75 (append(candidate<K>(std::index_sequence_for<Lists...>{})),...);
78 static constexpr table cells=enumerate(std::make_index_sequence<capacity>{});
79 template<std::size_t... I>
static auto policies_for(std::index_sequence<I...>)
80 -> ::native::isa_list<cells.records[I].requirements...>;
81 using policies=
decltype(policies_for(std::make_index_sequence<cells.size>{}));
85 template<isa_type A>
static consteval bool agrees() {
86 using choice=::native::abi_lookup<A,policies>;
87 constexpr bool all=(::native::abi_lookup<A,Lists>::matched && ...);
88 if constexpr(!
all)
return !choice::matched;
89 else if constexpr(!choice::matched)
return false;
90 else return cells.records[choice::index].choices==
91 std::array<int,dimensions>{::native::abi_lookup<A,Lists>::index...};
std::string_view const type
constexpr bool all(simd< T, N, A > a) noexcept
Test whether every integer lane is nonzero.
constexpr auto feature_closure(A input) noexcept