aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/include/rcc/CodeGen/CommandFlags.h72
-rw-r--r--backend/include/rcc/Tooling/BackendDriver.h1
-rw-r--r--backend/include/rcc/Tooling/BackendInvocation.h33
-rw-r--r--backend/include/rcc/Tooling/PipelineDriver.h2
-rw-r--r--backend/lib/CodeGen/CMakeLists.txt4
-rw-r--r--backend/lib/CodeGen/CommandFlags.cpp233
-rw-r--r--backend/lib/CodeGen/MachinePseudoExpansion.cpp2
-rw-r--r--backend/lib/CodeGen/MachineSSAExit.cpp4
-rw-r--r--backend/lib/CodeGen/PostRAScheduler.cpp2
-rw-r--r--backend/lib/CodeGen/PrologueEpilogueInsertion.cpp2
-rw-r--r--backend/lib/Tooling/BackendDriver.cpp44
-rw-r--r--backend/lib/Tooling/BackendInvocation.cpp74
-rw-r--r--backend/lib/Tooling/MIRFuzzer.cpp18
-rw-r--r--backend/lib/Tooling/PipelineDriver.cpp105
-rw-r--r--backend/tools/MIRTool/CMakeLists.txt4
-rw-r--r--backend/tools/MIRTool/MIRToolMain.cpp221
-rw-r--r--backend/tools/MIRTool/MIRToolOperationsTest.cmake34
-rw-r--r--backend/tools/MIRTool/MIRToolOutputTest.cmake8
-rw-r--r--backend/tools/MIRTool/MIRToolStageTest.cmake64
-rw-r--r--backend/unittests/Tooling/BackendManifestTest.cpp6
-rw-r--r--backend/unittests/Tooling/PipelineDriverTest.cpp22
21 files changed, 620 insertions, 335 deletions
diff --git a/backend/include/rcc/CodeGen/CommandFlags.h b/backend/include/rcc/CodeGen/CommandFlags.h
new file mode 100644
index 0000000..0ee2f0d
--- /dev/null
+++ b/backend/include/rcc/CodeGen/CommandFlags.h
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_COMMANDFLAGS_H
+#define RCC_CODEGEN_COMMANDFLAGS_H
+
+#include "rcc/Support/Error.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <span>
+#include <string>
+#include <string_view>
+#include <vector>
+
+namespace rcc {
+
+enum class RelocationModel : std::uint8_t {
+ Static,
+ PositionIndependent,
+};
+
+enum class CodeModel : std::uint8_t {
+ Small,
+ Medium,
+ Large,
+};
+
+enum class OptimizationLevel : std::uint8_t {
+ O0,
+ O1,
+ O2,
+ O3,
+ Os,
+ Oz,
+};
+
+enum class CodeGenFileType : std::uint8_t {
+ AssemblyFile,
+ ObjectFile,
+ Null,
+};
+
+struct CodeGenCommandFlags final {
+ std::optional<std::string> Triple;
+ std::optional<std::string> CPU;
+ std::optional<std::string> TuneCPU;
+ std::optional<std::string> ABI;
+ std::vector<std::string> FeatureOverrides;
+ std::optional<RelocationModel> Relocation;
+ std::optional<CodeModel> Code;
+ std::optional<OptimizationLevel> Optimization;
+ CodeGenFileType FileType = CodeGenFileType::AssemblyFile;
+ bool FileTypeWasSpecified = false;
+};
+
+[[nodiscard]] std::string_view spelling(RelocationModel Value) noexcept;
+[[nodiscard]] std::string_view spelling(CodeModel Value) noexcept;
+[[nodiscard]] std::string_view spelling(OptimizationLevel Value) noexcept;
+[[nodiscard]] std::string_view spelling(CodeGenFileType Value) noexcept;
+
+[[nodiscard]] Expected<RelocationModel> parseRelocationModel(std::string_view Value);
+[[nodiscard]] Expected<CodeModel> parseCodeModel(std::string_view Value);
+[[nodiscard]] Expected<OptimizationLevel> parseOptimizationLevel(std::string_view Value);
+[[nodiscard]] Expected<CodeGenFileType> parseCodeGenFileType(std::string_view Value);
+[[nodiscard]] Expected<bool> parseCodeGenCommandFlag(std::span<const std::string_view> Arguments,
+ std::size_t &Index,
+ CodeGenCommandFlags &Flags);
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_COMMANDFLAGS_H
diff --git a/backend/include/rcc/Tooling/BackendDriver.h b/backend/include/rcc/Tooling/BackendDriver.h
index f762c1e..7b62b6d 100644
--- a/backend/include/rcc/Tooling/BackendDriver.h
+++ b/backend/include/rcc/Tooling/BackendDriver.h
@@ -46,7 +46,6 @@ runBackend(CanonicalMIR Input, const TargetDescription &Target, const BackendInv
MachinePassInstrumentation *Instrumentation = nullptr);
[[nodiscard]] std::string_view spelling(BackendOutputKind Output) noexcept;
-[[nodiscard]] Expected<BackendOutputKind> parseBackendOutputKind(std::string_view Value);
[[nodiscard]] ArtifactKind manifestArtifactKind(BackendOutputKind Output) noexcept;
[[nodiscard]] Expected<ArtifactKind> cacheArtifactKind(BackendOutputKind Output);
diff --git a/backend/include/rcc/Tooling/BackendInvocation.h b/backend/include/rcc/Tooling/BackendInvocation.h
index db1c5d2..d61f038 100644
--- a/backend/include/rcc/Tooling/BackendInvocation.h
+++ b/backend/include/rcc/Tooling/BackendInvocation.h
@@ -3,6 +3,7 @@
#ifndef RCC_TOOLING_BACKENDINVOCATION_H
#define RCC_TOOLING_BACKENDINVOCATION_H
+#include "rcc/CodeGen/CommandFlags.h"
#include "rcc/Support/Error.h"
#include <cstdint>
@@ -25,26 +26,6 @@ inline constexpr std::string_view GenericOpcodeReferenceVersion = "rcc-generic-o
inline constexpr std::string_view RV64GCTargetABILoweringVersion = "rcc-rv64gc-lp64d-v1";
inline constexpr std::string_view CompilerBuildFingerprint = "rcc-backend-0.1.0-stage17";
-enum class RelocationModel : std::uint8_t {
- Static,
- PositionIndependent,
-};
-
-enum class CodeModel : std::uint8_t {
- Small,
- Medium,
- Large,
-};
-
-enum class OptimizationLevel : std::uint8_t {
- O0,
- O1,
- O2,
- O3,
- Os,
- Oz,
-};
-
enum class LayoutOwnership : std::uint8_t {
NativeObject,
CompilerFinalLayout,
@@ -74,14 +55,14 @@ struct BackendInvocation final {
std::vector<std::string> Features;
std::string ABI;
std::string DataLayout;
- RelocationModel Relocation = RelocationModel::PositionIndependent;
- CodeModel Code = CodeModel::Small;
+ rcc::RelocationModel Relocation = rcc::RelocationModel::PositionIndependent;
+ rcc::CodeModel Code = rcc::CodeModel::Small;
std::vector<BackendOption> TargetOptions;
LayoutOwnership Layout = LayoutOwnership::NativeObject;
std::string AssemblerFlavor;
std::string AssemblerVersion;
std::vector<BackendOption> AssemblerOptions;
- OptimizationLevel Optimization = OptimizationLevel::O2;
+ rcc::OptimizationLevel Optimization = rcc::OptimizationLevel::O2;
std::vector<std::string> PassPipeline{"default"};
DeterminismOptions Determinism;
std::optional<std::uint64_t> ActionFuel;
@@ -104,13 +85,7 @@ computeTargetDescriptionFingerprint(const TargetDescription &Target);
const BackendInvocation &Invocation,
std::string_view TargetFingerprint);
-[[nodiscard]] std::string_view spelling(RelocationModel Value) noexcept;
-[[nodiscard]] std::string_view spelling(CodeModel Value) noexcept;
-[[nodiscard]] std::string_view spelling(OptimizationLevel Value) noexcept;
[[nodiscard]] std::string_view spelling(LayoutOwnership Value) noexcept;
-[[nodiscard]] Expected<RelocationModel> parseRelocationModel(std::string_view Value);
-[[nodiscard]] Expected<CodeModel> parseCodeModel(std::string_view Value);
-[[nodiscard]] Expected<OptimizationLevel> parseOptimizationLevel(std::string_view Value);
[[nodiscard]] Expected<LayoutOwnership> parseLayoutOwnership(std::string_view Value);
} // namespace tooling
diff --git a/backend/include/rcc/Tooling/PipelineDriver.h b/backend/include/rcc/Tooling/PipelineDriver.h
index d6c9f58..5d2dc45 100644
--- a/backend/include/rcc/Tooling/PipelineDriver.h
+++ b/backend/include/rcc/Tooling/PipelineDriver.h
@@ -36,6 +36,8 @@ enum class SnapshotPhase : std::uint8_t {
};
struct PipelineControls final {
+ std::optional<std::string> StartBefore;
+ std::optional<std::string> StartAfter;
std::optional<std::string> StopBefore;
std::optional<std::string> StopAfter;
std::vector<std::string> PrintBefore;
diff --git a/backend/lib/CodeGen/CMakeLists.txt b/backend/lib/CodeGen/CMakeLists.txt
index d25d164..e584131 100644
--- a/backend/lib/CodeGen/CMakeLists.txt
+++ b/backend/lib/CodeGen/CMakeLists.txt
@@ -3,6 +3,7 @@
set(
RCCBackendCodeGenSources
CompilationUnit.cpp
+ CommandFlags.cpp
GlobalObject.cpp
GenericOpcodes.cpp
GenericConstant.cpp
@@ -83,6 +84,7 @@ set(
set(
RCCBackendCodeGenHeaders
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/CompilationUnit.h"
+ "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/CommandFlags.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GlobalObject.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GenericOpcodes.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GenericConstant.h"
@@ -204,6 +206,7 @@ install(
rcc_backend_register_format_files(
"${CMAKE_CURRENT_SOURCE_DIR}/CompilationUnit.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/CommandFlags.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GlobalObject.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GenericOpcodes.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GenericConstant.cpp"
@@ -285,6 +288,7 @@ rcc_backend_register_format_files(
)
rcc_backend_register_tidy_files(
"${CMAKE_CURRENT_SOURCE_DIR}/CompilationUnit.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/CommandFlags.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GlobalObject.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GenericOpcodes.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GenericConstant.cpp"
diff --git a/backend/lib/CodeGen/CommandFlags.cpp b/backend/lib/CodeGen/CommandFlags.cpp
new file mode 100644
index 0000000..dfbaadc
--- /dev/null
+++ b/backend/lib/CodeGen/CommandFlags.cpp
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/CodeGen/CommandFlags.h"
+
+#include <optional>
+#include <string>
+#include <utility>
+
+namespace rcc {
+namespace {
+
+[[nodiscard]] Expected<std::optional<std::string_view>>
+takeValue(std::span<const std::string_view> Arguments, std::size_t &Index, std::string_view Name) {
+ const std::string_view Argument = Arguments[Index];
+ const std::string LongName =
+ Name.starts_with('-') && !Name.starts_with("--") ? "-" + std::string(Name) : std::string();
+ if (Argument == Name || (!LongName.empty() && Argument == LongName)) {
+ if (Index + 1U >= Arguments.size()) {
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "missing value for command-line option '" + std::string(Name) + "'");
+ }
+ return Arguments[++Index];
+ }
+ std::string Prefix(Name);
+ Prefix.push_back('=');
+ if (Argument.starts_with(Prefix))
+ return Argument.substr(Prefix.size());
+ if (!LongName.empty()) {
+ std::string LongPrefix(LongName);
+ LongPrefix.push_back('=');
+ if (Argument.starts_with(LongPrefix))
+ return Argument.substr(LongPrefix.size());
+ }
+ return std::nullopt;
+}
+
+template <typename ValueT, typename ParserT>
+[[nodiscard]] Expected<bool> parseValueFlag(std::span<const std::string_view> Arguments,
+ std::size_t &Index, std::string_view Name,
+ std::optional<ValueT> &Destination, ParserT Parser) {
+ auto Value = takeValue(Arguments, Index, Name);
+ if (!Value)
+ return std::unexpected(Value.error());
+ if (!*Value)
+ return false;
+ auto Parsed = Parser(**Value);
+ if (!Parsed)
+ return std::unexpected(Parsed.error());
+ Destination = std::move(*Parsed);
+ return true;
+}
+
+} // namespace
+
+std::string_view spelling(RelocationModel Value) noexcept {
+ switch (Value) {
+ case RelocationModel::Static:
+ return "static";
+ case RelocationModel::PositionIndependent:
+ return "pic";
+ }
+ return "invalid";
+}
+
+std::string_view spelling(CodeModel Value) noexcept {
+ switch (Value) {
+ case CodeModel::Small:
+ return "small";
+ case CodeModel::Medium:
+ return "medium";
+ case CodeModel::Large:
+ return "large";
+ }
+ return "invalid";
+}
+
+std::string_view spelling(OptimizationLevel Value) noexcept {
+ switch (Value) {
+ case OptimizationLevel::O0:
+ return "O0";
+ case OptimizationLevel::O1:
+ return "O1";
+ case OptimizationLevel::O2:
+ return "O2";
+ case OptimizationLevel::O3:
+ return "O3";
+ case OptimizationLevel::Os:
+ return "Os";
+ case OptimizationLevel::Oz:
+ return "Oz";
+ }
+ return "invalid";
+}
+
+std::string_view spelling(CodeGenFileType Value) noexcept {
+ switch (Value) {
+ case CodeGenFileType::AssemblyFile:
+ return "asm";
+ case CodeGenFileType::ObjectFile:
+ return "obj";
+ case CodeGenFileType::Null:
+ return "null";
+ }
+ return "invalid";
+}
+
+Expected<RelocationModel> parseRelocationModel(std::string_view Value) {
+ if (Value == "static")
+ return RelocationModel::Static;
+ if (Value == "pic")
+ return RelocationModel::PositionIndependent;
+ return makeUnexpected(ErrorCode::InvalidInvocation, "unknown relocation model");
+}
+
+Expected<CodeModel> parseCodeModel(std::string_view Value) {
+ if (Value == "small")
+ return CodeModel::Small;
+ if (Value == "medium")
+ return CodeModel::Medium;
+ if (Value == "large")
+ return CodeModel::Large;
+ return makeUnexpected(ErrorCode::InvalidInvocation, "unknown code model");
+}
+
+Expected<OptimizationLevel> parseOptimizationLevel(std::string_view Value) {
+ if (Value == "O0")
+ return OptimizationLevel::O0;
+ if (Value == "O1")
+ return OptimizationLevel::O1;
+ if (Value == "O2")
+ return OptimizationLevel::O2;
+ if (Value == "O3")
+ return OptimizationLevel::O3;
+ if (Value == "Os")
+ return OptimizationLevel::Os;
+ if (Value == "Oz")
+ return OptimizationLevel::Oz;
+ return makeUnexpected(ErrorCode::InvalidInvocation, "unknown optimization level");
+}
+
+Expected<CodeGenFileType> parseCodeGenFileType(std::string_view Value) {
+ if (Value == "asm")
+ return CodeGenFileType::AssemblyFile;
+ if (Value == "obj")
+ return CodeGenFileType::ObjectFile;
+ if (Value == "null")
+ return CodeGenFileType::Null;
+ return makeUnexpected(ErrorCode::InvalidInvocation, "unknown file type");
+}
+
+Expected<bool> parseCodeGenCommandFlag(std::span<const std::string_view> Arguments,
+ std::size_t &Index, CodeGenCommandFlags &Flags) {
+ const std::string_view Argument = Arguments[Index];
+ const std::string_view Optimization = Argument.starts_with("--") ? Argument.substr(2)
+ : Argument.starts_with('-') ? Argument.substr(1)
+ : std::string_view{};
+ if ((Argument.starts_with('-') && !Argument.starts_with("---")) &&
+ (Optimization == "O0" || Optimization == "O1" || Optimization == "O2" ||
+ Optimization == "O3" || Optimization == "Os" || Optimization == "Oz")) {
+ auto Level = parseOptimizationLevel(Optimization);
+ if (!Level)
+ return std::unexpected(Level.error());
+ Flags.Optimization = *Level;
+ return true;
+ }
+
+ const auto ParseString = [&](std::string_view Name,
+ std::optional<std::string> &Destination) -> Expected<bool> {
+ auto Value = takeValue(Arguments, Index, Name);
+ if (!Value)
+ return std::unexpected(Value.error());
+ if (!*Value)
+ return false;
+ Destination = std::string(**Value);
+ return true;
+ };
+ for (const auto &[Name, Destination] :
+ {std::pair{"-mtriple", &Flags.Triple}, std::pair{"-mcpu", &Flags.CPU},
+ std::pair{"-mtune", &Flags.TuneCPU}, std::pair{"-target-abi", &Flags.ABI}}) {
+ auto Parsed = ParseString(Name, *Destination);
+ if (!Parsed)
+ return std::unexpected(Parsed.error());
+ if (*Parsed)
+ return true;
+ }
+
+ auto Features = takeValue(Arguments, Index, "-mattr");
+ if (!Features)
+ return std::unexpected(Features.error());
+ if (*Features) {
+ std::size_t Begin = 0;
+ while (Begin <= (**Features).size()) {
+ const std::size_t Comma = (**Features).find(',', Begin);
+ const std::size_t End = Comma == std::string_view::npos ? (**Features).size() : Comma;
+ if (End == Begin) {
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "target feature list contains an empty element");
+ }
+ Flags.FeatureOverrides.emplace_back((**Features).substr(Begin, End - Begin));
+ if (Comma == std::string_view::npos)
+ break;
+ Begin = Comma + 1U;
+ }
+ return true;
+ }
+
+ auto Relocation =
+ parseValueFlag(Arguments, Index, "-relocation-model", Flags.Relocation, parseRelocationModel);
+ if (!Relocation)
+ return std::unexpected(Relocation.error());
+ if (*Relocation)
+ return true;
+ auto Code = parseValueFlag(Arguments, Index, "-code-model", Flags.Code, parseCodeModel);
+ if (!Code)
+ return std::unexpected(Code.error());
+ if (*Code)
+ return true;
+
+ auto FileType = takeValue(Arguments, Index, "-filetype");
+ if (!FileType)
+ return std::unexpected(FileType.error());
+ if (*FileType) {
+ auto Parsed = parseCodeGenFileType(**FileType);
+ if (!Parsed)
+ return std::unexpected(Parsed.error());
+ Flags.FileType = *Parsed;
+ Flags.FileTypeWasSpecified = true;
+ return true;
+ }
+ return false;
+}
+
+} // namespace rcc
diff --git a/backend/lib/CodeGen/MachinePseudoExpansion.cpp b/backend/lib/CodeGen/MachinePseudoExpansion.cpp
index 924c515..022c63e 100644
--- a/backend/lib/CodeGen/MachinePseudoExpansion.cpp
+++ b/backend/lib/CodeGen/MachinePseudoExpansion.cpp
@@ -154,7 +154,7 @@ using BlockSizeSnapshot = std::vector<std::pair<MachineBlockStableID, std::uint6
}();
static const MachinePassContract PostRA = [] {
MachinePassContract Value{
- .Name = "expand-post-ra-pseudos",
+ .Name = "postrapseudos",
.Requires = {MachineFunctionProperty::Selected, MachineFunctionProperty::NoPHIs,
MachineFunctionProperty::NoVRegs, MachineFunctionProperty::TracksLiveness,
MachineFunctionProperty::FrameFinalized,
diff --git a/backend/lib/CodeGen/MachineSSAExit.cpp b/backend/lib/CodeGen/MachineSSAExit.cpp
index f2b0102..76963ea 100644
--- a/backend/lib/CodeGen/MachineSSAExit.cpp
+++ b/backend/lib/CodeGen/MachineSSAExit.cpp
@@ -776,7 +776,7 @@ placePhiCopiesOnEdge(MachineFunction &Function, const TargetDescription &Target,
const MachinePassContract &PHIEliminationPass::contract() const noexcept {
static const MachinePassContract Contract{
- .Name = "PHIElimination",
+ .Name = "phi-node-elimination",
.Requires = {MachineFunctionProperty::IsSSA, MachineFunctionProperty::Selected,
MachineFunctionProperty::RegBankSelected},
.Sets = {MachineFunctionProperty::NoPHIs},
@@ -912,7 +912,7 @@ Expected<MachinePassResult> PHIEliminationPass::runImplementation(MachineFunctio
const MachinePassContract &TwoAddressRewritePass::contract() const noexcept {
static const MachinePassContract Contract{
- .Name = "TwoAddressRewrite",
+ .Name = "twoaddressinstruction",
.Requires = {MachineFunctionProperty::Selected, MachineFunctionProperty::NoPHIs},
.Sets = {MachineFunctionProperty::TiedOpsRewritten},
.Clears = {MachineFunctionProperty::IsSSA},
diff --git a/backend/lib/CodeGen/PostRAScheduler.cpp b/backend/lib/CodeGen/PostRAScheduler.cpp
index 6a91239..38fd582 100644
--- a/backend/lib/CodeGen/PostRAScheduler.cpp
+++ b/backend/lib/CodeGen/PostRAScheduler.cpp
@@ -31,7 +31,7 @@ namespace {
[[nodiscard]] const MachinePassContract &postRASchedulerContract() {
static const MachinePassContract Contract = [] {
MachinePassContract Value{
- .Name = "post-ra-machine-scheduler",
+ .Name = "postmisched",
.Requires = {MachineFunctionProperty::Selected, MachineFunctionProperty::NoPHIs,
MachineFunctionProperty::TiedOpsRewritten, MachineFunctionProperty::NoVRegs,
MachineFunctionProperty::TracksLiveness},
diff --git a/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp b/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp
index acbcbcf..36315f7 100644
--- a/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp
+++ b/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp
@@ -31,7 +31,7 @@ namespace {
const MachinePassContract &PrologueEpilogueInsertionPass::contract() const noexcept {
static const MachinePassContract Contract = [] {
MachinePassContract Value{
- .Name = "PrologueEpilogueInsertion",
+ .Name = "prologepilog",
.Requires = {MachineFunctionProperty::Selected, MachineFunctionProperty::NoPHIs,
MachineFunctionProperty::TiedOpsRewritten, MachineFunctionProperty::NoVRegs},
.Sets = {MachineFunctionProperty::FrameFinalized, MachineFunctionProperty::NoFrameIndices},
diff --git a/backend/lib/Tooling/BackendDriver.cpp b/backend/lib/Tooling/BackendDriver.cpp
index fff58c5..c726fd3 100644
--- a/backend/lib/Tooling/BackendDriver.cpp
+++ b/backend/lib/Tooling/BackendDriver.cpp
@@ -164,30 +164,28 @@ std::string_view spelling(BackendOutputKind Output) noexcept {
return "invalid";
}
-Expected<BackendOutputKind> parseBackendOutputKind(std::string_view Value) {
- if (Value == "prelegalizer-mir")
- return BackendOutputKind::PreLegalizerMIR;
- if (Value == "legalized-mir")
- return BackendOutputKind::LegalizedMIR;
- if (Value == "regbank-mir")
- return BackendOutputKind::RegisterBankMIR;
- if (Value == "selected-mir")
- return BackendOutputKind::SelectedMIR;
- if (Value == "post-ssa-mir")
- return BackendOutputKind::PostSSAMIR;
- if (Value == "post-ra-mir")
- return BackendOutputKind::PostRegisterAllocationMIR;
- if (Value == "final-mir")
- return BackendOutputKind::FinalMIR;
- if (Value == "assembly" || Value == "asm")
- return BackendOutputKind::Assembly;
- if (Value == "object" || Value == "obj")
- return BackendOutputKind::RelocatableObject;
- return makeUnexpected(ErrorCode::InvalidInvocation, "unknown backend output kind");
-}
-
ArtifactKind manifestArtifactKind(BackendOutputKind Output) noexcept {
- return static_cast<ArtifactKind>(static_cast<std::uint8_t>(Output));
+ switch (Output) {
+ case BackendOutputKind::PreLegalizerMIR:
+ return ArtifactKind::PreLegalizerMIR;
+ case BackendOutputKind::LegalizedMIR:
+ return ArtifactKind::LegalizedMIR;
+ case BackendOutputKind::RegisterBankMIR:
+ return ArtifactKind::RegisterBankMIR;
+ case BackendOutputKind::SelectedMIR:
+ return ArtifactKind::SelectedMIR;
+ case BackendOutputKind::PostSSAMIR:
+ return ArtifactKind::PostSSAMIR;
+ case BackendOutputKind::PostRegisterAllocationMIR:
+ return ArtifactKind::PostRegisterAllocationMIR;
+ case BackendOutputKind::FinalMIR:
+ return ArtifactKind::FinalMIR;
+ case BackendOutputKind::Assembly:
+ return ArtifactKind::Assembly;
+ case BackendOutputKind::RelocatableObject:
+ return ArtifactKind::RelocatableObject;
+ }
+ return ArtifactKind::FinalMIR;
}
Expected<ArtifactKind> cacheArtifactKind(BackendOutputKind Output) {
diff --git a/backend/lib/Tooling/BackendInvocation.cpp b/backend/lib/Tooling/BackendInvocation.cpp
index 677cd2d..232d34f 100644
--- a/backend/lib/Tooling/BackendInvocation.cpp
+++ b/backend/lib/Tooling/BackendInvocation.cpp
@@ -265,46 +265,6 @@ void appendMIRTextInfo(std::string &Output, const TargetMIRTextInfo &MIRText) {
} // namespace
-std::string_view spelling(RelocationModel Value) noexcept {
- switch (Value) {
- case RelocationModel::Static:
- return "static";
- case RelocationModel::PositionIndependent:
- return "pic";
- }
- return "invalid";
-}
-
-std::string_view spelling(CodeModel Value) noexcept {
- switch (Value) {
- case CodeModel::Small:
- return "small";
- case CodeModel::Medium:
- return "medium";
- case CodeModel::Large:
- return "large";
- }
- return "invalid";
-}
-
-std::string_view spelling(OptimizationLevel Value) noexcept {
- switch (Value) {
- case OptimizationLevel::O0:
- return "O0";
- case OptimizationLevel::O1:
- return "O1";
- case OptimizationLevel::O2:
- return "O2";
- case OptimizationLevel::O3:
- return "O3";
- case OptimizationLevel::Os:
- return "Os";
- case OptimizationLevel::Oz:
- return "Oz";
- }
- return "invalid";
-}
-
std::string_view spelling(LayoutOwnership Value) noexcept {
switch (Value) {
case LayoutOwnership::NativeObject:
@@ -317,40 +277,6 @@ std::string_view spelling(LayoutOwnership Value) noexcept {
return "invalid";
}
-Expected<RelocationModel> parseRelocationModel(std::string_view Value) {
- if (Value == "static")
- return RelocationModel::Static;
- if (Value == "pic")
- return RelocationModel::PositionIndependent;
- return makeUnexpected(ErrorCode::ManifestError, "unknown relocation model");
-}
-
-Expected<CodeModel> parseCodeModel(std::string_view Value) {
- if (Value == "small")
- return CodeModel::Small;
- if (Value == "medium")
- return CodeModel::Medium;
- if (Value == "large")
- return CodeModel::Large;
- return makeUnexpected(ErrorCode::ManifestError, "unknown code model");
-}
-
-Expected<OptimizationLevel> parseOptimizationLevel(std::string_view Value) {
- if (Value == "O0")
- return OptimizationLevel::O0;
- if (Value == "O1")
- return OptimizationLevel::O1;
- if (Value == "O2")
- return OptimizationLevel::O2;
- if (Value == "O3")
- return OptimizationLevel::O3;
- if (Value == "Os")
- return OptimizationLevel::Os;
- if (Value == "Oz")
- return OptimizationLevel::Oz;
- return makeUnexpected(ErrorCode::ManifestError, "unknown optimization level");
-}
-
Expected<LayoutOwnership> parseLayoutOwnership(std::string_view Value) {
if (Value == "native-object")
return LayoutOwnership::NativeObject;
diff --git a/backend/lib/Tooling/MIRFuzzer.cpp b/backend/lib/Tooling/MIRFuzzer.cpp
index ed5b2fa..653b9fd 100644
--- a/backend/lib/Tooling/MIRFuzzer.cpp
+++ b/backend/lib/Tooling/MIRFuzzer.cpp
@@ -225,7 +225,23 @@ private:
}
[[nodiscard]] BackendOutputKind outputForStage(BackendStage Stage) noexcept {
- return static_cast<BackendOutputKind>(static_cast<std::uint8_t>(Stage));
+ switch (Stage) {
+ case BackendStage::PreLegalizerMIR:
+ return BackendOutputKind::PreLegalizerMIR;
+ case BackendStage::LegalizedMIR:
+ return BackendOutputKind::LegalizedMIR;
+ case BackendStage::RegisterBankMIR:
+ return BackendOutputKind::RegisterBankMIR;
+ case BackendStage::SelectedMIR:
+ return BackendOutputKind::SelectedMIR;
+ case BackendStage::PostSSAMIR:
+ return BackendOutputKind::PostSSAMIR;
+ case BackendStage::PostRegisterAllocationMIR:
+ return BackendOutputKind::PostRegisterAllocationMIR;
+ case BackendStage::FinalMIR:
+ return BackendOutputKind::FinalMIR;
+ }
+ return BackendOutputKind::FinalMIR;
}
[[nodiscard]] Expected<bool> propertyCase(std::string_view Canonical, DeterministicRandom &Random,
diff --git a/backend/lib/Tooling/PipelineDriver.cpp b/backend/lib/Tooling/PipelineDriver.cpp
index 620367f..3d137d8 100644
--- a/backend/lib/Tooling/PipelineDriver.cpp
+++ b/backend/lib/Tooling/PipelineDriver.cpp
@@ -11,6 +11,7 @@
#include <algorithm>
#include <atomic>
+#include <charconv>
#include <cstddef>
#include <cstdint>
#include <memory>
@@ -38,19 +39,27 @@ struct FunctionRunResult final {
}
[[nodiscard]] bool selectorMatches(std::string_view Selector, std::string_view Pass,
- std::uint32_t Occurrence) {
- if (Selector == "all" || Selector == Pass)
+ std::uint32_t Occurrence, bool MatchAllOccurrences) {
+ if (Selector == "all")
return true;
- std::string Qualified(Pass);
- Qualified.push_back('#');
- Qualified.append(std::to_string(Occurrence));
- return Selector == Qualified;
+ const std::size_t Comma = Selector.find(',');
+ const std::string_view Name =
+ Comma == std::string_view::npos ? Selector : Selector.substr(0, Comma);
+ if (Name != Pass)
+ return false;
+ if (Comma == std::string_view::npos)
+ return MatchAllOccurrences || Occurrence == 1U;
+ std::uint32_t Instance = 0;
+ const std::string_view Text = Selector.substr(Comma + 1U);
+ const auto Parsed = std::from_chars(Text.data(), Text.data() + Text.size(), Instance);
+ return Parsed.ec == std::errc{} && Parsed.ptr == Text.data() + Text.size() &&
+ Occurrence == Instance + 1U;
}
[[nodiscard]] bool anySelectorMatches(std::span<const std::string> Selectors, std::string_view Pass,
std::uint32_t Occurrence) {
return std::ranges::any_of(Selectors, [Pass, Occurrence](const std::string &Selector) {
- return selectorMatches(Selector, Pass, Occurrence);
+ return selectorMatches(Selector, Pass, Occurrence, true);
});
}
@@ -61,7 +70,7 @@ struct FunctionRunResult final {
return BackendStage::RegisterBankMIR;
if (Pass == "instruction-select")
return BackendStage::SelectedMIR;
- if (Pass == "TwoAddressRewrite")
+ if (Pass == "twoaddressinstruction")
return BackendStage::PostSSAMIR;
if (Pass == "PBQPAllocator")
return BackendStage::PostRegisterAllocationMIR;
@@ -84,8 +93,6 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
"the default pipeline marker cannot be mixed with named passes");
}
for (const std::string &Name : Invocation.PassPipeline) {
- if (Name == "none")
- continue;
auto Pass = riscv::createCanonicalPipelinePass(Name, Features);
if (!Pass)
return std::unexpected(Pass.error());
@@ -97,47 +104,67 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
return std::move(Pipeline).takePasses();
}
-[[nodiscard]] Expected<void> validateSelector(std::string_view Selector) {
- if (Selector == "all")
+[[nodiscard]] Expected<void> validateSelector(std::string_view Selector, bool AllowAll) {
+ if (Selector == "all" && AllowAll)
return {};
- const std::size_t Hash = Selector.rfind('#');
+ const std::size_t Comma = Selector.find(',');
const std::string_view Name =
- Hash == std::string_view::npos ? Selector : Selector.substr(0, Hash);
+ Comma == std::string_view::npos ? Selector : Selector.substr(0, Comma);
if (Name.empty())
return makeUnexpected(ErrorCode::InvalidInvocation, "empty pipeline pass selector");
auto Pass = riscv::createCanonicalPipelinePass(Name);
if (!Pass)
return std::unexpected(Pass.error());
- if (Hash != std::string_view::npos) {
- const std::string_view Occurrence = Selector.substr(Hash + 1U);
- if (Occurrence.empty() || Occurrence == "0" ||
- !std::ranges::all_of(Occurrence,
- [](char Character) { return Character >= '0' && Character <= '9'; })) {
+ if (Comma != std::string_view::npos) {
+ const std::string_view InstanceText = Selector.substr(Comma + 1U);
+ std::uint32_t Instance = 0;
+ const auto Parsed =
+ std::from_chars(InstanceText.data(), InstanceText.data() + InstanceText.size(), Instance);
+ if (InstanceText.empty() || Parsed.ec != std::errc{} ||
+ Parsed.ptr != InstanceText.data() + InstanceText.size()) {
return makeUnexpected(ErrorCode::InvalidInvocation,
- "pipeline pass occurrence must be a positive integer");
+ "pipeline pass instance must be a nonnegative integer");
}
}
return {};
}
[[nodiscard]] Expected<void> validateControls(const PipelineControls &Controls) {
+ if (Controls.StartBefore && Controls.StartAfter) {
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "-start-before and -start-after cannot be combined");
+ }
+ if (Controls.StopBefore && Controls.StopAfter) {
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "-stop-before and -stop-after cannot be combined");
+ }
+ if (Controls.StartBefore) {
+ auto Result = validateSelector(*Controls.StartBefore, false);
+ if (!Result)
+ return Result;
+ }
+ if (Controls.StartAfter) {
+ auto Result = validateSelector(*Controls.StartAfter, false);
+ if (!Result)
+ return Result;
+ }
if (Controls.StopBefore) {
- auto Result = validateSelector(*Controls.StopBefore);
+ auto Result = validateSelector(*Controls.StopBefore, false);
if (!Result)
return Result;
}
if (Controls.StopAfter) {
- auto Result = validateSelector(*Controls.StopAfter);
+ auto Result = validateSelector(*Controls.StopAfter, false);
if (!Result)
return Result;
}
for (const std::string &Selector : Controls.PrintBefore) {
- auto Result = validateSelector(Selector);
+ auto Result = validateSelector(Selector, true);
if (!Result)
return Result;
}
for (const std::string &Selector : Controls.PrintAfter) {
- auto Result = validateSelector(Selector);
+ auto Result = validateSelector(Selector, true);
if (!Result)
return Result;
}
@@ -198,13 +225,26 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD
}
std::unordered_map<std::string, std::uint32_t> Occurrences;
+ bool Started = !Controls.StartBefore && !Controls.StartAfter;
+ bool StopMatched = !Controls.StopBefore && !Controls.StopAfter;
for (std::unique_ptr<MachineFunctionPass> &Pass : *Passes) {
if (Pass == nullptr)
return makeUnexpected(ErrorCode::InternalError, "pipeline contains a null pass");
const std::string Name = Pass->contract().Name;
const std::uint32_t Occurrence = ++Occurrences[Name];
- if (Controls.StopBefore && selectorMatches(*Controls.StopBefore, Name, Occurrence))
+ if (!Started) {
+ if (Controls.StartBefore && selectorMatches(*Controls.StartBefore, Name, Occurrence, false)) {
+ Started = true;
+ } else {
+ if (Controls.StartAfter && selectorMatches(*Controls.StartAfter, Name, Occurrence, false))
+ Started = true;
+ continue;
+ }
+ }
+ if (Controls.StopBefore && selectorMatches(*Controls.StopBefore, Name, Occurrence, false)) {
+ StopMatched = true;
break;
+ }
if (AllowSnapshots && anySelectorMatches(Controls.PrintBefore, Name, Occurrence)) {
auto Captured =
captureSnapshot(Result, Document, Target, Invocation, SnapshotPhase::BeforePass,
@@ -241,12 +281,25 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD
if (!Captured)
return std::unexpected(Captured.error());
}
- if (Controls.StopAfter && selectorMatches(*Controls.StopAfter, Name, Occurrence))
+ if (Controls.StopAfter && selectorMatches(*Controls.StopAfter, Name, Occurrence, false)) {
+ StopMatched = true;
break;
+ }
if (Controls.StopAtStage && stageOrdinal(CurrentStage) >= stageOrdinal(*Controls.StopAtStage)) {
break;
}
}
+ if (!Started) {
+ const std::string &Selector =
+ Controls.StartBefore ? *Controls.StartBefore : *Controls.StartAfter;
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "pipeline start selector did not match: '" + Selector + "'");
+ }
+ if (!StopMatched) {
+ const std::string &Selector = Controls.StopBefore ? *Controls.StopBefore : *Controls.StopAfter;
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "pipeline stop selector did not match: '" + Selector + "'");
+ }
return Result;
}
diff --git a/backend/tools/MIRTool/CMakeLists.txt b/backend/tools/MIRTool/CMakeLists.txt
index 3388481..37738c1 100644
--- a/backend/tools/MIRTool/CMakeLists.txt
+++ b/backend/tools/MIRTool/CMakeLists.txt
@@ -53,7 +53,7 @@ foreach(
"-DTOOL=$<TARGET_FILE:RCCBackendMIRTool>"
"-DINPUT=${RCCBackendMIRToolInputDirectory}/${InputName}.mir"
"-DOUTPUT=${RCCBackendMIRToolTestDirectory}/${InputName}.s"
- -DOUTPUT_KIND=assembly
+ -DOUTPUT_KIND=asm
"-DLLVM_MC=${RCCBackendMIRToolLLVMMC}"
-P "${CMAKE_CURRENT_SOURCE_DIR}/MIRToolOutputTest.cmake"
)
@@ -64,7 +64,7 @@ foreach(
"-DTOOL=$<TARGET_FILE:RCCBackendMIRTool>"
"-DINPUT=${RCCBackendMIRToolInputDirectory}/${InputName}.mir"
"-DOUTPUT=${RCCBackendMIRToolTestDirectory}/${InputName}.o"
- -DOUTPUT_KIND=object
+ -DOUTPUT_KIND=obj
"-DLLVM_READELF=${RCCBackendMIRToolLLVMReadELF}"
"-DLLVM_OBJDUMP=${RCCBackendMIRToolLLVMObjdump}"
-P "${CMAKE_CURRENT_SOURCE_DIR}/MIRToolOutputTest.cmake"
diff --git a/backend/tools/MIRTool/MIRToolMain.cpp b/backend/tools/MIRTool/MIRToolMain.cpp
index ea180d6..2c0fe8d 100644
--- a/backend/tools/MIRTool/MIRToolMain.cpp
+++ b/backend/tools/MIRTool/MIRToolMain.cpp
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
+#include "rcc/CodeGen/CommandFlags.h"
#include "rcc/CodeGen/MachineFunction.h"
#include "rcc/Support/Error.h"
#include "rcc/Target/RISCV/RISCVPipeline.h"
@@ -68,6 +69,7 @@ struct CommandLine final {
rcc::tooling::PipelineControls Controls;
rcc::tooling::MIRFuzzOptions FuzzOptions;
bool OutputWasSpecified = false;
+ bool DiscardOutput = false;
bool PrintActions = false;
bool ShowHelp = false;
};
@@ -83,14 +85,16 @@ void printUsage(std::ostream &Output) {
"pipeline/output:\n"
" -run-pass <name> Run one named pass\n"
" -passes <name,...> Run an explicit pass sequence\n"
- " -stop-before <pass[#N]> Stop before a pass occurrence\n"
- " -stop-after <pass[#N]> Stop after a pass occurrence\n"
- " -print-before <pass[#N],...> Print snapshots before passes\n"
- " -print-after <pass[#N],...> Print snapshots after passes\n"
+ " -start-before <pass[,N]> Start before a pass instance\n"
+ " -start-after <pass[,N]> Start after a pass instance\n"
+ " -stop-before <pass[,N]> Stop before a pass instance\n"
+ " -stop-after <pass[,N]> Stop after a pass instance\n"
+ " -print-before <selector,...> Print snapshots before passes\n"
+ " -print-after <selector,...> Print snapshots after passes\n"
" -simplify-mir Omit default-valued MIR fields\n"
" -verify-machineinstrs Verify each machine pass result\n"
" --stage-snapshots Print every stage boundary\n"
- " --emit <stage|assembly|object> Select the output artifact\n"
+ " -filetype <asm|obj|null> Select the output artifact\n"
" -o <file|-> Select the output path\n"
"reproduction/cache/fuzz:\n"
" --crash-reproducer <path> Save input and manifest before execution\n"
@@ -118,7 +122,9 @@ void printUsage(std::ostream &Output) {
std::string_view Name,
int &Index, int ArgumentCount,
char *Arguments[]) {
- if (Argument == Name) {
+ const std::string LongName =
+ Name.starts_with('-') && !Name.starts_with("--") ? "-" + std::string(Name) : std::string();
+ if (Argument == Name || (!LongName.empty() && Argument == LongName)) {
if (Index + 1 >= ArgumentCount) {
return rcc::makeUnexpected(ErrorCode::InvalidInvocation,
"missing value for command-line option '" + std::string(Name) +
@@ -130,6 +136,12 @@ void printUsage(std::ostream &Output) {
Prefix.push_back('=');
if (Argument.starts_with(Prefix))
return Argument.substr(Prefix.size());
+ if (!LongName.empty()) {
+ std::string LongPrefix(LongName);
+ LongPrefix.push_back('=');
+ if (Argument.starts_with(LongPrefix))
+ return Argument.substr(LongPrefix.size());
+ }
return std::nullopt;
}
@@ -237,6 +249,13 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
[[nodiscard]] Expected<CommandLine> parseCommandLine(int ArgumentCount, char *Arguments[]) {
CommandLine Command;
bool ExplicitPipeline = false;
+ bool UsedRunPass = false;
+ bool UsedPasses = false;
+ rcc::CodeGenCommandFlags CodeGenFlags;
+ std::vector<std::string_view> ArgumentViews;
+ ArgumentViews.reserve(static_cast<std::size_t>(ArgumentCount));
+ for (int Index = 0; Index < ArgumentCount; ++Index)
+ ArgumentViews.emplace_back(Arguments[Index]);
for (int Index = 1; Index < ArgumentCount; ++Index) {
const std::string_view Argument(Arguments[Index]);
if (Argument == "--help" || Argument == "-h") {
@@ -259,11 +278,11 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
Command.Controls.CaptureStageSnapshots = true;
continue;
}
- if (Argument == "-simplify-mir") {
+ if (Argument == "-simplify-mir" || Argument == "--simplify-mir") {
Command.Controls.SimplifyMIR = true;
continue;
}
- if (Argument == "-verify-machineinstrs") {
+ if (Argument == "-verify-machineinstrs" || Argument == "--verify-machineinstrs") {
Command.Controls.VerifyEach = true;
continue;
}
@@ -279,24 +298,15 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
Command.PrintActions = true;
continue;
}
- if (Argument == "-O0" || Argument == "-O1" || Argument == "-O2" || Argument == "-O3" ||
- Argument == "-Os" || Argument == "-Oz") {
- auto Level = rcc::tooling::parseOptimizationLevel(Argument.substr(1));
- if (!Level)
- return std::unexpected(Level.error());
- Command.Invocation.Optimization = *Level;
+ std::size_t CodeGenIndex = static_cast<std::size_t>(Index);
+ auto CodeGenFlag = rcc::parseCodeGenCommandFlag(ArgumentViews, CodeGenIndex, CodeGenFlags);
+ if (!CodeGenFlag)
+ return std::unexpected(CodeGenFlag.error());
+ if (*CodeGenFlag) {
+ Index = static_cast<int>(CodeGenIndex);
continue;
}
- auto Input = takeOption(Argument, "--input", Index, ArgumentCount, Arguments);
- if (!Input)
- return std::unexpected(Input.error());
- if (*Input) {
- if (!Command.InputPath.empty())
- return rcc::makeUnexpected(ErrorCode::InvalidInvocation, "input path is specified twice");
- Command.InputPath = std::string(**Input);
- continue;
- }
auto Output = takeOption(Argument, "-o", Index, ArgumentCount, Arguments);
if (!Output)
return std::unexpected(Output.error());
@@ -305,25 +315,22 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
Command.OutputWasSpecified = true;
continue;
}
- auto Emit = takeOption(Argument, "--emit", Index, ArgumentCount, Arguments);
- if (!Emit)
- return std::unexpected(Emit.error());
- if (*Emit) {
- auto Kind = rcc::tooling::parseBackendOutputKind(**Emit);
- if (!Kind)
- return std::unexpected(Kind.error());
- Command.Output = *Kind;
- Command.OutputWasSpecified = true;
- continue;
- }
auto RunPass = takeOption(Argument, "-run-pass", Index, ArgumentCount, Arguments);
if (!RunPass)
return std::unexpected(RunPass.error());
if (*RunPass) {
- if (ExplicitPipeline)
+ if (UsedPasses)
return rcc::makeUnexpected(ErrorCode::InvalidInvocation,
"-run-pass and -passes cannot be combined");
- Command.Invocation.PassPipeline = {std::string(**RunPass)};
+ auto Names = splitList(**RunPass, "pass pipeline");
+ if (!Names)
+ return std::unexpected(Names.error());
+ if (!UsedRunPass)
+ Command.Invocation.PassPipeline.clear();
+ Command.Invocation.PassPipeline.insert(Command.Invocation.PassPipeline.end(),
+ std::make_move_iterator(Names->begin()),
+ std::make_move_iterator(Names->end()));
+ UsedRunPass = true;
ExplicitPipeline = true;
continue;
}
@@ -331,13 +338,14 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
if (!Passes)
return std::unexpected(Passes.error());
if (*Passes) {
- if (ExplicitPipeline)
+ if (UsedRunPass || UsedPasses)
return rcc::makeUnexpected(ErrorCode::InvalidInvocation,
"-run-pass and -passes cannot be combined");
auto Names = splitList(**Passes, "pass pipeline");
if (!Names)
return std::unexpected(Names.error());
Command.Invocation.PassPipeline = std::move(*Names);
+ UsedPasses = true;
ExplicitPipeline = true;
continue;
}
@@ -362,6 +370,26 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
return std::unexpected(StopAfter.error());
if (*StopAfter)
continue;
+ auto StartBefore = ParseSelector("-start-before", Command.Controls.StartBefore);
+ if (!StartBefore)
+ return std::unexpected(StartBefore.error());
+ if (*StartBefore)
+ continue;
+ auto StartAfter = ParseSelector("-start-after", Command.Controls.StartAfter);
+ if (!StartAfter)
+ return std::unexpected(StartAfter.error());
+ if (*StartAfter)
+ continue;
+
+ auto InputLanguage = takeOption(Argument, "-x", Index, ArgumentCount, Arguments);
+ if (!InputLanguage)
+ return std::unexpected(InputLanguage.error());
+ if (*InputLanguage) {
+ if (**InputLanguage != "mir") {
+ return rcc::makeUnexpected(ErrorCode::InvalidInvocation, "input language must be 'mir'");
+ }
+ continue;
+ }
const auto ParseSelectorList = [&](std::string_view Name,
std::vector<std::string> &Destination) -> Expected<bool> {
@@ -515,28 +543,6 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
Destination = std::string(**Value);
return true;
};
- auto Triple = takeOption(Argument, "-mtriple", Index, ArgumentCount, Arguments);
- if (!Triple)
- return std::unexpected(Triple.error());
- if (*Triple) {
- Command.Invocation.Triple = normalizeRV64Triple(**Triple);
- continue;
- }
- auto CPU = ParseString("-mcpu", Command.Invocation.CPU);
- if (!CPU)
- return std::unexpected(CPU.error());
- if (*CPU)
- continue;
- auto TuneCPU = ParseString("-mtune", Command.Invocation.TuneCPU);
- if (!TuneCPU)
- return std::unexpected(TuneCPU.error());
- if (*TuneCPU)
- continue;
- auto ABI = ParseString("-target-abi", Command.Invocation.ABI);
- if (!ABI)
- return std::unexpected(ABI.error());
- if (*ABI)
- continue;
auto DataLayout = ParseString("--data-layout", Command.Invocation.DataLayout);
if (!DataLayout)
return std::unexpected(DataLayout.error());
@@ -552,36 +558,6 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
return std::unexpected(AssemblerVersion.error());
if (*AssemblerVersion)
continue;
- auto Features = takeOption(Argument, "-mattr", Index, ArgumentCount, Arguments);
- if (!Features)
- return std::unexpected(Features.error());
- if (*Features) {
- auto Values = splitList(**Features, "target feature list");
- if (!Values)
- return std::unexpected(Values.error());
- applyFeatureOverrides(std::move(*Values), Command.Invocation.Features);
- continue;
- }
- auto Relocation = takeOption(Argument, "-relocation-model", Index, ArgumentCount, Arguments);
- if (!Relocation)
- return std::unexpected(Relocation.error());
- if (*Relocation) {
- auto Value = rcc::tooling::parseRelocationModel(**Relocation);
- if (!Value)
- return std::unexpected(Value.error());
- Command.Invocation.Relocation = *Value;
- continue;
- }
- auto Code = takeOption(Argument, "-code-model", Index, ArgumentCount, Arguments);
- if (!Code)
- return std::unexpected(Code.error());
- if (*Code) {
- auto Value = rcc::tooling::parseCodeModel(**Code);
- if (!Value)
- return std::unexpected(Value.error());
- Command.Invocation.Code = *Value;
- continue;
- }
auto Layout = takeOption(Argument, "--layout", Index, ArgumentCount, Arguments);
if (!Layout)
return std::unexpected(Layout.error());
@@ -636,6 +612,46 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
if (Command.ShowHelp)
return Command;
+ if (CodeGenFlags.Triple)
+ Command.Invocation.Triple = normalizeRV64Triple(*CodeGenFlags.Triple);
+ if (CodeGenFlags.CPU)
+ Command.Invocation.CPU = *CodeGenFlags.CPU;
+ if (CodeGenFlags.TuneCPU)
+ Command.Invocation.TuneCPU = *CodeGenFlags.TuneCPU;
+ if (CodeGenFlags.ABI)
+ Command.Invocation.ABI = *CodeGenFlags.ABI;
+ applyFeatureOverrides(std::move(CodeGenFlags.FeatureOverrides), Command.Invocation.Features);
+ if (CodeGenFlags.Relocation)
+ Command.Invocation.Relocation = *CodeGenFlags.Relocation;
+ if (CodeGenFlags.Code)
+ Command.Invocation.Code = *CodeGenFlags.Code;
+ if (CodeGenFlags.Optimization)
+ Command.Invocation.Optimization = *CodeGenFlags.Optimization;
+ const bool HasLimitedCodeGenPipeline = Command.Controls.StartBefore ||
+ Command.Controls.StartAfter ||
+ Command.Controls.StopBefore || Command.Controls.StopAfter;
+ if (UsedRunPass && HasLimitedCodeGenPipeline) {
+ return rcc::makeUnexpected(ErrorCode::InvalidInvocation,
+ "-run-pass cannot be used with a limited code-generation pipeline");
+ }
+ if (ExplicitPipeline || HasLimitedCodeGenPipeline) {
+ Command.Output = BackendOutputKind::FinalMIR;
+ } else {
+ switch (CodeGenFlags.FileType) {
+ case rcc::CodeGenFileType::AssemblyFile:
+ Command.Output = BackendOutputKind::Assembly;
+ break;
+ case rcc::CodeGenFileType::ObjectFile:
+ Command.Output = BackendOutputKind::RelocatableObject;
+ break;
+ case rcc::CodeGenFileType::Null:
+ Command.Output = BackendOutputKind::Assembly;
+ Command.DiscardOutput = true;
+ break;
+ }
+ }
+ Command.DiscardOutput =
+ CodeGenFlags.FileTypeWasSpecified && CodeGenFlags.FileType == rcc::CodeGenFileType::Null;
if (Command.Action == Operation::Reproduce) {
if (!Command.InputPath.empty())
return rcc::makeUnexpected(ErrorCode::InvalidInvocation,
@@ -700,10 +716,27 @@ void applyFeatureOverrides(std::vector<std::string> Overrides, std::vector<std::
}
[[nodiscard]] Expected<BackendOutputKind> outputFromArtifact(ArtifactKind Artifact) {
- const auto Value = static_cast<BackendOutputKind>(static_cast<std::uint8_t>(Artifact));
- if (rcc::tooling::spelling(Value) == "invalid")
- return rcc::makeUnexpected(ErrorCode::ReproducerError, "invalid reproducer artifact kind");
- return Value;
+ switch (Artifact) {
+ case ArtifactKind::PreLegalizerMIR:
+ return BackendOutputKind::PreLegalizerMIR;
+ case ArtifactKind::LegalizedMIR:
+ return BackendOutputKind::LegalizedMIR;
+ case ArtifactKind::RegisterBankMIR:
+ return BackendOutputKind::RegisterBankMIR;
+ case ArtifactKind::SelectedMIR:
+ return BackendOutputKind::SelectedMIR;
+ case ArtifactKind::PostSSAMIR:
+ return BackendOutputKind::PostSSAMIR;
+ case ArtifactKind::PostRegisterAllocationMIR:
+ return BackendOutputKind::PostRegisterAllocationMIR;
+ case ArtifactKind::FinalMIR:
+ return BackendOutputKind::FinalMIR;
+ case ArtifactKind::Assembly:
+ return BackendOutputKind::Assembly;
+ case ArtifactKind::RelocatableObject:
+ return BackendOutputKind::RelocatableObject;
+ }
+ return rcc::makeUnexpected(ErrorCode::ReproducerError, "invalid reproducer artifact kind");
}
void printSnapshots(const BackendRunResult &Result) {
@@ -996,6 +1029,8 @@ runWithCache(const CommandLine &Command, CanonicalMIR Input, const rcc::TargetDe
printSnapshots(*Run);
if (Command.PrintActions)
printActions(*Run);
+ if (Command.DiscardOutput)
+ return {};
return writeOutput(Command.OutputPath, Run->Output);
}
diff --git a/backend/tools/MIRTool/MIRToolOperationsTest.cmake b/backend/tools/MIRTool/MIRToolOperationsTest.cmake
index 8dee32f..ff03619 100644
--- a/backend/tools/MIRTool/MIRToolOperationsTest.cmake
+++ b/backend/tools/MIRTool/MIRToolOperationsTest.cmake
@@ -27,7 +27,7 @@ set(CachedAssembly "${WORK_DIRECTORY}/cached.s")
set(ReloadedAssembly "${WORK_DIRECTORY}/reloaded.s")
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" --emit assembly --cache-dir "${CacheDirectory}"
+ "${TOOL}" "${INPUT}" -filetype=asm --cache-dir "${CacheDirectory}"
--cache-policy write -o "${CachedAssembly}"
RESULT_VARIABLE CacheWriteResult
ERROR_VARIABLE CacheWriteDiagnostics
@@ -37,7 +37,7 @@ if(NOT CacheWriteResult EQUAL 0)
endif()
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" --emit assembly --cache-dir "${CacheDirectory}"
+ "${TOOL}" "${INPUT}" -filetype=asm --cache-dir "${CacheDirectory}"
--cache-policy read -o "${ReloadedAssembly}"
RESULT_VARIABLE CacheReadResult
ERROR_VARIABLE CacheReadDiagnostics
@@ -55,7 +55,7 @@ endif()
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" --emit assembly --cache-dir
+ "${TOOL}" "${INPUT}" -filetype=asm --cache-dir
"${WORK_DIRECTORY}/empty-cache" --cache-policy read -o "${WORK_DIRECTORY}/miss.s"
RESULT_VARIABLE CacheMissResult
ERROR_VARIABLE CacheMissDiagnostics
@@ -73,7 +73,7 @@ list(GET CachedArtifacts 0 CachedArtifact)
file(WRITE "${CachedArtifact}" "corrupt")
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" --emit assembly --cache-dir "${CacheDirectory}"
+ "${TOOL}" "${INPUT}" -filetype=asm --cache-dir "${CacheDirectory}"
--cache-policy read -o "${WORK_DIRECTORY}/corrupt.s"
RESULT_VARIABLE CorruptCacheResult
ERROR_VARIABLE CorruptCacheDiagnostics
@@ -87,7 +87,7 @@ set(SuccessAssembly "${WORK_DIRECTORY}/success.s")
set(ReplayedAssembly "${WORK_DIRECTORY}/success-replayed.s")
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" --emit assembly --crash-reproducer "${SuccessReproducer}"
+ "${TOOL}" "${INPUT}" -filetype=asm --crash-reproducer "${SuccessReproducer}"
-o "${SuccessAssembly}"
RESULT_VARIABLE ReproducerWriteResult
ERROR_VARIABLE ReproducerWriteDiagnostics
@@ -113,7 +113,7 @@ endif()
set(RegBankInput "${WORK_DIRECTORY}/regbank.mir")
execute_process(
- COMMAND "${TOOL}" --input "${INPUT}" --emit regbank-mir -o "${RegBankInput}"
+ COMMAND "${TOOL}" "${INPUT}" -stop-after=regbankselect -o "${RegBankInput}"
RESULT_VARIABLE RegBankResult
ERROR_VARIABLE RegBankDiagnostics
)
@@ -124,7 +124,7 @@ endif()
set(FailureReproducer "${WORK_DIRECTORY}/failure-reproducer")
execute_process(
COMMAND
- "${TOOL}" --input "${RegBankInput}" -run-pass instruction-select --emit selected-mir
+ "${TOOL}" "${RegBankInput}" -run-pass instruction-select
--fuel 0 --crash-reproducer "${FailureReproducer}" -o "${WORK_DIRECTORY}/failure.mir"
RESULT_VARIABLE FailureResult
ERROR_VARIABLE FailureDiagnostics
@@ -151,7 +151,7 @@ endif()
set(ActionOutput "${WORK_DIRECTORY}/selected.mir")
execute_process(
COMMAND
- "${TOOL}" --input "${RegBankInput}" -run-pass instruction-select --emit selected-mir
+ "${TOOL}" "${RegBankInput}" -run-pass instruction-select
--print-actions -o "${ActionOutput}"
RESULT_VARIABLE ActionResult
ERROR_VARIABLE ActionDiagnostics
@@ -172,7 +172,7 @@ set(CanonicalReducerSeed "${WORK_DIRECTORY}/reducer-seed.canonical.mir")
set(ReducedMIR "${WORK_DIRECTORY}/reduced.mir")
file(WRITE "${ReducerSeed}" "${ReducerSeedText}")
execute_process(
- COMMAND "${TOOL}" --verify --input "${ReducerSeed}" -o "${CanonicalReducerSeed}"
+ COMMAND "${TOOL}" --verify "${ReducerSeed}" -o "${CanonicalReducerSeed}"
RESULT_VARIABLE ReducerSeedResult
ERROR_VARIABLE ReducerSeedDiagnostics
)
@@ -180,7 +180,7 @@ if(NOT ReducerSeedResult EQUAL 0)
message(FATAL_ERROR "reducer seed failed canonicalization: ${ReducerSeedDiagnostics}")
endif()
execute_process(
- COMMAND "${TOOL}" --reduce validity --input "${ReducerSeed}" -o "${ReducedMIR}"
+ COMMAND "${TOOL}" --reduce validity "${ReducerSeed}" -o "${ReducedMIR}"
RESULT_VARIABLE ValidityReducerResult
ERROR_VARIABLE ValidityReducerDiagnostics
)
@@ -193,7 +193,7 @@ if(NOT ReducedMIRSize LESS CanonicalReducerSeedSize)
message(FATAL_ERROR "validity reducer did not make the canonical seed smaller")
endif()
execute_process(
- COMMAND "${TOOL}" --verify --input "${ReducedMIR}"
+ COMMAND "${TOOL}" --verify "${ReducedMIR}"
RESULT_VARIABLE ReducedVerifyResult
ERROR_VARIABLE ReducedVerifyDiagnostics
)
@@ -204,8 +204,8 @@ endif()
set(FailureReducedMIR "${WORK_DIRECTORY}/failure-reduced.mir")
execute_process(
COMMAND
- "${TOOL}" --reduce failure --input "${RegBankInput}" -run-pass instruction-select
- --emit selected-mir --fuel 0 -o "${FailureReducedMIR}"
+ "${TOOL}" --reduce failure "${RegBankInput}" -run-pass instruction-select --fuel 0 -o
+ "${FailureReducedMIR}"
RESULT_VARIABLE FailureReducerResult
ERROR_VARIABLE FailureReducerDiagnostics
)
@@ -214,7 +214,7 @@ if(NOT FailureReducerResult EQUAL 0)
endif()
execute_process(
COMMAND
- "${TOOL}" --input "${FailureReducedMIR}" -run-pass instruction-select --emit selected-mir
+ "${TOOL}" "${FailureReducedMIR}" -run-pass instruction-select
--fuel 0 -o "${WORK_DIRECTORY}/failure-reduced-output.mir"
RESULT_VARIABLE ReducedFailureResult
ERROR_VARIABLE ReducedFailureDiagnostics
@@ -228,7 +228,7 @@ set(FirstFuzz "${WORK_DIRECTORY}/fuzz-1.txt")
set(SecondFuzz "${WORK_DIRECTORY}/fuzz-2.txt")
execute_process(
COMMAND
- "${TOOL}" --fuzz all --fuzz-iterations 2 --seed 123 --input "${INPUT}" -o
+ "${TOOL}" --fuzz all --fuzz-iterations 2 --seed 123 "${INPUT}" -o
"${FirstFuzz}"
RESULT_VARIABLE FirstFuzzResult
ERROR_VARIABLE FirstFuzzDiagnostics
@@ -238,7 +238,7 @@ if(NOT FirstFuzzResult EQUAL 0)
endif()
execute_process(
COMMAND
- "${TOOL}" --fuzz all --fuzz-iterations 2 --seed 123 --input "${INPUT}" -o
+ "${TOOL}" --fuzz all --fuzz-iterations 2 --seed 123 "${INPUT}" -o
"${SecondFuzz}"
RESULT_VARIABLE SecondFuzzResult
ERROR_VARIABLE SecondFuzzDiagnostics
@@ -264,7 +264,7 @@ if(NOT FuzzText MATCHES "seed=123 executed=11" OR
message(FATAL_ERROR "layered fuzz output does not account for all six layers")
endif()
execute_process(
- COMMAND "${TOOL}" --fuzz parser,parser --input "${INPUT}"
+ COMMAND "${TOOL}" --fuzz parser,parser "${INPUT}"
RESULT_VARIABLE DuplicateFuzzResult
ERROR_VARIABLE DuplicateFuzzDiagnostics
)
diff --git a/backend/tools/MIRTool/MIRToolOutputTest.cmake b/backend/tools/MIRTool/MIRToolOutputTest.cmake
index 13159b8..00840bc 100644
--- a/backend/tools/MIRTool/MIRToolOutputTest.cmake
+++ b/backend/tools/MIRTool/MIRToolOutputTest.cmake
@@ -10,7 +10,7 @@ file(MAKE_DIRECTORY "${OutputDirectory}")
set(RepeatedOutput "${OUTPUT}.repeat")
execute_process(
- COMMAND "${TOOL}" --input "${INPUT}" --emit "${OUTPUT_KIND}" -o "${OUTPUT}"
+ COMMAND "${TOOL}" "${INPUT}" -filetype "${OUTPUT_KIND}" -o "${OUTPUT}"
RESULT_VARIABLE FirstResult
ERROR_VARIABLE FirstDiagnostics
)
@@ -18,7 +18,7 @@ if(NOT FirstResult EQUAL 0)
message(FATAL_ERROR "${OUTPUT_KIND} production failed: ${FirstDiagnostics}")
endif()
execute_process(
- COMMAND "${TOOL}" --input "${INPUT}" --emit "${OUTPUT_KIND}" -o "${RepeatedOutput}"
+ COMMAND "${TOOL}" "${INPUT}" -filetype "${OUTPUT_KIND}" -o "${RepeatedOutput}"
RESULT_VARIABLE SecondResult
ERROR_VARIABLE SecondDiagnostics
)
@@ -33,7 +33,7 @@ if(NOT ComparisonResult EQUAL 0)
message(FATAL_ERROR "${OUTPUT_KIND} output is not deterministic")
endif()
-if(OUTPUT_KIND STREQUAL "assembly")
+if(OUTPUT_KIND STREQUAL "asm")
file(READ "${OUTPUT}" Assembly)
if(NOT Assembly MATCHES "\\.attribute arch, \"rv64gc\"" OR
NOT Assembly MATCHES "jalr x0, x1, 0")
@@ -60,7 +60,7 @@ if(OUTPUT_KIND STREQUAL "assembly")
message(FATAL_ERROR "LLVM MC rejected MIR tool assembly: ${AssemblerDiagnostics}")
endif()
endif()
-elseif(OUTPUT_KIND STREQUAL "object")
+elseif(OUTPUT_KIND STREQUAL "obj")
file(READ "${OUTPUT}" ObjectMagic OFFSET 0 LIMIT 4 HEX)
if(NOT ObjectMagic STREQUAL "7f454c46")
message(FATAL_ERROR "object output is not an ELF file")
diff --git a/backend/tools/MIRTool/MIRToolStageTest.cmake b/backend/tools/MIRTool/MIRToolStageTest.cmake
index 25c55c3..0d3ef2e 100644
--- a/backend/tools/MIRTool/MIRToolStageTest.cmake
+++ b/backend/tools/MIRTool/MIRToolStageTest.cmake
@@ -17,12 +17,24 @@ set(
post-ra-mir
final-mir
)
+set(
+ StageOptions
+ --verify
+ -stop-after=legalizer
+ -stop-after=regbankselect
+ -stop-after=instruction-select
+ -stop-after=twoaddressinstruction
+ -stop-after=PBQPAllocator
+ -stop-after=final-encodability-verifier
+)
+set(StageIndex 0)
foreach(Stage IN LISTS Stages)
+ list(GET StageOptions ${StageIndex} StageOption)
set(StageOutput "${WORK_DIRECTORY}/${Stage}.mir")
set(RepeatedOutput "${WORK_DIRECTORY}/${Stage}.repeat.mir")
set(CanonicalOutput "${WORK_DIRECTORY}/${Stage}.canonical.mir")
execute_process(
- COMMAND "${TOOL}" --input "${INPUT}" --emit "${Stage}" -o "${StageOutput}"
+ COMMAND "${TOOL}" "${INPUT}" "${StageOption}" -o "${StageOutput}"
RESULT_VARIABLE StageResult
ERROR_VARIABLE StageDiagnostics
)
@@ -30,7 +42,7 @@ foreach(Stage IN LISTS Stages)
message(FATAL_ERROR "${Stage} production failed: ${StageDiagnostics}")
endif()
execute_process(
- COMMAND "${TOOL}" --input "${INPUT}" --emit "${Stage}" -o "${RepeatedOutput}"
+ COMMAND "${TOOL}" "${INPUT}" "${StageOption}" -o "${RepeatedOutput}"
RESULT_VARIABLE RepeatedResult
ERROR_VARIABLE RepeatedDiagnostics
)
@@ -45,7 +57,7 @@ foreach(Stage IN LISTS Stages)
message(FATAL_ERROR "${Stage} output is not deterministic")
endif()
execute_process(
- COMMAND "${TOOL}" --verify --input "${StageOutput}" -o "${CanonicalOutput}"
+ COMMAND "${TOOL}" --verify "${StageOutput}" -o "${CanonicalOutput}"
RESULT_VARIABLE VerifyResult
ERROR_VARIABLE VerifyDiagnostics
)
@@ -59,31 +71,13 @@ foreach(Stage IN LISTS Stages)
if(NOT CanonicalResult EQUAL 0)
message(FATAL_ERROR "${Stage} output is not canonical after strict reload")
endif()
+ math(EXPR StageIndex "${StageIndex} + 1")
endforeach()
-set(NoPassOutput "${WORK_DIRECTORY}/none.mir")
-execute_process(
- COMMAND
- "${TOOL}" --input "${INPUT}" -run-pass=none --emit final-mir -o "${NoPassOutput}"
- RESULT_VARIABLE NoPassResult
- ERROR_VARIABLE NoPassDiagnostics
-)
-if(NOT NoPassResult EQUAL 0)
- message(FATAL_ERROR "LLVM-compatible none pass failed: ${NoPassDiagnostics}")
-endif()
-execute_process(
- COMMAND "${CMAKE_COMMAND}" -E compare_files "${NoPassOutput}"
- "${WORK_DIRECTORY}/prelegalizer-mir.mir"
- RESULT_VARIABLE NoPassComparisonResult
-)
-if(NOT NoPassComparisonResult EQUAL 0)
- message(FATAL_ERROR "LLVM-compatible none pass changed canonical MIR")
-endif()
-
set(LLVMContractOutput "${WORK_DIRECTORY}/llvm-contract.mir")
execute_process(
COMMAND
- "${TOOL}" "${INPUT}" -run-pass=none -mtriple=riscv64
+ "${TOOL}" --verify "${INPUT}" -mtriple=riscv64
-mattr=+m,+a,+f,+d,+c -relocation-model=pic -code-model=small -simplify-mir
-verify-machineinstrs -o "${LLVMContractOutput}"
RESULT_VARIABLE LLVMContractResult
@@ -100,13 +94,7 @@ endif()
foreach(
RemovedOption
IN ITEMS
- --run-pass=none
- --passes=none
- --stop-after=legalizer
- --print-before=legalizer
--features=+m
- --relocation-model=pic
- --code-model=small
--output=-
)
execute_process(
@@ -122,7 +110,7 @@ endforeach()
set(PassList "${WORK_DIRECTORY}/passes.txt")
execute_process(
- COMMAND "${TOOL}" --list-passes --input "${INPUT}" -o "${PassList}"
+ COMMAND "${TOOL}" --list-passes "${INPUT}" -o "${PassList}"
RESULT_VARIABLE ListResult
ERROR_VARIABLE ListDiagnostics
)
@@ -130,7 +118,7 @@ if(NOT ListResult EQUAL 0)
message(FATAL_ERROR "pass listing failed: ${ListDiagnostics}")
endif()
file(READ "${PassList}" PassListText)
-foreach(RequiredPass IN ITEMS legalizer regbankselect instruction-select PrologueEpilogueInsertion)
+foreach(RequiredPass IN ITEMS legalizer regbankselect instruction-select prologepilog)
if(NOT PassListText MATCHES "(^|\n)${RequiredPass}(\n|$)")
message(FATAL_ERROR "canonical pass list is missing ${RequiredPass}")
endif()
@@ -139,7 +127,7 @@ endforeach()
set(LegalizedOutput "${WORK_DIRECTORY}/run-pass.mir")
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" -run-pass legalizer --emit legalized-mir -o
+ "${TOOL}" "${INPUT}" -run-pass legalizer -o
"${LegalizedOutput}"
RESULT_VARIABLE RunPassResult
ERROR_VARIABLE RunPassDiagnostics
@@ -151,7 +139,7 @@ endif()
set(RegBankOutput "${WORK_DIRECTORY}/passes.mir")
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" -passes legalizer,regbankselect --emit regbank-mir -o
+ "${TOOL}" "${INPUT}" -passes legalizer,regbankselect -o
"${RegBankOutput}"
RESULT_VARIABLE PassesResult
ERROR_VARIABLE PassesDiagnostics
@@ -163,7 +151,7 @@ endif()
set(StoppedOutput "${WORK_DIRECTORY}/stopped.mir")
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" -stop-after legalizer --emit final-mir -o
+ "${TOOL}" "${INPUT}" -stop-after legalizer -o
"${StoppedOutput}"
RESULT_VARIABLE StopResult
ERROR_VARIABLE StopDiagnostics
@@ -172,7 +160,7 @@ if(NOT StopResult EQUAL 0)
message(FATAL_ERROR "stop-after control failed: ${StopDiagnostics}")
endif()
execute_process(
- COMMAND "${TOOL}" --verify --input "${StoppedOutput}"
+ COMMAND "${TOOL}" --verify "${StoppedOutput}"
RESULT_VARIABLE StopVerifyResult
ERROR_VARIABLE StopVerifyDiagnostics
)
@@ -182,8 +170,7 @@ endif()
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" --emit legalized-mir -print-before legalizer -print-after
- legalizer -o "${WORK_DIRECTORY}/printed.mir"
+ "${TOOL}" "${INPUT}" -filetype=null -print-before legalizer -print-after legalizer
RESULT_VARIABLE PrintResult
ERROR_VARIABLE PrintDiagnostics
)
@@ -197,8 +184,7 @@ endif()
execute_process(
COMMAND
- "${TOOL}" --input "${INPUT}" --emit final-mir --stage-snapshots -o
- "${WORK_DIRECTORY}/snapshot-final.mir"
+ "${TOOL}" "${INPUT}" -filetype=null --stage-snapshots
RESULT_VARIABLE SnapshotResult
ERROR_VARIABLE SnapshotDiagnostics
)
diff --git a/backend/unittests/Tooling/BackendManifestTest.cpp b/backend/unittests/Tooling/BackendManifestTest.cpp
index 36a023c..2e2a04c 100644
--- a/backend/unittests/Tooling/BackendManifestTest.cpp
+++ b/backend/unittests/Tooling/BackendManifestTest.cpp
@@ -97,11 +97,11 @@ int main() {
if (!keyDiffers(Base, Changed, Input, *Fingerprint))
return tooling_test::fail("cache key must include the data layout");
Changed = Base;
- Changed.Relocation = rcc::tooling::RelocationModel::Static;
+ Changed.Relocation = rcc::RelocationModel::Static;
if (!keyDiffers(Base, Changed, Input, *Fingerprint))
return tooling_test::fail("cache key must include the relocation model");
Changed = Base;
- Changed.Code = rcc::tooling::CodeModel::Medium;
+ Changed.Code = rcc::CodeModel::Medium;
if (!keyDiffers(Base, Changed, Input, *Fingerprint))
return tooling_test::fail("cache key must include the code model");
Changed = Base;
@@ -121,7 +121,7 @@ int main() {
if (!keyDiffers(Base, Changed, Input, *Fingerprint))
return tooling_test::fail("cache key must include assembler options");
Changed = Base;
- Changed.Optimization = rcc::tooling::OptimizationLevel::O3;
+ Changed.Optimization = rcc::OptimizationLevel::O3;
if (!keyDiffers(Base, Changed, Input, *Fingerprint))
return tooling_test::fail("cache key must include the optimization level");
Changed = Base;
diff --git a/backend/unittests/Tooling/PipelineDriverTest.cpp b/backend/unittests/Tooling/PipelineDriverTest.cpp
index 273de52..473b444 100644
--- a/backend/unittests/Tooling/PipelineDriverTest.cpp
+++ b/backend/unittests/Tooling/PipelineDriverTest.cpp
@@ -195,7 +195,7 @@ int main() {
return tooling_test::fail(PrintInput.error().message());
rcc::tooling::PipelineControls PrintControls;
PrintControls.PrintBefore = {"legalizer"};
- PrintControls.PrintAfter = {"legalizer#1"};
+ PrintControls.PrintAfter = {"legalizer"};
auto PrintPoints =
rcc::tooling::runRV64GCPipeline(PrintInput->Document, *Target, Invocation, PrintControls);
if (!PrintPoints || PrintPoints->Snapshots.size() != 2 ||
@@ -209,7 +209,7 @@ int main() {
if (!StopInput)
return tooling_test::fail(StopInput.error().message());
rcc::tooling::PipelineControls StopControls;
- StopControls.StopAfter = "legalizer#1";
+ StopControls.StopAfter = "legalizer,0";
auto Stopped =
rcc::tooling::runRV64GCPipeline(StopInput->Document, *Target, Invocation, StopControls);
const rcc::MachineFunction *StoppedFunction = StopInput->Document.unit().functionAt(0);
@@ -221,9 +221,9 @@ int main() {
Stopped->ExecutedPasses[1].Pass != "legalizer") {
return tooling_test::fail("stop-after must stop at the selected pass occurrence");
}
- StopControls.StopAfter = "legalizer#0";
+ StopControls.StopAfter = "legalizer,-1";
if (rcc::tooling::runRV64GCPipeline(StopInput->Document, *Target, Invocation, StopControls))
- return tooling_test::fail("pipeline controls must reject occurrence zero");
+ return tooling_test::fail("pipeline controls must reject a negative pass instance");
rcc::tooling::BackendInvocation MixedPipeline = Invocation;
MixedPipeline.PassPipeline = {"default", "legalizer"};
@@ -234,20 +234,6 @@ int main() {
if (rcc::tooling::runRV64GCPipeline(MixedInput->Document, *Target, MixedPipeline))
return tooling_test::fail("named passes must not be mixed with the default pipeline marker");
- rcc::tooling::BackendInvocation NoPassInvocation = Invocation;
- NoPassInvocation.PassPipeline = {"none"};
- auto NoPassInput =
- rcc::tooling::parseAndCanonicalizeMIR("no-pass.mir", *Source, *Target, NoPassInvocation);
- if (!NoPassInput)
- return tooling_test::fail(NoPassInput.error().message());
- const std::string NoPassExpected = NoPassInput->Text;
- auto NoPassRun = rcc::tooling::runBackend(std::move(*NoPassInput), *Target, NoPassInvocation,
- rcc::tooling::BackendOutputKind::FinalMIR);
- if (!NoPassRun || !NoPassRun->Pipeline.ExecutedPasses.empty() ||
- NoPassRun->text() != NoPassExpected) {
- return tooling_test::fail("the LLVM-compatible none pass must preserve canonical MIR");
- }
-
if (!SelectedMIR)
return tooling_test::fail("selected MIR stage was not captured");
auto LaterInput =