Skip to content

Commit

Permalink
Merge TestgenCompilerTarget into TestgenTarget.
Browse files Browse the repository at this point in the history
  • Loading branch information
fruffy committed May 2, 2024
1 parent 5a7eeee commit d311574
Show file tree
Hide file tree
Showing 47 changed files with 362 additions and 469 deletions.
1 change: 1 addition & 0 deletions backends/p4tools/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ set(
options.cpp
version.cpp

compiler/compiler_result.cpp
compiler/compiler_target.cpp
compiler/convert_hs_index.cpp
compiler/convert_struct_expr.cpp
Expand Down
9 changes: 9 additions & 0 deletions backends/p4tools/common/compiler/compiler_result.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "backends/p4tools/common/compiler/compiler_result.h"

namespace P4Tools {

const IR::P4Program &CompilerResult::getProgram() const { return program; }

CompilerResult::CompilerResult(const IR::P4Program &program) : program(program) {}

} // namespace P4Tools
35 changes: 35 additions & 0 deletions backends/p4tools/common/compiler/compiler_result.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_RESULT_H_
#define BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_RESULT_H_

#include <functional>
#include <optional>

#include "ir/ir.h"
#include "lib/castable.h"

namespace P4Tools {

/// An extensible result object which is returned by the CompilerTarget.
/// In its simplest form, this holds the transformed P4 program after the front- and midend passes.
class CompilerResult : public ICastable {
private:
/// The reference to the input P4 program, after it has been transformed by the compiler.
std::reference_wrapper<const IR::P4Program> program;

public:
explicit CompilerResult(const IR::P4Program &program);

/// @returns the reference to the input P4 program, after it has been transformed by the
/// compiler.
[[nodiscard]] const IR::P4Program &getProgram() const;

DECLARE_TYPEINFO(CompilerResult);
};

/// P4Tools compilers may return an error instead of a compiler result.
/// This is a convenience definition for the return value.
using CompilerResultOrError = std::optional<std::reference_wrapper<const CompilerResult>>;

} // namespace P4Tools

#endif /* BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_RESULT_H_ */
43 changes: 23 additions & 20 deletions backends/p4tools/common/compiler/compiler_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,47 +18,46 @@

namespace P4Tools {

const IR::P4Program &CompilerResult::getProgram() const { return program; }

CompilerResult::CompilerResult(const IR::P4Program &program) : program(program) {}

ICompileContext *CompilerTarget::makeContext() { return get().makeContextImpl(); }
ICompileContext *CompilerTarget::makeContext(const std::string &toolName) {
return get(toolName).makeContextImpl();
}

std::vector<const char *> *CompilerTarget::initCompiler(int argc, char **argv) {
return get().initCompilerImpl(argc, argv);
std::vector<const char *> *CompilerTarget::initCompiler(const std::string &toolName, int argc,
char **argv) {
return get(toolName).initCompilerImpl(argc, argv);
}

CompilerResultOrError CompilerTarget::runCompiler() {
CompilerResultOrError CompilerTarget::runCompiler(const std::string &toolName) {
const auto *program = P4Tools::CompilerTarget::runParser();
if (program == nullptr) {
return std::nullopt;
}

return runCompiler(program);
return runCompiler(toolName, program);
}

CompilerResultOrError CompilerTarget::runCompiler(const std::string &source) {
CompilerResultOrError CompilerTarget::runCompiler(const std::string &toolName,
const std::string &source) {
const auto *program = P4::parseP4String(source, P4CContext::get().options().langVersion);
if (program == nullptr) {
return std::nullopt;
}

return runCompiler(program);
return runCompiler(toolName, program);
}

CompilerResultOrError CompilerTarget::runCompiler(const IR::P4Program *program) {
return get().runCompilerImpl(program);
CompilerResultOrError CompilerTarget::runCompiler(const std::string &toolName,
const IR::P4Program *program) {
return get(toolName).runCompilerImpl(program);
}

CompilerResultOrError CompilerTarget::runCompilerImpl(const IR::P4Program *program) const {
const auto &self = get();

program = self.runFrontend(program);
program = runFrontend(program);
if (program == nullptr) {
return std::nullopt;
}

program = self.runMidEnd(program);
program = runMidEnd(program);
if (program == nullptr) {
return std::nullopt;
}
Expand Down Expand Up @@ -119,8 +118,12 @@ const IR::P4Program *CompilerTarget::runMidEnd(const IR::P4Program *program) con
return program->apply(midEnd);
}

CompilerTarget::CompilerTarget(std::string deviceName, std::string archName)
: Target("compiler", std::move(deviceName), std::move(archName)) {}
CompilerTarget::CompilerTarget(const std::string &toolName, const std::string &deviceName,
const std::string &archName)
: Target(toolName, deviceName, archName) {}

const CompilerTarget &CompilerTarget::get(const std::string &toolName) {
return Target::get<CompilerTarget>(toolName);
}

const CompilerTarget &CompilerTarget::get() { return Target::get<CompilerTarget>("compiler"); }
} // namespace P4Tools
42 changes: 11 additions & 31 deletions backends/p4tools/common/compiler/compiler_target.h
Original file line number Diff line number Diff line change
@@ -1,69 +1,48 @@
#ifndef BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_TARGET_H_
#define BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_TARGET_H_

#include <functional>
#include <optional>
#include <string>
#include <vector>

#include "backends/p4tools/common/compiler/compiler_result.h"
#include "backends/p4tools/common/compiler/midend.h"
#include "backends/p4tools/common/core/target.h"
#include "frontends/common/options.h"
#include "frontends/p4/frontend.h"
#include "ir/ir.h"
#include "lib/castable.h"
#include "lib/compile_context.h"

namespace P4Tools {

/// An extensible result object which is returned by the CompilerTarget.
/// In its simplest form, this holds the transformed P4 program after the front- and midend passes.
class CompilerResult : public ICastable {
private:
/// The reference to the input P4 program, after it has been transformed by the compiler.
std::reference_wrapper<const IR::P4Program> program;

public:
explicit CompilerResult(const IR::P4Program &program);

/// @returns the reference to the input P4 program, after it has been transformed by the
/// compiler.
[[nodiscard]] const IR::P4Program &getProgram() const;

DECLARE_TYPEINFO(CompilerResult);
};

/// P4Tools compilers may return an error instead of a compiler result.
/// This is a convenience definition for the return value.
using CompilerResultOrError = std::optional<std::reference_wrapper<const CompilerResult>>;

/// Encapsulates the details of invoking the P4 compiler for a target device and architecture.
class CompilerTarget : public Target {
public:
/// @returns a new compilation context for the compiler.
static ICompileContext *makeContext();
static ICompileContext *makeContext(const std::string &toolName);

/// Initializes the P4 compiler with the given compiler-specific command-line arguments.
///
/// @returns any unprocessed arguments, or nullptr if there was an error.
static std::vector<const char *> *initCompiler(int argc, char **argv);
static std::vector<const char *> *initCompiler(const std::string &toolName, int argc,
char **argv);

/// Runs the P4 compiler to produce an IR and various other kinds of information on the input
/// program.
///
/// @returns std::nullopt if an error occurs during compilation.
static CompilerResultOrError runCompiler();
static CompilerResultOrError runCompiler(const std::string &toolName);

/// Runs the P4 compiler to produce an IR and other information for the given source code.
///
/// @returns std::nullopt if an error occurs during compilation.
static CompilerResultOrError runCompiler(const std::string &source);
static CompilerResultOrError runCompiler(const std::string &toolName,
const std::string &source);

private:
/// Runs the front and mid ends on the given parsed program.
///
/// @returns std::nullopt if an error occurs during compilation.
static CompilerResultOrError runCompiler(const IR::P4Program *);
static CompilerResultOrError runCompiler(const std::string &toolName, const IR::P4Program *);

protected:
/// @see @makeContext.
Expand Down Expand Up @@ -98,11 +77,12 @@ class CompilerTarget : public Target {
/// @returns nullptr if an error occurs during compilation.
const IR::P4Program *runMidEnd(const IR::P4Program *program) const;

explicit CompilerTarget(std::string deviceName, std::string archName);
explicit CompilerTarget(const std::string &toolName, const std::string &deviceName,
const std::string &archName);

private:
/// @returns the singleton instance for the current target.
static const CompilerTarget &get();
static const CompilerTarget &get(const std::string &toolName);
};

} // namespace P4Tools
Expand Down
3 changes: 2 additions & 1 deletion backends/p4tools/common/core/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ const IR::Expression *Target::createTargetUninitialized(const IR::Type *type,
return IR::getDefaultValue(type);
}

Target::Target(std::string toolName, std::string deviceName, std::string archName)
Target::Target(const std::string &toolName, const std::string &deviceName,
const std::string &archName)
: toolName(toolName), spec(deviceName, archName) {
// Register this instance.
BUG_CHECK(!registry[spec].count(toolName), "Already registered %1%/%2% instance for %3%",
Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/common/core/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Target {
protected:
/// Creates and registers a new Target instance for the given @toolName, @deviceName, and
/// @archName.
Target(std::string toolName, std::string deviceName, std::string archName);
Target(const std::string &toolName, const std::string &deviceName, const std::string &archName);

/// @returns the target instance for the given tool and active target, as selected by @init.
//
Expand Down
11 changes: 8 additions & 3 deletions backends/p4tools/common/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ std::optional<ICompileContext *> AbstractP4cToolOptions::process(
}

// Establish the real compilation context.
auto *compilerContext = P4Tools::CompilerTarget::makeContext();
auto *compilerContext = P4Tools::CompilerTarget::makeContext(_toolName);
AutoCompileContext autoContext(compilerContext);

// Initialize the compiler, forwarding any compiler-specific options.
std::tie(argc, argv) = convertArgs(compilerArgs);
auto *unprocessedCompilerArgs = P4Tools::CompilerTarget::initCompiler(argc, argv);
auto *unprocessedCompilerArgs = P4Tools::CompilerTarget::initCompiler(_toolName, argc, argv);

if ((unprocessedCompilerArgs == nullptr) || ::errorCount() > 0) {
return std::nullopt;
Expand Down Expand Up @@ -108,7 +108,8 @@ struct InheritedCompilerOptionSpec {
std::optional<std::function<bool(const char *)>> handler;
};

AbstractP4cToolOptions::AbstractP4cToolOptions(cstring message) : Options(message) {
AbstractP4cToolOptions::AbstractP4cToolOptions(const std::string &toolName, cstring message)
: Options(message), _toolName(toolName) {
// Register some common options.
registerOption(
"--help", nullptr,
Expand Down Expand Up @@ -209,4 +210,8 @@ AbstractP4cToolOptions::AbstractP4cToolOptions(cstring message) : Options(messag
}
}

bool AbstractP4cToolOptions::validateOptions() const { return true; }

const std::string &AbstractP4cToolOptions::getToolName() const { return _toolName; }

} // namespace P4Tools
22 changes: 15 additions & 7 deletions backends/p4tools/common/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ namespace P4Tools {
/// should use the singleton pattern and define a static get() for obtaining the singleton
/// instance.
class AbstractP4cToolOptions : protected Util::Options {
private:
/// The name of the tool associated with these options.
std::string _toolName;

public:
virtual ~AbstractP4cToolOptions() = default;
/// A seed for the PRNG.
std::optional<uint32_t> seed = std::nullopt;

Expand All @@ -29,6 +34,11 @@ class AbstractP4cToolOptions : protected Util::Options {
/// @returns a compilation context on success, std::nullopt on error.
std::optional<ICompileContext *> process(const std::vector<const char *> &args);

// No copy constructor and no self-assignments.
AbstractP4cToolOptions(const AbstractP4cToolOptions &) = delete;

AbstractP4cToolOptions &operator=(const AbstractP4cToolOptions &) = delete;

protected:
/// Command-line arguments to be sent to the compiler. Populated by @process.
std::vector<const char *> compilerArgs;
Expand All @@ -38,17 +48,15 @@ class AbstractP4cToolOptions : protected Util::Options {

/// Checks if parsed options make sense with respect to each-other.
/// @returns true if the validation was successfull and false otherwise.
virtual bool validateOptions() const { return true; }
[[nodiscard]] virtual bool validateOptions() const;

/// The name of the tool associated with these options.
[[nodiscard]] const std::string &getToolName() const;

/// Converts a vector of command-line arguments into the traditional (argc, argv) format.
static std::tuple<int, char **> convertArgs(const std::vector<const char *> &args);

explicit AbstractP4cToolOptions(cstring message);

// No copy constructor and no self-assignments.
AbstractP4cToolOptions(const AbstractP4cToolOptions &) = delete;

AbstractP4cToolOptions &operator=(const AbstractP4cToolOptions &) = delete;
explicit AbstractP4cToolOptions(const std::string &toolName, cstring message);
};

} // namespace P4Tools
Expand Down
4 changes: 2 additions & 2 deletions backends/p4tools/common/p4ctool.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class AbstractP4cTool {
/// @param args
/// Contains the path to the executable, followed by the command-line arguments for this
/// tool.
int main(const std::vector<const char *> &args) {
int main(const std::string &toolName, const std::vector<const char *> &args) {
// Register supported compiler targets.
registerTarget();

Expand All @@ -55,7 +55,7 @@ class AbstractP4cTool {
}

// Run the compiler to get an IR and invoke the tool.
const auto compilerResult = P4Tools::CompilerTarget::runCompiler();
const auto compilerResult = P4Tools::CompilerTarget::runCompiler(toolName);
if (!compilerResult.has_value()) {
return EXIT_FAILURE;
}
Expand Down
3 changes: 1 addition & 2 deletions backends/p4tools/modules/testgen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ set(
options.cpp
testgen.cpp

core/compiler_target.cpp
core/compiler_result.cpp
core/externs.cpp
core/program_info.cpp
core/small_step/abstract_stepper.cpp
Expand Down Expand Up @@ -92,7 +92,6 @@ foreach(ext ${testgen_targets})
message("-- Enabling target ${ext}")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/targets/${ext})
set(include_statements_var "${include_statements_var}#include \"backends/p4tools/modules/testgen/targets/${ext}/register.h\"\n")
set(compiler_targets_var "${compiler_targets_var} ${ext}RegisterCompilerTarget();\n")
set(testgen_targets_var "${testgen_targets_var} ${ext}RegisterTestgenTarget();\n")
endif()
endif()
Expand Down
26 changes: 26 additions & 0 deletions backends/p4tools/modules/testgen/core/compiler_result.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "backends/p4tools/modules/testgen/core/compiler_result.h"

#include <utility>

#include "backends/p4tools/common/compiler/reachability.h"
#include "midend/coverage.h"

namespace P4Tools::P4Testgen {

TestgenCompilerResult::TestgenCompilerResult(CompilerResult compilerResult,
P4::Coverage::CoverageSet coverableNodes,
const NodesCallGraph *callGraph)
: CompilerResult(std::move(compilerResult)),
coverableNodes(std::move(coverableNodes)),
callGraph(callGraph) {}

const NodesCallGraph &TestgenCompilerResult::getCallGraph() const {
BUG_CHECK(callGraph != nullptr, "The call graph has not been initialized.");
return *callGraph;
}

const P4::Coverage::CoverageSet &TestgenCompilerResult::getCoverableNodes() const {
return coverableNodes;
}

} // namespace P4Tools::P4Testgen
Loading

0 comments on commit d311574

Please sign in to comment.