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