[clang] [clang][ssaf] Implement Entity Linker CLI and patching for JSON Format (PR #184713)
Balázs Benics via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 6 07:45:10 PST 2026
================
@@ -0,0 +1,329 @@
+//===--- tools/ssaf-linker/SSAFLinker.cpp - SSAF Linker -------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SSAF entity linker tool that performs entity
+// linking across multiple TU summaries using the EntityLinker framework.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Scalable/EntityLinker/EntityLinker.h"
+#include "clang/Analysis/Scalable/EntityLinker/TUSummaryEncoding.h"
+#include "clang/Analysis/Scalable/Model/BuildNamespace.h"
+#include "clang/Analysis/Scalable/Serialization/JSONFormat.h"
+#include "clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h"
+#include "clang/Analysis/Scalable/Support/ErrorBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+#include <string>
+#include <system_error>
+
+using namespace llvm;
+using namespace clang::ssaf;
+
+namespace fs = llvm::sys::fs;
+namespace path = llvm::sys::path;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// Command-Line Options
+//===----------------------------------------------------------------------===//
+
+cl::OptionCategory SsafLinkerCategory("ssaf-linker options");
+
+cl::list<std::string> InputPaths(cl::Positional, cl::desc("<input files>"),
+ cl::OneOrMore, cl::cat(SsafLinkerCategory));
+
+cl::opt<std::string> OutputPath("o", cl::desc("Output summary path"),
+ cl::value_desc("path"), cl::Required,
+ cl::cat(SsafLinkerCategory));
+
+cl::opt<bool> Verbose("verbose", cl::desc("Enable verbose output"),
+ cl::init(false), cl::cat(SsafLinkerCategory));
+
+cl::opt<bool> Time("time", cl::desc("Enable timing"), cl::init(false),
+ cl::cat(SsafLinkerCategory));
+
+//===----------------------------------------------------------------------===//
+// Error Messages
+//===----------------------------------------------------------------------===//
+
+namespace ErrorMessages {
+
+constexpr const char *CannotValidateSummary =
+ "failed to validate summary '{0}': {1}.";
+
+constexpr const char *OutputDirectoryMissing =
+ "Parent directory does not exist.";
+
+constexpr const char *OutputDirectoryNotWritable =
+ "Parent directory is not writable.";
+
+constexpr const char *ExtensionNotSupplied = "Extension not supplied.";
+
+constexpr const char *NoFormatForExtension =
+ "Format not registered for extension '{0}'.";
+
+constexpr const char *LinkingSummary = "Linking summary '{0}'";
+
+} // namespace ErrorMessages
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Utilities
+//===----------------------------------------------------------------------===//
+
+constexpr unsigned IndentationWidth = 2;
+
+llvm::StringRef ToolName;
+
+template <typename... Ts> [[noreturn]] void Fail(const char *Msg) {
+ llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
+ llvm::sys::Process::Exit(1);
+}
+
+template <typename... Ts>
+[[noreturn]] void Fail(const char *Fmt, Ts &&...Args) {
+ std::string Message = llvm::formatv(Fmt, std::forward<Ts>(Args)...);
+ Fail(Message.data());
+}
+
+template <typename... Ts> [[noreturn]] void Fail(llvm::Error Err) {
+ std::string Message = toString(std::move(Err));
+ Fail(Message.data());
+}
+
+template <typename... Ts>
+void Info(unsigned IndentationLevel, const char *Fmt, Ts &&...Args) {
+ if (Verbose) {
+ llvm::WithColor::note()
+ << std::string(IndentationLevel * IndentationWidth, ' ') << "- "
+ << llvm::formatv(Fmt, std::forward<Ts>(Args)...) << "\n";
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Format Registry
+//===----------------------------------------------------------------------===//
+
+SerializationFormat *GetFormatForExtension(llvm::StringRef Extension) {
+ static llvm::SmallVector<
+ std::pair<std::string, std::unique_ptr<SerializationFormat>>, 4>
+ ExtensionFormatList;
+
+ // Most recently used format is most likely to be reused again.
+ auto ReversedList = llvm::reverse(ExtensionFormatList);
+ auto It = llvm::find_if(ReversedList, [&](const auto &Entry) {
+ return Entry.first == Extension;
+ });
+ if (It != ReversedList.end()) {
+ return It->second.get();
+ }
+
+ // SerializationFormats are uppercase while file extensions are lowercase.
+ std::string CapitalizedExtension = Extension.upper();
----------------
steakhal wrote:
This will get simplified, so that the Name is actually the extension.
https://github.com/llvm/llvm-project/pull/184713
More information about the cfe-commits
mailing list