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