[AArch64] Fix SDNode type mismatches between *.td files and ISel (#116523)
[llvm-project.git] / compiler-rt / lib / nsan / nsan_stats.cpp
blob49041a76dfb2d5701b7e57231068172bd0c0f1ef
1 //===-- nsan_stats.cc -----------------------------------------------------===//
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 // This file is a part of NumericalStabilitySanitizer.
11 // NumericalStabilitySanitizer statistics.
12 //===----------------------------------------------------------------------===//
14 #include "nsan_stats.h"
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "sanitizer_common/sanitizer_placement_new.h"
18 #include "sanitizer_common/sanitizer_stackdepot.h"
19 #include "sanitizer_common/sanitizer_stacktrace.h"
20 #include "sanitizer_common/sanitizer_symbolizer.h"
22 #include <assert.h>
23 #include <stdio.h>
25 using namespace __sanitizer;
26 using namespace __nsan;
28 Stats::Stats() {
29 check_and_warnings.Initialize(0);
30 TrackedLoads.Initialize(0);
33 Stats::~Stats() { Printf("deleting nsan stats\n"); }
35 static uptr Key(CheckTypeT CheckType, u32 StackId) {
36 return static_cast<uptr>(CheckType) +
37 StackId * static_cast<uptr>(CheckTypeT::kMaxCheckType);
40 template <typename MapT, typename VectorT, typename Fn>
41 static void UpdateEntry(CheckTypeT check_ty, uptr pc, uptr bp, MapT *map,
42 VectorT *vector, Mutex *mutex, Fn F) {
43 BufferedStackTrace Stack;
44 Stack.Unwind(pc, bp, nullptr, false);
45 u32 stack_id = StackDepotPut(Stack);
46 typename MapT::Handle Handle(map, Key(check_ty, stack_id));
47 Lock L(mutex);
48 if (Handle.created()) {
49 typename VectorT::value_type entry;
50 entry.stack_id = stack_id;
51 entry.check_ty = check_ty;
52 F(entry);
53 vector->push_back(entry);
54 } else {
55 auto &entry = (*vector)[*Handle];
56 F(entry);
60 void Stats::AddCheck(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {
61 UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,
62 &check_and_warning_mutex,
63 [rel_err](CheckAndWarningsValue &entry) {
64 ++entry.num_checks;
65 if (rel_err > entry.max_relative_err) {
66 entry.max_relative_err = rel_err;
68 });
71 void Stats::AddWarning(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {
72 UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,
73 &check_and_warning_mutex,
74 [rel_err](CheckAndWarningsValue &entry) {
75 ++entry.num_warnings;
76 if (rel_err > entry.max_relative_err) {
77 entry.max_relative_err = rel_err;
79 });
82 void Stats::AddInvalidLoadTrackingEvent(uptr pc, uptr bp) {
83 UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,
84 &TrackedLoadsMutex,
85 [](LoadTrackingValue &entry) { ++entry.num_invalid; });
88 void Stats::AddUnknownLoadTrackingEvent(uptr pc, uptr bp) {
89 UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,
90 &TrackedLoadsMutex,
91 [](LoadTrackingValue &entry) { ++entry.num_unknown; });
94 static const char *CheckTypeDisplay(CheckTypeT CheckType) {
95 switch (CheckType) {
96 case CheckTypeT::kUnknown:
97 return "unknown";
98 case CheckTypeT::kRet:
99 return "return";
100 case CheckTypeT::kArg:
101 return "argument";
102 case CheckTypeT::kLoad:
103 return "load";
104 case CheckTypeT::kStore:
105 return "store";
106 case CheckTypeT::kInsert:
107 return "vector insert";
108 case CheckTypeT::kUser:
109 return "user-initiated";
110 case CheckTypeT::kFcmp:
111 return "fcmp";
112 case CheckTypeT::kMaxCheckType:
113 return "[max]";
115 assert(false && "unknown CheckType case");
116 return "";
119 void Stats::Print() const {
121 Lock L(&check_and_warning_mutex);
122 for (const auto &entry : check_and_warnings) {
123 Printf("warned %llu times out of %llu %s checks ", entry.num_warnings,
124 entry.num_checks, CheckTypeDisplay(entry.check_ty));
125 if (entry.num_warnings > 0) {
126 char RelErrBuf[64];
127 snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%f",
128 entry.max_relative_err * 100.0);
129 Printf("(max relative error: %s%%) ", RelErrBuf);
131 Printf("at:\n");
132 StackDepotGet(entry.stack_id).Print();
137 Lock L(&TrackedLoadsMutex);
138 u64 TotalInvalidLoadTracking = 0;
139 u64 TotalUnknownLoadTracking = 0;
140 for (const auto &entry : TrackedLoads) {
141 TotalInvalidLoadTracking += entry.num_invalid;
142 TotalUnknownLoadTracking += entry.num_unknown;
143 Printf("invalid/unknown type for %llu/%llu loads at:\n",
144 entry.num_invalid, entry.num_unknown);
145 StackDepotGet(entry.stack_id).Print();
147 Printf(
148 "There were %llu/%llu floating-point loads where the shadow type was "
149 "invalid/unknown.\n",
150 TotalInvalidLoadTracking, TotalUnknownLoadTracking);
154 alignas(64) static char stats_placeholder[sizeof(Stats)];
155 Stats *__nsan::nsan_stats = nullptr;
157 void __nsan::InitializeStats() { nsan_stats = new (stats_placeholder) Stats(); }