1/**
2 * Copyright (c) Glow Contributors. See CONTRIBUTORS file.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef GLOW_SUPPORT_LOG_H
18#define GLOW_SUPPORT_LOG_H
19
20#include "llvm/ADT/StringRef.h"
21
22#include <string>
23#include <vector>
24
25namespace llvm {
26class raw_fd_ostream;
27}
28
29namespace glow {
30
31class Module;
32class Function;
33class Node;
34
35struct NodeValue;
36
37struct LogEvent {
38 std::string name;
39 LogEvent *parent{nullptr};
40 std::vector<LogEvent *> children;
41
42 LogEvent(llvm::StringRef n) : name(n) {}
43
44 virtual ~LogEvent() {
45 for (auto *c : children) {
46 delete c;
47 }
48 }
49
50 void pushEvent(LogEvent *e) {
51 e->parent = this;
52 children.push_back(e);
53 }
54
55 /// writes this Event and all children to the provided stream.
56 /// \returns true if anything was written.
57 virtual bool dump(llvm::raw_fd_ostream &ostream);
58
59 virtual bool dumpChildren(llvm::raw_fd_ostream &ostream);
60
61 /// \returns true if this even will not log to the stream.
62 virtual bool silent() { return false; }
63
64 virtual LogEvent *clone();
65};
66
67// A special LogEvent for Scope enclosing events.
68struct LogScope : public LogEvent {
69 LogScope(llvm::StringRef name) : LogEvent(name) {}
70 virtual ~LogScope(){};
71 bool dump(llvm::raw_fd_ostream &ostream) override;
72 bool silent() override;
73 LogEvent *clone() override;
74};
75
76struct LogCreate : public LogEvent {
77 std::string kindName;
78 std::vector<std::string> inputs;
79
80 LogCreate(const Node *node);
81 LogCreate(llvm::StringRef n, llvm::StringRef k, std::vector<std::string> &i);
82 virtual ~LogCreate(){};
83
84 bool dump(llvm::raw_fd_ostream &ostream) override;
85 LogEvent *clone() override;
86};
87
88struct LogDelete : public LogEvent {
89 std::string kindName;
90
91 LogDelete(const Node *node);
92 LogDelete(llvm::StringRef n, llvm::StringRef k);
93 virtual ~LogDelete(){};
94
95 bool dump(llvm::raw_fd_ostream &ostream) override;
96 LogEvent *clone() override;
97};
98
99struct LogInputChange : public LogEvent {
100 std::string kindName;
101 std::string beforeName;
102 std::string afterName;
103
104 LogInputChange(const Node *user, const NodeValue &before,
105 const NodeValue &after);
106 LogInputChange(llvm::StringRef n, llvm::StringRef k, llvm::StringRef b,
107 llvm::StringRef a);
108
109 bool dump(llvm::raw_fd_ostream &ostream) override;
110 LogEvent *clone() override;
111};
112
113/// A class for logging all compilation related activities.
114class LogContext final {
115private:
116 LogScope topScope_{"Init"};
117 LogEvent *currentScope_{nullptr};
118 Module *parent_;
119
120public:
121 LogContext(Module *parent);
122
123 /// Add a new event to the log.
124 void pushEvent(LogEvent *ev);
125
126 /// Add a new scope.
127 void pushLogScope(llvm::StringRef scopeName);
128
129 /// Pops out the most recently added scope.
130 void popLogScope();
131
132 /// Dumps the log in JSON format into the logfile (configured by command line
133 /// option). /p funcName currently unused.
134 void dumpLog(llvm::StringRef funcName);
135
136 /// Logs the node creation. Also logs into Module log context if \p
137 /// logIntoModule set as true.
138 void logNodeCreation(const Node &newNode, bool logIntoModule = false);
139
140 /// Logs the node deletion. Also logs into Module log context if \p
141 /// logIntoModule set as true.
142 void logNodeDeletion(const Node &deletedNode, bool logIntoModule = false);
143
144 /// Logs node's input changes.
145 /// \p user is the user node of the operands
146 /// \p prevOpr previous operand
147 /// \p newOpr new operand
148 void logNodeInputChange(const Node &user, const NodeValue &prevOprVal,
149 const NodeValue &newOprVal);
150
151 /// Get a deep cloned copy of the top level scope of this LogContext.
152 LogEvent *getClonedScope();
153};
154
155/// Logs a new log scope.
156#define LOG_SCOPE(ctx, name) ScopedLogBlock __scope__(ctx, name);
157
158/// Helper class which traces the start and end of a compilation log scope.
159class ScopedLogBlock {
160
161 /// Reference to the log context.
162 std::shared_ptr<LogContext> ctx_;
163
164 /// The name of the log scope.
165 std::string name_;
166
167 /// Whether this log scope has already ended, avoiding logging
168 /// it twice.
169 bool end_{false};
170
171public:
172 ScopedLogBlock(std::shared_ptr<LogContext> ctx, llvm::StringRef name);
173 ~ScopedLogBlock();
174
175private:
176 /// Triggers the endding operation of the current log scope.
177 void end();
178};
179
180} // namespace glow.
181
182#endif // GLOW_SUPPORT_LOG_H
183