1 | //===-- Instrumentation.h ---------------------------------------*- C++ -*-===// |
2 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
3 | // See https://llvm.org/LICENSE.txt for license information. |
4 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
5 | // |
6 | //===----------------------------------------------------------------------===// |
7 | |
8 | #ifndef LLDB_UTILITY_INSTRUMENTATION_H |
9 | #define LLDB_UTILITY_INSTRUMENTATION_H |
10 | |
11 | #include "lldb/Utility/FileSpec.h" |
12 | #include "lldb/Utility/Log.h" |
13 | #include "llvm/ADT/DenseMap.h" |
14 | #include "llvm/ADT/StringRef.h" |
15 | #include "llvm/Support/ErrorHandling.h" |
16 | |
17 | #include <map> |
18 | #include <thread> |
19 | #include <type_traits> |
20 | |
21 | namespace lldb_private { |
22 | namespace instrumentation { |
23 | |
24 | template <typename T, std::enable_if_t<std::is_fundamental<T>::value, int> = 0> |
25 | inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { |
26 | ss << t; |
27 | } |
28 | |
29 | template <typename T, std::enable_if_t<!std::is_fundamental<T>::value, int> = 0> |
30 | inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { |
31 | ss << &t; |
32 | } |
33 | |
34 | template <typename T> |
35 | inline void stringify_append(llvm::raw_string_ostream &ss, T *t) { |
36 | ss << reinterpret_cast<void *>(t); |
37 | } |
38 | |
39 | template <typename T> |
40 | inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) { |
41 | ss << reinterpret_cast<const void *>(t); |
42 | } |
43 | |
44 | template <> |
45 | inline void stringify_append<char>(llvm::raw_string_ostream &ss, |
46 | const char *t) { |
47 | ss << '\"' << t << '\"'; |
48 | } |
49 | |
50 | template <> |
51 | inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss, |
52 | const std::nullptr_t &t) { |
53 | ss << "\"nullptr\"" ; |
54 | } |
55 | |
56 | template <typename Head> |
57 | inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) { |
58 | stringify_append(ss, head); |
59 | } |
60 | |
61 | template <typename Head, typename... Tail> |
62 | inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head, |
63 | const Tail &...tail) { |
64 | stringify_append(ss, head); |
65 | ss << ", " ; |
66 | stringify_helper(ss, tail...); |
67 | } |
68 | |
69 | template <typename... Ts> inline std::string stringify_args(const Ts &...ts) { |
70 | std::string buffer; |
71 | llvm::raw_string_ostream ss(buffer); |
72 | stringify_helper(ss, ts...); |
73 | return ss.str(); |
74 | } |
75 | |
76 | /// RAII object for instrumenting LLDB API functions. |
77 | class Instrumenter { |
78 | public: |
79 | Instrumenter(llvm::StringRef pretty_func, std::string &&pretty_args = {}); |
80 | ~Instrumenter(); |
81 | |
82 | private: |
83 | void UpdateBoundary(); |
84 | |
85 | llvm::StringRef m_pretty_func; |
86 | |
87 | /// Whether this function call was the one crossing the API boundary. |
88 | bool m_local_boundary = false; |
89 | }; |
90 | } // namespace instrumentation |
91 | } // namespace lldb_private |
92 | |
93 | #define LLDB_INSTRUMENT() \ |
94 | lldb_private::instrumentation::Instrumenter _instr(LLVM_PRETTY_FUNCTION); |
95 | |
96 | #define LLDB_INSTRUMENT_VA(...) \ |
97 | lldb_private::instrumentation::Instrumenter _instr( \ |
98 | LLVM_PRETTY_FUNCTION, \ |
99 | lldb_private::instrumentation::stringify_args(__VA_ARGS__)); |
100 | |
101 | #endif // LLDB_UTILITY_INSTRUMENTATION_H |
102 | |