diff options
Diffstat (limited to 'backend/lib')
| -rw-r--r-- | backend/lib/Tooling/ArtifactStore.cpp | 8 | ||||
| -rw-r--r-- | backend/lib/Tooling/BackendDriver.cpp | 113 | ||||
| -rw-r--r-- | backend/lib/Tooling/MIRFuzzer.cpp | 35 | ||||
| -rw-r--r-- | backend/lib/Tooling/PipelineDriver.cpp | 28 |
4 files changed, 66 insertions, 118 deletions
diff --git a/backend/lib/Tooling/ArtifactStore.cpp b/backend/lib/Tooling/ArtifactStore.cpp index 115f58f..9427a6b 100644 --- a/backend/lib/Tooling/ArtifactStore.cpp +++ b/backend/lib/Tooling/ArtifactStore.cpp @@ -32,7 +32,9 @@ namespace { constexpr std::uintmax_t MaximumPackageFileSize = std::uintmax_t{1} << 30U; std::atomic<std::uint64_t> TemporarySequence = 0; -[[nodiscard]] bool isMIRArtifact(ArtifactKind Artifact) noexcept { +} // namespace + +bool isMIRArtifact(ArtifactKind Artifact) noexcept { switch (Artifact) { case ArtifactKind::PreLegalizerMIR: case ArtifactKind::LegalizedMIR: @@ -49,7 +51,7 @@ std::atomic<std::uint64_t> TemporarySequence = 0; return false; } -[[nodiscard]] bool isCacheableArtifact(ArtifactKind Artifact) noexcept { +bool isCacheableArtifact(ArtifactKind Artifact) noexcept { switch (Artifact) { case ArtifactKind::PreLegalizerMIR: case ArtifactKind::SelectedMIR: @@ -66,6 +68,8 @@ std::atomic<std::uint64_t> TemporarySequence = 0; return false; } +namespace { + [[nodiscard]] std::string_view artifactFileName(ArtifactKind Artifact) noexcept { switch (Artifact) { case ArtifactKind::PreLegalizerMIR: diff --git a/backend/lib/Tooling/BackendDriver.cpp b/backend/lib/Tooling/BackendDriver.cpp index 0402f5a..fa82c0c 100644 --- a/backend/lib/Tooling/BackendDriver.cpp +++ b/backend/lib/Tooling/BackendDriver.cpp @@ -17,36 +17,28 @@ namespace rcc::tooling { namespace { -[[nodiscard]] bool isMIR(BackendOutputKind Output) noexcept { - return Output <= BackendOutputKind::FinalMIR; -} - -[[nodiscard]] BackendStage outputStage(BackendOutputKind Output) noexcept { +[[nodiscard]] BackendStage outputStage(ArtifactKind Output) noexcept { switch (Output) { - case BackendOutputKind::PreLegalizerMIR: + case ArtifactKind::PreLegalizerMIR: return BackendStage::PreLegalizerMIR; - case BackendOutputKind::LegalizedMIR: + case ArtifactKind::LegalizedMIR: return BackendStage::LegalizedMIR; - case BackendOutputKind::RegisterBankMIR: + case ArtifactKind::RegisterBankMIR: return BackendStage::RegisterBankMIR; - case BackendOutputKind::SelectedMIR: + case ArtifactKind::SelectedMIR: return BackendStage::SelectedMIR; - case BackendOutputKind::PostSSAMIR: + case ArtifactKind::PostSSAMIR: return BackendStage::PostSSAMIR; - case BackendOutputKind::PostRegisterAllocationMIR: + case ArtifactKind::PostRegisterAllocationMIR: return BackendStage::PostRegisterAllocationMIR; - case BackendOutputKind::FinalMIR: - case BackendOutputKind::Assembly: - case BackendOutputKind::RelocatableObject: + case ArtifactKind::FinalMIR: + case ArtifactKind::Assembly: + case ArtifactKind::RelocatableObject: return BackendStage::FinalMIR; } return BackendStage::FinalMIR; } -[[nodiscard]] std::uint8_t ordinal(BackendStage Stage) noexcept { - return static_cast<std::uint8_t>(Stage); -} - [[nodiscard]] Expected<std::vector<std::uint8_t>> printMIR(const mir::MIRDocument &Document, const TargetDescription &Target, const BackendInvocation &Invocation, @@ -64,13 +56,13 @@ namespace { } // namespace std::string_view BackendRunResult::text() const noexcept { - if (Kind == BackendOutputKind::RelocatableObject || Output.empty()) + if (Kind == ArtifactKind::RelocatableObject || Output.empty()) return {}; return {reinterpret_cast<const char *>(Output.data()), Output.size()}; } Expected<BackendRunResult> runBackend(CanonicalMIR Input, const TargetDescription &Target, - const BackendInvocation &Invocation, BackendOutputKind Output, + const BackendInvocation &Invocation, ArtifactKind Output, PipelineControls Controls, MachinePassInstrumentation *Instrumentation) { auto InvocationVerification = verifyRV64GCInvocation(Invocation); @@ -87,16 +79,16 @@ Expected<BackendRunResult> runBackend(CanonicalMIR Input, const TargetDescriptio if (Function == nullptr) return makeUnexpected(ErrorCode::InternalError, "backend input contains a null function"); const BackendStage Stage = stageForFunction(*Function); - if (Index == 0 || ordinal(Stage) < ordinal(InitialStage)) + if (Index == 0 || isEarlierStage(Stage, InitialStage)) InitialStage = Stage; } const BackendStage RequiredStage = outputStage(Output); - if (isMIR(Output) && ordinal(RequiredStage) < ordinal(InitialStage)) { + if (isMIRArtifact(Output) && isEarlierStage(RequiredStage, InitialStage)) { return makeUnexpected(ErrorCode::InvalidInvocation, "backend cannot reconstruct an earlier MIR stage from a later snapshot"); } - if (isMIR(Output)) { + if (isMIRArtifact(Output)) { if (Controls.StopAtStage && *Controls.StopAtStage != RequiredStage) { return makeUnexpected(ErrorCode::InvalidInvocation, "output stage conflicts with the explicit pipeline stop stage"); @@ -115,12 +107,12 @@ Expected<BackendRunResult> runBackend(CanonicalMIR Input, const TargetDescriptio return std::unexpected(Pipeline.error()); std::vector<std::uint8_t> Bytes; - if (isMIR(Output)) { + if (isMIRArtifact(Output)) { auto Printed = printMIR(Input.Document, Target, Invocation, SimplifyMIR); if (!Printed) return std::unexpected(Printed.error()); Bytes = std::move(*Printed); - } else if (Output == BackendOutputKind::Assembly) { + } else if (Output == ArtifactKind::Assembly) { auto Assembly = riscv::emitAssembly(Input.Document.unit(), Target); if (!Assembly) return std::unexpected(Assembly.error()); @@ -140,75 +132,4 @@ Expected<BackendRunResult> runBackend(CanonicalMIR Input, const TargetDescriptio }; } -std::string_view spelling(BackendOutputKind Output) noexcept { - switch (Output) { - case BackendOutputKind::PreLegalizerMIR: - return "prelegalizer-mir"; - case BackendOutputKind::LegalizedMIR: - return "legalized-mir"; - case BackendOutputKind::RegisterBankMIR: - return "regbank-mir"; - case BackendOutputKind::SelectedMIR: - return "selected-mir"; - case BackendOutputKind::PostSSAMIR: - return "post-ssa-mir"; - case BackendOutputKind::PostRegisterAllocationMIR: - return "post-ra-mir"; - case BackendOutputKind::FinalMIR: - return "final-mir"; - case BackendOutputKind::Assembly: - return "assembly"; - case BackendOutputKind::RelocatableObject: - return "object"; - } - return "invalid"; -} - -ArtifactKind manifestArtifactKind(BackendOutputKind Output) noexcept { - 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) { - switch (Output) { - case BackendOutputKind::PreLegalizerMIR: - return ArtifactKind::PreLegalizerMIR; - case BackendOutputKind::SelectedMIR: - return ArtifactKind::SelectedMIR; - case BackendOutputKind::PostRegisterAllocationMIR: - return ArtifactKind::PostRegisterAllocationMIR; - case BackendOutputKind::FinalMIR: - return ArtifactKind::FinalMIR; - case BackendOutputKind::Assembly: - return ArtifactKind::Assembly; - case BackendOutputKind::RelocatableObject: - return ArtifactKind::RelocatableObject; - case BackendOutputKind::LegalizedMIR: - case BackendOutputKind::RegisterBankMIR: - case BackendOutputKind::PostSSAMIR: - return makeUnexpected(ErrorCode::InvalidInvocation, - "the selected intermediate stage is not a cache boundary"); - } - return makeUnexpected(ErrorCode::InvalidInvocation, "invalid backend output kind"); -} - } // namespace rcc::tooling diff --git a/backend/lib/Tooling/MIRFuzzer.cpp b/backend/lib/Tooling/MIRFuzzer.cpp index 83762c4..467291c 100644 --- a/backend/lib/Tooling/MIRFuzzer.cpp +++ b/backend/lib/Tooling/MIRFuzzer.cpp @@ -224,24 +224,24 @@ private: return true; } -[[nodiscard]] BackendOutputKind outputForStage(BackendStage Stage) noexcept { +[[nodiscard]] ArtifactKind outputForStage(BackendStage Stage) noexcept { switch (Stage) { case BackendStage::PreLegalizerMIR: - return BackendOutputKind::PreLegalizerMIR; + return ArtifactKind::PreLegalizerMIR; case BackendStage::LegalizedMIR: - return BackendOutputKind::LegalizedMIR; + return ArtifactKind::LegalizedMIR; case BackendStage::RegisterBankMIR: - return BackendOutputKind::RegisterBankMIR; + return ArtifactKind::RegisterBankMIR; case BackendStage::SelectedMIR: - return BackendOutputKind::SelectedMIR; + return ArtifactKind::SelectedMIR; case BackendStage::PostSSAMIR: - return BackendOutputKind::PostSSAMIR; + return ArtifactKind::PostSSAMIR; case BackendStage::PostRegisterAllocationMIR: - return BackendOutputKind::PostRegisterAllocationMIR; + return ArtifactKind::PostRegisterAllocationMIR; case BackendStage::FinalMIR: - return BackendOutputKind::FinalMIR; + return ArtifactKind::FinalMIR; } - return BackendOutputKind::FinalMIR; + return ArtifactKind::FinalMIR; } [[nodiscard]] Expected<bool> propertyCase(std::string_view Canonical, DeterministicRandom &Random, @@ -251,10 +251,15 @@ private: parseAndCanonicalizeMIR("property-fuzz.mir", std::string(Canonical), Target, Invocation); if (!Parsed) return std::unexpected(Parsed.error()); - const auto Stage = static_cast<BackendStage>(Random.index(7U)); + constexpr std::array Stages{ + BackendStage::PreLegalizerMIR, BackendStage::LegalizedMIR, + BackendStage::RegisterBankMIR, BackendStage::SelectedMIR, + BackendStage::PostSSAMIR, BackendStage::PostRegisterAllocationMIR, + BackendStage::FinalMIR, + }; + const BackendStage Stage = Stages[Random.index(Stages.size())]; const MachineFunction *Function = Parsed->Document.unit().functionAt(0); - if (Function == nullptr || - static_cast<std::uint8_t>(Stage) < static_cast<std::uint8_t>(stageForFunction(*Function))) { + if (Function == nullptr || isEarlierStage(Stage, stageForFunction(*Function))) { return false; } auto Run = runBackend(std::move(*Parsed), Target, Invocation, outputForStage(Stage)); @@ -304,8 +309,7 @@ private: Controls.DetectUnreportedChanges = true; Invocation.Determinism.ThreadCount = std::array<std::uint32_t, 3>{1, 2, 4}[Random.index(3U)]; const std::string Stop = Controls.StopAfter ? *Controls.StopAfter : "end"; - auto Run = - runBackend(std::move(*Parsed), Target, Invocation, BackendOutputKind::FinalMIR, Controls); + auto Run = runBackend(std::move(*Parsed), Target, Invocation, ArtifactKind::FinalMIR, Controls); if (!Run) return std::unexpected(Run.error()); auto RoundTrip = verifyCanonicalRoundTrip(std::string(Run->text()), Target, Invocation); @@ -479,8 +483,7 @@ using RegisterValues = std::unordered_map<std::uint64_t, std::uint64_t>; parseAndCanonicalizeMIR("semantic-pipeline.mir", std::string(Canonical), Target, Invocation); if (!CompiledInput) return std::unexpected(CompiledInput.error()); - auto Compiled = - runBackend(std::move(*CompiledInput), Target, Invocation, BackendOutputKind::FinalMIR); + auto Compiled = runBackend(std::move(*CompiledInput), Target, Invocation, ArtifactKind::FinalMIR); if (!Compiled) return std::unexpected(Compiled.error()); auto Final = parseAndCanonicalizeMIR("semantic-final.mir", std::string(Compiled->text()), Target, diff --git a/backend/lib/Tooling/PipelineDriver.cpp b/backend/lib/Tooling/PipelineDriver.cpp index 68cbb57..1a584f7 100644 --- a/backend/lib/Tooling/PipelineDriver.cpp +++ b/backend/lib/Tooling/PipelineDriver.cpp @@ -34,8 +34,24 @@ struct FunctionRunResult final { std::optional<Error> Failure; }; -[[nodiscard]] unsigned stageOrdinal(BackendStage Stage) noexcept { - return static_cast<unsigned>(Stage); +[[nodiscard]] std::uint8_t stageRank(BackendStage Stage) noexcept { + switch (Stage) { + case BackendStage::PreLegalizerMIR: + return 0; + case BackendStage::LegalizedMIR: + return 1; + case BackendStage::RegisterBankMIR: + return 2; + case BackendStage::SelectedMIR: + return 3; + case BackendStage::PostSSAMIR: + return 4; + case BackendStage::PostRegisterAllocationMIR: + return 5; + case BackendStage::FinalMIR: + return 6; + } + return 0; } [[nodiscard]] bool selectorMatches(std::string_view Selector, std::string_view Pass, @@ -224,7 +240,7 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD if (!Captured) return std::unexpected(Captured.error()); } - if (Controls.StopAtStage && stageOrdinal(CurrentStage) >= stageOrdinal(*Controls.StopAtStage)) { + if (Controls.StopAtStage && !isEarlierStage(CurrentStage, *Controls.StopAtStage)) { return Result; } @@ -289,7 +305,7 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD StopMatched = true; break; } - if (Controls.StopAtStage && stageOrdinal(CurrentStage) >= stageOrdinal(*Controls.StopAtStage)) { + if (Controls.StopAtStage && !isEarlierStage(CurrentStage, *Controls.StopAtStage)) { break; } } @@ -314,6 +330,10 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD } // namespace +bool isEarlierStage(BackendStage Left, BackendStage Right) noexcept { + return stageRank(Left) < stageRank(Right); +} + BackendStage stageForFunction(const MachineFunction &Function) noexcept { const MachineFunctionProperties &Properties = Function.properties(); if (Properties.has(MachineFunctionProperty::Selected) && |
