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 ilist_node_base; 19 template <bool EnableSentinelTracking> 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 namespace ilist_detail { 43 44 /// Helper trait for recording whether an option is specified explicitly. 45 template <bool IsExplicit> struct explicitness { 46 static const bool is_explicit = IsExplicit; 47 }; 48 typedef explicitness<true> is_explicit; 49 typedef explicitness<false> is_implicit; 50 51 /// Check whether an option is valid. 52 /// 53 /// The steps for adding and enabling a new ilist option include: 54 /// \li define the option, ilist_foo<Bar>, above; 55 /// \li add new parameters for Bar to \a ilist_detail::node_options; 56 /// \li add an extraction meta-function, ilist_detail::extract_foo; 57 /// \li call extract_foo from \a ilist_detail::compute_node_options and pass it 58 /// into \a ilist_detail::node_options; and 59 /// \li specialize \c is_valid_option<ilist_foo<Bar>> to inherit from \c 60 /// std::true_type to get static assertions passing in \a simple_ilist and \a 61 /// ilist_node. 62 template <class Option> struct is_valid_option : std::false_type {}; 63 64 /// Extract sentinel tracking option. 65 /// 66 /// Look through \p Options for the \a ilist_sentinel_tracking option, with the 67 /// default depending on LLVM_ENABLE_ABI_BREAKING_CHECKS. 68 template <class... Options> struct extract_sentinel_tracking; 69 template <bool EnableSentinelTracking, class... Options> 70 struct extract_sentinel_tracking< 71 ilist_sentinel_tracking<EnableSentinelTracking>, Options...> 72 : std::integral_constant<bool, EnableSentinelTracking>, is_explicit {}; 73 template <class Option1, class... Options> 74 struct extract_sentinel_tracking<Option1, Options...> 75 : extract_sentinel_tracking<Options...> {}; 76 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 77 template <> struct extract_sentinel_tracking<> : std::true_type, is_implicit {}; 78 #else 79 template <> 80 struct extract_sentinel_tracking<> : std::false_type, is_implicit {}; 81 #endif 82 template <bool EnableSentinelTracking> 83 struct is_valid_option<ilist_sentinel_tracking<EnableSentinelTracking>> 84 : std::true_type {}; 85 86 /// Extract custom tag option. 87 /// 88 /// Look through \p Options for the \a ilist_tag option, pulling out the 89 /// custom tag type, using void as a default. 90 template <class... Options> struct extract_tag; 91 template <class Tag, class... Options> 92 struct extract_tag<ilist_tag<Tag>, Options...> { 93 typedef Tag type; 94 }; 95 template <class Option1, class... Options> 96 struct extract_tag<Option1, Options...> : extract_tag<Options...> {}; 97 template <> struct extract_tag<> { 98 typedef void type; 99 }; 100 template <class Tag> struct is_valid_option<ilist_tag<Tag>> : std::true_type {}; 101 102 /// Extract iterator bits option. 103 /// 104 /// Look through \p Options for the \a ilist_iterator_bits option. Defaults 105 /// to false. 106 template <class... Options> struct extract_iterator_bits; 107 template <bool IteratorBits, class... Options> 108 struct extract_iterator_bits<ilist_iterator_bits<IteratorBits>, Options...> 109 : std::integral_constant<bool, IteratorBits> {}; 110 template <class Option1, class... Options> 111 struct extract_iterator_bits<Option1, Options...> 112 : extract_iterator_bits<Options...> {}; 113 template <> struct extract_iterator_bits<> : std::false_type, is_implicit {}; 114 template <bool IteratorBits> 115 struct is_valid_option<ilist_iterator_bits<IteratorBits>> : std::true_type {}; 116 117 /// Check whether options are valid. 118 /// 119 /// The conjunction of \a is_valid_option on each individual option. 120 template <class... Options> struct check_options; 121 template <> struct check_options<> : std::true_type {}; 122 template <class Option1, class... Options> 123 struct check_options<Option1, Options...> 124 : std::integral_constant<bool, is_valid_option<Option1>::value && 125 check_options<Options...>::value> {}; 126 127 /// Traits for options for \a ilist_node. 128 /// 129 /// This is usually computed via \a compute_node_options. 130 template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit, 131 class TagT, bool HasIteratorBits> 132 struct node_options { 133 typedef T value_type; 134 typedef T *pointer; 135 typedef T &reference; 136 typedef const T *const_pointer; 137 typedef const T &const_reference; 138 139 static const bool enable_sentinel_tracking = EnableSentinelTracking; 140 static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit; 141 static const bool has_iterator_bits = HasIteratorBits; 142 typedef TagT tag; 143 typedef ilist_node_base<enable_sentinel_tracking> node_base_type; 144 typedef ilist_base<enable_sentinel_tracking> list_base_type; 145 }; 146 147 template <class T, class... Options> struct compute_node_options { 148 typedef node_options<T, extract_sentinel_tracking<Options...>::value, 149 extract_sentinel_tracking<Options...>::is_explicit, 150 typename extract_tag<Options...>::type, 151 extract_iterator_bits<Options...>::value> 152 type; 153 }; 154 155 } // end namespace ilist_detail 156 } // end namespace llvm 157 158 #endif // LLVM_ADT_ILIST_NODE_OPTIONS_H 159