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