• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_BASE_COMPILER_H_
18 #define INCLUDE_PERFETTO_BASE_COMPILER_H_
19 
20 #include <cstddef>
21 #include <type_traits>
22 #include <variant>
23 
24 #include "perfetto/public/compiler.h"
25 
26 // __has_attribute is supported only by clang and recent versions of GCC.
27 // Add a layer to wrap the __has_attribute macro.
28 #if defined(__has_attribute)
29 #define PERFETTO_HAS_ATTRIBUTE(x) __has_attribute(x)
30 #else
31 #define PERFETTO_HAS_ATTRIBUTE(x) 0
32 #endif
33 
34 #if defined(__GNUC__) || defined(__clang__)
35 #define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
36 #else
37 #define PERFETTO_WARN_UNUSED_RESULT
38 #endif
39 
40 #if defined(__GNUC__) || defined(__clang__)
41 #define PERFETTO_UNUSED __attribute__((unused))
42 #else
43 #define PERFETTO_UNUSED
44 #endif
45 
46 #if defined(__GNUC__) || defined(__clang__)
47 #define PERFETTO_NORETURN __attribute__((__noreturn__))
48 #else
49 #define PERFETTO_NORETURN __declspec(noreturn)
50 #endif
51 
52 #if defined(__GNUC__) || defined(__clang__)
53 #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__
54 #elif defined(_MSC_VER)
55 #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__
56 #else
57 #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() \
58   static_assert(false, "Not implemented for this compiler")
59 #endif
60 
61 #if defined(__GNUC__) || defined(__clang__)
62 #define PERFETTO_PRINTF_FORMAT(x, y) \
63   __attribute__((__format__(__printf__, x, y)))
64 #else
65 #define PERFETTO_PRINTF_FORMAT(x, y)
66 #endif
67 
68 #if defined(__GNUC__) || defined(__clang__)
69 #define PERFETTO_POPCOUNT(x) __builtin_popcountll(x)
70 #else
71 #include <intrin.h>
72 #define PERFETTO_POPCOUNT(x) __popcnt64(x)
73 #endif
74 
75 #if defined(__clang__)
76 #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
77 extern "C" void __asan_poison_memory_region(void const volatile*, size_t);
78 extern "C" void __asan_unpoison_memory_region(void const volatile*, size_t);
79 #define PERFETTO_ASAN_POISON(a, s) __asan_poison_memory_region((a), (s))
80 #define PERFETTO_ASAN_UNPOISON(a, s) __asan_unpoison_memory_region((a), (s))
81 #else
82 #define PERFETTO_ASAN_POISON(addr, size)
83 #define PERFETTO_ASAN_UNPOISON(addr, size)
84 #endif  // __has_feature(address_sanitizer)
85 #else
86 #define PERFETTO_ASAN_POISON(addr, size)
87 #define PERFETTO_ASAN_UNPOISON(addr, size)
88 #endif  // __clang__
89 
90 #if defined(__GNUC__) || defined(__clang__)
91 #define PERFETTO_IS_LITTLE_ENDIAN() __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
92 #else
93 // Assume all MSVC targets are little endian.
94 #define PERFETTO_IS_LITTLE_ENDIAN() 1
95 #endif
96 
97 // This is used for exporting xxxMain() symbols (e.g., PerfettoCmdMain,
98 // ProbesMain) from libperfetto.so when the GN arg monolithic_binaries = false.
99 #if defined(__GNUC__) || defined(__clang__)
100 #define PERFETTO_EXPORT_ENTRYPOINT __attribute__((visibility("default")))
101 #else
102 // TODO(primiano): on Windows this should be a pair of dllexport/dllimport. But
103 // that requires a -DXXX_IMPLEMENTATION depending on whether we are on the
104 // impl-site or call-site. Right now it's not worth the trouble as we
105 // force-export the xxxMain() symbols only on Android, where we pack all the
106 // code for N binaries into one .so to save binary size. On Windows we support
107 // only monolithic binaries, as they are easier to deal with.
108 #define PERFETTO_EXPORT_ENTRYPOINT
109 #endif
110 
111 // Disables undefined behavior analysis for a function.
112 #if defined(__clang__)
113 #define PERFETTO_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
114 #else
115 #define PERFETTO_NO_SANITIZE_UNDEFINED
116 #endif
117 
118 // Avoid calling the exit-time destructor on an object with static lifetime.
119 #if PERFETTO_HAS_ATTRIBUTE(no_destroy)
120 #define PERFETTO_HAS_NO_DESTROY() 1
121 #define PERFETTO_NO_DESTROY __attribute__((no_destroy))
122 #else
123 #define PERFETTO_HAS_NO_DESTROY() 0
124 #define PERFETTO_NO_DESTROY
125 #endif
126 
127 // Macro for telling -Wimplicit-fallthrough that a fallthrough is intentional.
128 #define PERFETTO_FALLTHROUGH [[fallthrough]]
129 
130 // Depending on the version of the compiler, __has_builtin can be provided or
131 // not.
132 #if defined(__has_builtin)
133 #if __has_builtin(__builtin_stack_address)
134 #define PERFETTO_HAS_BUILTIN_STACK_ADDRESS() 1
135 #else
136 #define PERFETTO_HAS_BUILTIN_STACK_ADDRESS() 0
137 #endif
138 #else
139 #define PERFETTO_HAS_BUILTIN_STACK_ADDRESS() 0
140 #endif
141 
142 namespace perfetto::base {
143 
144 template <typename... T>
ignore_result(const T &...)145 inline void ignore_result(const T&...) {}
146 
147 // Given a std::variant and a type T, returns the index of the T in the variant.
148 template <typename VariantType, typename T, size_t i = 0>
variant_index()149 constexpr size_t variant_index() {
150   static_assert(i < std::variant_size_v<VariantType>,
151                 "Type not found in variant");
152   if constexpr (std::is_same_v<std::variant_alternative_t<i, VariantType>, T>) {
153     return i;
154   } else {
155     return variant_index<VariantType, T, i + 1>();
156   }
157 }
158 
159 }  // namespace perfetto::base
160 
161 #endif  // INCLUDE_PERFETTO_BASE_COMPILER_H_
162