aboutsummaryrefslogtreecommitdiff
path: root/backend/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backend/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r--backend/utils/TableGen/GlobalISelEmitter.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/backend/utils/TableGen/GlobalISelEmitter.cpp b/backend/utils/TableGen/GlobalISelEmitter.cpp
new file mode 100644
index 0000000..3ce9411
--- /dev/null
+++ b/backend/utils/TableGen/GlobalISelEmitter.cpp
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "TableGenBackends.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <string_view>
+
+namespace rcc::targetgen {
+namespace {
+
+[[nodiscard]] std::string_view typeKindName(NormalizedSelectionTypeKind Kind) noexcept {
+ switch (Kind) {
+ case NormalizedSelectionTypeKind::Any:
+ return "Any";
+ case NormalizedSelectionTypeKind::Scalar:
+ return "Scalar";
+ case NormalizedSelectionTypeKind::Pointer:
+ return "Pointer";
+ }
+ return "Any";
+}
+
+void emitInstruction(std::ostream &Output, std::string_view Opcode, std::uint32_t OperandIndex,
+ std::uint32_t Value = 0, std::string_view Auxiliary = "0",
+ std::int64_t Immediate = 0, std::string_view Symbol = {}) {
+ Output << " {GIMatchTableOpcode::" << Opcode << ", " << OperandIndex << ", " << Value << ", "
+ << Auxiliary << ", " << Immediate << ", ";
+ appendQuoted(Output, Symbol);
+ Output << "},\n";
+}
+
+void emitTypePredicate(std::ostream &Output, std::uint32_t OperandIndex,
+ const NormalizedSelectionTypePredicate &Predicate) {
+ emitInstruction(Output, "CheckOperandType", OperandIndex, Predicate.Bits,
+ "static_cast<std::uint32_t>(GIMatchTypeKind::" +
+ std::string(typeKindName(Predicate.Kind)) + ")");
+}
+
+[[nodiscard]] std::size_t instructionCount(const NormalizedSelectionRule &Rule) noexcept {
+ std::size_t Count = 2U + (Rule.ResultType ? 1U : 0U) + (Rule.IntegerPredicate ? 1U : 0U) +
+ (Rule.FloatingPredicate ? 1U : 0U) + (Rule.MemoryPredicate ? 1U : 0U) +
+ Rule.TargetPredicates.size() + Rule.OperandTypes.size() +
+ Rule.OperandBanks.size() + Rule.OperandClasses.size() +
+ Rule.OperandImmediates.size() + Rule.OperandDefConstants.size() +
+ Rule.Temporaries.size() + Rule.EraseOperandDefinitions.size();
+ for (const NormalizedSelectionDefUsePredicate &Predicate : Rule.DefUsePredicates)
+ Count += 1U + static_cast<std::size_t>(Predicate.IntegerPredicate.has_value()) +
+ Predicate.Captures.size() + Predicate.OperandDefConstants.size();
+ for (const NormalizedSelectionAction &Action : Rule.Actions)
+ Count += 1U + Action.OperandRenderers.size();
+ return Count;
+}
+
+} // namespace
+
+std::string emitGlobalISel(const NormalizedTargetModel &Model, std::string_view SourceName) {
+ std::size_t InstructionCount = 0;
+ std::size_t ConstantRangeCount = 0;
+ for (const NormalizedSelectionRule &Rule : Model.SelectionRules)
+ InstructionCount += instructionCount(Rule);
+ for (const NormalizedSelectionRule &Rule : Model.SelectionRules) {
+ for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) {
+ ConstantRangeCount += Predicate.Ranges.size();
+ }
+ for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
+ Rule.OperandDefConstants) {
+ ConstantRangeCount += Predicate.Ranges.size();
+ }
+ for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) {
+ for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
+ DefUse.OperandDefConstants) {
+ ConstantRangeCount += Predicate.Ranges.size();
+ }
+ }
+ }
+
+ std::ostringstream Output;
+ Output << "// SPDX-License-Identifier: GPL-3.0-or-later\n\n";
+ Output << "// This file is generated by rcc-tblgen from ";
+ appendQuoted(Output, SourceName);
+ Output << ". Do not edit it manually.\n\n";
+ Output << "#ifdef GET_GLOBALISEL_MATCH_TABLE\n\n";
+ Output << "constexpr std::array<GIMatchTableConstantRange, " << ConstantRangeCount
+ << "> GeneratedGlobalISelConstantRanges = {{\n";
+ for (const NormalizedSelectionRule &Rule : Model.SelectionRules) {
+ for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) {
+ for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges)
+ Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n";
+ }
+ for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
+ Rule.OperandDefConstants) {
+ for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges)
+ Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n";
+ }
+ for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) {
+ for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
+ DefUse.OperandDefConstants) {
+ for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges)
+ Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n";
+ }
+ }
+ }
+ Output << "}};\n\n";
+
+ Output << "constexpr std::array<GIMatchTableInstruction, " << InstructionCount
+ << "> GeneratedGlobalISelInstructions = {{\n";
+ std::size_t FirstConstantRange = 0;
+ for (const NormalizedSelectionRule &Rule : Model.SelectionRules) {
+ emitInstruction(Output, "CheckOpcode", 0, Rule.MatchOpcode);
+ if (Rule.ResultType)
+ emitTypePredicate(Output, 0, *Rule.ResultType);
+ if (Rule.IntegerPredicate)
+ emitInstruction(Output, "CheckIntegerPredicate", Rule.IntegerPredicate->OperandIndex,
+ Rule.IntegerPredicate->Predicate);
+ if (Rule.FloatingPredicate)
+ emitInstruction(Output, "CheckFloatingPredicate", Rule.FloatingPredicate->OperandIndex,
+ Rule.FloatingPredicate->Predicate);
+ if (Rule.MemoryPredicate)
+ emitInstruction(Output, "CheckMemorySize", Rule.MemoryPredicate->MemoryOperandIndex,
+ Rule.MemoryPredicate->Bytes);
+ for (const std::string &Predicate : Rule.TargetPredicates)
+ emitInstruction(Output, "CheckTargetPredicate", 0, 0, "0", 0, Predicate);
+ for (const NormalizedSelectionOperandTypePredicate &Predicate : Rule.OperandTypes)
+ emitTypePredicate(Output, Predicate.OperandIndex, Predicate.Type);
+ for (const NormalizedSelectionOperandBankPredicate &Predicate : Rule.OperandBanks)
+ emitInstruction(Output, "CheckOperandBank", Predicate.OperandIndex, Predicate.Bank);
+ for (const NormalizedSelectionOperandClassPredicate &Predicate : Rule.OperandClasses)
+ emitInstruction(Output, "CheckOperandClass", Predicate.OperandIndex, Predicate.RegClass);
+ for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) {
+ emitInstruction(Output, "CheckOperandImmediateRanges", Predicate.OperandIndex,
+ static_cast<std::uint32_t>(FirstConstantRange),
+ std::to_string(Predicate.Ranges.size()));
+ FirstConstantRange += Predicate.Ranges.size();
+ }
+ for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
+ Rule.OperandDefConstants) {
+ emitInstruction(Output, "CheckOperandDefConstantRanges", Predicate.OperandIndex,
+ static_cast<std::uint32_t>(FirstConstantRange),
+ std::to_string(Predicate.Ranges.size()));
+ FirstConstantRange += Predicate.Ranges.size();
+ }
+ for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) {
+ emitInstruction(Output, "CheckOperandDefOpcode", DefUse.RootOperandIndex, DefUse.Opcode);
+ if (DefUse.IntegerPredicate) {
+ emitInstruction(Output, "CheckOperandDefIntegerPredicate", DefUse.RootOperandIndex,
+ DefUse.IntegerPredicate->Predicate,
+ std::to_string(DefUse.IntegerPredicate->OperandIndex));
+ }
+ for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
+ DefUse.OperandDefConstants) {
+ emitInstruction(Output, "CheckOperandDefOperandConstantRanges", DefUse.RootOperandIndex,
+ static_cast<std::uint32_t>(FirstConstantRange),
+ std::to_string(Predicate.OperandIndex),
+ static_cast<std::int64_t>(Predicate.Ranges.size()));
+ FirstConstantRange += Predicate.Ranges.size();
+ }
+ for (const NormalizedSelectionDefUseCapture &Capture : DefUse.Captures)
+ emitInstruction(Output, "CaptureDefOperand", DefUse.RootOperandIndex, Capture.ID,
+ std::to_string(Capture.OperandIndex));
+ }
+ for (const NormalizedSelectionTemporary &Temporary : Rule.Temporaries) {
+ if (Temporary.TypeFromOperand) {
+ emitInstruction(Output, "CreateTemporary", *Temporary.TypeFromOperand, Temporary.ID);
+ continue;
+ }
+ emitInstruction(Output, "CreateTemporaryType", 0, Temporary.ID,
+ "static_cast<std::uint32_t>(GIMatchTypeKind::" +
+ std::string(typeKindName(Temporary.Type->Kind)) + ")",
+ Temporary.Type->Bits);
+ }
+ for (const NormalizedSelectionAction &Action : Rule.Actions) {
+ emitInstruction(Output, Action.ReplacesRoot ? "MutateOpcode" : "BuildInstruction", 0,
+ Action.ResultOpcode);
+ for (const NormalizedSelectionOperandRenderer &Renderer : Action.OperandRenderers) {
+ switch (Renderer.SourceKind) {
+ case NormalizedSelectionOperandRenderer::Kind::Operand:
+ emitInstruction(Output, "RenderOperand", Renderer.Value);
+ break;
+ case NormalizedSelectionOperandRenderer::Kind::ComplexOperand:
+ emitInstruction(Output, "RenderComplexOperand", Renderer.Value, 0, "0", 0,
+ Renderer.ComplexRenderer);
+ break;
+ case NormalizedSelectionOperandRenderer::Kind::PhysicalRegister:
+ emitInstruction(Output, "RenderPhysicalRegister", 0, Renderer.Value,
+ std::to_string(Renderer.Flags));
+ break;
+ case NormalizedSelectionOperandRenderer::Kind::Temporary:
+ emitInstruction(Output, "RenderTemporary", 0, Renderer.Value,
+ std::to_string(Renderer.Flags));
+ break;
+ case NormalizedSelectionOperandRenderer::Kind::CapturedOperand:
+ emitInstruction(Output, "RenderCapturedOperand", 0, Renderer.Value);
+ break;
+ case NormalizedSelectionOperandRenderer::Kind::CapturedImmediate:
+ emitInstruction(Output, "RenderCapturedImmediate", Renderer.Value,
+ static_cast<std::uint32_t>(Renderer.Transform));
+ break;
+ case NormalizedSelectionOperandRenderer::Kind::Immediate:
+ emitInstruction(Output, "RenderImmediate", 0, 0, "0", Renderer.Immediate);
+ break;
+ }
+ }
+ }
+ for (const std::uint32_t OperandIndex : Rule.EraseOperandDefinitions)
+ emitInstruction(Output, "EraseOperandDefinition", OperandIndex);
+ emitInstruction(Output, "Complete", 0);
+ }
+ Output << "}};\n\n";
+
+ Output << "constexpr std::array<GIMatchTableRule, " << Model.SelectionRules.size()
+ << "> GeneratedGlobalISelRules = {{\n";
+ std::size_t FirstInstruction = 0;
+ for (const NormalizedSelectionRule &Rule : Model.SelectionRules) {
+ const std::size_t Count = instructionCount(Rule);
+ Output << " {";
+ appendQuoted(Output, Rule.Symbol);
+ Output << ", " << Rule.Priority << ", " << FirstInstruction << ", " << Count << "},\n";
+ FirstInstruction += Count;
+ }
+ Output << "}};\n\n";
+ Output << "[[nodiscard]] constexpr GIMatchTable generatedGlobalISelMatchTable() noexcept {\n"
+ " return {GeneratedGlobalISelInstructions, GeneratedGlobalISelRules,\n"
+ " GeneratedGlobalISelConstantRanges};\n"
+ "}\n\n";
+ Output << "#endif // GET_GLOBALISEL_MATCH_TABLE\n";
+ return Output.str();
+}
+
+} // namespace rcc::targetgen