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