1 //===- llvm/ADT/ilist_node_options.h - ilist_node Options -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_ADT_ILIST_NODE_OPTIONS_H 10 #define LLVM_ADT_ILIST_NODE_OPTIONS_H 11 12 #include "llvm/Config/abi-breaking.h" 13 14 #include <type_traits> 15 16 namespace llvm { 17 18 template <bool EnableSentinelTracking, class ParentTy> class ilist_node_base; 19 template <bool EnableSentinelTracking, class ParentTy> class ilist_base; 20 21 /// Option to choose whether to track sentinels. 22 /// 23 /// This option affects the ABI for the nodes. When not specified explicitly, 24 /// the ABI depends on LLVM_ENABLE_ABI_BREAKING_CHECKS. Specify explicitly to 25 /// enable \a ilist_node::isSentinel(). 26 template <bool EnableSentinelTracking> struct ilist_sentinel_tracking {}; 27 28 /// Option to specify a tag for the node type. 29 /// 30 /// This option allows a single value type to be inserted in multiple lists 31 /// simultaneously. See \a ilist_node for usage examples. 32 template <class Tag> struct ilist_tag {}; 33 34 /// Option to add extra bits to the ilist_iterator. 35 /// 36 /// Some use-cases (debug-info) need to know whether a position is intended 37 /// to be half-open or fully open, i.e. whether to include any immediately 38 /// adjacent debug-info in an operation. This option adds two bits to the 39 /// iterator class to store that information. 40 template <bool ExtraIteratorBits> struct ilist_iterator_bits {}; 41 42 /// Option to add a pointer to this list's owner in every node. 43 /// 44 /// This option causes the \a ilist_base_node for this list to contain a pointer 45 /// ParentTy *Parent, returned by \a ilist_base_node::getNodeBaseParent() and 46 /// set by \a ilist_base_node::setNodeBaseParent(ParentTy *Parent). The parent 47 /// value is not set automatically; the ilist owner should set itself as the 48 /// parent of the list sentinel, and the parent should be set on each node 49 /// inserted into the list. This value is also not used by 50 /// \a ilist_node_with_parent::getNodeParent(), but is used by \a 51 /// ilist_iterator::getNodeParent(), which allows the parent to be fetched from 52 /// any valid (non-null) iterator to this list, including the sentinel. 53 template <class ParentTy> struct ilist_parent {}; 54 55 namespace ilist_detail { 56 57 /// Helper trait for recording whether an option is specified explicitly. 58 template <bool IsExplicit> struct explicitness { 59 static const bool is_explicit = IsExplicit; 60 }; 61 typedef explicitness<true> is_explicit; 62 typedef explicitness<false> is_implicit; 63 64 /// Check whether an option is valid. 65 /// 66 /// The steps for adding and enabling a new ilist option include: 67 /// \li define the option, ilist_foo<Bar>, above; 68 /// \li add new parameters for Bar to \a ilist_detail::node_options; 69 /// \li add an extraction meta-function, ilist_detail::extract_foo; 70 /// \li call extract_foo from \a ilist_detail::compute_node_options and pass it 71 /// into \a ilist_detail::node_options; and 72 /// \li specialize \c is_valid_option<ilist_foo<Bar>> to inherit from \c 73 /// std::true_type to get static assertions passing in \a simple_ilist and \a 74 /// ilist_node. 75 template <class Option> struct is_valid_option : std::false_type {}; 76 77 /// Extract sentinel tracking option. 78 /// 79 /// Look through \p Options for the \a ilist_sentinel_tracking option, with the 80 /// default depending on LLVM_ENABLE_ABI_BREAKING_CHECKS. 81 template <class... Options> struct extract_sentinel_tracking; 82 template <bool EnableSentinelTracking, class... Options> 83 struct extract_sentinel_tracking< 84 ilist_sentinel_tracking<EnableSentinelTracking>, Options...> 85 : std::integral_constant<bool, EnableSentinelTracking>, is_explicit {}; 86 template <class Option1, class... Options> 87 struct extract_sentinel_tracking<Option1, Options...> 88 : extract_sentinel_tracking<Options...> {}; 89 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 90 template <> struct extract_sentinel_tracking<> : std::true_type, is_implicit {}; 91 #else 92 template <> 93 struct extract_sentinel_tracking<> : std::false_type, is_implicit {}; 94 #endif 95 template <bool EnableSentinelTracking> 96 struct is_valid_option<ilist_sentinel_tracking<EnableSentinelTracking>> 97 : std::true_type {}; 98 99 /// Extract custom tag option. 100 /// 101 /// Look through \p Options for the \a ilist_tag option, pulling out the 102 /// custom tag type, using void as a default. 103 template <class... Options> struct extract_tag; 104 template <class Tag, class... Options> 105 struct extract_tag<ilist_tag<Tag>, Options...> { 106 typedef Tag type; 107 }; 108 template <class Option1, class... Options> 109 struct extract_tag<Option1, Options...> : extract_tag<Options...> {}; 110 template <> struct extract_tag<> { 111 typedef void type; 112 }; 113 template <class Tag> struct is_valid_option<ilist_tag<Tag>> : std::true_type {}; 114 115 /// Extract iterator bits option. 116 /// 117 /// Look through \p Options for the \a ilist_iterator_bits option. Defaults 118 /// to false. 119 template <class... Options> struct extract_iterator_bits; 120 template <bool IteratorBits, class... Options> 121 struct extract_iterator_bits<ilist_iterator_bits<IteratorBits>, Options...> 122 : std::integral_constant<bool, IteratorBits> {}; 123 template <class Option1, class... Options> 124 struct extract_iterator_bits<Option1, Options...> 125 : extract_iterator_bits<Options...> {}; 126 template <> struct extract_iterator_bits<> : std::false_type, is_implicit {}; 127 template <bool IteratorBits> 128 struct is_valid_option<ilist_iterator_bits<IteratorBits>> : std::true_type {}; 129 130 /// Extract node parent option. 131 /// 132 /// Look through \p Options for the \a ilist_parent option, pulling out the 133 /// custom parent type, using void as a default. 134 template <class... Options> struct extract_parent; 135 template <class ParentTy, class... Options> 136 struct extract_parent<ilist_parent<ParentTy>, Options...> { 137 typedef ParentTy type; 138 }; 139 template <class Option1, class... Options> 140 struct extract_parent<Option1, Options...> : extract_parent<Options...> {}; 141 template <> struct extract_parent<> { typedef void type; }; 142 template <class ParentTy> 143 struct is_valid_option<ilist_parent<ParentTy>> : std::true_type {}; 144 145 /// Check whether options are valid. 146 /// 147 /// The conjunction of \a is_valid_option on each individual option. 148 template <class... Options> struct check_options; 149 template <> struct check_options<> : std::true_type {}; 150 template <class Option1, class... Options> 151 struct check_options<Option1, Options...> 152 : std::integral_constant<bool, is_valid_option<Option1>::value && 153 check_options<Options...>::value> {}; 154 155 /// Traits for options for \a ilist_node. 156 /// 157 /// This is usually computed via \a compute_node_options. 158 template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit, 159 class TagT, bool HasIteratorBits, class ParentTy> 160 struct node_options { 161 typedef T value_type; 162 typedef T *pointer; 163 typedef T &reference; 164 typedef const T *const_pointer; 165 typedef const T &const_reference; 166 167 static const bool enable_sentinel_tracking = EnableSentinelTracking; 168 static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit; 169 static const bool has_iterator_bits = HasIteratorBits; 170 typedef TagT tag; 171 typedef ParentTy parent_ty; 172 typedef ilist_node_base<enable_sentinel_tracking, parent_ty> node_base_type; 173 typedef ilist_base<enable_sentinel_tracking, parent_ty> list_base_type; 174 }; 175 176 template <class T, class... Options> struct compute_node_options { 177 typedef node_options<T, extract_sentinel_tracking<Options...>::value, 178 extract_sentinel_tracking<Options...>::is_explicit, 179 typename extract_tag<Options...>::type, 180 extract_iterator_bits<Options...>::value, 181 typename extract_parent<Options...>::type> 182 type; 183 }; 184 185 } // end namespace ilist_detail 186 } // end namespace llvm 187 188 #endif // LLVM_ADT_ILIST_NODE_OPTIONS_H 189