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