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 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
14 #include "llvm/ADT/DenseMap.h"
15 #include "llvm/Support/Mutex.h"
16 #endif
17 
18 using namespace llvm;
19 
20 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
21 namespace {
LogCreator()22 os_log_t *LogCreator() {
23   os_log_t *X = new os_log_t;
24   *X = os_log_create("org.llvm.signposts", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
25   return X;
26 }
27 struct LogDeleter {
operator ()__anon0086af0c0111::LogDeleter28   void operator()(os_log_t *X) const {
29     os_release(*X);
30     delete X;
31   }
32 };
33 } // end anonymous namespace
34 
35 namespace llvm {
36 class SignpostEmitterImpl {
37   using LogPtrTy = std::unique_ptr<os_log_t, LogDeleter>;
38 
39   LogPtrTy SignpostLog;
40   DenseMap<const void *, os_signpost_id_t> Signposts;
41   sys::SmartMutex<true> Mutex;
42 
43 public:
getLogger() const44   os_log_t &getLogger() const { return *SignpostLog; }
getSignpostForObject(const void * O)45   os_signpost_id_t getSignpostForObject(const void *O) {
46     sys::SmartScopedLock<true> Lock(Mutex);
47     const auto &I = Signposts.find(O);
48     if (I != Signposts.end())
49       return I->second;
50     os_signpost_id_t ID = {};
51     if (SIGNPOSTS_AVAILABLE()) {
52       ID = os_signpost_id_make_with_pointer(getLogger(), O);
53     }
54     const auto &Inserted = Signposts.insert(std::make_pair(O, ID));
55     return Inserted.first->second;
56   }
57 
SignpostEmitterImpl()58   SignpostEmitterImpl() : SignpostLog(LogCreator()) {}
59 
isEnabled() const60   bool isEnabled() const {
61     if (SIGNPOSTS_AVAILABLE())
62       return os_signpost_enabled(*SignpostLog);
63     return false;
64   }
65 
startInterval(const void * O,llvm::StringRef Name)66   void startInterval(const void *O, llvm::StringRef Name) {
67     if (isEnabled()) {
68       if (SIGNPOSTS_AVAILABLE()) {
69         // Both strings used here are required to be constant literal strings.
70         os_signpost_interval_begin(getLogger(), getSignpostForObject(O),
71                                    "LLVM Timers", "%s", Name.data());
72       }
73     }
74   }
75 
endInterval(const void * O)76   void endInterval(const void *O) {
77     if (isEnabled()) {
78       if (SIGNPOSTS_AVAILABLE()) {
79         // Both strings used here are required to be constant literal strings.
80         os_signpost_interval_end(getLogger(), getSignpostForObject(O),
81                                  "LLVM Timers", "");
82       }
83     }
84   }
85 };
86 } // end namespace llvm
87 #else
88 /// Definition necessary for use of std::unique_ptr in SignpostEmitter::Impl.
89 class llvm::SignpostEmitterImpl {};
90 #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
91 
92 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
93 #define HAVE_ANY_SIGNPOST_IMPL 1
94 #else
95 #define HAVE_ANY_SIGNPOST_IMPL 0
96 #endif
97 
SignpostEmitter()98 SignpostEmitter::SignpostEmitter() {
99 #if HAVE_ANY_SIGNPOST_IMPL
100   Impl = std::make_unique<SignpostEmitterImpl>();
101 #endif // if !HAVE_ANY_SIGNPOST_IMPL
102 }
103 
104 SignpostEmitter::~SignpostEmitter() = default;
105 
isEnabled() const106 bool SignpostEmitter::isEnabled() const {
107 #if HAVE_ANY_SIGNPOST_IMPL
108   return Impl->isEnabled();
109 #else
110   return false;
111 #endif // if !HAVE_ANY_SIGNPOST_IMPL
112 }
113 
startInterval(const void * O,StringRef Name)114 void SignpostEmitter::startInterval(const void *O, StringRef Name) {
115 #if HAVE_ANY_SIGNPOST_IMPL
116   if (Impl == nullptr)
117     return;
118   return Impl->startInterval(O, Name);
119 #endif // if !HAVE_ANY_SIGNPOST_IMPL
120 }
121 
122 #if HAVE_ANY_SIGNPOST_IMPL
getLogger() const123 os_log_t &SignpostEmitter::getLogger() const { return Impl->getLogger(); }
getSignpostForObject(const void * O)124 os_signpost_id_t SignpostEmitter::getSignpostForObject(const void *O) {
125   return Impl->getSignpostForObject(O);
126 }
127 #endif
128 
endInterval(const void * O)129 void SignpostEmitter::endInterval(const void *O) {
130 #if HAVE_ANY_SIGNPOST_IMPL
131   if (Impl == nullptr)
132     return;
133   Impl->endInterval(O);
134 #endif // if !HAVE_ANY_SIGNPOST_IMPL
135 }
136