1//===- include/Core/Instrumentation.h - Instrumentation API ---------------===//
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/// \file
10/// Provide an Instrumentation API that optionally uses VTune interfaces.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLD_CORE_INSTRUMENTATION_H
15#define LLD_CORE_INSTRUMENTATION_H
16
17#include "llvm/Support/Compiler.h"
18#include <utility>
19
20#ifdef LLD_HAS_VTUNE
21# include <ittnotify.h>
22#endif
23
24namespace lld {
25#ifdef LLD_HAS_VTUNE
26/// A unique global scope for instrumentation data.
27///
28/// Domains last for the lifetime of the application and cannot be destroyed.
29/// Multiple Domains created with the same name represent the same domain.
30class Domain {
31  __itt_domain *_domain;
32
33public:
34  explicit Domain(const char *name) : _domain(__itt_domain_createA(name)) {}
35
36  operator __itt_domain *() const { return _domain; }
37  __itt_domain *operator->() const { return _domain; }
38};
39
40/// A global reference to a string constant.
41///
42/// These are uniqued by the ITT runtime and cannot be deleted. They are not
43/// specific to a domain.
44///
45/// Prefer reusing a single StringHandle over passing a ntbs when the same
46/// string will be used often.
47class StringHandle {
48  __itt_string_handle *_handle;
49
50public:
51  StringHandle(const char *name) : _handle(__itt_string_handle_createA(name)) {}
52
53  operator __itt_string_handle *() const { return _handle; }
54};
55
56/// A task on a single thread. Nests within other tasks.
57///
58/// Each thread has its own task stack and tasks nest recursively on that stack.
59/// A task cannot transfer threads.
60///
61/// SBRM is used to ensure task starts and ends are balanced. The lifetime of
62/// a task is either the lifetime of this object, or until end is called.
63class ScopedTask {
64  __itt_domain *_domain;
65
66  ScopedTask(const ScopedTask &) = delete;
67  ScopedTask &operator=(const ScopedTask &) = delete;
68
69public:
70  /// Create a task in Domain \p d named \p s.
71  ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) {
72    __itt_task_begin(d, __itt_null, __itt_null, s);
73  }
74
75  ScopedTask(ScopedTask &&other) {
76    *this = std::move(other);
77  }
78
79  ScopedTask &operator=(ScopedTask &&other) {
80    _domain = other._domain;
81    other._domain = nullptr;
82    return *this;
83  }
84
85  /// Prematurely end this task.
86  void end() {
87    if (_domain)
88      __itt_task_end(_domain);
89    _domain = nullptr;
90  }
91
92  ~ScopedTask() { end(); }
93};
94
95/// A specific point in time. Allows metadata to be associated.
96class Marker {
97public:
98  Marker(const Domain &d, const StringHandle &s) {
99    __itt_marker(d, __itt_null, s, __itt_scope_global);
100  }
101};
102#else
103class Domain {
104public:
105  Domain(const char *name) {}
106};
107
108class StringHandle {
109public:
110  StringHandle(const char *name) {}
111};
112
113class ScopedTask {
114public:
115  ScopedTask(const Domain &d, const StringHandle &s) {}
116  void end() {}
117};
118
119class Marker {
120public:
121  Marker(const Domain &d, const StringHandle &s) {}
122};
123#endif
124
125inline const Domain &getDefaultDomain() {
126  static Domain domain("org.llvm.lld");
127  return domain;
128}
129} // end namespace lld.
130
131#endif
132