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