Skip to content

Commit

Permalink
Contribute DiagnosticCountInPassHook
Browse files Browse the repository at this point in the history
  • Loading branch information
vlstill committed Apr 18, 2024
1 parent 6643d68 commit 90e367d
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set (IR_SRCS
json_parser.cpp
node.cpp
pass_manager.cpp
pass_utils.cpp
type.cpp
v1.cpp
visitor.cpp
Expand All @@ -50,6 +51,7 @@ set (IR_HDRS
node.h
nodemap.h
pass_manager.h
pass_utils.h
vector.h
visitor.h
)
Expand Down
64 changes: 64 additions & 0 deletions ir/pass_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "ir/pass_utils.h"

#include <initializer_list>
#include <tuple>

#include "lib/log.h"

/// @file
/// @authors Vladimír Štill
/// @brief Utilities for passes and pass managers.

namespace P4 {

// The state needs to be shared between all hook copies as the hook is copied in the pass manager.
struct DiagnosticCountInPassHookState {
explicit DiagnosticCountInPassHookState(BaseCompileContext &ctxt)
: lastDiagCount(ctxt.errorReporter().getDiagnosticCount()),
lastErrorCount(ctxt.errorReporter().getErrorCount()),
lastWarningCount(ctxt.errorReporter().getWarningCount()),
lastInfoCount(ctxt.errorReporter().getInfoCount()) {}

unsigned lastDiagCount, lastErrorCount, lastWarningCount, lastInfoCount;
};

DebugHook getDiagnosticCountInPassHook(BaseCompileContext &ctxt) {
return [state = std::make_shared<DiagnosticCountInPassHookState>(ctxt), &ctxt](
const char *manager, unsigned seqNo, const char *pass, const IR::Node *) mutable {
unsigned diag = ctxt.errorReporter().getDiagnosticCount();

if (diag != state->lastDiagCount) {
unsigned errs = ctxt.errorReporter().getErrorCount(),
warns = ctxt.errorReporter().getWarningCount(),
infos = ctxt.errorReporter().getInfoCount();
std::stringstream summary;
const char *sep = "";
for (auto [newCnt, oldCnt, kind] :
{std::tuple(errs, state->lastErrorCount, "error"),
std::tuple(warns, state->lastWarningCount, "warning"),
std::tuple(infos, state->lastInfoCount, "info")}) {
if (newCnt > oldCnt) {
auto diff = newCnt - oldCnt;
summary << sep << diff << " " << kind << (diff > 1 ? "s" : "");
sep = ", ";
}
}

// if the log level is high enough, emit also pass count
if (Log::fileLogLevelIsAtLeast(DIAGNOSTIC_COUNT_IN_PASS_TAG, 4)) {
LOG_FEATURE(DIAGNOSTIC_COUNT_IN_PASS_TAG, 4,
"PASS " << manager << "[" << seqNo << "] ~> " << pass << " emitted "
<< summary.str());
} else {
LOG_FEATURE(DIAGNOSTIC_COUNT_IN_PASS_TAG, 1,
"PASS " << manager << " ~> " << pass << " emitted " << summary.str());
}
state->lastDiagCount = diag;
state->lastErrorCount = errs;
state->lastWarningCount = warns;
state->lastInfoCount = infos;
}
};
}

} // namespace P4
35 changes: 35 additions & 0 deletions ir/pass_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef IR_PASS_UTILS_H_
#define IR_PASS_UTILS_H_

#include "ir/pass_manager.h"
#include "lib/compile_context.h"

/// @file
/// @authors Vladimír Štill
/// @brief Utilities for passes and pass managers.

namespace P4 {

inline const char *DIAGNOSTIC_COUNT_IN_PASS_TAG = "diagnosticCountInPass";

/// @brief This creates a debug hook that prints information about the number of diagnostics of
/// different levels (error, warning, info) printed by each of the pass after it ended. This is
/// intended to help in debuggig and testing.
///
/// NOTE: You either need to create one pass and use its copies in all the pass managers in the
/// compilation, or create each of the following hooks only after the previous compilations teps had
/// already run. Otherwise, you can get spurious logs for a first pass of a pass manager running
/// after some diagnostics were emitted.
///
/// It logs the messages if the log level for "diagnosticCountInPass" is at least 1. If the log
/// level is at least 4, the logs also include the sequence number of the pass that printed the
/// message in the pass manager.
///
/// @param ctxt Optionally, you can provide a compilation context to take the diagnostic counts
/// from. If not provied BaseCompileContext::get() is used.
/// @return A debug hook suitable for using in pass managers.
DebugHook getDiagnosticCountInPassHook(BaseCompileContext &ctxt = BaseCompileContext::get());

}; // namespace P4

#endif // IR_PASS_UTILS_H_

0 comments on commit 90e367d

Please sign in to comment.