================
@@ -0,0 +1,201 @@
+//===- EntryPointStats.cpp --------------------------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <iterator>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+struct Registry {
+  std::vector<BoolEPStat *> BoolStats;
+  std::vector<CounterEPStat *> CounterStats;
+  std::vector<UnsignedMaxEPStat *> UnsignedMaxStats;
+  std::vector<UnsignedEPStat *> UnsignedStats;
+
+  bool IsLocked = false;
+
+  struct Snapshot {
+    const Decl *EntryPoint;
+    std::vector<bool> BoolStatValues;
+    std::vector<unsigned> UnsignedStatValues;
+
+    void dumpDynamicStatsAsCSV(llvm::raw_ostream &OS) const;
+  };
+
+  std::vector<Snapshot> Snapshots;
+};
+} // namespace
+
+static llvm::ManagedStatic<Registry> StatsRegistry;
+
+namespace {
+template <typename Callback> void enumerateStatVectors(const Callback &Fn) {
+  Fn(StatsRegistry->BoolStats);
+  Fn(StatsRegistry->CounterStats);
+  Fn(StatsRegistry->UnsignedMaxStats);
+  Fn(StatsRegistry->UnsignedStats);
+}
+} // namespace
+
+static void checkStatName(const EntryPointStat *M) {
+#ifdef NDEBUG
+  return;
+#endif // NDEBUG
+  constexpr std::array AllowedSpecialChars = {
+      '+', '-', '_', '=', ':', '(',  ')', '@', '!', '~',
+      '$', '%', '^', '&', '*', '\'', ';', '<', '>', '/'};
+  for (unsigned char C : M->name()) {
+    if (!std::isalnum(C) && !llvm::is_contained(AllowedSpecialChars, C)) {
+      llvm::errs() << "Stat name \"" << M->name() << "\" contains character '"
+                   << C << "' (" << static_cast<int>(C)
+                   << ") that is not allowed.";
+      assert(false && "The Stat name contains unallowed character");
+    }
+  }
+}
+
+void EntryPointStat::lockRegistry() {
+  auto CmpByNames = [](const EntryPointStat *L, const EntryPointStat *R) {
+    return L->name() < R->name();
+  };
+  enumerateStatVectors(
+      [CmpByNames](auto &Stats) { llvm::sort(Stats, CmpByNames); });
+  enumerateStatVectors(
+      [](const auto &Stats) { llvm::for_each(Stats, checkStatName); });
+  StatsRegistry->IsLocked = true;
+}
+
+static bool isRegistered(llvm::StringLiteral Name) {
+  auto ByName = [Name](const EntryPointStat *M) { return M->name() == Name; };
+  bool Result = false;
+  enumerateStatVectors([ByName, &Result](const auto &Stats) {
+    Result = Result || llvm::any_of(Stats, ByName);
+  });
+  return Result;
+}
+
+BoolEPStat::BoolEPStat(llvm::StringLiteral Name) : EntryPointStat(Name) {
+  assert(!StatsRegistry->IsLocked);
+  assert(!isRegistered(Name));
+  StatsRegistry->BoolStats.push_back(this);
+}
+
+CounterEPStat::CounterEPStat(llvm::StringLiteral Name) : EntryPointStat(Name) {
+  assert(!StatsRegistry->IsLocked);
+  assert(!isRegistered(Name));
+  StatsRegistry->CounterStats.push_back(this);
+}
+
+UnsignedMaxEPStat::UnsignedMaxEPStat(llvm::StringLiteral Name)
+    : EntryPointStat(Name) {
+  assert(!StatsRegistry->IsLocked);
+  assert(!isRegistered(Name));
+  StatsRegistry->UnsignedMaxStats.push_back(this);
+}
+
+UnsignedEPStat::UnsignedEPStat(llvm::StringLiteral Name)
+    : EntryPointStat(Name) {
+  assert(!StatsRegistry->IsLocked);
+  assert(!isRegistered(Name));
+  StatsRegistry->UnsignedStats.push_back(this);
+}
+
+static std::vector<unsigned> consumeUnsignedStats() {
+  std::vector<unsigned> Result;
+  Result.reserve(StatsRegistry->CounterStats.size() +
+                 StatsRegistry->UnsignedMaxStats.size() +
+                 StatsRegistry->UnsignedStats.size());
+  for (auto *M : StatsRegistry->CounterStats) {
+    Result.push_back(M->value());
+    M->reset();
+  }
+  for (auto *M : StatsRegistry->UnsignedMaxStats) {
+    Result.push_back(M->value());
+    M->reset();
+  }
+  for (auto *M : StatsRegistry->UnsignedStats) {
+    Result.push_back(M->value());
+    M->reset();
+  }
+  return Result;
+}
+
+static std::vector<llvm::StringLiteral> getStatNames() {
+  std::vector<llvm::StringLiteral> Ret;
+  auto GetName = [](const EntryPointStat *M) { return M->name(); };
+  enumerateStatVectors([GetName, &Ret](const auto &Stats) {
+    transform(Stats, std::back_inserter(Ret), GetName);
+  });
+  return Ret;
+}
+
+void Registry::Snapshot::dumpDynamicStatsAsCSV(llvm::raw_ostream &OS) const {
+  OS << '"';
+  llvm::printEscapedString(
+      clang::AnalysisDeclContext::getFunctionName(EntryPoint), OS);
+  OS << "\", ";
+  auto PrintAsBool = [&OS](bool B) { OS << (B ? "true" : "false"); };
+  llvm::interleaveComma(BoolStatValues, OS, PrintAsBool);
+  OS << ((BoolStatValues.empty() || UnsignedStatValues.empty()) ? "" : ", ");
+  llvm::interleaveComma(UnsignedStatValues, OS);
+}
+
+static std::vector<bool> consumeBoolStats() {
+  std::vector<bool> Result;
+  Result.reserve(StatsRegistry->BoolStats.size());
+  for (auto *M : StatsRegistry->BoolStats) {
+    Result.push_back(M->value());
+    M->reset();
+  }
+  return Result;
+}
+
+void EntryPointStat::takeSnapshot(const Decl *EntryPoint) {
+  auto BoolValues = consumeBoolStats();
+  auto UnsignedValues = consumeUnsignedStats();
+  StatsRegistry->Snapshots.push_back(
+      {EntryPoint, std::move(BoolValues), std::move(UnsignedValues)});
+}
+
+void EntryPointStat::dumpStatsAsCSV(llvm::StringRef FileName) {
+  std::error_code EC;
+  llvm::raw_fd_ostream File(FileName, EC, llvm::sys::fs::OF_Text);
+  if (EC)
+    return;
+  dumpStatsAsCSV(File);
+}
+
+void EntryPointStat::dumpStatsAsCSV(llvm::raw_ostream &OS) {
+  OS << "EntryPoint, ";
+  llvm::interleaveComma(getStatNames(), OS);
+  OS << "\n";
+
+  std::vector<std::string> Rows;
+  Rows.reserve(StatsRegistry->Snapshots.size());
+  for (const auto &Snapshot : StatsRegistry->Snapshots) {
+    std::string Row;
+    llvm::raw_string_ostream RowOs(Row);
+    Snapshot.dumpDynamicStatsAsCSV(RowOs);
----------------
necto wrote:

Renamed:
933e090f38b2 [NFC] Rename dumpDynamicStatsAsCSV to dumpAsCSV


https://github.com/llvm/llvm-project/pull/131175
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to