xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===-- allocator_config_wrapper.h ------------------------------*- C++ -*-===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric 
9*0fca6ea1SDimitry Andric #ifndef SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
10*0fca6ea1SDimitry Andric #define SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
11*0fca6ea1SDimitry Andric 
12*0fca6ea1SDimitry Andric #include "condition_variable.h"
13*0fca6ea1SDimitry Andric #include "internal_defs.h"
14*0fca6ea1SDimitry Andric #include "secondary.h"
15*0fca6ea1SDimitry Andric 
16*0fca6ea1SDimitry Andric namespace {
17*0fca6ea1SDimitry Andric 
18*0fca6ea1SDimitry Andric template <typename T> struct removeConst {
19*0fca6ea1SDimitry Andric   using type = T;
20*0fca6ea1SDimitry Andric };
21*0fca6ea1SDimitry Andric template <typename T> struct removeConst<const T> {
22*0fca6ea1SDimitry Andric   using type = T;
23*0fca6ea1SDimitry Andric };
24*0fca6ea1SDimitry Andric 
25*0fca6ea1SDimitry Andric // This is only used for SFINAE when detecting if a type is defined.
26*0fca6ea1SDimitry Andric template <typename T> struct voidAdaptor {
27*0fca6ea1SDimitry Andric   using type = void;
28*0fca6ea1SDimitry Andric };
29*0fca6ea1SDimitry Andric 
30*0fca6ea1SDimitry Andric // This is used for detecting the case that defines the flag with wrong type and
31*0fca6ea1SDimitry Andric // it'll be viewed as undefined optional flag.
32*0fca6ea1SDimitry Andric template <typename L, typename R> struct assertSameType {
33*0fca6ea1SDimitry Andric   template <typename, typename> struct isSame {
34*0fca6ea1SDimitry Andric     static constexpr bool value = false;
35*0fca6ea1SDimitry Andric   };
36*0fca6ea1SDimitry Andric   template <typename T> struct isSame<T, T> {
37*0fca6ea1SDimitry Andric     static constexpr bool value = true;
38*0fca6ea1SDimitry Andric   };
39*0fca6ea1SDimitry Andric   static_assert(isSame<L, R>::value, "Flag type mismatches");
40*0fca6ea1SDimitry Andric   using type = R;
41*0fca6ea1SDimitry Andric };
42*0fca6ea1SDimitry Andric 
43*0fca6ea1SDimitry Andric } // namespace
44*0fca6ea1SDimitry Andric 
45*0fca6ea1SDimitry Andric namespace scudo {
46*0fca6ea1SDimitry Andric 
47*0fca6ea1SDimitry Andric #define OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, MEMBER)                         \
48*0fca6ea1SDimitry Andric   template <typename Config, typename = TYPE> struct NAME##State {             \
49*0fca6ea1SDimitry Andric     static constexpr removeConst<TYPE>::type getValue() { return DEFAULT; }    \
50*0fca6ea1SDimitry Andric   };                                                                           \
51*0fca6ea1SDimitry Andric   template <typename Config>                                                   \
52*0fca6ea1SDimitry Andric   struct NAME##State<                                                          \
53*0fca6ea1SDimitry Andric       Config, typename assertSameType<decltype(Config::MEMBER), TYPE>::type> { \
54*0fca6ea1SDimitry Andric     static constexpr removeConst<TYPE>::type getValue() {                      \
55*0fca6ea1SDimitry Andric       return Config::MEMBER;                                                   \
56*0fca6ea1SDimitry Andric     }                                                                          \
57*0fca6ea1SDimitry Andric   };
58*0fca6ea1SDimitry Andric 
59*0fca6ea1SDimitry Andric #define OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, MEMBER)                          \
60*0fca6ea1SDimitry Andric   template <typename Config, typename Void = void> struct NAME##Type {         \
61*0fca6ea1SDimitry Andric     static constexpr bool enabled() { return false; }                          \
62*0fca6ea1SDimitry Andric     using NAME = DEFAULT;                                                      \
63*0fca6ea1SDimitry Andric   };                                                                           \
64*0fca6ea1SDimitry Andric   template <typename Config>                                                   \
65*0fca6ea1SDimitry Andric   struct NAME##Type<Config,                                                    \
66*0fca6ea1SDimitry Andric                     typename voidAdaptor<typename Config::MEMBER>::type> {     \
67*0fca6ea1SDimitry Andric     static constexpr bool enabled() { return true; }                           \
68*0fca6ea1SDimitry Andric     using NAME = typename Config::MEMBER;                                      \
69*0fca6ea1SDimitry Andric   };
70*0fca6ea1SDimitry Andric 
71*0fca6ea1SDimitry Andric template <typename AllocatorConfig> struct BaseConfig {
72*0fca6ea1SDimitry Andric #define BASE_REQUIRED_TEMPLATE_TYPE(NAME)                                      \
73*0fca6ea1SDimitry Andric   template <typename T> using NAME = typename AllocatorConfig::template NAME<T>;
74*0fca6ea1SDimitry Andric 
75*0fca6ea1SDimitry Andric #define BASE_OPTIONAL(TYPE, NAME, DEFAULT)                                     \
76*0fca6ea1SDimitry Andric   OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME)                                 \
77*0fca6ea1SDimitry Andric   static constexpr removeConst<TYPE>::type get##NAME() {                       \
78*0fca6ea1SDimitry Andric     return NAME##State<AllocatorConfig>::getValue();                           \
79*0fca6ea1SDimitry Andric   }
80*0fca6ea1SDimitry Andric 
81*0fca6ea1SDimitry Andric #include "allocator_config.def"
82*0fca6ea1SDimitry Andric }; // BaseConfig
83*0fca6ea1SDimitry Andric 
84*0fca6ea1SDimitry Andric template <typename AllocatorConfig> struct PrimaryConfig {
85*0fca6ea1SDimitry Andric   // TODO: Pass this flag through template argument to remove this hard-coded
86*0fca6ea1SDimitry Andric   //       function.
87*0fca6ea1SDimitry Andric   static constexpr bool getMaySupportMemoryTagging() {
88*0fca6ea1SDimitry Andric     return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
89*0fca6ea1SDimitry Andric   }
90*0fca6ea1SDimitry Andric 
91*0fca6ea1SDimitry Andric #define PRIMARY_REQUIRED_TYPE(NAME)                                            \
92*0fca6ea1SDimitry Andric   using NAME = typename AllocatorConfig::Primary::NAME;
93*0fca6ea1SDimitry Andric 
94*0fca6ea1SDimitry Andric #define PRIMARY_REQUIRED(TYPE, NAME)                                           \
95*0fca6ea1SDimitry Andric   static constexpr removeConst<TYPE>::type get##NAME() {                       \
96*0fca6ea1SDimitry Andric     return AllocatorConfig::Primary::NAME;                                     \
97*0fca6ea1SDimitry Andric   }
98*0fca6ea1SDimitry Andric 
99*0fca6ea1SDimitry Andric #define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT)                                  \
100*0fca6ea1SDimitry Andric   OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME)                                 \
101*0fca6ea1SDimitry Andric   static constexpr removeConst<TYPE>::type get##NAME() {                       \
102*0fca6ea1SDimitry Andric     return NAME##State<typename AllocatorConfig::Primary>::getValue();         \
103*0fca6ea1SDimitry Andric   }
104*0fca6ea1SDimitry Andric 
105*0fca6ea1SDimitry Andric #define PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT)                                   \
106*0fca6ea1SDimitry Andric   OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, NAME)                                  \
107*0fca6ea1SDimitry Andric   static constexpr bool has##NAME() {                                          \
108*0fca6ea1SDimitry Andric     return NAME##Type<typename AllocatorConfig::Primary>::enabled();           \
109*0fca6ea1SDimitry Andric   }                                                                            \
110*0fca6ea1SDimitry Andric   using NAME = typename NAME##Type<typename AllocatorConfig::Primary>::NAME;
111*0fca6ea1SDimitry Andric 
112*0fca6ea1SDimitry Andric #include "allocator_config.def"
113*0fca6ea1SDimitry Andric 
114*0fca6ea1SDimitry Andric }; // PrimaryConfig
115*0fca6ea1SDimitry Andric 
116*0fca6ea1SDimitry Andric template <typename AllocatorConfig> struct SecondaryConfig {
117*0fca6ea1SDimitry Andric   // TODO: Pass this flag through template argument to remove this hard-coded
118*0fca6ea1SDimitry Andric   //       function.
119*0fca6ea1SDimitry Andric   static constexpr bool getMaySupportMemoryTagging() {
120*0fca6ea1SDimitry Andric     return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
121*0fca6ea1SDimitry Andric   }
122*0fca6ea1SDimitry Andric 
123*0fca6ea1SDimitry Andric #define SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME)                                 \
124*0fca6ea1SDimitry Andric   template <typename T>                                                        \
125*0fca6ea1SDimitry Andric   using NAME = typename AllocatorConfig::Secondary::template NAME<T>;
126*0fca6ea1SDimitry Andric #include "allocator_config.def"
127*0fca6ea1SDimitry Andric 
128*0fca6ea1SDimitry Andric   struct CacheConfig {
129*0fca6ea1SDimitry Andric     // TODO: Pass this flag through template argument to remove this hard-coded
130*0fca6ea1SDimitry Andric     //       function.
131*0fca6ea1SDimitry Andric     static constexpr bool getMaySupportMemoryTagging() {
132*0fca6ea1SDimitry Andric       return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
133*0fca6ea1SDimitry Andric     }
134*0fca6ea1SDimitry Andric 
135*0fca6ea1SDimitry Andric #define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT)                          \
136*0fca6ea1SDimitry Andric   OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, Cache::NAME)                          \
137*0fca6ea1SDimitry Andric   static constexpr removeConst<TYPE>::type get##NAME() {                       \
138*0fca6ea1SDimitry Andric     return NAME##State<typename AllocatorConfig::Secondary>::getValue();       \
139*0fca6ea1SDimitry Andric   }
140*0fca6ea1SDimitry Andric #include "allocator_config.def"
141*0fca6ea1SDimitry Andric   }; // CacheConfig
142*0fca6ea1SDimitry Andric };   // SecondaryConfig
143*0fca6ea1SDimitry Andric 
144*0fca6ea1SDimitry Andric #undef OPTIONAL_TEMPLATE
145*0fca6ea1SDimitry Andric #undef OPTIONAL_TEMPLATE_TYPE
146*0fca6ea1SDimitry Andric 
147*0fca6ea1SDimitry Andric } // namespace scudo
148*0fca6ea1SDimitry Andric 
149*0fca6ea1SDimitry Andric #endif // SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
150