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 16namespace llvm { 17 18template <bool EnableSentinelTracking> class ilist_node_base; 19template <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(). 26template <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. 32template <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. 40template <bool ExtraIteratorBits> struct ilist_iterator_bits {}; 41 42namespace ilist_detail { 43 44/// Helper trait for recording whether an option is specified explicitly. 45template <bool IsExplicit> struct explicitness { 46 static const bool is_explicit = IsExplicit; 47}; 48typedef explicitness<true> is_explicit; 49typedef 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. 62template <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. 68template <class... Options> struct extract_sentinel_tracking; 69template <bool EnableSentinelTracking, class... Options> 70struct extract_sentinel_tracking< 71 ilist_sentinel_tracking<EnableSentinelTracking>, Options...> 72 : std::integral_constant<bool, EnableSentinelTracking>, is_explicit {}; 73template <class Option1, class... Options> 74struct extract_sentinel_tracking<Option1, Options...> 75 : extract_sentinel_tracking<Options...> {}; 76#if LLVM_ENABLE_ABI_BREAKING_CHECKS 77template <> struct extract_sentinel_tracking<> : std::true_type, is_implicit {}; 78#else 79template <> 80struct extract_sentinel_tracking<> : std::false_type, is_implicit {}; 81#endif 82template <bool EnableSentinelTracking> 83struct 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. 90template <class... Options> struct extract_tag; 91template <class Tag, class... Options> 92struct extract_tag<ilist_tag<Tag>, Options...> { 93 typedef Tag type; 94}; 95template <class Option1, class... Options> 96struct extract_tag<Option1, Options...> : extract_tag<Options...> {}; 97template <> struct extract_tag<> { 98 typedef void type; 99}; 100template <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. 106template <class... Options> struct extract_iterator_bits; 107template <bool IteratorBits, class... Options> 108struct extract_iterator_bits<ilist_iterator_bits<IteratorBits>, Options...> 109 : std::integral_constant<bool, IteratorBits> {}; 110template <class Option1, class... Options> 111struct extract_iterator_bits<Option1, Options...> 112 : extract_iterator_bits<Options...> {}; 113template <> struct extract_iterator_bits<> : std::false_type, is_implicit {}; 114template <bool IteratorBits> 115struct 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. 120template <class... Options> struct check_options; 121template <> struct check_options<> : std::true_type {}; 122template <class Option1, class... Options> 123struct 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. 130template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit, 131 class TagT, bool HasIteratorBits> 132struct 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 147template <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