10b57cec5SDimitry Andric //===-- Signposts.cpp - Interval debug annotations ------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // The LLVM Compiler Infrastructure
40b57cec5SDimitry Andric //
50b57cec5SDimitry Andric // This file is distributed under the University of Illinois Open Source
60b57cec5SDimitry Andric // License. See LICENSE.TXT for details.
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric #include "llvm/Support/Signposts.h"
110b57cec5SDimitry Andric #include "llvm/Support/Timer.h"
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #if LLVM_SUPPORT_XCODE_SIGNPOSTS
140b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
15af732203SDimitry Andric #include "llvm/Support/Mutex.h"
16*5f7ddb14SDimitry Andric #endif
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric #if LLVM_SUPPORT_XCODE_SIGNPOSTS
210b57cec5SDimitry Andric namespace {
LogCreator()220b57cec5SDimitry Andric os_log_t *LogCreator() {
230b57cec5SDimitry Andric os_log_t *X = new os_log_t;
240b57cec5SDimitry Andric *X = os_log_create("org.llvm.signposts", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
250b57cec5SDimitry Andric return X;
260b57cec5SDimitry Andric }
27*5f7ddb14SDimitry Andric struct LogDeleter {
operator ()__anon4452ca3a0111::LogDeleter28*5f7ddb14SDimitry Andric void operator()(os_log_t *X) const {
290b57cec5SDimitry Andric os_release(*X);
300b57cec5SDimitry Andric delete X;
310b57cec5SDimitry Andric }
32*5f7ddb14SDimitry Andric };
330b57cec5SDimitry Andric } // end anonymous namespace
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric namespace llvm {
360b57cec5SDimitry Andric class SignpostEmitterImpl {
37*5f7ddb14SDimitry Andric using LogPtrTy = std::unique_ptr<os_log_t, LogDeleter>;
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric LogPtrTy SignpostLog;
40af732203SDimitry Andric DenseMap<const void *, os_signpost_id_t> Signposts;
41af732203SDimitry Andric sys::SmartMutex<true> Mutex;
420b57cec5SDimitry Andric
43*5f7ddb14SDimitry Andric public:
getLogger() const44*5f7ddb14SDimitry Andric os_log_t &getLogger() const { return *SignpostLog; }
getSignpostForObject(const void * O)45af732203SDimitry Andric os_signpost_id_t getSignpostForObject(const void *O) {
46af732203SDimitry Andric sys::SmartScopedLock<true> Lock(Mutex);
47af732203SDimitry Andric const auto &I = Signposts.find(O);
480b57cec5SDimitry Andric if (I != Signposts.end())
490b57cec5SDimitry Andric return I->second;
50*5f7ddb14SDimitry Andric os_signpost_id_t ID = {};
51*5f7ddb14SDimitry Andric if (SIGNPOSTS_AVAILABLE()) {
52*5f7ddb14SDimitry Andric ID = os_signpost_id_make_with_pointer(getLogger(), O);
53*5f7ddb14SDimitry Andric }
54*5f7ddb14SDimitry Andric const auto &Inserted = Signposts.insert(std::make_pair(O, ID));
550b57cec5SDimitry Andric return Inserted.first->second;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
SignpostEmitterImpl()58*5f7ddb14SDimitry Andric SignpostEmitterImpl() : SignpostLog(LogCreator()) {}
590b57cec5SDimitry Andric
isEnabled() const60*5f7ddb14SDimitry Andric bool isEnabled() const {
61*5f7ddb14SDimitry Andric if (SIGNPOSTS_AVAILABLE())
62*5f7ddb14SDimitry Andric return os_signpost_enabled(*SignpostLog);
63*5f7ddb14SDimitry Andric return false;
64*5f7ddb14SDimitry Andric }
650b57cec5SDimitry Andric
startInterval(const void * O,llvm::StringRef Name)66af732203SDimitry Andric void startInterval(const void *O, llvm::StringRef Name) {
670b57cec5SDimitry Andric if (isEnabled()) {
68*5f7ddb14SDimitry Andric if (SIGNPOSTS_AVAILABLE()) {
69af732203SDimitry Andric // Both strings used here are required to be constant literal strings.
70af732203SDimitry Andric os_signpost_interval_begin(getLogger(), getSignpostForObject(O),
71*5f7ddb14SDimitry Andric "LLVM Timers", "%s", Name.data());
72*5f7ddb14SDimitry Andric }
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
endInterval(const void * O)76*5f7ddb14SDimitry Andric void endInterval(const void *O) {
770b57cec5SDimitry Andric if (isEnabled()) {
78*5f7ddb14SDimitry Andric if (SIGNPOSTS_AVAILABLE()) {
79af732203SDimitry Andric // Both strings used here are required to be constant literal strings.
80af732203SDimitry Andric os_signpost_interval_end(getLogger(), getSignpostForObject(O),
81*5f7ddb14SDimitry Andric "LLVM Timers", "");
82*5f7ddb14SDimitry Andric }
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric };
860b57cec5SDimitry Andric } // end namespace llvm
87*5f7ddb14SDimitry Andric #else
88*5f7ddb14SDimitry Andric /// Definition necessary for use of std::unique_ptr in SignpostEmitter::Impl.
89*5f7ddb14SDimitry Andric class llvm::SignpostEmitterImpl {};
900b57cec5SDimitry Andric #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric #if LLVM_SUPPORT_XCODE_SIGNPOSTS
930b57cec5SDimitry Andric #define HAVE_ANY_SIGNPOST_IMPL 1
948bcb0991SDimitry Andric #else
958bcb0991SDimitry Andric #define HAVE_ANY_SIGNPOST_IMPL 0
960b57cec5SDimitry Andric #endif
970b57cec5SDimitry Andric
SignpostEmitter()980b57cec5SDimitry Andric SignpostEmitter::SignpostEmitter() {
990b57cec5SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
100*5f7ddb14SDimitry Andric Impl = std::make_unique<SignpostEmitterImpl>();
1010b57cec5SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
104*5f7ddb14SDimitry Andric SignpostEmitter::~SignpostEmitter() = default;
1050b57cec5SDimitry Andric
isEnabled() const1060b57cec5SDimitry Andric bool SignpostEmitter::isEnabled() const {
1070b57cec5SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
1080b57cec5SDimitry Andric return Impl->isEnabled();
1090b57cec5SDimitry Andric #else
1100b57cec5SDimitry Andric return false;
1110b57cec5SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
startInterval(const void * O,StringRef Name)114af732203SDimitry Andric void SignpostEmitter::startInterval(const void *O, StringRef Name) {
1150b57cec5SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
1160b57cec5SDimitry Andric if (Impl == nullptr)
1170b57cec5SDimitry Andric return;
118af732203SDimitry Andric return Impl->startInterval(O, Name);
1190b57cec5SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric
122*5f7ddb14SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
getLogger() const123*5f7ddb14SDimitry Andric os_log_t &SignpostEmitter::getLogger() const { return Impl->getLogger(); }
getSignpostForObject(const void * O)124*5f7ddb14SDimitry Andric os_signpost_id_t SignpostEmitter::getSignpostForObject(const void *O) {
125*5f7ddb14SDimitry Andric return Impl->getSignpostForObject(O);
126*5f7ddb14SDimitry Andric }
127*5f7ddb14SDimitry Andric #endif
128*5f7ddb14SDimitry Andric
endInterval(const void * O)129*5f7ddb14SDimitry Andric void SignpostEmitter::endInterval(const void *O) {
1300b57cec5SDimitry Andric #if HAVE_ANY_SIGNPOST_IMPL
1310b57cec5SDimitry Andric if (Impl == nullptr)
1320b57cec5SDimitry Andric return;
133*5f7ddb14SDimitry Andric Impl->endInterval(O);
1340b57cec5SDimitry Andric #endif // if !HAVE_ANY_SIGNPOST_IMPL
1350b57cec5SDimitry Andric }
136