Skip to content

Commit

Permalink
cc: emit diagnostics as SARIF report
Browse files Browse the repository at this point in the history
  • Loading branch information
frabert committed Aug 12, 2024
1 parent 53b3e5e commit 476eeba
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 20 deletions.
3 changes: 3 additions & 0 deletions docs/Tools/vast-front.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ Additional customization options include:
- After each pass that was specified as an option store MLIR into a file (format is `src.pass_name`).
- `"*"` stores snapshot after every conversion.

- `-vast-output-sarif="report.sarif"`
- Outputs diagnostics as a SARIF report file.

## Pipelines

WIP pipelines documentation
2 changes: 2 additions & 0 deletions include/vast/Config/config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace vast {

constexpr std::string_view version = "${VAST_VERSION}";

constexpr std::string_view homepage_url = "${PROJECT_HOMEPAGE_URL}";

constexpr std::string_view bug_report_url = "${BUG_REPORT_URL}";

constexpr std::string_view default_resource_dir = "${VAST_DEFAULT_RESOURCE_DIR}";
Expand Down
2 changes: 2 additions & 0 deletions include/vast/Frontend/Options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ namespace vast::cc
constexpr option_t vast_verify_diags = "verify-diags";
constexpr option_t disable_emit_cxx_default = "disable-emit-cxx-default";

constexpr option_t output_sarif = "output-sarif";

bool emit_only_mlir(const vast_args &vargs);
bool emit_only_llvm(const vast_args &vargs);
} // namespace opt
Expand Down
1 change: 1 addition & 0 deletions lib/vast/Frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_vast_library(Frontend
Targets.cpp

LINK_LIBS PUBLIC
gap::gap-sarif
MLIRBytecodeWriter
VASTCodeGen
)
126 changes: 107 additions & 19 deletions lib/vast/Frontend/Consumer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) 2023-present, Trail of Bits, Inc.

#include "vast/Frontend/Consumer.hpp"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Location.h"

VAST_RELAX_WARNINGS
#include <llvm/Support/Signals.h>
Expand All @@ -17,6 +19,7 @@ VAST_RELAX_WARNINGS
VAST_UNRELAX_WARNINGS

#include <filesystem>
#include <fstream>

#include "vast/CodeGen/CodeGenDriver.hpp"

Expand All @@ -27,6 +30,10 @@ VAST_UNRELAX_WARNINGS

#include "vast/Target/LLVMIR/Convert.hpp"

#include "vast/Config/config.h"

#include <gap/sarif/sarif.hpp>

