Skip to content

Commit

Permalink
Steps 1: Extend the CompilerTarget runProgram function with data stru…
Browse files Browse the repository at this point in the history
…ctures which can pass on more information.
  • Loading branch information
fruffy committed Jan 4, 2024
1 parent 5cb2c18 commit e437009
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 77 deletions.
16 changes: 9 additions & 7 deletions backends/p4tools/common/compiler/compiler_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <vector>

#include "backends/p4tools/common/compiler/context.h"
#include "backends/p4tools/common/compiler/convert_hs_index.h"
#include "backends/p4tools/common/compiler/midend.h"
#include "backends/p4tools/common/core/target.h"
#include "frontends/common/applyOptionsPragmas.h"
Expand All @@ -18,13 +17,17 @@

namespace P4Tools {

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

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

ICompileContext *CompilerTarget::makeContext() { return get().makeContextImpl(); }

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

std::optional<const IR::P4Program *> CompilerTarget::runCompiler() {
std::optional<const CompilerResult *> CompilerTarget::runCompiler() {
const auto *program = P4Tools::CompilerTarget::runParser();
if (program == nullptr) {
return std::nullopt;
Expand All @@ -33,7 +36,7 @@ std::optional<const IR::P4Program *> CompilerTarget::runCompiler() {
return runCompiler(program);
}

std::optional<const IR::P4Program *> CompilerTarget::runCompiler(const std::string &source) {
std::optional<const CompilerResult *> CompilerTarget::runCompiler(const std::string &source) {
const auto *program = P4::parseP4String(source, P4CContext::get().options().langVersion);
if (program == nullptr) {
return std::nullopt;
Expand All @@ -42,11 +45,11 @@ std::optional<const IR::P4Program *> CompilerTarget::runCompiler(const std::stri
return runCompiler(program);
}

std::optional<const IR::P4Program *> CompilerTarget::runCompiler(const IR::P4Program *program) {
std::optional<const CompilerResult *> CompilerTarget::runCompiler(const IR::P4Program *program) {
return get().runCompilerImpl(program);
}

std::optional<const IR::P4Program *> CompilerTarget::runCompilerImpl(
std::optional<const CompilerResult *> CompilerTarget::runCompilerImpl(
const IR::P4Program *program) const {
const auto &self = get();

Expand All @@ -60,7 +63,7 @@ std::optional<const IR::P4Program *> CompilerTarget::runCompilerImpl(
return std::nullopt;
}

return program;
return new CompilerResult(*program);
}

ICompileContext *CompilerTarget::makeContextImpl() const {
Expand Down Expand Up @@ -119,5 +122,4 @@ CompilerTarget::CompilerTarget(std::string deviceName, std::string archName)
: Target("compiler", std::move(deviceName), std::move(archName)) {}

const CompilerTarget &CompilerTarget::get() { return Target::get<CompilerTarget>("compiler"); }

} // namespace P4Tools
32 changes: 25 additions & 7 deletions backends/p4tools/common/compiler/compiler_target.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_TARGET_H_
#define BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_TARGET_H_

#include <functional>
#include <optional>
#include <string>
#include <vector>
Expand All @@ -10,10 +11,26 @@
#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;
};

/// Encapsulates the details of invoking the P4 compiler for a target device and architecture.
class CompilerTarget : public Target {
public:
Expand All @@ -25,28 +42,29 @@ class CompilerTarget : public Target {
/// @returns any unprocessed arguments, or nullptr if there was an error.
static std::vector<const char *> *initCompiler(int argc, char **argv);

/// Runs the P4 compiler to produce an IR.
/// 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 std::optional<const IR::P4Program *> runCompiler();
static std::optional<const CompilerResult *> runCompiler();

/// Runs the P4 compiler to produce an IR for the given source code.
/// 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 std::optional<const IR::P4Program *> runCompiler(const std::string &source);
static std::optional<const CompilerResult *> runCompiler(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 std::optional<const IR::P4Program *> runCompiler(const IR::P4Program *);
static std::optional<const CompilerResult *> runCompiler(const IR::P4Program *);

protected:
/// @see @makeContext.
virtual ICompileContext *makeContextImpl() const;
[[nodiscard]] virtual ICompileContext *makeContextImpl() const;

/// @see runCompiler.
virtual std::optional<const IR::P4Program *> runCompilerImpl(const IR::P4Program *) const;
virtual std::optional<const CompilerResult *> runCompilerImpl(const IR::P4Program *) const;

/// This implementation just forwards the given arguments to the compiler.
///
Expand Down
13 changes: 6 additions & 7 deletions backends/p4tools/common/p4ctool.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#ifndef BACKENDS_P4TOOLS_COMMON_P4CTOOL_H_
#define BACKENDS_P4TOOLS_COMMON_P4CTOOL_H_

#include <cstdlib>
#include <vector>

#include "backends/p4tools/common/compiler/compiler_target.h"
#include "backends/p4tools/common/core/target.h"
#include "ir/ir.h"

namespace P4Tools {

Expand All @@ -19,7 +18,7 @@ class AbstractP4cTool {
/// Provides the implementation of the tool.
///
/// @param program The P4 program after mid-end processing.
virtual int mainImpl(const IR::P4Program *program) = 0;
virtual int mainImpl(const CompilerResult &compilerResult) = 0;

virtual void registerTarget() = 0;

Expand All @@ -41,11 +40,11 @@ class AbstractP4cTool {
AutoCompileContext autoContext(*compileContext);

// Run the compiler to get an IR and invoke the tool.
const auto program = P4Tools::CompilerTarget::runCompiler();
if (!program) {
return 1;
const auto compilerResult = P4Tools::CompilerTarget::runCompiler();
if (!compilerResult.has_value()) {
return EXIT_FAILURE;
}
return mainImpl(*program);
return mainImpl(*compilerResult.value());
}
};

Expand Down
1 change: 0 additions & 1 deletion backends/p4tools/modules/testgen/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <vector>

#include "lib/crash.h"
#include "lib/exceptions.h"

#include "backends/p4tools/modules/testgen/testgen.h"

Expand Down
29 changes: 29 additions & 0 deletions backends/p4tools/modules/testgen/targets/bmv2/bmv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

namespace P4Tools::P4Testgen::Bmv2 {

BMv2V1ModelCompilerResult::BMv2V1ModelCompilerResult(const IR::P4Program &program,
P4::P4RuntimeAPI p4runtimeApi)
: CompilerResult(program), p4runtimeApi(p4runtimeApi) {}

const P4::P4RuntimeAPI &BMv2V1ModelCompilerResult::getP4RuntimeApi() const { return p4runtimeApi; }

Bmv2V1ModelCompilerTarget::Bmv2V1ModelCompilerTarget() : CompilerTarget("bmv2", "v1model") {}

void Bmv2V1ModelCompilerTarget::make() {
Expand All @@ -23,6 +29,25 @@ void Bmv2V1ModelCompilerTarget::make() {
}
}

std::optional<const CompilerResult *> Bmv2V1ModelCompilerTarget::runCompilerImpl(
const IR::P4Program *program) const {
const auto &self = get();

program = self.runFrontend(program);
if (program == nullptr) {
return std::nullopt;
}
/// After the front end, get the P4Runtime API for the V1model architecture.
auto p4runtimeApi = P4::P4RuntimeSerializer::get()->generateP4Runtime(program, "v1model");

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

return new BMv2V1ModelCompilerResult{*program, p4runtimeApi};
}

MidEnd Bmv2V1ModelCompilerTarget::mkMidEnd(const CompilerOptions &options) const {
MidEnd midEnd(options);
auto *refMap = midEnd.getRefMap();
Expand All @@ -42,4 +67,8 @@ MidEnd Bmv2V1ModelCompilerTarget::mkMidEnd(const CompilerOptions &options) const
return midEnd;
}

const Bmv2V1ModelCompilerTarget &Bmv2V1ModelCompilerTarget::get() {
return Target::get<Bmv2V1ModelCompilerTarget>("V1ModelCompiler");
}

} // namespace P4Tools::P4Testgen::Bmv2
20 changes: 19 additions & 1 deletion backends/p4tools/modules/testgen/targets/bmv2/bmv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,33 @@

namespace P4Tools::P4Testgen::Bmv2 {

/// Extends the CompilerResult with the associated P4RuntimeApi
class BMv2V1ModelCompilerResult : public CompilerResult {
private:
/// The runtimeAPI inferred from this particular BMv2 V1Model P4 program.
P4::P4RuntimeAPI p4runtimeApi;

public:
explicit BMv2V1ModelCompilerResult(const IR::P4Program &program, P4::P4RuntimeAPI p4runtimeApi);

[[nodiscard]] const P4::P4RuntimeAPI &getP4RuntimeApi() const;
};

class Bmv2V1ModelCompilerTarget : public CompilerTarget {
public:
/// Registers this target.
static void make();

private:
MidEnd mkMidEnd(const CompilerOptions &options) const override;
[[nodiscard]] MidEnd mkMidEnd(const CompilerOptions &options) const override;

std::optional<const CompilerResult *> runCompilerImpl(
const IR::P4Program *program) const override;

Bmv2V1ModelCompilerTarget();

/// @returns the singleton instance for the current target.
static const Bmv2V1ModelCompilerTarget &get();
};

} // namespace P4Tools::P4Testgen::Bmv2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ TEST_F(SmallStepTest, Binary01) {
const auto test = createSmallStepExprTest("bit<8> f;", "8w42 + hdr.h.f");
ASSERT_TRUE(test);

const auto *opBin = extractExpr<IR::Operation_Binary>(test->program);
const auto *opBin = extractExpr<IR::Operation_Binary>(test->getProgram());
ASSERT_TRUE(opBin);

// Step on the binary operation and examine the resulting continuation
// to include the rebuilt IR::Add node.
stepAndExamineOp(opBin, opBin->right, test->program, [opBin](const IR::PathExpression *expr) {
return new IR::Add(opBin->left, expr);
});
stepAndExamineOp(
opBin, opBin->right, test->getProgram(),
[opBin](const IR::PathExpression *expr) { return new IR::Add(opBin->left, expr); });
}

/// Test the step function for e + e binary operation.
Expand All @@ -39,44 +39,44 @@ TEST_F(SmallStepTest, Binary02) {
"hdr.h.f1 + hdr.h.f2");
ASSERT_TRUE(test);

const auto *opBin = extractExpr<IR::Operation_Binary>(test->program);
const auto *opBin = extractExpr<IR::Operation_Binary>(test->getProgram());
ASSERT_TRUE(opBin);

// Step on the binary operation and examine the resulting continuation
// to include the rebuilt IR::Add node.
stepAndExamineOp(opBin, opBin->left, test->program, [opBin](const IR::PathExpression *expr) {
return new IR::Add(expr, opBin->right);
});
stepAndExamineOp(
opBin, opBin->left, test->getProgram(),
[opBin](const IR::PathExpression *expr) { return new IR::Add(expr, opBin->right); });
}

/// Test the step function for e == v binary operation.
TEST_F(SmallStepTest, Binary03) {
const auto test = createSmallStepExprTest("bit<8> f;", "hdr.h.f == 8w42");
ASSERT_TRUE(test);

const auto *opBin = extractExpr<IR::Operation_Binary>(test->program);
const auto *opBin = extractExpr<IR::Operation_Binary>(test->getProgram());
ASSERT_TRUE(opBin);

// Step on the binary operation and examine the resulting continuation
// to include the rebuilt IR::Equ node.
stepAndExamineOp(opBin, opBin->left, test->program, [opBin](const IR::PathExpression *expr) {
return new IR::Equ(expr, opBin->right);
});
stepAndExamineOp(
opBin, opBin->left, test->getProgram(),
[opBin](const IR::PathExpression *expr) { return new IR::Equ(expr, opBin->right); });
}

/// Test the step function for v ++ e binary operation.
TEST_F(SmallStepTest, Binary04) {
const auto test = createSmallStepExprTest("bit<8> f;", "8w42 ++ hdr.h.f");
ASSERT_TRUE(test);

const auto *opBin = extractExpr<IR::Operation_Binary>(test->program);
const auto *opBin = extractExpr<IR::Operation_Binary>(test->getProgram());
ASSERT_TRUE(opBin);

// Step on the binary operation and examine the resulting continuation
// to include the rebuilt IR::Concat node.
stepAndExamineOp(opBin, opBin->right, test->program, [opBin](const IR::PathExpression *expr) {
return new IR::Concat(opBin->left, expr);
});
stepAndExamineOp(
opBin, opBin->right, test->getProgram(),
[opBin](const IR::PathExpression *expr) { return new IR::Concat(opBin->left, expr); });
}

} // anonymous namespace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ TEST_F(SmallStepTest, Unary01) {
const auto test = createSmallStepExprTest("bit<8> f;", "-(hdr.h.f)");
ASSERT_TRUE(test);

const auto *opUn = extractExpr<IR::Operation_Unary>(test->program);
const auto *opUn = extractExpr<IR::Operation_Unary>(test->getProgram());
ASSERT_TRUE(opUn);

// Step on the unary operation and examine the resulting continuation
// to include the rebuilt IR::Neg node.
stepAndExamineOp(opUn, opUn->expr, test->program,
stepAndExamineOp(opUn, opUn->expr, test->getProgram(),
[](const IR::PathExpression *expr) { return new IR::Neg(expr); });
}

Expand All @@ -35,12 +35,12 @@ TEST_F(SmallStepTest, Unary02) {
const auto test = createSmallStepExprTest("bool f;", "!(hdr.h.f)");
ASSERT_TRUE(test);

const auto *opUn = extractExpr<IR::Operation_Unary>(test->program);
const auto *opUn = extractExpr<IR::Operation_Unary>(test->getProgram());
ASSERT_TRUE(opUn);

// Step on the unary operation and examine the resulting continuation
// to include the rebuilt IR::LNot node.
stepAndExamineOp(opUn, opUn->expr, test->program, [](const IR::PathExpression *expr) {
stepAndExamineOp(opUn, opUn->expr, test->getProgram(), [](const IR::PathExpression *expr) {
return new IR::LNot(IR::Type_Boolean::get(), expr);
});
}
Expand All @@ -50,12 +50,12 @@ TEST_F(SmallStepTest, Unary03) {
const auto test = createSmallStepExprTest("bit<8> f;", "~(hdr.h.f)");
ASSERT_TRUE(test);

const auto *opUn = extractExpr<IR::Operation_Unary>(test->program);
const auto *opUn = extractExpr<IR::Operation_Unary>(test->getProgram());
ASSERT_TRUE(opUn);

// Step on the unary operation and examine the resulting continuation
// to include the rebuilt IR::Cmpl node.
stepAndExamineOp(opUn, opUn->expr, test->program,
stepAndExamineOp(opUn, opUn->expr, test->getProgram(),
[](const IR::PathExpression *expr) { return new IR::Cmpl(expr); });
}

Expand Down
Loading

0 comments on commit e437009

Please sign in to comment.