================ @@ -0,0 +1,483 @@ +//===- SSAFFormat.cpp - SSAF Format Tool ----------------------------------===// +// +// 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 format tool that validates and converts +// TU and LU summaries between registered serialization formats. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/Scalable/EntityLinker/LUSummaryEncoding.h" +#include "clang/Analysis/Scalable/EntityLinker/TUSummaryEncoding.h" +#include "clang/Analysis/Scalable/Serialization/JSONFormat.h" +#include "clang/Analysis/Scalable/Serialization/SerializationFormatRegistry.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" +#include <memory> +#include <optional> +#include <string> +#include <system_error> + +using namespace llvm; +using namespace clang::ssaf; + +namespace { + +namespace fs = llvm::sys::fs; +namespace path = llvm::sys::path; + +//===----------------------------------------------------------------------===// +// Summary Type +//===----------------------------------------------------------------------===// + +enum class SummaryType { TU, LU }; + +//===----------------------------------------------------------------------===// +// Command-Line Options +//===----------------------------------------------------------------------===// + +cl::OptionCategory SsafFormatCategory("ssaf-format options"); + +cl::list<std::string> LoadPlugins("load", + cl::desc("Load a plugin shared library"), + cl::value_desc("path"), + cl::cat(SsafFormatCategory)); + +// --type and the input file are required for convert/validateInput operations +// but must be optional at the cl layer so that --list can be used standalone. +cl::opt<SummaryType> Type( + "type", cl::desc("Summary type (required unless --list is given)"), + cl::values(clEnumValN(SummaryType::TU, "tu", "Translation unit summary"), + clEnumValN(SummaryType::LU, "lu", "Link unit summary")), + cl::cat(SsafFormatCategory)); + +cl::opt<std::string> InputPath(cl::Positional, cl::desc("<input file>"), + cl::cat(SsafFormatCategory)); + +cl::opt<std::string> OutputPath("o", cl::desc("Output summary path"), + cl::value_desc("path"), + cl::cat(SsafFormatCategory)); + +cl::opt<bool> UseEncoding("encoding", + cl::desc("Read and write summary encodings rather " + "than decoded summaries"), + cl::cat(SsafFormatCategory)); + +cl::opt<bool> ListFormats("list", + cl::desc("List registered serialization formats and " + "analyses, then exit"), + cl::init(false), cl::cat(SsafFormatCategory)); + +llvm::StringRef ToolName; + +void printVersion(llvm::raw_ostream &OS) { OS << ToolName << " 0.1\n"; } + +//===----------------------------------------------------------------------===// +// Error Messages +//===----------------------------------------------------------------------===// + +namespace ErrorMessages { + +constexpr const char *FailedToLoadPlugin = "failed to load plugin '{0}': {1}"; + +constexpr const char *CannotValidateSummary = + "failed to validate summary '{0}': {1}"; + +constexpr const char *ExtensionNotSupplied = "Extension not supplied"; + +constexpr const char *NoFormatForExtension = + "Format not registered for extension '{0}'"; + +constexpr const char *OutputDirectoryMissing = + "Parent directory does not exist"; + +constexpr const char *OutputFileAlreadyExists = "Output file already exists"; + +constexpr const char *InputOutputSamePath = + "Input and Output resolve to the same path"; + +} // namespace ErrorMessages + +//===----------------------------------------------------------------------===// +// Diagnostic Utilities +//===----------------------------------------------------------------------===// + +[[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()); +} + +[[noreturn]] void fail(llvm::Error Err) { + fail(toString(std::move(Err)).data()); +} + +//===----------------------------------------------------------------------===// +// Format Registry +//===----------------------------------------------------------------------===// + +// FIXME: This will be revisited after we add support for registering formats +// with extensions. +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(); + + if (!isFormatRegistered(CapitalizedExtension)) { + return nullptr; + } + + auto Format = makeFormat(CapitalizedExtension); + SerializationFormat *Result = Format.get(); + assert(Result); + + ExtensionFormatList.emplace_back(Extension, std::move(Format)); + + return Result; +} + +//===----------------------------------------------------------------------===// +// Format Listing +//===----------------------------------------------------------------------===// + +constexpr size_t FormatIndent = 4; +constexpr size_t AnalysisIndent = 4; + +struct AnalysisData { + std::string Name; + std::string Desc; +}; + +struct FormatData { + std::string Name; + std::string Desc; + llvm::SmallVector<AnalysisData> Analyses; +}; + +struct PrintLayout { + size_t FormatNumWidth; + size_t MaxFormatNameWidth; + size_t FormatNameCol; + size_t AnalysisCol; + size_t AnalysisNumWidth; + size_t MaxAnalysisNameWidth; ---------------- aviralg wrote:
I think its fine. I did think about this while implementing. I use the size of containers for computing some values and I decided its easier to go with a uniform type instead of sprinkling static casts. A few bytes extra for this tool is not going to affect anyone. The intended use case is one-off format conversion and lit tests. https://github.com/llvm/llvm-project/pull/185575 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
