CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
213 lines
6.6 KiB
C++
213 lines
6.6 KiB
C++
//===- 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/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
|
|
#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
|
|
#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
|
|
#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
|
|
#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
|
|
#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/FormatVariadic.h"
|
|
#include "llvm/Support/InitLLVM.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/Timer.h"
|
|
#include "llvm/Support/WithColor.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
using namespace llvm;
|
|
using namespace clang::ssaf;
|
|
|
|
namespace path = llvm::sys::path;
|
|
|
|
namespace {
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Command-Line Options
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
cl::OptionCategory SsafLinkerCategory("clang-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 file 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 LocalErrorMessages {
|
|
|
|
constexpr const char *LinkingSummary = "Linking summary '{0}'";
|
|
|
|
} // namespace LocalErrorMessages
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Diagnostic Utilities
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
constexpr unsigned IndentationWidth = 2;
|
|
|
|
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";
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Data Structures
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
struct LinkerInput {
|
|
std::vector<FormatFile> InputFiles;
|
|
FormatFile OutputFile;
|
|
std::string LinkUnitName;
|
|
};
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Pipeline
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
LinkerInput validate(llvm::TimerGroup &TG) {
|
|
llvm::Timer TValidate("validate", "Validate Input", TG);
|
|
LinkerInput LI;
|
|
|
|
{
|
|
llvm::TimeRegion _(Time ? &TValidate : nullptr);
|
|
|
|
LI.OutputFile = FormatFile::fromOutputPath(OutputPath);
|
|
LI.LinkUnitName = path::stem(LI.OutputFile.Path).str();
|
|
}
|
|
|
|
info(2, "Validated output summary path '{0}'.", LI.OutputFile.Path);
|
|
|
|
{
|
|
llvm::TimeRegion _(Time ? &TValidate : nullptr);
|
|
for (const auto &InputPath : InputPaths) {
|
|
LI.InputFiles.push_back(FormatFile::fromInputPath(InputPath));
|
|
}
|
|
}
|
|
|
|
info(2, "Validated {0} input summary paths.", LI.InputFiles.size());
|
|
|
|
return LI;
|
|
}
|
|
|
|
void link(const LinkerInput &LI, llvm::TimerGroup &TG) {
|
|
info(2, "Constructing linker.");
|
|
|
|
EntityLinker EL(NestedBuildNamespace(
|
|
BuildNamespace(BuildNamespaceKind::LinkUnit, LI.LinkUnitName)));
|
|
|
|
llvm::Timer TRead("read", "Read Summaries", TG);
|
|
llvm::Timer TLink("link", "Link Summaries", TG);
|
|
llvm::Timer TWrite("write", "Write Summary", TG);
|
|
|
|
info(2, "Linking summaries.");
|
|
|
|
for (auto [Index, InputFile] : llvm::enumerate(LI.InputFiles)) {
|
|
std::unique_ptr<TUSummaryEncoding> Summary;
|
|
|
|
{
|
|
info(3, "[{0}/{1}] Reading '{2}'.", (Index + 1), LI.InputFiles.size(),
|
|
InputFile.Path);
|
|
|
|
llvm::TimeRegion _(Time ? &TRead : nullptr);
|
|
|
|
auto ExpectedSummaryEncoding =
|
|
InputFile.Format->readTUSummaryEncoding(InputFile.Path);
|
|
if (!ExpectedSummaryEncoding) {
|
|
fail(ExpectedSummaryEncoding.takeError());
|
|
}
|
|
|
|
Summary = std::make_unique<TUSummaryEncoding>(
|
|
std::move(*ExpectedSummaryEncoding));
|
|
}
|
|
|
|
{
|
|
info(3, "[{0}/{1}] Linking '{2}'.", (Index + 1), LI.InputFiles.size(),
|
|
InputFile.Path);
|
|
|
|
llvm::TimeRegion _(Time ? &TLink : nullptr);
|
|
|
|
if (auto Err = EL.link(std::move(Summary))) {
|
|
fail(ErrorBuilder::wrap(std::move(Err))
|
|
.context(LocalErrorMessages::LinkingSummary, InputFile.Path)
|
|
.build());
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
info(2, "Writing output summary to '{0}'.", LI.OutputFile.Path);
|
|
|
|
llvm::TimeRegion _(Time ? &TWrite : nullptr);
|
|
|
|
auto Output = std::move(EL).takeOutput();
|
|
if (auto Err = LI.OutputFile.Format->writeLUSummaryEncoding(
|
|
Output, LI.OutputFile.Path)) {
|
|
fail(std::move(Err));
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Driver
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
int main(int argc, const char **argv) {
|
|
llvm::StringRef ToolHeading = "SSAF Linker";
|
|
|
|
InitLLVM X(argc, argv);
|
|
initTool(argc, argv, "0.1", SsafLinkerCategory, ToolHeading);
|
|
|
|
llvm::TimerGroup LinkerTimers(getToolName(), ToolHeading);
|
|
LinkerInput LI;
|
|
|
|
{
|
|
info(0, "Linking started.");
|
|
|
|
{
|
|
info(1, "Validating input.");
|
|
LI = validate(LinkerTimers);
|
|
}
|
|
|
|
{
|
|
info(1, "Linking input.");
|
|
link(LI, LinkerTimers);
|
|
}
|
|
|
|
info(0, "Linking finished.");
|
|
}
|
|
|
|
return 0;
|
|
}
|