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