Skip to content

Commit

Permalink
Make preprocess and getIncludePath const functions.
Browse files Browse the repository at this point in the history
Signed-off-by: fruffy <[email protected]>
  • Loading branch information
fruffy committed Jul 9, 2024
1 parent e135f41 commit c1c375d
Show file tree
Hide file tree
Showing 15 changed files with 103 additions and 72 deletions.
2 changes: 1 addition & 1 deletion backends/dpdk/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ std::vector<const char *> *DpdkOptions::process(int argc, char *const argv[]) {
return remainingOptions;
}

const char *DpdkOptions::getIncludePath() {
const char *DpdkOptions::getIncludePath() const {
char *driverP4IncludePath =
isv1() ? getenv("P4C_14_INCLUDE_PATH") : getenv("P4C_16_INCLUDE_PATH");
cstring path = cstring::empty;
Expand Down
2 changes: 1 addition & 1 deletion backends/dpdk/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class DpdkOptions : public CompilerOptions {
/// Process the command line arguments and set options accordingly.
std::vector<const char *> *process(int argc, char *const argv[]) override;

const char *getIncludePath() override;
const char *getIncludePath() const override;
};

using DpdkContext = P4CContextWithOptions<DpdkOptions>;
Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/modules/smith/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ SmithOptions &SmithOptions::get() {
return INSTANCE;
}

const char *SmithOptions::getIncludePath() {
const char *SmithOptions::getIncludePath() const {
P4C_UNIMPLEMENTED("getIncludePath is not implemented for P4Smith.");
}

Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/modules/smith/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SmithOptions : public AbstractP4cToolOptions {
~SmithOptions() override = default;
static SmithOptions &get();

const char *getIncludePath() override;
const char *getIncludePath() const override;
void processArgs(const std::vector<const char *> &args);

private:
Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/modules/testgen/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ TestgenOptions &TestgenOptions::get() {
return INSTANCE;
}

const char *TestgenOptions::getIncludePath() {
const char *TestgenOptions::getIncludePath() const {
P4C_UNIMPLEMENTED("getIncludePath not implemented for P4Testgen.");
}

Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/modules/testgen/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class TestgenOptions : public AbstractP4cToolOptions {
/// Defaults to the name of the input program, if provided.
std::optional<cstring> testBaseName;

const char *getIncludePath() override;
const char *getIncludePath() const override;

protected:
bool validateOptions() const override;
Expand Down
8 changes: 2 additions & 6 deletions frontends/common/parseInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,21 @@ limitations under the License.
#include "parseInput.h"

#include <cstdio>
#include <iostream>
#include <optional>
#include <sstream>

#include "frontends/p4/fromv1.0/converters.h"
#include "frontends/p4/frontend.h"
#include "frontends/parsers/parserDriver.h"
#include "lib/error.h"
#include "lib/source_file.h"

namespace P4 {

const IR::P4Program *parseP4String(const char *sourceFile, unsigned sourceLine,
const std::string &input,
CompilerOptions::FrontendVersion version) {
std::istringstream stream(input);
auto result =
const auto *result =
version == CompilerOptions::FrontendVersion::P4_14
? parseV1Program<std::istringstream, P4V1::Converter>(stream, sourceFile, sourceLine)
? parseV1Program<std::istringstream &, P4V1::Converter>(stream, sourceFile, sourceLine)
: P4ParserDriver::parse(stream, sourceFile, sourceLine);

if (::errorCount() > 0) {
Expand Down
37 changes: 19 additions & 18 deletions frontends/common/parseInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ limitations under the License.

#include "frontends/common/options.h"
#include "frontends/p4/fromv1.0/converters.h"
#include "frontends/p4/frontend.h"
#include "frontends/parsers/parserDriver.h"
#include "lib/error.h"
#include "lib/source_file.h"

namespace IR {
class P4Program;
Expand All @@ -31,7 +29,7 @@ class P4Program;
namespace P4 {

template <typename Input, typename C = P4V1::Converter>
static const IR::P4Program *parseV1Program(Input &stream, std::string_view sourceFile,
static const IR::P4Program *parseV1Program(Input stream, std::string_view sourceFile,
unsigned sourceLine,
std::optional<DebugHook> debugHook = std::nullopt) {
// We load the model before parsing the input file, so that the SourceInfo
Expand Down Expand Up @@ -61,29 +59,32 @@ static const IR::P4Program *parseV1Program(Input &stream, std::string_view sourc
* on failure. If failure occurs, an error will also be reported.
*/
template <typename C = P4V1::Converter>
const IR::P4Program *parseP4File(ParserOptions &options) {
const IR::P4Program *parseP4File(const ParserOptions &options) {
BUG_CHECK(&options == &P4CContext::get().options(),
"Parsing using options that don't match the current "
"compiler context");
FILE *in = nullptr;

const IR::P4Program *result = nullptr;
if (options.doNotPreprocess) {
in = fopen(options.file.c_str(), "r");
if (in == nullptr) {
auto *file = fopen(options.file.c_str(), "r");
if (file == nullptr) {
::error(ErrorType::ERR_NOT_FOUND, "%1%: No such file or directory.", options.file);
return nullptr;
}
result = options.isv1() ? parseV1Program<FILE *, C>(file, options.file.string(), 1,
options.getDebugHook())
: P4ParserDriver::parse(file, options.file.string());
fclose(file);
} else {
in = options.preprocess();
if (::errorCount() > 0 || in == nullptr) return nullptr;
}

auto result = options.isv1() ? parseV1Program<FILE *, C>(in, options.file.string(), 1,
options.getDebugHook())
: P4ParserDriver::parse(in, options.file.string());
if (options.doNotPreprocess) {
fclose(in);
} else {
options.closePreprocessedInput(in);
auto preprocessorResult = options.preprocess();
if (::errorCount() > 0 || preprocessorResult.file() == nullptr) {
return nullptr;
}
// Need to assign file here because the parser requires an lvalue.
result = options.isv1()
? parseV1Program<FILE *, C>(preprocessorResult.file(), options.file.string(),
1, options.getDebugHook())
: P4ParserDriver::parse(preprocessorResult.file(), options.file.string());
}

if (::errorCount() > 0) {
Expand Down
50 changes: 28 additions & 22 deletions frontends/common/parser_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ const char *p4_14includePath = CONFIG_PKGDATADIR "/p4_14include";

using namespace P4::literals;

void ParserOptions::PreprocessorResult::closeFile() {
if (!_closeInput || _file == nullptr) {
return;
}
int exitCode = pclose(_file);
if (WIFEXITED(exitCode) && WEXITSTATUS(exitCode) == 4) {
::error(ErrorType::ERR_IO, "input file does not exist");
return;
}
if (exitCode != 0) {
::error(ErrorType::ERR_IO, "Preprocessor returned exit code %d; aborting compilation",
exitCode);
return;
}
}

ParserOptions::ParserOptions(std::string_view defaultMessage) : Util::Options(defaultMessage) {
registerOption(
"--help", nullptr,
Expand Down Expand Up @@ -387,7 +403,7 @@ std::vector<const char *> *ParserOptions::process(int argc, char *const argv[])
return remainingOptions;
}

const char *ParserOptions::getIncludePath() {
const char *ParserOptions::getIncludePath() const {
cstring path = cstring::empty;
// the p4c driver sets environment variables for include
// paths. check the environment and add these to the command
Expand All @@ -400,11 +416,11 @@ const char *ParserOptions::getIncludePath() {
return path.c_str();
}

FILE *ParserOptions::preprocess() {
ParserOptions::PreprocessorResult ParserOptions::preprocess() const {
FILE *in = nullptr;
bool closeInput = false;

if (file == "-") {
file = "<stdin>";
in = stdin;
} else {
#ifdef __clang__
Expand All @@ -421,32 +437,22 @@ FILE *ParserOptions::preprocess() {
if (in == nullptr) {
::error(ErrorType::ERR_IO, "Error invoking preprocessor");
perror("");
return nullptr;
return {};
}
close_input = true;
closeInput = true;
}

if (doNotCompile) {
char *line = NULL;
char *line = nullptr;
size_t len = 0;
ssize_t read;
ssize_t read = 0;

while ((read = getline(&line, &len, in)) != -1) printf("%s", line);
closePreprocessedInput(in);
return nullptr;
}
return in;
}

void ParserOptions::closePreprocessedInput(FILE *inputStream) const {
if (close_input) {
int exitCode = pclose(inputStream);
if (WIFEXITED(exitCode) && WEXITSTATUS(exitCode) == 4)
::error(ErrorType::ERR_IO, "input file %s does not exist", file);
else if (exitCode != 0)
::error(ErrorType::ERR_IO, "Preprocessor returned exit code %d; aborting compilation",
exitCode);
while ((read = getline(&line, &len, in)) != -1) {
printf("%s", line);
}
return {};
}
return {in, closeInput};
}

// From (folder, file.ext, suffix) returns
Expand Down
34 changes: 28 additions & 6 deletions frontends/common/parser_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ extern const char *p4_14includePath;
/// This class contains the options for the front-ends.
/// Each back-end should subclass this file.
class ParserOptions : public Util::Options {
bool close_input = false;

/// Annotation names that are to be ignored by the compiler.
std::set<cstring> disabledAnnotations;

Expand All @@ -54,6 +52,32 @@ class ParserOptions : public Util::Options {

std::vector<const char *> *process(int argc, char *const argv[]) override;
enum class FrontendVersion { P4_14, P4_16 };

/// Records the result of the preprocessor.
class PreprocessorResult {
private:
/// The input stream.
FILE *_file = nullptr;
/// Whether the input stream should be closed.
bool _closeInput = false;

/// Tries to close the input stream associated with the result.
void closeFile();

public:
PreprocessorResult() = default;
PreprocessorResult(const PreprocessorResult &) = delete;
PreprocessorResult(PreprocessorResult &&) = default;
PreprocessorResult &operator=(const PreprocessorResult &) = delete;
PreprocessorResult &operator=(PreprocessorResult &&) = default;
PreprocessorResult(FILE *file, bool closeInput) : _file(file), _closeInput(closeInput) {}

~PreprocessorResult() { closeFile(); }

/// @return the input stream.
[[nodiscard]] FILE *file() const { return _file; }
};

/// Name of executable that is being run.
cstring exe_name;
/// Which language to compile
Expand All @@ -77,11 +101,9 @@ class ParserOptions : public Util::Options {
/// Expect that the only remaining argument is the input file.
void setInputFile();
/// Return target specific include path.
const char *getIncludePath() override;
const char *getIncludePath() const override;
/// Returns the output of the preprocessor.
FILE *preprocess();
/// Closes the input stream returned by preprocess.
void closePreprocessedInput(FILE *input) const;
PreprocessorResult preprocess() const;
/// True if we are compiling a P4 v1.0 or v1.1 program
bool isv1() const;
/// Get a debug hook function suitable for insertion
Expand Down
26 changes: 16 additions & 10 deletions frontends/p4/fromv1.0/programStructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,28 +661,34 @@ void ProgramStructure::createParser() {
}

void ProgramStructure::include(cstring filename, cstring ppoptions) {
if (included_files.count(filename)) return;
if (included_files.count(filename) != 0U) {
return;
}
included_files.insert(filename);
// the p4c driver sets environment variables for include
// paths. check the environment and add these to the command
// line for the preporicessor
// line for the preprocessor
char *drvP4IncludePath = getenv("P4C_16_INCLUDE_PATH");
std::filesystem::path path(drvP4IncludePath ? drvP4IncludePath : p4includePath);
std::filesystem::path path((drvP4IncludePath != nullptr) ? drvP4IncludePath : p4includePath);
path /= std::string(filename);

CompilerOptions options;
if (ppoptions) {
if (ppoptions != nullptr) {
options.preprocessor_options += " ";
options.preprocessor_options += ppoptions;
}
options.langVersion = CompilerOptions::FrontendVersion::P4_16;
options.file = path;
if (!::errorCount()) {
if (FILE *file = options.preprocess()) {
auto code = P4::P4ParserDriver::parse(file, options.file.string());
if (code && !::errorCount())
for (auto decl : code->objects) declarations->push_back(decl);
options.closePreprocessedInput(file);
if (::errorCount() == 0U) {
auto preprocessorResult = options.preprocess();
if (preprocessorResult.file() != nullptr) {
const auto *code =
P4::P4ParserDriver::parse(preprocessorResult.file(), options.file.string());
if ((code != nullptr) && (::errorCount() == 0U)) {
for (const auto *decl : code->objects) {
declarations->push_back(decl);
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class Options {
*/
virtual std::vector<const char *> *process(int argc, char *const argv[]);

virtual const char *getIncludePath() = 0;
[[nodiscard]] virtual const char *getIncludePath() const = 0;
cstring getCompileCommand() { return compileCommand; }
cstring getBuildDate() { return buildDate; }
cstring getBinaryName() { return cstring(binaryName); }
Expand Down
1 change: 1 addition & 0 deletions test/gtest/midend_def_use.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ limitations under the License.
#include <string>

#include "frontends/common/parseInput.h"
#include "frontends/p4/frontend.h"
#include "helpers.h"
#include "midend/def_use.h"
#include "midend_pass.h"
Expand Down
2 changes: 1 addition & 1 deletion test/gtest/p4runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ limitations under the License.
#include <google/protobuf/util/message_differencer.h>
#include <gtest/gtest.h>

#include <iterator>
#include <optional>
#include <string>
#include <vector>
Expand All @@ -36,6 +35,7 @@ limitations under the License.
#include "frontends/common/parseInput.h"
#include "frontends/common/resolveReferences/referenceMap.h"
#include "frontends/common/resolveReferences/resolveReferences.h"
#include "frontends/p4/frontend.h"
#include "frontends/p4/parseAnnotations.h"
#include "frontends/p4/typeChecking/typeChecker.h"
#include "frontends/p4/typeMap.h"
Expand Down
3 changes: 1 addition & 2 deletions test/gtest/parser_unroll.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#include <gtest/gtest.h>

#include <cstdlib>
#include <fstream>

#include "frontends/common/parseInput.h"
#include "frontends/p4/frontend.h"
#include "ir/ir.h"
#include "lib/log.h"
#include "test/gtest/env.h"
#include "test/gtest/helpers.h"
#include "test/gtest/midend_pass.h"
Expand Down

0 comments on commit c1c375d

Please sign in to comment.