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