aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Tooling
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 18:51:10 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 18:51:10 +0800
commitf89d528efc0228c049c2867dcba886a56bac8619 (patch)
tree7a47f751e729845af1537beee20bc57007d3e21c /backend/lib/Tooling
parent6889b82a5c9ecc6bd178760c66653d7af0121162 (diff)
downloadrcc-project-f89d528efc0228c049c2867dcba886a56bac8619.tar.gz
rcc-project-f89d528efc0228c049c2867dcba886a56bac8619.tar.xz
[CodeGen] Add target machine registry
Diffstat (limited to 'backend/lib/Tooling')
-rw-r--r--backend/lib/Tooling/BackendDriver.cpp23
-rw-r--r--backend/lib/Tooling/BackendInvocation.cpp72
-rw-r--r--backend/lib/Tooling/CMakeLists.txt3
-rw-r--r--backend/lib/Tooling/MIRFuzzer.cpp20
-rw-r--r--backend/lib/Tooling/PipelineDriver.cpp137
5 files changed, 120 insertions, 135 deletions
diff --git a/backend/lib/Tooling/BackendDriver.cpp b/backend/lib/Tooling/BackendDriver.cpp
index fa82c0c..5932335 100644
--- a/backend/lib/Tooling/BackendDriver.cpp
+++ b/backend/lib/Tooling/BackendDriver.cpp
@@ -4,8 +4,7 @@
#include "rcc/CodeGen/MIRPrinter.h"
#include "rcc/CodeGen/MachineFunction.h"
-#include "rcc/Target/RISCV/RISCVAssemblyPrinter.h"
-#include "rcc/Target/RISCV/RISCVObjectFile.h"
+#include "rcc/Target/TargetMachine.h"
#include <cstddef>
#include <cstdint>
@@ -61,13 +60,13 @@ std::string_view BackendRunResult::text() const noexcept {
return {reinterpret_cast<const char *>(Output.data()), Output.size()};
}
-Expected<BackendRunResult> runBackend(CanonicalMIR Input, const TargetDescription &Target,
- const BackendInvocation &Invocation, ArtifactKind Output,
- PipelineControls Controls,
+Expected<BackendRunResult> runBackend(CanonicalMIR Input, const BackendInvocation &Invocation,
+ ArtifactKind Output, PipelineControls Controls,
MachinePassInstrumentation *Instrumentation) {
- auto InvocationVerification = verifyRV64GCInvocation(Invocation);
- if (!InvocationVerification)
- return std::unexpected(InvocationVerification.error());
+ auto TargetMachine = createTargetMachine(Invocation);
+ if (!TargetMachine)
+ return std::unexpected(TargetMachine.error());
+ const TargetDescription &Target = (*TargetMachine)->targetDescription();
if (Input.Document.unit().functionCount() == 0) {
return makeUnexpected(ErrorCode::InvalidArgument,
"backend input must contain at least one machine function");
@@ -101,8 +100,8 @@ Expected<BackendRunResult> runBackend(CanonicalMIR Input, const TargetDescriptio
MachinePassInstrumentation LocalInstrumentation;
MachinePassInstrumentation *ActiveInstrumentation =
Instrumentation == nullptr ? &LocalInstrumentation : Instrumentation;
- auto Pipeline = runRV64GCPipeline(Input.Document, Target, Invocation, std::move(Controls),
- ActiveInstrumentation);
+ auto Pipeline = runTargetPipeline(Input.Document, **TargetMachine, Invocation,
+ std::move(Controls), ActiveInstrumentation);
if (!Pipeline)
return std::unexpected(Pipeline.error());
@@ -113,12 +112,12 @@ Expected<BackendRunResult> runBackend(CanonicalMIR Input, const TargetDescriptio
return std::unexpected(Printed.error());
Bytes = std::move(*Printed);
} else if (Output == ArtifactKind::Assembly) {
- auto Assembly = riscv::emitAssembly(Input.Document.unit(), Target);
+ auto Assembly = (*TargetMachine)->emitAssembly(Input.Document.unit());
if (!Assembly)
return std::unexpected(Assembly.error());
Bytes.assign(Assembly->begin(), Assembly->end());
} else {
- auto Object = riscv::emitObject(Input.Document.unit(), Target);
+ auto Object = (*TargetMachine)->emitObject(Input.Document.unit());
if (!Object)
return std::unexpected(Object.error());
Bytes = std::move(*Object);
diff --git a/backend/lib/Tooling/BackendInvocation.cpp b/backend/lib/Tooling/BackendInvocation.cpp
index 232d34f..8fbc4d6 100644
--- a/backend/lib/Tooling/BackendInvocation.cpp
+++ b/backend/lib/Tooling/BackendInvocation.cpp
@@ -7,7 +7,9 @@
#include "rcc/CodeGen/TargetDescription.h"
#include "rcc/CodeGen/TargetMIRTextInfo.h"
#include "rcc/CodeGen/TargetRegisterInfo.h"
+#include "rcc/MC/TargetRegistry.h"
#include "rcc/Support/SHA256.h"
+#include "rcc/Target/TargetMachine.h"
#include <algorithm>
#include <cctype>
@@ -374,27 +376,65 @@ std::string BackendInvocation::canonicalText() const {
return Output;
}
-BackendInvocation defaultRV64GCInvocation() {
+Expected<BackendInvocation> defaultBackendInvocation(const Target &Target) {
+ TargetMachineOptions Defaults = Target.defaultMachineOptions();
BackendInvocation Result;
- Result.Triple = "riscv64-unknown-linux-gnu";
- Result.CPU = "generic-rv64gc";
- Result.TuneCPU = "generic-rv64gc";
- Result.Features = {"+i", "+m", "+a", "+f", "+d", "+c", "+zicsr", "+zifencei"};
- Result.ABI = "lp64d";
- Result.DataLayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
- Result.TargetOptions = {
- {"function-sections", "false"},
- {"omit-frame-pointer", "true"},
- {"stack-realignment", "false"},
- };
- Result.AssemblerFlavor = "rcc-integrated-gnu";
- Result.AssemblerVersion = "rcc-mc-v1";
- Result.AssemblerOptions = {{"relax", "true"}};
+ Result.Triple = std::move(Defaults.Triple);
+ Result.CPU = std::move(Defaults.CPU);
+ Result.TuneCPU = std::move(Defaults.TuneCPU);
+ Result.Features = std::move(Defaults.Features);
+ Result.ABI = std::move(Defaults.ABI);
+ Result.DataLayout = std::move(Defaults.DataLayout);
+ Result.Relocation = Defaults.Relocation;
+ Result.Code = Defaults.Code;
+ Result.Optimization = Defaults.Optimization;
+ Result.TargetOptions = std::move(Defaults.Options);
+ Result.TargetABILoweringVersion = std::move(Defaults.ABILoweringVersion);
+ Result.AssemblerFlavor = std::move(Defaults.AssemblerFlavor);
+ Result.AssemblerVersion = std::move(Defaults.AssemblerVersion);
+ Result.AssemblerOptions = std::move(Defaults.AssemblerOptions);
auto Verified = Result.canonicalizeAndVerify();
- (void)Verified;
+ if (!Verified)
+ return std::unexpected(Verified.error());
return Result;
}
+Expected<std::unique_ptr<TargetMachine>> createTargetMachine(const BackendInvocation &Invocation) {
+ BackendInvocation Canonical = Invocation;
+ auto Verified = Canonical.canonicalizeAndVerify();
+ if (!Verified)
+ return std::unexpected(Verified.error());
+ if (Canonical != Invocation) {
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "backend invocation must be canonicalized before execution");
+ }
+ if (Invocation.MIRReferenceRevision != LLVMReferenceRevision ||
+ Invocation.GenericOpcodeVersion != GenericOpcodeReferenceVersion) {
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "backend invocation reference versions do not match this build");
+ }
+ auto RegisteredTarget = TargetRegistry::lookupTarget(Invocation.Triple);
+ if (!RegisteredTarget)
+ return std::unexpected(RegisteredTarget.error());
+ TargetMachineOptions Options{
+ .Triple = Invocation.Triple,
+ .CPU = Invocation.CPU,
+ .TuneCPU = Invocation.TuneCPU,
+ .Features = Invocation.Features,
+ .ABI = Invocation.ABI,
+ .DataLayout = Invocation.DataLayout,
+ .Relocation = Invocation.Relocation,
+ .Code = Invocation.Code,
+ .Optimization = Invocation.Optimization,
+ .Options = Invocation.TargetOptions,
+ .ABILoweringVersion = Invocation.TargetABILoweringVersion,
+ .AssemblerFlavor = Invocation.AssemblerFlavor,
+ .AssemblerVersion = Invocation.AssemblerVersion,
+ .AssemblerOptions = Invocation.AssemblerOptions,
+ };
+ return (*RegisteredTarget)->createTargetMachine(std::move(Options));
+}
+
Expected<std::string> computeTargetDescriptionFingerprint(const TargetDescription &Target) {
std::string Canonical;
appendField(Canonical, "fingerprint-schema", "rcc-target-fingerprint-v1");
diff --git a/backend/lib/Tooling/CMakeLists.txt b/backend/lib/Tooling/CMakeLists.txt
index bf20e37..361a776 100644
--- a/backend/lib/Tooling/CMakeLists.txt
+++ b/backend/lib/Tooling/CMakeLists.txt
@@ -36,8 +36,9 @@ target_link_libraries(
RCCBackendTooling
PUBLIC
RCCBackend::MIR
- RCCBackend::RISCV
+ RCCBackend::MC
RCCBackend::Support
+ RCCBackend::Target
)
set_target_properties(
diff --git a/backend/lib/Tooling/MIRFuzzer.cpp b/backend/lib/Tooling/MIRFuzzer.cpp
index 79e1b50..2ab3b6f 100644
--- a/backend/lib/Tooling/MIRFuzzer.cpp
+++ b/backend/lib/Tooling/MIRFuzzer.cpp
@@ -14,7 +14,7 @@
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/MachineVerifier.h"
#include "rcc/CodeGen/TargetDescription.h"
-#include "rcc/Target/RISCV/RISCVPipeline.h"
+#include "rcc/Target/TargetMachine.h"
#include "rcc/Tooling/ArtifactStore.h"
#include "rcc/Tooling/BackendDriver.h"
@@ -262,7 +262,7 @@ private:
if (Function == nullptr || isEarlierStage(Stage, stageForFunction(*Function))) {
return false;
}
- auto Run = runBackend(std::move(*Parsed), Target, Invocation, outputForStage(Stage));
+ auto Run = runBackend(std::move(*Parsed), Invocation, outputForStage(Stage));
if (!Run)
return std::unexpected(Run.error());
auto RoundTrip = verifyCanonicalRoundTrip(std::string(Run->text()), Target, Invocation);
@@ -295,14 +295,10 @@ private:
const MachineFunction *Function = Parsed->Document.unit().functionAt(0);
if (Function == nullptr)
return std::unexpected(Error(ErrorCode::InternalError, "pipeline fuzz input has no function"));
- auto Features = riscv::RISCVSubtargetFeatures::fromFeatureList(Invocation.Features);
- if (!Features)
- return std::unexpected(Features.error());
- auto ABI = riscv::parseRISCVABI(Invocation.ABI);
- if (!ABI)
- return std::unexpected(ABI.error());
- const riscv::RISCVSubtarget Subtarget(*Features, Invocation.Relocation, Invocation.Code, *ABI);
- auto Names = riscv::canonicalPipelinePassNames(*Function, Subtarget);
+ auto TargetMachine = createTargetMachine(Invocation);
+ if (!TargetMachine)
+ return std::unexpected(TargetMachine.error());
+ auto Names = (*TargetMachine)->codeGenPassNames(*Function);
if (!Names)
return std::unexpected(Names.error());
PipelineControls Controls;
@@ -312,7 +308,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, ArtifactKind::FinalMIR, Controls);
+ auto Run = runBackend(std::move(*Parsed), Invocation, ArtifactKind::FinalMIR, Controls);
if (!Run)
return std::unexpected(Run.error());
auto RoundTrip = verifyCanonicalRoundTrip(std::string(Run->text()), Target, Invocation);
@@ -486,7 +482,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, ArtifactKind::FinalMIR);
+ auto Compiled = runBackend(std::move(*CompiledInput), 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 72c7dd2..6020979 100644
--- a/backend/lib/Tooling/PipelineDriver.cpp
+++ b/backend/lib/Tooling/PipelineDriver.cpp
@@ -10,7 +10,7 @@
#include "rcc/CodeGen/MachineStripDebug.h"
#include "rcc/CodeGen/MachineVerifier.h"
#include "rcc/MIR/ReachingDefPrinter.h"
-#include "rcc/Target/RISCV/RISCVPipeline.h"
+#include "rcc/Target/TargetMachine.h"
#include <algorithm>
#include <atomic>
@@ -100,12 +100,6 @@ struct FunctionRunResult final {
return false;
}
-[[nodiscard]] bool booleanTargetOption(const BackendInvocation &Invocation,
- std::string_view Name) noexcept {
- const auto Option = std::ranges::find(Invocation.TargetOptions, Name, &BackendOption::Name);
- return Option != Invocation.TargetOptions.end() && Option->Value == "true";
-}
-
[[nodiscard]] std::optional<BackendStage> stageAfterPass(std::string_view Pass) noexcept {
if (Pass == "legalizer")
return BackendStage::LegalizedMIR;
@@ -123,16 +117,16 @@ struct FunctionRunResult final {
}
[[nodiscard]] Expected<std::unique_ptr<MachineFunctionPass>>
-createNamedMachinePass(std::string_view Name, const riscv::RISCVSubtarget &Subtarget,
- riscv::RISCVPipelineOptions Options = {}) {
+createNamedMachinePass(std::string_view Name, const TargetMachine &TargetMachine,
+ TargetPipelineOptions Options = {}) {
if (Name == mir::ReachingDefPrinterPass::name())
return std::make_unique<mir::ReachingDefPrinterPass>();
- return riscv::createCanonicalPipelinePass(Name, Subtarget, Options);
+ return TargetMachine.createMachinePass(Name, Options);
}
[[nodiscard]] Expected<MachineFunctionPassManager::PassList>
createPasses(const MachineFunction &Function, const BackendInvocation &Invocation,
- const riscv::RISCVSubtarget &Subtarget, MachinePassManagerOptions Options) {
+ const TargetMachine &TargetMachine, MachinePassManagerOptions Options) {
const auto GlobalISelAbortOption = std::ranges::find(
Invocation.TargetOptions, std::string_view{"global-isel-abort"}, &BackendOption::Name);
GlobalISelAbortMode GlobalISelAbort = GlobalISelAbortMode::Enable;
@@ -146,13 +140,13 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
const bool DebugMachineScheduler = hasDebugType(Invocation, "machine-scheduler");
const bool DebugPrologueEpilogue = hasDebugType(Invocation, "prologepilog");
if (Invocation.PassPipeline.size() == 1 && Invocation.PassPipeline.front() == "default") {
- auto Added = riscv::addCanonicalPipeline(
- Pipeline, Function, Subtarget,
- riscv::RISCVPipelineOptions{.Optimization = Invocation.Optimization,
- .UseTargetCopyInstructions = true,
- .GlobalISelAbort = GlobalISelAbort,
- .DebugMachineScheduler = DebugMachineScheduler,
- .DebugPrologueEpilogue = DebugPrologueEpilogue});
+ auto Added = TargetMachine.addCodeGenPasses(
+ Pipeline, Function,
+ TargetPipelineOptions{.Optimization = Invocation.Optimization,
+ .UseTargetCopyInstructions = true,
+ .GlobalISelAbort = GlobalISelAbort,
+ .DebugMachineScheduler = DebugMachineScheduler,
+ .DebugPrologueEpilogue = DebugPrologueEpilogue});
if (!Added)
return std::unexpected(Added.error());
} else {
@@ -166,12 +160,12 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
TargetCopyOption != Invocation.TargetOptions.end() && TargetCopyOption->Value == "true";
for (const std::string &Name : Invocation.PassPipeline) {
auto Pass = createNamedMachinePass(
- Name, Subtarget,
- riscv::RISCVPipelineOptions{.Optimization = Invocation.Optimization,
- .UseTargetCopyInstructions = UseTargetCopyInstructions,
- .GlobalISelAbort = GlobalISelAbort,
- .DebugMachineScheduler = DebugMachineScheduler,
- .DebugPrologueEpilogue = DebugPrologueEpilogue});
+ Name, TargetMachine,
+ TargetPipelineOptions{.Optimization = Invocation.Optimization,
+ .UseTargetCopyInstructions = UseTargetCopyInstructions,
+ .GlobalISelAbort = GlobalISelAbort,
+ .DebugMachineScheduler = DebugMachineScheduler,
+ .DebugPrologueEpilogue = DebugPrologueEpilogue});
if (!Pass)
return std::unexpected(Pass.error());
auto Added = Pipeline.addPass(std::move(*Pass));
@@ -183,7 +177,7 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
}
[[nodiscard]] Expected<void> validateSelector(std::string_view Selector, bool AllowAll,
- const riscv::RISCVSubtarget &Subtarget) {
+ const TargetMachine &TargetMachine) {
if (Selector == "all" && AllowAll)
return {};
const std::size_t Comma = Selector.find(',');
@@ -192,7 +186,7 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
if (Name.empty())
return makeUnexpected(ErrorCode::InvalidInvocation, "empty pipeline pass selector");
if (Name != "machine-outliner") {
- auto Pass = createNamedMachinePass(Name, Subtarget);
+ auto Pass = createNamedMachinePass(Name, TargetMachine);
if (!Pass)
return std::unexpected(Pass.error());
}
@@ -211,8 +205,7 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
}
[[nodiscard]] Expected<void> validateControls(const PipelineControls &Controls,
- riscv::RISCVSubtargetFeatures Features) {
- const riscv::RISCVSubtarget Subtarget(Features);
+ const TargetMachine &TargetMachine) {
if (Controls.StartBefore && Controls.StartAfter) {
return makeUnexpected(ErrorCode::InvalidInvocation,
"-start-before and -start-after cannot be combined");
@@ -222,32 +215,32 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
"-stop-before and -stop-after cannot be combined");
}
if (Controls.StartBefore) {
- auto Result = validateSelector(*Controls.StartBefore, false, Subtarget);
+ auto Result = validateSelector(*Controls.StartBefore, false, TargetMachine);
if (!Result)
return Result;
}
if (Controls.StartAfter) {
- auto Result = validateSelector(*Controls.StartAfter, false, Subtarget);
+ auto Result = validateSelector(*Controls.StartAfter, false, TargetMachine);
if (!Result)
return Result;
}
if (Controls.StopBefore) {
- auto Result = validateSelector(*Controls.StopBefore, false, Subtarget);
+ auto Result = validateSelector(*Controls.StopBefore, false, TargetMachine);
if (!Result)
return Result;
}
if (Controls.StopAfter) {
- auto Result = validateSelector(*Controls.StopAfter, false, Subtarget);
+ auto Result = validateSelector(*Controls.StopAfter, false, TargetMachine);
if (!Result)
return Result;
}
for (const std::string &Selector : Controls.PrintBefore) {
- auto Result = validateSelector(Selector, true, Subtarget);
+ auto Result = validateSelector(Selector, true, TargetMachine);
if (!Result)
return Result;
}
for (const std::string &Selector : Controls.PrintAfter) {
- auto Result = validateSelector(Selector, true, Subtarget);
+ auto Result = validateSelector(Selector, true, TargetMachine);
if (!Result)
return Result;
}
@@ -278,21 +271,18 @@ captureSnapshot(FunctionRunResult &Result, const mir::MIRDocument &Document,
}
[[nodiscard]] Expected<FunctionRunResult>
-runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetDescription &Target,
- const BackendInvocation &Invocation, const PipelineControls &Controls,
- riscv::RISCVSubtargetFeatures Features, bool AllowSnapshots,
+runFunction(MachineFunction &Function, mir::MIRDocument &Document,
+ const TargetMachine &TargetMachine, const BackendInvocation &Invocation,
+ const PipelineControls &Controls, bool AllowSnapshots,
MachinePassInstrumentation *Instrumentation) {
FunctionRunResult Result;
- auto ABI = riscv::parseRISCVABI(Invocation.ABI);
- if (!ABI)
- return std::unexpected(ABI.error());
- const riscv::RISCVSubtarget Subtarget(Features, Invocation.Relocation, Invocation.Code, *ABI);
+ const TargetDescription &Target = TargetMachine.targetDescription();
MachinePassManagerOptions ManagerOptions{
.VerifyBefore = true,
.VerifyEach = Controls.VerifyEach,
.DetectUnreportedChanges = Controls.DetectUnreportedChanges,
};
- auto Passes = createPasses(Function, Invocation, Subtarget, ManagerOptions);
+ auto Passes = createPasses(Function, Invocation, TargetMachine, ManagerOptions);
if (!Passes)
return std::unexpected(Passes.error());
MachineFunctionAnalysisManager Analyses;
@@ -402,12 +392,9 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD
}
[[nodiscard]] Expected<PipelineRunResult>
-runMachineOutliner(mir::MIRDocument &Document, const TargetDescription &Target,
- const BackendInvocation &Invocation, const PipelineControls &Controls,
- MachinePassInstrumentation *Instrumentation) {
- auto TargetInfo =
- riscv::createMachineOutlinerInfo(booleanTargetOption(Invocation, "function-sections"),
- booleanTargetOption(Invocation, "riscv-outliner-regsave"));
+runMachineOutliner(mir::MIRDocument &Document, const TargetMachine &TargetMachine,
+ const PipelineControls &Controls, MachinePassInstrumentation *Instrumentation) {
+ auto TargetInfo = TargetMachine.createOutlinerInfo();
if (!TargetInfo)
return std::unexpected(TargetInfo.error());
@@ -434,7 +421,8 @@ runMachineOutliner(mir::MIRDocument &Document, const TargetDescription &Target,
auto Registered = registerMachineOptimizationAnalyses(FunctionAnalyses);
if (!Registered)
return std::unexpected(Registered.error());
- auto Run = Pipeline.run(Document.unit(), Target, UnitAnalyses, FunctionAnalyses, Instrumentation);
+ auto Run = Pipeline.run(Document.unit(), TargetMachine.targetDescription(), UnitAnalyses,
+ FunctionAnalyses, Instrumentation);
if (!Run)
return std::unexpected(Run.error());
PipelineRunResult Result;
@@ -507,51 +495,12 @@ Expected<BackendStage> parseBackendStage(std::string_view Value) {
return makeUnexpected(ErrorCode::InvalidInvocation, "unknown backend stage");
}
-Expected<void> verifyRV64GCInvocation(const BackendInvocation &Invocation) {
- BackendInvocation Canonical = Invocation;
- auto Verified = Canonical.canonicalizeAndVerify();
- if (!Verified)
- return std::unexpected(Verified.error());
- if (Canonical != Invocation) {
- return makeUnexpected(ErrorCode::InvalidInvocation,
- "RV64GC backend invocation must be canonicalized before execution");
- }
- const BackendInvocation Expected = defaultRV64GCInvocation();
- auto Features = riscv::RISCVSubtargetFeatures::fromFeatureList(Invocation.Features);
- if (!Features)
- return std::unexpected(Features.error());
- auto ABI = riscv::parseRISCVABI(Invocation.ABI);
- if (!ABI)
- return std::unexpected(ABI.error());
- if (*ABI == riscv::RISCVABI::LP64D && !Features->has(riscv::RISCVExtension::D)) {
- return makeUnexpected(ErrorCode::InvalidInvocation, "RISC-V LP64D requires the D extension");
- }
- if (Invocation.Triple != Expected.Triple || Invocation.CPU != Expected.CPU ||
- Invocation.TuneCPU != Expected.TuneCPU || Invocation.DataLayout != Expected.DataLayout) {
- return makeUnexpected(ErrorCode::InvalidInvocation,
- "backend invocation does not select a supported RV64 target");
- }
- if (Invocation.MIRReferenceRevision != LLVMReferenceRevision ||
- Invocation.GenericOpcodeVersion != GenericOpcodeReferenceVersion ||
- Invocation.TargetABILoweringVersion != RV64GCTargetABILoweringVersion) {
- return makeUnexpected(ErrorCode::InvalidInvocation,
- "backend invocation reference versions do not match this build");
- }
- return {};
-}
-
-Expected<PipelineRunResult> runRV64GCPipeline(mir::MIRDocument &Document,
- const TargetDescription &Target,
+Expected<PipelineRunResult> runTargetPipeline(mir::MIRDocument &Document,
+ const TargetMachine &TargetMachine,
const BackendInvocation &Invocation,
PipelineControls Controls,
MachinePassInstrumentation *Instrumentation) {
- auto InvocationVerification = verifyRV64GCInvocation(Invocation);
- if (!InvocationVerification)
- return std::unexpected(InvocationVerification.error());
- auto Features = riscv::RISCVSubtargetFeatures::fromFeatureList(Invocation.Features);
- if (!Features)
- return std::unexpected(Features.error());
- auto ControlVerification = validateControls(Controls, *Features);
+ auto ControlVerification = validateControls(Controls, TargetMachine);
if (!ControlVerification)
return std::unexpected(ControlVerification.error());
auto UnitVerification = Document.unit().verify();
@@ -583,7 +532,7 @@ Expected<PipelineRunResult> runRV64GCPipeline(mir::MIRDocument &Document,
return makeUnexpected(ErrorCode::InvalidInvocation,
"machine-outliner cannot be mixed with per-function passes");
}
- return runMachineOutliner(Document, Target, Invocation, Controls, ActiveInstrumentation);
+ return runMachineOutliner(Document, TargetMachine, Controls, ActiveInstrumentation);
}
const std::size_t FunctionCount = Document.unit().functionCount();
@@ -596,7 +545,7 @@ Expected<PipelineRunResult> runRV64GCPipeline(mir::MIRDocument &Document,
if (Function == nullptr)
return makeUnexpected(ErrorCode::InternalError,
"compilation unit contains a null function");
- auto Run = runFunction(*Function, Document, Target, Invocation, Controls, *Features, true,
+ auto Run = runFunction(*Function, Document, TargetMachine, Invocation, Controls, true,
ActiveInstrumentation);
if (!Run)
return std::unexpected(Run.error());
@@ -617,7 +566,7 @@ Expected<PipelineRunResult> runRV64GCPipeline(mir::MIRDocument &Document,
Error(ErrorCode::InternalError, "compilation unit contains a null function");
continue;
}
- auto Run = runFunction(*Function, Document, Target, Invocation, Controls, *Features, false,
+ auto Run = runFunction(*Function, Document, TargetMachine, Invocation, Controls, false,
ActiveInstrumentation);
if (!Run) {
FunctionResults[Index].Failure = Run.error();