xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Support/Signposts.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 //===-- Signposts.cpp - Interval debug annotations ------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/Support/Signposts.h"
11 #include "llvm/Support/Timer.h"
12 
13 #include "llvm/Config/config.h"
14 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
15 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/Support/Mutex.h"
17 #include <Availability.h>
18 #include <os/signpost.h>
19 #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
20 
21 using namespace llvm;
22 
23 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
24 #define SIGNPOSTS_AVAILABLE()                                                  \
25   __builtin_available(macos 10.14, iOS 12, tvOS 12, watchOS 5, *)
26 namespace {
LogCreator()27 os_log_t *LogCreator() {
28   os_log_t *X = new os_log_t;
29   *X = os_log_create("org.llvm.signposts", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
30   return X;
31 }
32 struct LogDeleter {
operator ()__anon0a2b4bb10111::LogDeleter33   void operator()(os_log_t *X) const {
34     os_release(*X);
35     delete X;
36   }
37 };
38 } // end anonymous namespace
39 
40 namespace llvm {
41 class SignpostEmitterImpl {
42   using LogPtrTy = std::unique_ptr<os_log_t, LogDeleter>;
43   using LogTy = LogPtrTy::element_type;
44 
45   LogPtrTy SignpostLog;
46   DenseMap<const void *, os_signpost_id_t> Signposts;
47   sys::SmartMutex<true> Mutex;
48 
getLogger() const49   LogTy &getLogger() const { return *SignpostLog; }
getSignpostForObject(const void * O)50   os_signpost_id_t getSignpostForObject(const void *O) {
51     sys::SmartScopedLock<true> Lock(Mutex);
52     const auto &I = Signposts.find(O);
53     if (I != Signposts.end())
54       return I->second;
55     os_signpost_id_t ID = {};
56     if (SIGNPOSTS_AVAILABLE()) {
57       ID = os_signpost_id_make_with_pointer(getLogger(), O);
58     }
59     const auto &Inserted = Signposts.insert(std::make_pair(O, ID));
60     return Inserted.first->second;
61   }
62 
63 public:
SignpostEmitterImpl()64   SignpostEmitterImpl() : SignpostLog(LogCreator()) {}
65 
isEnabled() const66   bool isEnabled() const {
67     if (SIGNPOSTS_AVAILABLE())
68       return os_signpost_enabled(*SignpostLog);
69     return false;
70   }
71 
startInterval(const void * O,llvm::StringRef Name)72   void startInterval(const void *O, llvm::StringRef Name) {
73     if (isEnabled()) {
74       if (SIGNPOSTS_AVAILABLE()) {
75         // Both strings used here are required to be constant literal strings.
76         os_signpost_interval_begin(getLogger(), getSignpostForObject(O),
77                                    "LLVM Timers", "Begin %s", Name.data());
78       }
79     }
80   }
81 
endInterval(const void * O,llvm::StringRef Name)82   void endInterval(const void *O, llvm::StringRef Name) {
83     if (isEnabled()) {
84       if (SIGNPOSTS_AVAILABLE()) {
85         // Both strings used here are required to be constant literal strings.
86         os_signpost_interval_end(getLogger(), getSignpostForObject(O),
87                                  "LLVM Timers", "End %s", Name.data());
88       }
89     }
90   }
91 };
92 } // end namespace llvm
93 #else
94 /// Definition necessary for use of std::unique_ptr in SignpostEmitter::Impl.
95 class llvm::SignpostEmitterImpl {};
96 #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
97 
98 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
99 #define HAVE_ANY_SIGNPOST_IMPL 1
100 #else
101 #define HAVE_ANY_SIGNPOST_IMPL 0
102 #endif
103 
SignpostEmitter()104 SignpostEmitter::SignpostEmitter() {
105 #if HAVE_ANY_SIGNPOST_IMPL
106   Impl = std::make_unique<SignpostEmitterImpl>();
107 #endif // if !HAVE_ANY_SIGNPOST_IMPL
108 }
109 
110 SignpostEmitter::~SignpostEmitter() = default;
111 
isEnabled() const112 bool SignpostEmitter::isEnabled() const {
113 #if HAVE_ANY_SIGNPOST_IMPL
114   return Impl->isEnabled();
115 #else
116   return false;
117 #endif // if !HAVE_ANY_SIGNPOST_IMPL
118 }
119 
startInterval(const void * O,StringRef Name)120 void SignpostEmitter::startInterval(const void *O, StringRef Name) {
121 #if HAVE_ANY_SIGNPOST_IMPL
122   if (Impl == nullptr)
123     return;
124   return Impl->startInterval(O, Name);
125 #endif // if !HAVE_ANY_SIGNPOST_IMPL
126 }
127 
endInterval(const void * O,StringRef Name)128 void SignpostEmitter::endInterval(const void *O, StringRef Name) {
129 #if HAVE_ANY_SIGNPOST_IMPL
130   if (Impl == nullptr)
131     return;
132   Impl->endInterval(O, Name);
133 #endif // if !HAVE_ANY_SIGNPOST_IMPL
134 }
135