Skip to content

Commit

Permalink
Unify compiler options and tool options. Ensure tool option context i…
Browse files Browse the repository at this point in the history
…s always initialized correctly.

Signed-off-by: fruffy <[email protected]>
  • Loading branch information
fruffy committed Jul 16, 2024
1 parent cbc3e81 commit 0bb6a4b
Show file tree
Hide file tree
Showing 29 changed files with 230 additions and 381 deletions.
20 changes: 0 additions & 20 deletions backends/p4tools/common/compiler/compiler_target.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#include "backends/p4tools/common/compiler/compiler_target.h"

#include <string>
#include <vector>

#include "backends/p4tools/common/compiler/context.h"
#include "backends/p4tools/common/compiler/midend.h"
#include "backends/p4tools/common/core/target.h"
#include "frontends/common/applyOptionsPragmas.h"
Expand All @@ -16,15 +14,6 @@

namespace P4Tools {

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

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

CompilerResultOrError CompilerTarget::runCompiler(const CompilerOptions &options,
std::string_view toolName) {
const auto *program = P4Tools::CompilerTarget::runParser(options);
Expand Down Expand Up @@ -67,15 +56,6 @@ CompilerResultOrError CompilerTarget::runCompilerImpl(const CompilerOptions &opt
return *new CompilerResult(*program);
}

ICompileContext *CompilerTarget::makeContextImpl() const {
return new CompileContext<CompilerOptions>();
}

std::vector<const char *> *CompilerTarget::initCompilerImpl(int argc, char **argv) const {
auto *result = CompileContext<CompilerOptions>::get().options().process(argc, argv);
return ::errorCount() > 0 ? nullptr : result;
}

const IR::P4Program *CompilerTarget::runParser(const ParserOptions &options) {
const auto *program = P4::parseP4File(options);
if (::errorCount() > 0) {
Expand Down
19 changes: 0 additions & 19 deletions backends/p4tools/common/compiler/compiler_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
#define BACKENDS_P4TOOLS_COMMON_COMPILER_COMPILER_TARGET_H_

#include <string>
#include <vector>

#include "backends/p4tools/common/compiler/compiler_result.h"
#include "backends/p4tools/common/compiler/context.h"
#include "backends/p4tools/common/compiler/midend.h"
#include "backends/p4tools/common/core/target.h"
#include "frontends/common/options.h"
Expand All @@ -19,15 +17,6 @@ namespace P4Tools {
/// 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(std::string_view 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(std::string_view toolName, int argc,
char **argv);

/// Runs the P4 compiler to produce an IR and various other kinds of information on the input
/// program.
///
Expand All @@ -49,18 +38,10 @@ class CompilerTarget : public Target {
std::string_view toolName, const IR::P4Program *);

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

/// @see runCompiler.
virtual CompilerResultOrError runCompilerImpl(const CompilerOptions &options,
const IR::P4Program *) const;

/// This implementation just forwards the given arguments to the compiler.
///
/// @see @initCompiler.
virtual std::vector<const char *> *initCompilerImpl(int argc, char **argv) const;

/// Parses the P4 program specified on the command line.
///
/// @returns nullptr if an error occurs during parsing.
Expand Down
36 changes: 0 additions & 36 deletions backends/p4tools/common/compiler/context.h

This file was deleted.

98 changes: 84 additions & 14 deletions backends/p4tools/common/core/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
#include <map>
#include <optional>
#include <string>
#include <utility>

#include "backends/p4tools/common/lib/variables.h"
#include "ir/irutils.h"

namespace P4Tools {

Target::Spec::Spec(std::string deviceName, std::string archName)
: deviceName(std::move(deviceName)), archName(std::move(archName)) {
Target::Spec::Spec(std::string_view deviceName, std::string_view archName)
: deviceName(deviceName), archName(archName) {
// Convert names to lower case.
std::transform(this->archName.begin(), this->archName.end(), this->archName.begin(), ::tolower);
std::transform(this->deviceName.begin(), this->deviceName.end(), this->deviceName.begin(),
Expand All @@ -37,8 +36,8 @@ std::map<Target::Spec, std::map<std::string, const Target *, std::less<>>> Targe
std::map<std::string, std::string, std::less<>> Target::defaultArchByDevice = {};
std::map<std::string, std::string, std::less<>> Target::defaultDeviceByArch = {};

bool Target::init(std::string deviceName, std::string archName) {
Spec spec(std::move(deviceName), std::move(archName));
bool Target::init(std::string_view deviceName, std::string_view archName) {
Spec spec(deviceName, archName);

if (registry.count(spec) != 0U) {
curTarget = spec;
Expand All @@ -48,23 +47,95 @@ bool Target::init(std::string deviceName, std::string archName) {
return false;
}

bool Target::setDevice(std::string deviceName) {
std::transform(deviceName.begin(), deviceName.end(), deviceName.begin(), ::tolower);
if (defaultArchByDevice.count(deviceName) == 0U) {
std::optional<ICompileContext *> Target::initializeTarget(std::string_view toolName,
std::string_view target,
std::string_view arch) {
// Establish a dummy compilation context so that we can use ::error to report errors while
// processing target and arch.
class DummyCompileContext : public BaseCompileContext {
} dummyContext;
AutoCompileContext autoDummyContext(&dummyContext);
if (!P4Tools::Target::setDevice(target)) {
::error("Unsupported device: %s", target);
return std::nullopt;
}
if (!P4Tools::Target::setArch(arch)) {
::error("Unsupported architecture: %s", arch);
return std::nullopt;
}
const auto &instances = registry.at(*curTarget);
auto instance = instances.find(toolName);
BUG_CHECK(instance != instances.end(), "Architecture %1% on device %2% not supported for %3%",
curTarget->archName, curTarget->deviceName, toolName);

return instance->second->makeContext();
}

std::optional<ICompileContext *> Target::initializeTarget(std::string_view toolName,
const std::vector<const char *> &args) {
// Establish a dummy compilation context so that we can use ::error to report errors while
// processing target and arch.
class DummyCompileContext : public BaseCompileContext {
} dummyContext;
AutoCompileContext autoDummyContext(&dummyContext);
if (args.size() < 3) {
::error("Missing --target and --arch arguments");
return std::nullopt;
}
std::optional<std::string> target;
std::optional<std::string> arch;
// Loop through arguments (skip the program name)
for (size_t i = 1; i < args.size(); ++i) {
const std::string &arg = args[i];
if (arg == "--arch") {
if (i + 1 < args.size()) {
arch = args[i + 1];
} else {
::error("Missing architecture name after --arch");
return std::nullopt;
}
}
if (arg == "--target") {
if (i + 1 < args.size()) {
target = args[i + 1];
} else {
::error("Missing device name after --target");
return std::nullopt;
}
}
}
if (!target) {
::error("Missing --target argument");
return std::nullopt;
}
if (!arch) {
::error("Missing --arch argument");
return std::nullopt;
}
return initializeTarget(toolName, target.value(), arch.value());
}

bool Target::setDevice(std::string_view deviceName) {
std::string lowerCaseDeviceName(deviceName);
std::transform(lowerCaseDeviceName.begin(), lowerCaseDeviceName.end(),
lowerCaseDeviceName.begin(), ::tolower);
if (defaultArchByDevice.count(lowerCaseDeviceName) == 0U) {
return false;
}

auto archName = curTarget ? curTarget->archName : defaultArchByDevice.at(deviceName);
auto archName = curTarget ? curTarget->archName : defaultArchByDevice.at(deviceName.data());
return init(deviceName, archName);
}

bool Target::setArch(std::string archName) {
std::transform(archName.begin(), archName.end(), archName.begin(), ::tolower);
if (defaultDeviceByArch.count(archName) == 0U) {
bool Target::setArch(std::string_view archName) {
std::string lowerCaseArchName(archName);
std::transform(lowerCaseArchName.begin(), lowerCaseArchName.end(), lowerCaseArchName.begin(),
::tolower);
if (defaultDeviceByArch.count(lowerCaseArchName) == 0U) {
return false;
}

auto deviceName = curTarget ? curTarget->deviceName : defaultDeviceByArch.at(archName);
auto deviceName = curTarget ? curTarget->deviceName : defaultDeviceByArch.at(archName.data());
return init(deviceName, archName);
}

Expand Down Expand Up @@ -92,5 +163,4 @@ Target::Target(std::string_view toolName, const std::string &deviceName,
defaultArchByDevice[spec.deviceName] = spec.archName;
}
}

} // namespace P4Tools
21 changes: 17 additions & 4 deletions backends/p4tools/common/core/target.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#ifndef BACKENDS_P4TOOLS_COMMON_CORE_TARGET_H_
#define BACKENDS_P4TOOLS_COMMON_CORE_TARGET_H_

#include <cstdlib>
#include <map>
#include <optional>
#include <string>

#include "ir/ir.h"
#include "lib/compile_context.h"
#include "lib/exceptions.h"

namespace P4Tools {
Expand All @@ -22,7 +24,7 @@ class Target {
std::string archName;

/// Names provided to this constructor are converted to lower case.
Spec(std::string deviceName, std::string archName);
Spec(std::string_view deviceName, std::string_view archName);

/// Lexicographic ordering on (deviceName, archName).
bool operator<(const Spec &) const;
Expand All @@ -32,23 +34,23 @@ class Target {
///
/// @returns true on success. If initialization fails, false is returned, and nothing is
/// changed.
static bool init(std::string deviceName, std::string archName);
static bool init(std::string_view deviceName, std::string_view archName);

/// Initializes the global target device to @deviceName without changing the architecture. If
/// no architecture was previously selected, then the first architecture registered for the
/// device is chosen.
///
/// @returns true on success. If initialization fails, false is returned, and nothing is
/// changed.
static bool setDevice(std::string deviceName);
static bool setDevice(std::string_view deviceName);

/// Initializes the global target architecture to @archName without changing the device. If no
/// device was previously selected, then the first device registered for the architecture is
/// chosen.
///
/// @returns true on success. If initialization fails, false is returned, and nothing is
/// changed.
static bool setArch(std::string archName);
static bool setArch(std::string_view archName);

/// The name of the tool supported by this instance.
std::string toolName;
Expand All @@ -67,11 +69,22 @@ class Target {
virtual const IR::Expression *createTargetUninitialized(const IR::Type *type,
bool forceTaint) const;

/// Initializes the global target device and architecture to @deviceName and @archName.
/// Returns 0 on success. If initialization fails, returns -1.
static std::optional<ICompileContext *> initializeTarget(std::string_view toolName,
const std::vector<const char *> &args);
static std::optional<ICompileContext *> initializeTarget(std::string_view toolName,
std::string_view target,
std::string_view arch);

protected:
/// Creates and registers a new Target instance for the given @toolName, @deviceName, and
/// @archName.
Target(std::string_view toolName, const std::string &deviceName, const std::string &archName);

/// @returns a new compilation context for the compiler.
[[nodiscard]] virtual ICompileContext *makeContext() const = 0;

/// @returns the target instance for the given tool and active target, as selected by @init.
//
// Implemented here because of limitations of templates.
Expand Down
Loading

0 comments on commit 0bb6a4b

Please sign in to comment.