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