17330f729Sjoerg //===-- Signposts.cpp - Interval debug annotations ------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // The LLVM Compiler Infrastructure
47330f729Sjoerg //
57330f729Sjoerg // This file is distributed under the University of Illinois Open Source
67330f729Sjoerg // License. See LICENSE.TXT for details.
77330f729Sjoerg //
87330f729Sjoerg //===----------------------------------------------------------------------===//
97330f729Sjoerg
107330f729Sjoerg #include "llvm/Support/Signposts.h"
117330f729Sjoerg #include "llvm/Support/Timer.h"
127330f729Sjoerg
137330f729Sjoerg #include "llvm/Config/config.h"
147330f729Sjoerg #if LLVM_SUPPORT_XCODE_SIGNPOSTS
157330f729Sjoerg #include "llvm/ADT/DenseMap.h"
16*82d56013Sjoerg #include "llvm/Support/Mutex.h"
17*82d56013Sjoerg #include <Availability.h>
187330f729Sjoerg #include <os/signpost.h>
197330f729Sjoerg #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
207330f729Sjoerg
217330f729Sjoerg using namespace llvm;
227330f729Sjoerg
237330f729Sjoerg #if LLVM_SUPPORT_XCODE_SIGNPOSTS
24*82d56013Sjoerg #define SIGNPOSTS_AVAILABLE() \
25*82d56013Sjoerg __builtin_available(macos 10.14, iOS 12, tvOS 12, watchOS 5, *)
267330f729Sjoerg namespace {
LogCreator()277330f729Sjoerg os_log_t *LogCreator() {
287330f729Sjoerg os_log_t *X = new os_log_t;
297330f729Sjoerg *X = os_log_create("org.llvm.signposts", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
307330f729Sjoerg return X;
317330f729Sjoerg }
32*82d56013Sjoerg struct LogDeleter {
operator ()__anon0a2b4bb10111::LogDeleter33*82d56013Sjoerg void operator()(os_log_t *X) const {
347330f729Sjoerg os_release(*X);
357330f729Sjoerg delete X;
367330f729Sjoerg }
37*82d56013Sjoerg };
387330f729Sjoerg } // end anonymous namespace
397330f729Sjoerg
407330f729Sjoerg namespace llvm {
417330f729Sjoerg class SignpostEmitterImpl {
42*82d56013Sjoerg using LogPtrTy = std::unique_ptr<os_log_t, LogDeleter>;
437330f729Sjoerg using LogTy = LogPtrTy::element_type;
447330f729Sjoerg
457330f729Sjoerg LogPtrTy SignpostLog;
46*82d56013Sjoerg DenseMap<const void *, os_signpost_id_t> Signposts;
47*82d56013Sjoerg sys::SmartMutex<true> Mutex;
487330f729Sjoerg
getLogger() const497330f729Sjoerg LogTy &getLogger() const { return *SignpostLog; }
getSignpostForObject(const void * O)50*82d56013Sjoerg os_signpost_id_t getSignpostForObject(const void *O) {
51*82d56013Sjoerg sys::SmartScopedLock<true> Lock(Mutex);
52*82d56013Sjoerg const auto &I = Signposts.find(O);
537330f729Sjoerg if (I != Signposts.end())
547330f729Sjoerg return I->second;
55*82d56013Sjoerg os_signpost_id_t ID = {};
56*82d56013Sjoerg if (SIGNPOSTS_AVAILABLE()) {
57*82d56013Sjoerg ID = os_signpost_id_make_with_pointer(getLogger(), O);
58*82d56013Sjoerg }
59*82d56013Sjoerg const auto &Inserted = Signposts.insert(std::make_pair(O, ID));
607330f729Sjoerg return Inserted.first->second;
617330f729Sjoerg }
627330f729Sjoerg
637330f729Sjoerg public:
SignpostEmitterImpl()64*82d56013Sjoerg SignpostEmitterImpl() : SignpostLog(LogCreator()) {}
657330f729Sjoerg
isEnabled() const66*82d56013Sjoerg bool isEnabled() const {
67*82d56013Sjoerg if (SIGNPOSTS_AVAILABLE())
68*82d56013Sjoerg return os_signpost_enabled(*SignpostLog);
69*82d56013Sjoerg return false;
70*82d56013Sjoerg }
717330f729Sjoerg
startInterval(const void * O,llvm::StringRef Name)72*82d56013Sjoerg void startInterval(const void *O, llvm::StringRef Name) {
737330f729Sjoerg if (isEnabled()) {
74*82d56013Sjoerg if (SIGNPOSTS_AVAILABLE()) {
75*82d56013Sjoerg // Both strings used here are required to be constant literal strings.
76*82d56013Sjoerg os_signpost_interval_begin(getLogger(), getSignpostForObject(O),
77*82d56013Sjoerg "LLVM Timers", "Begin %s", Name.data());
78*82d56013Sjoerg }
797330f729Sjoerg }
807330f729Sjoerg }
817330f729Sjoerg
endInterval(const void * O,llvm::StringRef Name)82*82d56013Sjoerg void endInterval(const void *O, llvm::StringRef Name) {
837330f729Sjoerg if (isEnabled()) {
84*82d56013Sjoerg if (SIGNPOSTS_AVAILABLE()) {
85*82d56013Sjoerg // Both strings used here are required to be constant literal strings.
86*82d56013Sjoerg os_signpost_interval_end(getLogger(), getSignpostForObject(O),
87*82d56013Sjoerg "LLVM Timers", "End %s", Name.data());
88*82d56013Sjoerg }
897330f729Sjoerg }
907330f729Sjoerg }
917330f729Sjoerg };
927330f729Sjoerg } // end namespace llvm
93*82d56013Sjoerg #else
94*82d56013Sjoerg /// Definition necessary for use of std::unique_ptr in SignpostEmitter::Impl.
95*82d56013Sjoerg class llvm::SignpostEmitterImpl {};
967330f729Sjoerg #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
977330f729Sjoerg
987330f729Sjoerg #if LLVM_SUPPORT_XCODE_SIGNPOSTS
997330f729Sjoerg #define HAVE_ANY_SIGNPOST_IMPL 1
1007330f729Sjoerg #else
1017330f729Sjoerg #define HAVE_ANY_SIGNPOST_IMPL 0
1027330f729Sjoerg #endif
1037330f729Sjoerg
SignpostEmitter()1047330f729Sjoerg SignpostEmitter::SignpostEmitter() {
1057330f729Sjoerg #if HAVE_ANY_SIGNPOST_IMPL
106*82d56013Sjoerg Impl = std::make_unique<SignpostEmitterImpl>();
1077330f729Sjoerg #endif // if !HAVE_ANY_SIGNPOST_IMPL
1087330f729Sjoerg }
1097330f729Sjoerg
110*82d56013Sjoerg SignpostEmitter::~SignpostEmitter() = default;
1117330f729Sjoerg
isEnabled() const1127330f729Sjoerg bool SignpostEmitter::isEnabled() const {
1137330f729Sjoerg #if HAVE_ANY_SIGNPOST_IMPL
1147330f729Sjoerg return Impl->isEnabled();
1157330f729Sjoerg #else
1167330f729Sjoerg return false;
1177330f729Sjoerg #endif // if !HAVE_ANY_SIGNPOST_IMPL
1187330f729Sjoerg }
1197330f729Sjoerg
startInterval(const void * O,StringRef Name)120*82d56013Sjoerg void SignpostEmitter::startInterval(const void *O, StringRef Name) {
1217330f729Sjoerg #if HAVE_ANY_SIGNPOST_IMPL
1227330f729Sjoerg if (Impl == nullptr)
1237330f729Sjoerg return;
124*82d56013Sjoerg return Impl->startInterval(O, Name);
1257330f729Sjoerg #endif // if !HAVE_ANY_SIGNPOST_IMPL
1267330f729Sjoerg }
1277330f729Sjoerg
endInterval(const void * O,StringRef Name)128*82d56013Sjoerg void SignpostEmitter::endInterval(const void *O, StringRef Name) {
1297330f729Sjoerg #if HAVE_ANY_SIGNPOST_IMPL
1307330f729Sjoerg if (Impl == nullptr)
1317330f729Sjoerg return;
132*82d56013Sjoerg Impl->endInterval(O, Name);
1337330f729Sjoerg #endif // if !HAVE_ANY_SIGNPOST_IMPL
1347330f729Sjoerg }
135