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 { 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 { 28 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: 44 os_log_t &getLogger() const { return *SignpostLog; } 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 58 SignpostEmitterImpl() : SignpostLog(LogCreator()) {} 59 60 bool isEnabled() const { 61 if (SIGNPOSTS_AVAILABLE()) 62 return os_signpost_enabled(*SignpostLog); 63 return false; 64 } 65 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 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 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 106 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 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 123 os_log_t &SignpostEmitter::getLogger() const { return Impl->getLogger(); } 124 os_signpost_id_t SignpostEmitter::getSignpostForObject(const void *O) { 125 return Impl->getSignpostForObject(O); 126 } 127 #endif 128 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