Skip to content

Commit

Permalink
#12: convert command-line options
Browse files Browse the repository at this point in the history
  • Loading branch information
cz4rs committed Feb 21, 2021
1 parent 87026f7 commit d23e368
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 104 deletions.
156 changes: 60 additions & 96 deletions src/sanitizer/sanitizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// DARMA Toolkit v. 1.0.0
// DARMA/Serialization Sanitizer
//
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC
// Copyright 2021 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
Expand Down Expand Up @@ -42,43 +42,31 @@
//@HEADER
*/

// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"

#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"

#include <memory>

#include <fmt/format.h>

#include <algorithm>
#include <memory>

#include "generator.h"
#include "sanitizer.h"
#include "walk_record.h"

using namespace clang;
using namespace llvm;
using namespace clang::tooling;
using namespace clang::ast_matchers;

static FILE* out = stdout;

static cl::opt<std::string> Filename("o", cl::desc("Filename to output generated code"));
static cl::opt<bool> GenerateInline("inline", cl::desc("Generate code inline and modify files"));
static cl::opt<bool> OutputMainFile("include-input", cl::desc("Output input file with generated code"));
static cl::opt<bool> IncludeVTHeader("Ivt", cl::desc("Include VT headers in generated code"));
namespace sanitizer {

DeclarationMatcher RecordMatcher = cxxRecordDecl().bind("recordDecl");
static FILE* out = stdout;
static bool GenerateInline = false;
static bool OutputMainFile = false;

struct ClassFuncDeclRewriter : MatchFinder::MatchCallback {
explicit ClassFuncDeclRewriter(Rewriter& in_rw)
struct SerializeRewriter : MatchFinder::MatchCallback {
explicit SerializeRewriter(Rewriter& in_rw)
: rw(in_rw)
{ }

Expand All @@ -99,9 +87,11 @@ struct ClassFuncDeclRewriter : MatchFinder::MatchCallback {
Rewriter& rw;
};

struct MyASTConsumer : ASTConsumer {
MyASTConsumer(Rewriter& in_rw) : record_handler(in_rw) {
matcher_.addMatcher(RecordMatcher, &record_handler);
struct SanitizerASTConsumer : ASTConsumer {
SanitizerASTConsumer(Rewriter& in_rw) : record_handler(in_rw) {
auto record_matcher = cxxRecordDecl().bind("recordDecl");

matcher_.addMatcher(record_matcher, &record_handler);
}

void HandleTranslationUnit(ASTContext& Context) override {
Expand All @@ -110,92 +100,66 @@ struct MyASTConsumer : ASTConsumer {
}

private:
ClassFuncDeclRewriter record_handler;
SerializeRewriter record_handler;
MatchFinder matcher_;
};

// For each source file provided to the tool, a new FrontendAction is created.
struct MyFrontendAction : ASTFrontendAction {
void EndSourceFileAction() override {
//rw_.getEditBuffer(rw_.getSourceMgr().getMainFileID()).write(llvm::outs());
//rw_.getSourceMgr().getMainFileID()

auto& sm = rw_.getSourceMgr();
for (auto iter = rw_.buffer_begin(); iter != rw_.buffer_end(); ++iter) {
fmt::print(
stderr, "Modified file {}\n",
sm.getFileEntryForID(iter->first)->getName().str()
);
}

rw_.overwriteChangedFiles();
bool SanitizerPluginAction::ParseArgs(
CompilerInstance const&, std::vector<std::string> const& args
) {
// output input file with generated code
if (std::find(args.begin(), args.end(), "-include-input") != args.end()) {
OutputMainFile = true;
}

std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance &CI, StringRef file) override {
rw_.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
// filename to output generated code
auto filename_opt = std::find(args.begin(), args.end(), "-o");
if (filename_opt != args.end()) {
out = fopen((++filename_opt)->c_str(), "w");
}

if (OutputMainFile) {
auto buf = rw_.getSourceMgr().getBufferData(rw_.getSourceMgr().getMainFileID());
fmt::print(out, "{}", buf.str());
}
// "inline", Generate code inline and modify files"

// "Ivt", Include VT headers in generated code
// if (IncludeVTHeader) {
// fmt::print(out, "#include <vt/transport.h>\n");
// }

return true;
}

std::unique_ptr<ASTConsumer> SanitizerPluginAction::CreateASTConsumer(
CompilerInstance &ci, StringRef file
) {
rw_.setSourceMgr(ci.getSourceManager(), ci.getLangOpts());

return std::make_unique<MyASTConsumer>(rw_);
if (OutputMainFile) {
auto buf = rw_.getSourceMgr().getBufferData(rw_.getSourceMgr().getMainFileID());
fmt::print(out, "{}", buf.str());
}

private:
Rewriter rw_;
};
return std::make_unique<SanitizerASTConsumer>(rw_);
}

// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nGenerates sanitizer code for serializers\n");

// int main(int argc, const char **argv) {
// if (Filename == "") {
// out = stdout;
// } else {
// out = fopen(Filename.c_str(), "w");
// }

// if (IncludeVTHeader) {
// fmt::print(out, "#include <vt/transport.h>\n");
// }

// for (auto&& e : Includes) {
// auto str = std::string("-I") + e;
// ArgumentsAdjuster ad1 = getInsertArgumentAdjuster(str.c_str());
// Tool.appendArgumentsAdjuster(ad1);
// fmt::print(stderr, "Including {}\n", e);
// }

// Tool.run(newFrontendActionFactory<MyFrontendAction>().get());

// if (Filename == "" and out != nullptr) {
// fclose(out);
// }
// return 0;
// }

struct SanitizerPluginAction : public PluginASTAction {
public:
bool ParseArgs(CompilerInstance const&,
std::vector<std::string> const& args) override {
for (auto&& arg : args) {
llvm::errs() << arg;
}
return true;
void SanitizerPluginAction::EndSourceFileAction() {
auto& sm = rw_.getSourceMgr();
for (auto iter = rw_.buffer_begin(); iter != rw_.buffer_end(); ++iter) {
fmt::print(
stderr, "Modified file {}\n",
sm.getFileEntryForID(iter->first)->getName().str()
);
}

std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance&,
StringRef) override {
return std::make_unique<MyASTConsumer>(rw_);
rw_.overwriteChangedFiles();
if (out != stdout) {
fclose(out);
}
}

private:
Rewriter rw_;
};
} /* end namespace sanitizer */

// register the plugin
static FrontendPluginRegistry::Add<SanitizerPluginAction>
static FrontendPluginRegistry::Add<sanitizer::SanitizerPluginAction>
X(/*Name=*/"sanitizer",
/*Desc=*/"Serialization Sanitizer");
15 changes: 8 additions & 7 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,18 @@ foreach(test_file ${TEST_SOURCE_FILES})

get_filename_component(test_name ${test_file} NAME_WE)

# FIXME: this is obviously not the right way (just checking CI)
# FIXME: it would be better to add clang flags (per target?), but we have to
# make sure that the plugin is built first
# note: add_dependencies(${test_name} sanitizer) doesn't seem to work
add_custom_command(
OUTPUT "${test_name}.generated.cc"
COMMAND cp
ARGS ${test_file}
"${test_name}.generated.cc"
COMMAND clang++
ARGS "-std=c++14"
ARGS "-std=c++14" "-c" ${test_file}
"-Xclang" "-load" "-Xclang" "${PROJECT_BINARY_DIR}/libsanitizer.so"
"-Xclang" "-plugin" "-Xclang" "sanitizer" "-c" ${test_file}
">>" "${test_name}.generated.cc"
"-Xclang" "-plugin" "-Xclang" "sanitizer"
"-Xclang" "-plugin-arg-sanitizer" "-Xclang" "-include-input"
"-Xclang" "-plugin-arg-sanitizer" "-Xclang" "-o"
"-Xclang" "-plugin-arg-sanitizer" "-Xclang" "${test_name}.generated.cc"
DEPENDS sanitizer
)

Expand Down
6 changes: 5 additions & 1 deletion tests/test-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ struct Sanitizer {
}
};

struct Serializer { };
struct Serializer {
// necessary for InlineGenerator
// template <typename Arg, typename... Args>
// void check(Arg& m, Args&&...) { }
};

template <typename SerializerT, typename T>
void operator|(SerializerT& s, T& t) {
Expand Down

0 comments on commit d23e368

Please sign in to comment.