1280461Sdim//===- include/Core/Instrumentation.h - Instrumentation API ---------------===//
2280461Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6280461Sdim//
7280461Sdim//===----------------------------------------------------------------------===//
8280461Sdim///
9280461Sdim/// \file
10341825Sdim/// Provide an Instrumentation API that optionally uses VTune interfaces.
11280461Sdim///
12280461Sdim//===----------------------------------------------------------------------===//
13280461Sdim
14280461Sdim#ifndef LLD_CORE_INSTRUMENTATION_H
15280461Sdim#define LLD_CORE_INSTRUMENTATION_H
16280461Sdim
17280461Sdim#include "llvm/Support/Compiler.h"
18280461Sdim#include <utility>
19280461Sdim
20280461Sdim#ifdef LLD_HAS_VTUNE
21280461Sdim# include <ittnotify.h>
22280461Sdim#endif
23280461Sdim
24280461Sdimnamespace lld {
25280461Sdim#ifdef LLD_HAS_VTUNE
26341825Sdim/// A unique global scope for instrumentation data.
27280461Sdim///
28280461Sdim/// Domains last for the lifetime of the application and cannot be destroyed.
29280461Sdim/// Multiple Domains created with the same name represent the same domain.
30280461Sdimclass Domain {
31280461Sdim  __itt_domain *_domain;
32280461Sdim
33280461Sdimpublic:
34280461Sdim  explicit Domain(const char *name) : _domain(__itt_domain_createA(name)) {}
35280461Sdim
36280461Sdim  operator __itt_domain *() const { return _domain; }
37280461Sdim  __itt_domain *operator->() const { return _domain; }
38280461Sdim};
39280461Sdim
40341825Sdim/// A global reference to a string constant.
41280461Sdim///
42280461Sdim/// These are uniqued by the ITT runtime and cannot be deleted. They are not
43280461Sdim/// specific to a domain.
44280461Sdim///
45280461Sdim/// Prefer reusing a single StringHandle over passing a ntbs when the same
46280461Sdim/// string will be used often.
47280461Sdimclass StringHandle {
48280461Sdim  __itt_string_handle *_handle;
49280461Sdim
50280461Sdimpublic:
51280461Sdim  StringHandle(const char *name) : _handle(__itt_string_handle_createA(name)) {}
52280461Sdim
53280461Sdim  operator __itt_string_handle *() const { return _handle; }
54280461Sdim};
55280461Sdim
56341825Sdim/// A task on a single thread. Nests within other tasks.
57280461Sdim///
58280461Sdim/// Each thread has its own task stack and tasks nest recursively on that stack.
59280461Sdim/// A task cannot transfer threads.
60280461Sdim///
61360784Sdim/// SBRM is used to ensure task starts and ends are balanced. The lifetime of
62280461Sdim/// a task is either the lifetime of this object, or until end is called.
63280461Sdimclass ScopedTask {
64280461Sdim  __itt_domain *_domain;
65280461Sdim
66280461Sdim  ScopedTask(const ScopedTask &) = delete;
67280461Sdim  ScopedTask &operator=(const ScopedTask &) = delete;
68280461Sdim
69280461Sdimpublic:
70341825Sdim  /// Create a task in Domain \p d named \p s.
71280461Sdim  ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) {
72280461Sdim    __itt_task_begin(d, __itt_null, __itt_null, s);
73280461Sdim  }
74280461Sdim
75280461Sdim  ScopedTask(ScopedTask &&other) {
76280461Sdim    *this = std::move(other);
77280461Sdim  }
78280461Sdim
79280461Sdim  ScopedTask &operator=(ScopedTask &&other) {
80280461Sdim    _domain = other._domain;
81280461Sdim    other._domain = nullptr;
82280461Sdim    return *this;
83280461Sdim  }
84280461Sdim
85341825Sdim  /// Prematurely end this task.
86280461Sdim  void end() {
87280461Sdim    if (_domain)
88280461Sdim      __itt_task_end(_domain);
89280461Sdim    _domain = nullptr;
90280461Sdim  }
91280461Sdim
92280461Sdim  ~ScopedTask() { end(); }
93280461Sdim};
94280461Sdim
95341825Sdim/// A specific point in time. Allows metadata to be associated.
96280461Sdimclass Marker {
97280461Sdimpublic:
98280461Sdim  Marker(const Domain &d, const StringHandle &s) {
99280461Sdim    __itt_marker(d, __itt_null, s, __itt_scope_global);
100280461Sdim  }
101280461Sdim};
102280461Sdim#else
103280461Sdimclass Domain {
104280461Sdimpublic:
105280461Sdim  Domain(const char *name) {}
106280461Sdim};
107280461Sdim
108280461Sdimclass StringHandle {
109280461Sdimpublic:
110280461Sdim  StringHandle(const char *name) {}
111280461Sdim};
112280461Sdim
113280461Sdimclass ScopedTask {
114280461Sdimpublic:
115280461Sdim  ScopedTask(const Domain &d, const StringHandle &s) {}
116280461Sdim  void end() {}
117280461Sdim};
118280461Sdim
119280461Sdimclass Marker {
120280461Sdimpublic:
121280461Sdim  Marker(const Domain &d, const StringHandle &s) {}
122280461Sdim};
123280461Sdim#endif
124280461Sdim
125280461Sdiminline const Domain &getDefaultDomain() {
126280461Sdim  static Domain domain("org.llvm.lld");
127280461Sdim  return domain;
128280461Sdim}
129280461Sdim} // end namespace lld.
130280461Sdim
131280461Sdim#endif
132