From 93a060d5e06b8ead3ed14cbceaacda499cb73dd8 Mon Sep 17 00:00:00 2001 From: xlauko Date: Tue, 3 Sep 2024 16:16:58 +0200 Subject: [PATCH] cc: Refactor out sarif diagnostics. --- include/vast/Frontend/Sarif.hpp | 53 ++++++++++ lib/vast/Frontend/CMakeLists.txt | 1 + lib/vast/Frontend/Consumer.cpp | 164 +++++++++---------------------- lib/vast/Frontend/Sarif.cpp | 79 +++++++++++++++ 4 files changed, 182 insertions(+), 115 deletions(-) create mode 100644 include/vast/Frontend/Sarif.hpp create mode 100644 lib/vast/Frontend/Sarif.cpp diff --git a/include/vast/Frontend/Sarif.hpp b/include/vast/Frontend/Sarif.hpp new file mode 100644 index 0000000000..76f535ce0b --- /dev/null +++ b/include/vast/Frontend/Sarif.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2024, Trail of Bits, Inc. + +#pragma once + + +#ifdef VAST_ENABLE_SARIF + #include + + #include "vast/Frontend/Options.hpp" + #include "vast/Util/Common.hpp" + +namespace vast::cc::sarif { + + gap::sarif::location mk_location(loc_t loc); + gap::sarif::location mk_location(file_loc_t loc); + gap::sarif::location mk_location(name_loc_t loc); + + gap::sarif::physical_location get_physical_loc(file_loc_t loc); + + gap::sarif::level get_severity_level(mlir::DiagnosticSeverity severity); + + struct diagnostics { + gap::sarif::run run; + + explicit diagnostics(const vast_args &vargs); + + auto handler() { + return [&] (auto &diag) { + gap::sarif::result result = { + .ruleId = "mlir-diag", + .message = { .text = diag.str() } + }; + + if (auto loc = mk_location(diag.getLocation()); loc.physicalLocation.has_value()) { + result.locations.push_back(std::move(loc)); + } + + result.level = get_severity_level(diag.getSeverity()); + run.results.push_back(std::move(result)); + }; + }; + + gap::sarif::root emit(logical_result result) && { + run.invocations[0].executionSuccessful = mlir::succeeded(result); + return { + .version = gap::sarif::version::k2_1_0, + .runs{ std::move(run) }, + }; + } + }; + +} // namespace vast::cc::sarif +#endif // VAST_ENABLE_SARIF diff --git a/lib/vast/Frontend/CMakeLists.txt b/lib/vast/Frontend/CMakeLists.txt index cc99558040..d6817e7a90 100644 --- a/lib/vast/Frontend/CMakeLists.txt +++ b/lib/vast/Frontend/CMakeLists.txt @@ -5,6 +5,7 @@ add_vast_library(Frontend Consumer.cpp Options.cpp Pipelines.cpp + Sarif.cpp Targets.cpp LINK_LIBS PUBLIC diff --git a/lib/vast/Frontend/Consumer.cpp b/lib/vast/Frontend/Consumer.cpp index 7de8cc06dc..49070f32fb 100644 --- a/lib/vast/Frontend/Consumer.cpp +++ b/lib/vast/Frontend/Consumer.cpp @@ -26,6 +26,7 @@ VAST_UNRELAX_WARNINGS #include "vast/Util/Common.hpp" #include "vast/Frontend/Pipelines.hpp" +#include "vast/Frontend/Sarif.hpp" #include "vast/Frontend/Targets.hpp" #include "vast/Target/LLVMIR/Convert.hpp" @@ -34,10 +35,6 @@ VAST_UNRELAX_WARNINGS #include "vast/Config/config.h" -#ifdef VAST_ENABLE_SARIF - #include -#endif // VAST_ENABLE_SARIF - namespace vast::cc { [[nodiscard]] target_dialect parse_target_dialect(string_ref from); @@ -169,79 +166,40 @@ namespace vast::cc { ); } -#ifdef VAST_ENABLE_SARIF - gap::sarif::physical_location get_physical_loc(file_loc_t 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(), - } }, - }; - } - - struct sarif_diag_handler - { - gap::sarif::run &run; - - void operator()(mlir::Diagnostic &diag) const { - auto result = mk_result(diag); - - if (auto loc = mk_location(diag.getLocation()); loc.physicalLocation.has_value()) { - result.locations.push_back(std::move(loc)); - } - - result.level = severity_to_sarif(diag.getSeverity()); - run.results.push_back(std::move(result)); - } + namespace sarif { + struct diagnostics; + } // namespace sarif - private: - gap::sarif::location mk_location(file_loc_t loc) const { - return { - .physicalLocation{ get_physical_loc(loc) }, - }; - } - - gap::sarif::location mk_location(name_loc_t loc) const { - return { - .physicalLocation{ - get_physical_loc(mlir::cast< file_loc_t >(loc.getChildLoc())) - }, - .logicalLocations{ { .name = loc.getName().str() } }, - }; + #ifdef VAST_ENABLE_SARIF + std::unique_ptr< vast::cc::sarif::diagnostics > setup_sarif_diagnostics( + const vast_args &vargs, mcontext_t &mctx + ) { + if (vargs.get_option(opt::output_sarif)) { + auto diags = std::make_unique< vast::cc::sarif::diagnostics >(vargs); + mctx.getDiagEngine().registerHandler(diags->handler()); + return diags; + } else { + return nullptr; } + } + #endif // VAST_ENABLE_SARIF - gap::sarif::location mk_location(loc_t loc) const { - if (auto file_loc = mlir::dyn_cast< file_loc_t >(loc)) { - return mk_location(file_loc); - } else if (auto name_loc = mlir::dyn_cast< name_loc_t >(loc)) { - return mk_location(name_loc); + void emit_sarif_diagnostics( + vast::cc::sarif::diagnostics &&sarif_diagnostics, logical_result result, string_ref path + ) { + #ifdef VAST_ENABLE_SARIF + std::error_code ec; + llvm::raw_fd_ostream os(path, ec, llvm::sys::fs::OF_None); + if (ec) { + VAST_FATAL("Failed to open file for SARIF output: {}", ec.message()); } - return {}; - } - - gap::sarif::result mk_result(mlir::Diagnostic &diag) const { - return { - .ruleId = "mlir-diag", - .message = { .text = diag.str() } - }; - } - - gap::sarif::level severity_to_sarif(mlir::DiagnosticSeverity severity) const { - using enum gap::sarif::level; - using enum mlir::DiagnosticSeverity; - switch (severity) { - case Note: return kNote; - case Warning: return kWarning; - case Error: return kError; - case Remark: return kNote; - } - } - }; -#endif // VAST_ENABLE_SARIF + nlohmann::json report = std::move(sarif_diagnostics).emit(result); + os << report.dump(2); + #else + VAST_REPORT("SARIF support is disabled"); + #endif // VAST_ENABLE_SARIF + } void vast_stream_consumer::process_mlir_module(target_dialect target, mlir_module mod) { // Handle source manager properly given that lifetime analysis @@ -267,58 +225,20 @@ namespace vast::cc { llvm::DebugFlag = true; } -#ifdef VAST_ENABLE_SARIF - 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, - }, }, - }; - sarif_diag_handler diag_handler{ sarif_run }; -#endif // VAST_ENABLE_SARIF - // 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"); -#ifdef VAST_ENABLE_SARIF - if (auto sarif_path = vargs.get_option(opt::output_sarif)) { - mctx.getDiagEngine().registerHandler(diag_handler); - } -#endif // VAST_ENABLE_SARIF + #ifdef VAST_ENABLE_SARIF + auto sarif_diagnostics = setup_sarif_diagnostics(vargs, mctx); + #endif // VAST_ENABLE_SARIF auto result = pipeline->run(mod); -#ifdef VAST_ENABLE_SARIF - 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.dump(2); - } -#endif // VAST_ENABLE_SARIF - VAST_CHECK( mlir::succeeded(result), "MLIR pass manager failed when running vast passes" ); @@ -330,6 +250,20 @@ namespace vast::cc { VAST_FATAL("failed mlir codegen"); } + if (auto path = vargs.get_option(opt::output_sarif)) { + #ifdef VAST_ENABLE_SARIF + if (sarif_diagnostics) { + emit_sarif_diagnostics( + std::move(*sarif_diagnostics), result, path.value().str() + ); + } else { + VAST_REPORT("SARIF diagnostics are missing"); + } + #else + VAST_REPORT("SARIF support is disabled"); + #endif // VAST_ENABLE_SARIF + } + // Emit remaining defaulted C++ methods // if (!vargs.has_option(opt::disable_emit_cxx_default)) { // generator->build_default_methods(); diff --git a/lib/vast/Frontend/Sarif.cpp b/lib/vast/Frontend/Sarif.cpp new file mode 100644 index 0000000000..4ac949ac0a --- /dev/null +++ b/lib/vast/Frontend/Sarif.cpp @@ -0,0 +1,79 @@ +// Copyright (c) 2024, Trail of Bits, Inc. + +#include "vast/Frontend/Sarif.hpp" + +#ifdef VAST_ENABLE_SARIF + +#include "vast/Config/config.h" + +namespace vast::cc::sarif { + + gap::sarif::location mk_location(loc_t loc) { + if (auto file_loc = mlir::dyn_cast< file_loc_t >(loc)) { + return mk_location(file_loc); + } else if (auto name_loc = mlir::dyn_cast< name_loc_t >(loc)) { + return mk_location(name_loc); + } + + return {}; + } + + gap::sarif::location mk_location(file_loc_t loc) { + return { + .physicalLocation{ get_physical_loc(loc) }, + }; + } + + gap::sarif::location mk_location(name_loc_t loc) { + return { + .physicalLocation{ + get_physical_loc(mlir::cast< file_loc_t >(loc.getChildLoc())) + }, + .logicalLocations{ { .name = loc.getName().str() } }, + }; + } + + gap::sarif::physical_location get_physical_loc(file_loc_t 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(), + } }, + }; + } + + gap::sarif::level get_severity_level(mlir::DiagnosticSeverity severity) { + using enum gap::sarif::level; + using enum mlir::DiagnosticSeverity; + switch (severity) { + case Note: return kNote; + case Warning: return kWarning; + case Error: return kError; + case Remark: return kNote; + } + } + + diagnostics::diagnostics(const vast_args &vargs) + : run(gap::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{ std::begin(vargs.args), std::end(vargs.args) }, + .executionSuccessful = true, + }} + }) + {} + +} // namespace vast::cc::sarif + +#endif // VAST_ENABLE_SARIF