1e1414d17SDaniel Sanders //===-- Signposts.cpp - Interval debug annotations ------------------------===// 2e1414d17SDaniel Sanders // 3c874dd53SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c874dd53SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information. 5c874dd53SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e1414d17SDaniel Sanders // 7e1414d17SDaniel Sanders //===----------------------------------------------------------------------===// 8e1414d17SDaniel Sanders 9e1414d17SDaniel Sanders #include "llvm/Support/Signposts.h" 10*aedea002SSimon Pilgrim #include "llvm/ADT/StringRef.h" 11070315d0SJonas Devlieghere #include "llvm/Config/config.h" 12*aedea002SSimon Pilgrim 13e1414d17SDaniel Sanders #if LLVM_SUPPORT_XCODE_SIGNPOSTS 14e1414d17SDaniel Sanders #include "llvm/ADT/DenseMap.h" 15a4b42c62SJonas Devlieghere #include "llvm/Support/Mutex.h" 16070315d0SJonas Devlieghere #include <Availability.h> 17070315d0SJonas Devlieghere #include <os/signpost.h> 18070315d0SJonas Devlieghere #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS 19e1414d17SDaniel Sanders 20e1414d17SDaniel Sanders using namespace llvm; 21e1414d17SDaniel Sanders 22e1414d17SDaniel Sanders #if LLVM_SUPPORT_XCODE_SIGNPOSTS 23070315d0SJonas Devlieghere #define SIGNPOSTS_AVAILABLE() \ 24070315d0SJonas Devlieghere __builtin_available(macos 10.14, iOS 12, tvOS 12, watchOS 5, *) 25e1414d17SDaniel Sanders namespace { 26e1414d17SDaniel Sanders os_log_t *LogCreator() { 27e1414d17SDaniel Sanders os_log_t *X = new os_log_t; 28e1414d17SDaniel Sanders *X = os_log_create("org.llvm.signposts", OS_LOG_CATEGORY_POINTS_OF_INTEREST); 29e1414d17SDaniel Sanders return X; 30e1414d17SDaniel Sanders } 319be43874SDuncan P. N. Exon Smith struct LogDeleter { 329be43874SDuncan P. N. Exon Smith void operator()(os_log_t *X) const { 33e1414d17SDaniel Sanders os_release(*X); 34e1414d17SDaniel Sanders delete X; 35e1414d17SDaniel Sanders } 369be43874SDuncan P. N. Exon Smith }; 37e1414d17SDaniel Sanders } // end anonymous namespace 38e1414d17SDaniel Sanders 39e1414d17SDaniel Sanders namespace llvm { 40e1414d17SDaniel Sanders class SignpostEmitterImpl { 419be43874SDuncan P. N. Exon Smith using LogPtrTy = std::unique_ptr<os_log_t, LogDeleter>; 42070315d0SJonas Devlieghere using LogTy = LogPtrTy::element_type; 43e1414d17SDaniel Sanders 44e1414d17SDaniel Sanders LogPtrTy SignpostLog; 45b37de2afSJonas Devlieghere DenseMap<const void *, os_signpost_id_t> Signposts; 46a4b42c62SJonas Devlieghere sys::SmartMutex<true> Mutex; 47e1414d17SDaniel Sanders 48070315d0SJonas Devlieghere LogTy &getLogger() const { return *SignpostLog; } 49b37de2afSJonas Devlieghere os_signpost_id_t getSignpostForObject(const void *O) { 50a4b42c62SJonas Devlieghere sys::SmartScopedLock<true> Lock(Mutex); 51b37de2afSJonas Devlieghere const auto &I = Signposts.find(O); 52e1414d17SDaniel Sanders if (I != Signposts.end()) 53e1414d17SDaniel Sanders return I->second; 54b03bb054SJonas Devlieghere os_signpost_id_t ID = {}; 55b03bb054SJonas Devlieghere if (SIGNPOSTS_AVAILABLE()) { 56b03bb054SJonas Devlieghere ID = os_signpost_id_make_with_pointer(getLogger(), O); 57b03bb054SJonas Devlieghere } 58b03bb054SJonas Devlieghere const auto &Inserted = Signposts.insert(std::make_pair(O, ID)); 59e1414d17SDaniel Sanders return Inserted.first->second; 60e1414d17SDaniel Sanders } 61e1414d17SDaniel Sanders 62070315d0SJonas Devlieghere public: 639be43874SDuncan P. N. Exon Smith SignpostEmitterImpl() : SignpostLog(LogCreator()) {} 64e1414d17SDaniel Sanders 65b03bb054SJonas Devlieghere bool isEnabled() const { 66b03bb054SJonas Devlieghere if (SIGNPOSTS_AVAILABLE()) 67b03bb054SJonas Devlieghere return os_signpost_enabled(*SignpostLog); 68b03bb054SJonas Devlieghere return false; 69b03bb054SJonas Devlieghere } 70e1414d17SDaniel Sanders 71b37de2afSJonas Devlieghere void startInterval(const void *O, llvm::StringRef Name) { 72e1414d17SDaniel Sanders if (isEnabled()) { 73b03bb054SJonas Devlieghere if (SIGNPOSTS_AVAILABLE()) { 74b37de2afSJonas Devlieghere // Both strings used here are required to be constant literal strings. 75b37de2afSJonas Devlieghere os_signpost_interval_begin(getLogger(), getSignpostForObject(O), 76a8099b47SAdrian Prantl "LLVM Timers", "%s", Name.data()); 77e1414d17SDaniel Sanders } 78e1414d17SDaniel Sanders } 79b03bb054SJonas Devlieghere } 80e1414d17SDaniel Sanders 81070315d0SJonas Devlieghere void endInterval(const void *O, llvm::StringRef Name) { 82e1414d17SDaniel Sanders if (isEnabled()) { 83b03bb054SJonas Devlieghere if (SIGNPOSTS_AVAILABLE()) { 84b37de2afSJonas Devlieghere // Both strings used here are required to be constant literal strings. 85b37de2afSJonas Devlieghere os_signpost_interval_end(getLogger(), getSignpostForObject(O), 86a8099b47SAdrian Prantl "LLVM Timers", ""); 87e1414d17SDaniel Sanders } 88e1414d17SDaniel Sanders } 89b03bb054SJonas Devlieghere } 90e1414d17SDaniel Sanders }; 91e1414d17SDaniel Sanders } // end namespace llvm 926dc43251SDuncan P. N. Exon Smith #else 936dc43251SDuncan P. N. Exon Smith /// Definition necessary for use of std::unique_ptr in SignpostEmitter::Impl. 946dc43251SDuncan P. N. Exon Smith class llvm::SignpostEmitterImpl {}; 95e1414d17SDaniel Sanders #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS 96e1414d17SDaniel Sanders 97e1414d17SDaniel Sanders #if LLVM_SUPPORT_XCODE_SIGNPOSTS 98e1414d17SDaniel Sanders #define HAVE_ANY_SIGNPOST_IMPL 1 990096d193SSven van Haastregt #else 1000096d193SSven van Haastregt #define HAVE_ANY_SIGNPOST_IMPL 0 101e1414d17SDaniel Sanders #endif 102e1414d17SDaniel Sanders 103e1414d17SDaniel Sanders SignpostEmitter::SignpostEmitter() { 104e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL 1056dc43251SDuncan P. N. Exon Smith Impl = std::make_unique<SignpostEmitterImpl>(); 106e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL 107e1414d17SDaniel Sanders } 108e1414d17SDaniel Sanders 1096dc43251SDuncan P. N. Exon Smith SignpostEmitter::~SignpostEmitter() = default; 110e1414d17SDaniel Sanders 111e1414d17SDaniel Sanders bool SignpostEmitter::isEnabled() const { 112e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL 113e1414d17SDaniel Sanders return Impl->isEnabled(); 114e1414d17SDaniel Sanders #else 115e1414d17SDaniel Sanders return false; 116e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL 117e1414d17SDaniel Sanders } 118e1414d17SDaniel Sanders 119b37de2afSJonas Devlieghere void SignpostEmitter::startInterval(const void *O, StringRef Name) { 120e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL 121e1414d17SDaniel Sanders if (Impl == nullptr) 122e1414d17SDaniel Sanders return; 123b37de2afSJonas Devlieghere return Impl->startInterval(O, Name); 124e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL 125e1414d17SDaniel Sanders } 126e1414d17SDaniel Sanders 127070315d0SJonas Devlieghere void SignpostEmitter::endInterval(const void *O, StringRef Name) { 128e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL 129e1414d17SDaniel Sanders if (Impl == nullptr) 130e1414d17SDaniel Sanders return; 131070315d0SJonas Devlieghere Impl->endInterval(O, Name); 132e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL 133e1414d17SDaniel Sanders } 134