Skip to content

Commit

Permalink
Add a formatter binary skeleton as P4C back end (#4710)
Browse files Browse the repository at this point in the history
* init: p4 formatter

Signed-off-by: Nitish <[email protected]>

* eliminate implicit char* -> cstring conversion in `P4fmtOptions`

---------

Signed-off-by: Nitish <[email protected]>
  • Loading branch information
snapdgn authored Jun 7, 2024
1 parent 8d6bb9d commit 6359549
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ OPTION (ENABLE_EBPF "Build the EBPF backend (required for the full test suite)"
OPTION (ENABLE_UBPF "Build the uBPF backend (required for the full test suite)" ON)
OPTION (ENABLE_DPDK "Build the DPDK backend (required for the full test suite)" ON)
OPTION (ENABLE_P4TC "Build the P4TC backend" ON)
OPTION (ENABLE_P4FMT "Build the P4FMT backend" ON)
OPTION (ENABLE_P4TEST "Build the P4Test backend (required for the full test suite)" ON)
OPTION (ENABLE_TEST_TOOLS "Build the P4Tools development platform" OFF)
OPTION (ENABLE_P4C_GRAPHS "Build the p4c-graphs backend" ON)
Expand Down Expand Up @@ -479,6 +480,9 @@ endif ()
if (ENABLE_TEST_TOOLS)
add_subdirectory (backends/p4tools)
endif ()
if (ENABLE_P4FMT)
add_subdirectory (backends/p4fmt)
endif ()
if (ENABLE_UBPF)
add_subdirectory (backends/ubpf)
endif ()
Expand Down
14 changes: 14 additions & 0 deletions backends/p4fmt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
set(FMT_SRCS
p4fmt.cpp
options.cpp
)

add_executable(p4fmt ${FMT_SRCS})
target_link_libraries(p4fmt ${P4C_LIBRARIES} ${P4C_LIB_DEPS})
add_dependencies(p4fmt frontend)

add_custom_target(p4formatter
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_BINARY_DIR}/p4fmt ${P4C_BINARY_DIR}/p4fmt
)

add_dependencies(p4c_driver p4formatter)
27 changes: 27 additions & 0 deletions backends/p4fmt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# p4fmt (P4 Formatter)

p4fmt is a WIP formatter for P4. It's in a highly experimental phase
and, not yet stable/reliable for general use.
Contributions and feedbacks from the community
would be highly appreciated.

## Build
- Setup P4C correctly, from [here](https://github.com/p4lang/p4c#dependencies).

- Follow the instructions here to [build](https://github.com/p4lang/p4c#installing-p4c-from-source).

Later `p4fmt` executable can be found inside the `p4c/build/` dir, and can be invoked as `./build/p4fmt` from p4c's root dir.

## Usage
- Takes an output file with a `-o` flag and writes to it.

`./build/p4fmt <p4 source file> -o <output_file>`

- If an output file is not provided with `-o` flag, it just prints the output on the stdout.

`./build/p4fmt <p4 source file>`

Sample Usage:

./build/p4fmt/p4fmt sample.p4
./build/p4fmt/p4fmt sample.p4 -o out.p4
17 changes: 17 additions & 0 deletions backends/p4fmt/options.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "options.h"

namespace P4Fmt {

P4fmtOptions::P4fmtOptions() {
registerOption(
"-o", "outfile",
[this](const char *arg) {
outFile = cstring(arg);
return true;
},
"Write formatted output to outfile");
}

const cstring &P4fmtOptions::outputFile() const { return outFile; }

} // namespace P4Fmt
29 changes: 29 additions & 0 deletions backends/p4fmt/options.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef BACKENDS_P4FMT_OPTIONS_H_
#define BACKENDS_P4FMT_OPTIONS_H_

#include "frontends/common/options.h"
#include "frontends/common/parser_options.h"

namespace P4Fmt {

class P4fmtOptions : public CompilerOptions {
public:
P4fmtOptions();
virtual ~P4fmtOptions() = default;
P4fmtOptions(const P4fmtOptions &) = default;
P4fmtOptions(P4fmtOptions &&) = delete;
P4fmtOptions &operator=(const P4fmtOptions &) = default;
P4fmtOptions &operator=(P4fmtOptions &&) = delete;

const cstring &outputFile() const;

private:
/// File to output to.
cstring outFile = nullptr;
};

using P4FmtContext = P4CContextWithOptions<P4fmtOptions>;

} // namespace P4Fmt

#endif /* BACKENDS_P4FMT_OPTIONS_H_ */
52 changes: 52 additions & 0 deletions backends/p4fmt/p4fmt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <cstdlib>

#include "frontends/common/parseInput.h"
#include "frontends/common/parser_options.h"
#include "frontends/p4/toP4/toP4.h"
#include "ir/ir.h"
#include "lib/compile_context.h"
#include "lib/cstring.h"
#include "lib/error.h"
#include "lib/nullstream.h"
#include "options.h"
#include "test/gtest/helpers.h"

int main(int argc, char *const argv[]) {
AutoCompileContext autoP4FmtContext(new P4Fmt::P4FmtContext);
auto &options = P4Fmt::P4FmtContext::get().options();

if (options.process(argc, argv) == nullptr) {
return EXIT_FAILURE;
}

options.setInputFile();

std::ostream *out = nullptr;

// Write to stdout in absence of an output file.
if (options.outputFile().isNullOrEmpty()) {
out = &std::cout;
} else {
out = openFile(options.outputFile(), false);
if (!(*out)) {
::error(ErrorType::ERR_NOT_FOUND, "%2%: No such file or directory.",
options.outputFile());
options.usage();
return EXIT_FAILURE;
}
}

const IR::P4Program *program = P4::parseP4File(options);

if (program == nullptr && ::errorCount() != 0) {
return EXIT_FAILURE;
}

auto top4 = P4::ToP4(out, false);

*out << "\n############################## INITIAL ##############################\n";
// Print the program before running front end passes.
program->apply(top4);

return ::errorCount() > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

0 comments on commit 6359549

Please sign in to comment.