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, 25 typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0> 26 inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { 27 ss << t; 28 } 29 30 template <typename T, typename std::enable_if<!std::is_fundamental<T>::value, 31 int>::type = 0> 32 inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { 33 ss << &t; 34 } 35 36 template <typename T> 37 inline void stringify_append(llvm::raw_string_ostream &ss, T *t) { 38 ss << reinterpret_cast<void *>(t); 39 } 40 41 template <typename T> 42 inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) { 43 ss << reinterpret_cast<const void *>(t); 44 } 45 46 template <> 47 inline void stringify_append<char>(llvm::raw_string_ostream &ss, 48 const char *t) { 49 ss << '\"' << t << '\"'; 50 } 51 52 template <> 53 inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss, 54 const std::nullptr_t &t) { 55 ss << "\"nullptr\""; 56 } 57 58 template <typename Head> 59 inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) { 60 stringify_append(ss, head); 61 } 62 63 template <typename Head, typename... Tail> 64 inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head, 65 const Tail &...tail) { 66 stringify_append(ss, head); 67 ss << ", "; 68 stringify_helper(ss, tail...); 69 } 70 71 template <typename... Ts> inline std::string stringify_args(const Ts &...ts) { 72 std::string buffer; 73 llvm::raw_string_ostream ss(buffer); 74 stringify_helper(ss, ts...); 75 return ss.str(); 76 } 77 78 /// RAII object for instrumenting LLDB API functions. 79 class Instrumenter { 80 public: 81 Instrumenter(llvm::StringRef pretty_func, std::string &&pretty_args = {}); 82 ~Instrumenter(); 83 84 private: 85 void UpdateBoundary(); 86 87 llvm::StringRef m_pretty_func; 88 89 /// Whether this function call was the one crossing the API boundary. 90 bool m_local_boundary = false; 91 }; 92 } // namespace instrumentation 93 } // namespace lldb_private 94 95 #define LLDB_INSTRUMENT() \ 96 lldb_private::instrumentation::Instrumenter _instr(LLVM_PRETTY_FUNCTION); 97 98 #define LLDB_INSTRUMENT_VA(...) \ 99 lldb_private::instrumentation::Instrumenter _instr( \ 100 LLVM_PRETTY_FUNCTION, \ 101 lldb_private::instrumentation::stringify_args(__VA_ARGS__)); 102 103 #endif // LLDB_UTILITY_INSTRUMENTATION_H 104