native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
abi_refinement.h
1// SPDX-FileCopyrightText: 2026 Edward Kmett <ekmett@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
3#pragma once
4#include <native/isa.h>
5#include <array>
6#include <cstddef>
7#include <utility>
8#include <type_traits>
9
10// Internal ordered common refinement. Preserve each callee's first-match policy;
11// no public policy-composition API or compiler retargeting is introduced.
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{};
17 };
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...};
23 };
24
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>;
29 };
30
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());
39 struct cell {
40 isa_type requirements{};
41 std::array<int,dimensions> choices{};
42 bool possible=false;
43 };
44 struct table {
45 std::array<cell,capacity> records{};
46 std::size_t size=0;
47 };
48
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{};
52 auto remaining=K;
53 // Last coordinate varies fastest: preserve lexicographic policy priority.
54 for(std::size_t i=dimensions;i>0;--i) {
55 result[i-1]=int(remaining%radices[i-1]);
56 remaining/=radices[i-1];
57 }
58 return result;
59 }
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>();
63 constexpr auto requirements=::native::feature_closure(
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};
69 }
70 template<std::size_t... K> static consteval table enumerate(std::index_sequence<K...>) {
71 table result;
72 auto append=[&](cell value) {
73 if(value.possible) result.records[result.size++]=value;
74 };
75 (append(candidate<K>(std::index_sequence_for<Lists...>{})),...);
76 return result;
77 }
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>{}));
82
83 // Verify the realized cell against each original callee, rather than only
84 // checking membership in the generated positive-requirement list.
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...};
92 }
93 };
94}
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
Definition isa.h:538