xref: /src/contrib/llvm-project/llvm/lib/Support/Signposts.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1e6d15924SDimitry Andric //===-- Signposts.cpp - Interval debug annotations ------------------------===//
2e6d15924SDimitry Andric //
3c0981da4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c0981da4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5c0981da4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e6d15924SDimitry Andric //
7e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
8e6d15924SDimitry Andric 
9e6d15924SDimitry Andric #include "llvm/Support/Signposts.h"
10145449b1SDimitry Andric #include "llvm/ADT/StringRef.h"
11c0981da4SDimitry Andric #include "llvm/Config/config.h"
12145449b1SDimitry Andric 
13e6d15924SDimitry Andric #if LLVM_SUPPORT_XCODE_SIGNPOSTS
14e6d15924SDimitry Andric #include "llvm/ADT/DenseMap.h"
15b60736ecSDimitry Andric #include "llvm/Support/Mutex.h"
16c0981da4SDimitry Andric #include <Availability.h>
17c0981da4SDimitry Andric #include <os/signpost.h>
18c0981da4SDimitry Andric #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
19e6d15924SDimitry Andric 
20e6d15924SDimitry Andric using namespace llvm;
21e6d15924SDimitry Andric 
22e6d15924SDimitry Andric #if LLVM_SUPPORT_XCODE_SIGNPOSTS
23c0981da4SDimitry Andric #define SIGNPOSTS_AVAILABLE()                                                  \
24c0981da4SDimitry Andric   __builtin_available(macos 10.14, iOS 12, tvOS 12, watchOS 5, *)
25e6d15924SDimitry Andric namespace {
LogCreator()26e6d15924SDimitry Andric os_log_t *LogCreator() {
27e6d15924SDimitry Andric   os_log_t *X = new os_log_t;
28145449b1SDimitry Andric   *X = os_log_create("org.llvm.signposts", "toolchain");
29e6d15924SDimitry Andric   return X;
30e6d15924SDimitry Andric }
31344a3780SDimitry Andric struct LogDeleter {
operator ()__anon9a91db3b0111::LogDeleter32344a3780SDimitry Andric   void operator()(os_log_t *X) const {
33e6d15924SDimitry Andric     os_release(*X);
34e6d15924SDimitry Andric     delete X;
35e6d15924SDimitry Andric   }
36344a3780SDimitry Andric };
37e6d15924SDimitry Andric } // end anonymous namespace
38e6d15924SDimitry Andric 
39e6d15924SDimitry Andric namespace llvm {
40e6d15924SDimitry Andric class SignpostEmitterImpl {
41344a3780SDimitry Andric   using LogPtrTy = std::unique_ptr<os_log_t, LogDeleter>;
42c0981da4SDimitry Andric   using LogTy = LogPtrTy::element_type;
43e6d15924SDimitry Andric 
44e6d15924SDimitry Andric   LogPtrTy SignpostLog;
45b60736ecSDimitry Andric   DenseMap<const void *, os_signpost_id_t> Signposts;
46b60736ecSDimitry Andric   sys::SmartMutex<true> Mutex;
47e6d15924SDimitry Andric 
getLogger() const48c0981da4SDimitry Andric   LogTy &getLogger() const { return *SignpostLog; }
getSignpostForObject(const void * O)49b60736ecSDimitry Andric   os_signpost_id_t getSignpostForObject(const void *O) {
50b60736ecSDimitry Andric     sys::SmartScopedLock<true> Lock(Mutex);
51b60736ecSDimitry Andric     const auto &I = Signposts.find(O);
52e6d15924SDimitry Andric     if (I != Signposts.end())
53e6d15924SDimitry Andric       return I->second;
54344a3780SDimitry Andric     os_signpost_id_t ID = {};
55344a3780SDimitry Andric     if (SIGNPOSTS_AVAILABLE()) {
56344a3780SDimitry Andric       ID = os_signpost_id_make_with_pointer(getLogger(), O);
57344a3780SDimitry Andric     }
58344a3780SDimitry Andric     const auto &Inserted = Signposts.insert(std::make_pair(O, ID));
59e6d15924SDimitry Andric     return Inserted.first->second;
60e6d15924SDimitry Andric   }
61e6d15924SDimitry Andric 
62c0981da4SDimitry Andric public:
SignpostEmitterImpl()63344a3780SDimitry Andric   SignpostEmitterImpl() : SignpostLog(LogCreator()) {}
64e6d15924SDimitry Andric 
isEnabled() const65344a3780SDimitry Andric   bool isEnabled() const {
66344a3780SDimitry Andric     if (SIGNPOSTS_AVAILABLE())
67344a3780SDimitry Andric       return os_signpost_enabled(*SignpostLog);
68344a3780SDimitry Andric     return false;
69344a3780SDimitry Andric   }
70e6d15924SDimitry Andric 
startInterval(const void * O,llvm::StringRef Name)71b60736ecSDimitry Andric   void startInterval(const void *O, llvm::StringRef Name) {
72e6d15924SDimitry Andric     if (isEnabled()) {
73344a3780SDimitry Andric       if (SIGNPOSTS_AVAILABLE()) {
74b60736ecSDimitry Andric         // Both strings used here are required to be constant literal strings.
75b60736ecSDimitry Andric         os_signpost_interval_begin(getLogger(), getSignpostForObject(O),
76344a3780SDimitry Andric                                    "LLVM Timers", "%s", Name.data());
77344a3780SDimitry Andric       }
78e6d15924SDimitry Andric     }
79e6d15924SDimitry Andric   }
80e6d15924SDimitry Andric 
endInterval(const void * O,llvm::StringRef Name)81c0981da4SDimitry Andric   void endInterval(const void *O, llvm::StringRef Name) {
82e6d15924SDimitry Andric     if (isEnabled()) {
83344a3780SDimitry Andric       if (SIGNPOSTS_AVAILABLE()) {
84b60736ecSDimitry Andric         // Both strings used here are required to be constant literal strings.
85b60736ecSDimitry Andric         os_signpost_interval_end(getLogger(), getSignpostForObject(O),
86344a3780SDimitry Andric                                  "LLVM Timers", "");
87344a3780SDimitry Andric       }
88e6d15924SDimitry Andric     }
89e6d15924SDimitry Andric   }
90e6d15924SDimitry Andric };
91e6d15924SDimitry Andric } // end namespace llvm
92344a3780SDimitry Andric #else
93344a3780SDimitry Andric /// Definition necessary for use of std::unique_ptr in SignpostEmitter::Impl.
94344a3780SDimitry Andric class llvm::SignpostEmitterImpl {};
95e6d15924SDimitry Andric #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
96e6d15924SDimitry Andric 
97e6d15924SDimitry Andric #if LLVM_SUPPORT_XCODE_SIGNPOSTS
98e6d15924SDimitry Andric #define HAVE_ANY_SIGNPOST_IMPL 1
991d5ae102SDimitry Andric #else
1001d5ae102SDimitry Andric #define HAVE_ANY_SIGNPOST_IMPL 0
101e6d15924SDimitry Andric #endif
102e6d15924SDimitry Andric 
SignpostEmitter()103e6d15924SDimitry Andric SignpostEmitter::SignpostEmitter() {
104e6d15924SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
105344a3780SDimitry Andric   Impl = std::make_unique<SignpostEmitterImpl>();
106e6d15924SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
107e6d15924SDimitry Andric }
108e6d15924SDimitry Andric 
109344a3780SDimitry Andric SignpostEmitter::~SignpostEmitter() = default;
110e6d15924SDimitry Andric 
isEnabled() const111e6d15924SDimitry Andric bool SignpostEmitter::isEnabled() const {
112e6d15924SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
113e6d15924SDimitry Andric   return Impl->isEnabled();
114e6d15924SDimitry Andric #else
115e6d15924SDimitry Andric   return false;
116e6d15924SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
117e6d15924SDimitry Andric }
118e6d15924SDimitry Andric 
startInterval(const void * O,StringRef Name)119b60736ecSDimitry Andric void SignpostEmitter::startInterval(const void *O, StringRef Name) {
120e6d15924SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
121e6d15924SDimitry Andric   if (Impl == nullptr)
122e6d15924SDimitry Andric     return;
123b60736ecSDimitry Andric   return Impl->startInterval(O, Name);
124e6d15924SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
125e6d15924SDimitry Andric }
126e6d15924SDimitry Andric 
endInterval(const void * O,StringRef Name)127c0981da4SDimitry Andric void SignpostEmitter::endInterval(const void *O, StringRef Name) {
128e6d15924SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
129e6d15924SDimitry Andric   if (Impl == nullptr)
130e6d15924SDimitry Andric     return;
131c0981da4SDimitry Andric   Impl->endInterval(O, Name);
132e6d15924SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
133e6d15924SDimitry Andric }
134