aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h')
-rw-r--r--contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h149
1 files changed, 149 insertions, 0 deletions
diff --git a/contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h b/contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h
new file mode 100644
index 000000000000..5477236ac1f3
--- /dev/null
+++ b/contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h
@@ -0,0 +1,149 @@
+//===-- allocator_config_wrapper.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
+#define SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
+
+#include "condition_variable.h"
+#include "internal_defs.h"
+#include "secondary.h"
+
+namespace {
+
+template <typename T> struct removeConst {
+ using type = T;
+};
+template <typename T> struct removeConst<const T> {
+ using type = T;
+};
+
+// This is only used for SFINAE when detecting if a type is defined.
+template <typename T> struct voidAdaptor {
+ using type = void;
+};
+
+// This is used for detecting the case that defines the flag with wrong type and
+// it'll be viewed as undefined optional flag.
+template <typename L, typename R> struct assertSameType {
+ template <typename, typename> struct isSame {
+ static constexpr bool value = false;
+ };
+ template <typename T> struct isSame<T, T> {
+ static constexpr bool value = true;
+ };
+ static_assert(isSame<L, R>::value, "Flag type mismatches");
+ using type = R;
+};
+
+} // namespace
+
+namespace scudo {
+
+#define OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, MEMBER) \
+ template <typename Config, typename = TYPE> struct NAME##State { \
+ static constexpr removeConst<TYPE>::type getValue() { return DEFAULT; } \
+ }; \
+ template <typename Config> \
+ struct NAME##State< \
+ Config, typename assertSameType<decltype(Config::MEMBER), TYPE>::type> { \
+ static constexpr removeConst<TYPE>::type getValue() { \
+ return Config::MEMBER; \
+ } \
+ };
+
+#define OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, MEMBER) \
+ template <typename Config, typename Void = void> struct NAME##Type { \
+ static constexpr bool enabled() { return false; } \
+ using NAME = DEFAULT; \
+ }; \
+ template <typename Config> \
+ struct NAME##Type<Config, \
+ typename voidAdaptor<typename Config::MEMBER>::type> { \
+ static constexpr bool enabled() { return true; } \
+ using NAME = typename Config::MEMBER; \
+ };
+
+template <typename AllocatorConfig> struct BaseConfig {
+#define BASE_REQUIRED_TEMPLATE_TYPE(NAME) \
+ template <typename T> using NAME = typename AllocatorConfig::template NAME<T>;
+
+#define BASE_OPTIONAL(TYPE, NAME, DEFAULT) \
+ OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
+ static constexpr removeConst<TYPE>::type get##NAME() { \
+ return NAME##State<AllocatorConfig>::getValue(); \
+ }
+
+#include "allocator_config.def"
+}; // BaseConfig
+
+template <typename AllocatorConfig> struct PrimaryConfig {
+ // TODO: Pass this flag through template argument to remove this hard-coded
+ // function.
+ static constexpr bool getMaySupportMemoryTagging() {
+ return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
+ }
+
+#define PRIMARY_REQUIRED_TYPE(NAME) \
+ using NAME = typename AllocatorConfig::Primary::NAME;
+
+#define PRIMARY_REQUIRED(TYPE, NAME) \
+ static constexpr removeConst<TYPE>::type get##NAME() { \
+ return AllocatorConfig::Primary::NAME; \
+ }
+
+#define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) \
+ OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
+ static constexpr removeConst<TYPE>::type get##NAME() { \
+ return NAME##State<typename AllocatorConfig::Primary>::getValue(); \
+ }
+
+#define PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) \
+ OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, NAME) \
+ static constexpr bool has##NAME() { \
+ return NAME##Type<typename AllocatorConfig::Primary>::enabled(); \
+ } \
+ using NAME = typename NAME##Type<typename AllocatorConfig::Primary>::NAME;
+
+#include "allocator_config.def"
+
+}; // PrimaryConfig
+
+template <typename AllocatorConfig> struct SecondaryConfig {
+ // TODO: Pass this flag through template argument to remove this hard-coded
+ // function.
+ static constexpr bool getMaySupportMemoryTagging() {
+ return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
+ }
+
+#define SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) \
+ template <typename T> \
+ using NAME = typename AllocatorConfig::Secondary::template NAME<T>;
+#include "allocator_config.def"
+
+ struct CacheConfig {
+ // TODO: Pass this flag through template argument to remove this hard-coded
+ // function.
+ static constexpr bool getMaySupportMemoryTagging() {
+ return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
+ }
+
+#define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) \
+ OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, Cache::NAME) \
+ static constexpr removeConst<TYPE>::type get##NAME() { \
+ return NAME##State<typename AllocatorConfig::Secondary>::getValue(); \
+ }
+#include "allocator_config.def"
+ }; // CacheConfig
+}; // SecondaryConfig
+
+#undef OPTIONAL_TEMPLATE
+#undef OPTIONAL_TEMPLATE_TYPE
+
+} // namespace scudo
+
+#endif // SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_