diff options
Diffstat (limited to 'backend/lib/Tooling')
| -rw-r--r-- | backend/lib/Tooling/BackendDriver.cpp | 44 | ||||
| -rw-r--r-- | backend/lib/Tooling/BackendInvocation.cpp | 74 | ||||
| -rw-r--r-- | backend/lib/Tooling/MIRFuzzer.cpp | 18 | ||||
| -rw-r--r-- | backend/lib/Tooling/PipelineDriver.cpp | 105 |
4 files changed, 117 insertions, 124 deletions
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; } |