namespace vast::cc {

[[nodiscard]] target_dialect parse_target_dialect(string_ref from);
Expand Down Expand Up @@ -99,9 +106,7 @@ namespace vast::cc {

void vast_consumer::HandleVTable(clang::CXXRecordDecl * /* decl */) { VAST_UNIMPLEMENTED; }

owning_module_ref vast_consumer::result() {
return driver->freeze();
}
owning_module_ref vast_consumer::result() { return driver->freeze(); }

//
// vast stream consumer
Expand Down Expand Up @@ -144,34 +149,42 @@ namespace vast::cc {
}
}

void vast_stream_consumer::emit_backend_output(
backend backend_action, owning_module_ref mod
) {
void
vast_stream_consumer::emit_backend_output(backend backend_action, owning_module_ref mod) {
llvm::LLVMContext llvm_context;

process_mlir_module(target_dialect::llvm, mod.get());

auto llvm_mod = target::llvmir::translate(mod.get(), llvm_context);
auto dl = driver->acontext().getTargetInfo().getDataLayoutString();
auto dl = driver->acontext().getTargetInfo().getDataLayoutString();

clang::EmitBackendOutput(
opts.diags, opts.headers, opts.codegen, opts.target, opts.lang, dl, llvm_mod.get(),
backend_action, &opts.vfs, std::move(output_stream)
);
}

void vast_stream_consumer::process_mlir_module(
target_dialect target, mlir::ModuleOp mod
) {
static gap::sarif::physical_location get_physical_loc(mlir::FileLineColLoc loc) {
std::filesystem::path file_path{ loc.getFilename().str() };
auto abs_path = std::filesystem::absolute(file_path);
return {
.artifactLocation{ { .uri{ "file://" + abs_path.string() } } },
.region{ {
.startLine = loc.getLine(),
.startColumn = loc.getColumn(),
} },
};
}

void vast_stream_consumer::process_mlir_module(target_dialect target, mlir::ModuleOp mod) {
// Handle source manager properly given that lifetime analysis
// might emit warnings and remarks.
auto &src_mgr = driver->acontext().getSourceManager();
auto &mctx = driver->mcontext();
auto main_file_id = src_mgr.getMainFileID();

auto file_buff = llvm::MemoryBuffer::getMemBuffer(
src_mgr.getBufferOrFake(main_file_id)
);
auto file_buff =
llvm::MemoryBuffer::getMemBuffer(src_mgr.getBufferOrFake(main_file_id));

llvm::SourceMgr mlir_src_mgr;
mlir_src_mgr.AddNewSourceBuffer(std::move(file_buff), llvm::SMLoc());
Expand All @@ -186,16 +199,93 @@ namespace vast::cc {
llvm::DebugFlag = true;
}

gap::sarif::run sarif_run{
.tool{
.driver{
.name = "vast-front",
.organization = "Trail of Bits, inc.",
.product = "VAST",
.version = std::string{ vast::version },
.informationUri = std::string{ vast::homepage_url },
}, },
.invocations{
{
.arguments{ vargs.args.begin(), vargs.args.end() },
.executionSuccessful = true,
}, },
};

// Setup and execute vast pipeline
auto file_entry = src_mgr.getFileEntryRefForID(main_file_id);
VAST_CHECK(file_entry, "failed to recover file entry ref");
auto snapshot_prefix = std::filesystem::path(file_entry->getName().str()).stem().string();
auto snapshot_prefix =
std::filesystem::path(file_entry->getName().str()).stem().string();

auto pipeline = setup_pipeline(pipeline_source::ast, target, mctx, vargs, snapshot_prefix);
auto pipeline =
setup_pipeline(pipeline_source::ast, target, mctx, vargs, snapshot_prefix);
VAST_CHECK(pipeline, "failed to setup pipeline");

mlir::ScopedDiagnosticHandler sarif_diag_handler{
&mctx,
[&](mlir::Diagnostic &diag) {
gap::sarif::result result{
.ruleId{ "mlir-diag" },
.message{ .text = diag.str() },
};

auto loc = diag.getLocation();
if (auto flc_loc = loc.dyn_cast< mlir::FileLineColLoc >()) {
result.locations.push_back({
.physicalLocation{ get_physical_loc(flc_loc) },
});
} else if (auto name_loc = loc.dyn_cast< mlir::NameLoc >()) {
if (auto flc_child_loc =
name_loc.getChildLoc().dyn_cast< mlir::FileLineColLoc >())
{
result.locations.push_back(
{ .physicalLocation{ get_physical_loc(flc_child_loc) },
.logicalLocations{ { .name = name_loc.getName().str() } } }
);
}
}

switch (diag.getSeverity()) {
using enum gap::sarif::level;
case mlir::DiagnosticSeverity::Note:
result.level = kNote;
break;
case mlir::DiagnosticSeverity::Warning:
result.level = kWarning;
break;
case mlir::DiagnosticSeverity::Error:
result.level = kError;
break;
case mlir::DiagnosticSeverity::Remark:
result.level = kNote;
break;
}
sarif_run.results.push_back(result);
}
};

auto result = pipeline->run(mod);
VAST_CHECK(mlir::succeeded(result), "MLIR pass manager failed when running vast passes");

sarif_run.invocations[0].executionSuccessful = mlir::succeeded(result);

gap::sarif::root sarif_report{
.version = gap::sarif::version::k2_1_0,
.runs{ sarif_run },
};

if (auto sarif_path = vargs.get_option(opt::output_sarif)) {
std::ofstream os{ sarif_path.value().str() };
nlohmann::json j = sarif_report;
os << j;
}

VAST_CHECK(
mlir::succeeded(result), "MLIR pass manager failed when running vast passes"
);

// Verify the diagnostic handler to make sure that each of the
// diagnostics matched.
Expand All @@ -210,9 +300,7 @@ namespace vast::cc {
// }
}

void vast_stream_consumer::emit_mlir_output(
target_dialect target, owning_module_ref mod
) {
void vast_stream_consumer::emit_mlir_output(target_dialect target, owning_module_ref mod) {
if (!output_stream || !mod) {
return;
}
Expand Down
7 changes: 6 additions & 1 deletion vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
"dependencies": [
"gap"
{
"name": "gap",
"features": [
"sarif"
]
}
]
}

0 comments on commit 476eeba

Please sign in to comment.