1e1414d17SDaniel Sanders //===-- Signposts.cpp - Interval debug annotations ------------------------===//
2e1414d17SDaniel Sanders //
3e1414d17SDaniel Sanders //                     The LLVM Compiler Infrastructure
4e1414d17SDaniel Sanders //
5e1414d17SDaniel Sanders // This file is distributed under the University of Illinois Open Source
6e1414d17SDaniel Sanders // License. See LICENSE.TXT for details.
7e1414d17SDaniel Sanders //
8e1414d17SDaniel Sanders //===----------------------------------------------------------------------===//
9e1414d17SDaniel Sanders 
10e1414d17SDaniel Sanders #include "llvm/Support/Signposts.h"
11e1414d17SDaniel Sanders #include "llvm/Support/Timer.h"
12e1414d17SDaniel Sanders 
13e1414d17SDaniel Sanders #include "llvm/Config/config.h"
14e1414d17SDaniel Sanders #if LLVM_SUPPORT_XCODE_SIGNPOSTS
15e1414d17SDaniel Sanders #include "llvm/ADT/DenseMap.h"
16e1414d17SDaniel Sanders #include <os/signpost.h>
17e1414d17SDaniel Sanders #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
18e1414d17SDaniel Sanders 
19e1414d17SDaniel Sanders using namespace llvm;
20e1414d17SDaniel Sanders 
21e1414d17SDaniel Sanders #if LLVM_SUPPORT_XCODE_SIGNPOSTS
22e1414d17SDaniel Sanders namespace {
23e1414d17SDaniel Sanders os_log_t *LogCreator() {
24e1414d17SDaniel Sanders   os_log_t *X = new os_log_t;
25e1414d17SDaniel Sanders   *X = os_log_create("org.llvm.signposts", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
26e1414d17SDaniel Sanders   return X;
27e1414d17SDaniel Sanders }
28e1414d17SDaniel Sanders void LogDeleter(os_log_t *X) {
29e1414d17SDaniel Sanders   os_release(*X);
30e1414d17SDaniel Sanders   delete X;
31e1414d17SDaniel Sanders }
32e1414d17SDaniel Sanders } // end anonymous namespace
33e1414d17SDaniel Sanders 
34e1414d17SDaniel Sanders namespace llvm {
35e1414d17SDaniel Sanders class SignpostEmitterImpl {
36*b37de2afSJonas Devlieghere   using LogPtrTy = std::unique_ptr<os_log_t, std::function<void(os_log_t *)>>;
37e1414d17SDaniel Sanders   using LogTy = LogPtrTy::element_type;
38e1414d17SDaniel Sanders 
39e1414d17SDaniel Sanders   LogPtrTy SignpostLog;
40*b37de2afSJonas Devlieghere   DenseMap<const void *, os_signpost_id_t> Signposts;
41e1414d17SDaniel Sanders 
42e1414d17SDaniel Sanders   LogTy &getLogger() const { return *SignpostLog; }
43*b37de2afSJonas Devlieghere   os_signpost_id_t getSignpostForObject(const void *O) {
44*b37de2afSJonas Devlieghere     const auto &I = Signposts.find(O);
45e1414d17SDaniel Sanders     if (I != Signposts.end())
46e1414d17SDaniel Sanders       return I->second;
47e1414d17SDaniel Sanders 
48e1414d17SDaniel Sanders     const auto &Inserted = Signposts.insert(
49*b37de2afSJonas Devlieghere         std::make_pair(O, os_signpost_id_make_with_pointer(getLogger(), O)));
50e1414d17SDaniel Sanders     return Inserted.first->second;
51e1414d17SDaniel Sanders   }
52e1414d17SDaniel Sanders 
53e1414d17SDaniel Sanders public:
54e1414d17SDaniel Sanders   SignpostEmitterImpl() : SignpostLog(LogCreator(), LogDeleter), Signposts() {}
55e1414d17SDaniel Sanders 
56e1414d17SDaniel Sanders   bool isEnabled() const { return os_signpost_enabled(*SignpostLog); }
57e1414d17SDaniel Sanders 
58*b37de2afSJonas Devlieghere   void startInterval(const void *O, llvm::StringRef Name) {
59e1414d17SDaniel Sanders     if (isEnabled()) {
60*b37de2afSJonas Devlieghere       // Both strings used here are required to be constant literal strings.
61*b37de2afSJonas Devlieghere       os_signpost_interval_begin(getLogger(), getSignpostForObject(O),
62*b37de2afSJonas Devlieghere                                  "LLVM Timers", "Begin %s", Name.data());
63e1414d17SDaniel Sanders     }
64e1414d17SDaniel Sanders   }
65e1414d17SDaniel Sanders 
66*b37de2afSJonas Devlieghere   void endInterval(const void *O, llvm::StringRef Name) {
67e1414d17SDaniel Sanders     if (isEnabled()) {
68*b37de2afSJonas Devlieghere       // Both strings used here are required to be constant literal strings.
69*b37de2afSJonas Devlieghere       os_signpost_interval_end(getLogger(), getSignpostForObject(O),
70*b37de2afSJonas Devlieghere                                "LLVM Timers", "End %s", Name.data());
71e1414d17SDaniel Sanders     }
72e1414d17SDaniel Sanders   }
73e1414d17SDaniel Sanders };
74e1414d17SDaniel Sanders } // end namespace llvm
75e1414d17SDaniel Sanders #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
76e1414d17SDaniel Sanders 
77e1414d17SDaniel Sanders #if LLVM_SUPPORT_XCODE_SIGNPOSTS
78e1414d17SDaniel Sanders #define HAVE_ANY_SIGNPOST_IMPL 1
790096d193SSven van Haastregt #else
800096d193SSven van Haastregt #define HAVE_ANY_SIGNPOST_IMPL 0
81e1414d17SDaniel Sanders #endif
82e1414d17SDaniel Sanders 
83e1414d17SDaniel Sanders SignpostEmitter::SignpostEmitter() {
84e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL
85e1414d17SDaniel Sanders   Impl = new SignpostEmitterImpl();
86e1414d17SDaniel Sanders #else  // if HAVE_ANY_SIGNPOST_IMPL
87e1414d17SDaniel Sanders   Impl = nullptr;
88e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL
89e1414d17SDaniel Sanders }
90e1414d17SDaniel Sanders 
91e1414d17SDaniel Sanders SignpostEmitter::~SignpostEmitter() {
92e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL
93e1414d17SDaniel Sanders   delete Impl;
94e1414d17SDaniel Sanders #endif // if HAVE_ANY_SIGNPOST_IMPL
95e1414d17SDaniel Sanders }
96e1414d17SDaniel Sanders 
97e1414d17SDaniel Sanders bool SignpostEmitter::isEnabled() const {
98e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL
99e1414d17SDaniel Sanders   return Impl->isEnabled();
100e1414d17SDaniel Sanders #else
101e1414d17SDaniel Sanders   return false;
102e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL
103e1414d17SDaniel Sanders }
104e1414d17SDaniel Sanders 
105*b37de2afSJonas Devlieghere void SignpostEmitter::startInterval(const void *O, StringRef Name) {
106e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL
107e1414d17SDaniel Sanders   if (Impl == nullptr)
108e1414d17SDaniel Sanders     return;
109*b37de2afSJonas Devlieghere   return Impl->startInterval(O, Name);
110e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL
111e1414d17SDaniel Sanders }
112e1414d17SDaniel Sanders 
113*b37de2afSJonas Devlieghere void SignpostEmitter::endInterval(const void *O, StringRef Name) {
114e1414d17SDaniel Sanders #if HAVE_ANY_SIGNPOST_IMPL
115e1414d17SDaniel Sanders   if (Impl == nullptr)
116e1414d17SDaniel Sanders     return;
117*b37de2afSJonas Devlieghere   Impl->endInterval(O, Name);
118e1414d17SDaniel Sanders #endif // if !HAVE_ANY_SIGNPOST_IMPL
119e1414d17SDaniel Sanders }
120