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 | |