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