1//===-- allocator_config_wrapper.h ------------------------------*- 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 SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
10#define SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
11
12#include "condition_variable.h"
13#include "internal_defs.h"
14#include "secondary.h"
15#include "type_traits.h"
16
17namespace scudo {
18
19#define OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, MEMBER) \
20 template <typename Config, typename = TYPE> struct NAME##State { \
21 static constexpr removeConst<TYPE>::type getValue() { return DEFAULT; } \
22 }; \
23 template <typename Config> \
24 struct NAME##State< \
25 Config, typename assertSameType<decltype(Config::MEMBER), TYPE>::type> { \
26 static constexpr removeConst<TYPE>::type getValue() { \
27 return Config::MEMBER; \
28 } \
29 };
30
31#define OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, MEMBER) \
32 template <typename Config, typename Void = void> struct NAME##Type { \
33 static constexpr bool enabled() { return false; } \
34 using NAME = DEFAULT; \
35 }; \
36 template <typename Config> \
37 struct NAME##Type<Config, \
38 typename voidAdaptor<typename Config::MEMBER>::type> { \
39 static constexpr bool enabled() { return true; } \
40 using NAME = typename Config::MEMBER; \
41 };
42
43template <typename AllocatorConfig> struct BaseConfig {
44#define BASE_REQUIRED_TEMPLATE_TYPE(NAME) \
45 template <typename T> using NAME = typename AllocatorConfig::template NAME<T>;
46
47#define BASE_OPTIONAL(TYPE, NAME, DEFAULT) \
48 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
49 static constexpr removeConst<TYPE>::type get##NAME() { \
50 return NAME##State<AllocatorConfig>::getValue(); \
51 }
52
53#include "allocator_config.def"
54}; // BaseConfig
55
56template <typename AllocatorConfig> struct PrimaryConfig {
57 // TODO: Pass this flag through template argument to remove this hard-coded
58 // function.
59 static constexpr bool getMaySupportMemoryTagging() {
60 return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
61 }
62
63 static constexpr bool getQuarantineDisabled() {
64 return BaseConfig<AllocatorConfig>::getQuarantineDisabled();
65 }
66
67#define PRIMARY_REQUIRED_TYPE(NAME) \
68 using NAME = typename AllocatorConfig::Primary::NAME;
69
70#define PRIMARY_REQUIRED(TYPE, NAME) \
71 static constexpr removeConst<TYPE>::type get##NAME() { \
72 return AllocatorConfig::Primary::NAME; \
73 }
74
75#define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) \
76 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
77 static constexpr removeConst<TYPE>::type get##NAME() { \
78 return NAME##State<typename AllocatorConfig::Primary>::getValue(); \
79 }
80
81#define PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) \
82 OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, NAME) \
83 static constexpr bool has##NAME() { \
84 return NAME##Type<typename AllocatorConfig::Primary>::enabled(); \
85 } \
86 using NAME = typename NAME##Type<typename AllocatorConfig::Primary>::NAME;
87
88#include "allocator_config.def"
89
90}; // PrimaryConfig
91
92template <typename AllocatorConfig> struct SecondaryConfig {
93 // TODO: Pass this flag through template argument to remove this hard-coded
94 // function.
95 static constexpr bool getMaySupportMemoryTagging() {
96 return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
97 }
98
99 static constexpr bool getQuarantineDisabled() {
100 return BaseConfig<AllocatorConfig>::getQuarantineDisabled();
101 }
102
103#define SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) \
104 template <typename T> \
105 using NAME = typename AllocatorConfig::Secondary::template NAME<T>;
106
107#define SECONDARY_OPTIONAL(TYPE, NAME, DEFAULT) \
108 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
109 static constexpr removeConst<TYPE>::type get##NAME() { \
110 return NAME##State<typename AllocatorConfig::Secondary>::getValue(); \
111 }
112
113#include "allocator_config.def"
114
115 struct CacheConfig {
116 // TODO: Pass this flag through template argument to remove this hard-coded
117 // function.
118 static constexpr bool getMaySupportMemoryTagging() {
119 return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
120 }
121
122 static constexpr bool getQuarantineDisabled() {
123 return BaseConfig<AllocatorConfig>::getQuarantineDisabled();
124 }
125
126#define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) \
127 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, Cache::NAME) \
128 static constexpr removeConst<TYPE>::type get##NAME() { \
129 return NAME##State<typename AllocatorConfig::Secondary>::getValue(); \
130 }
131#include "allocator_config.def"
132 }; // CacheConfig
133}; // SecondaryConfig
134
135#undef OPTIONAL_TEMPLATE
136#undef OPTIONAL_TEMPLATE_TYPE
137
138} // namespace scudo
139
140#endif // SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
141