// SPDX-License-Identifier: GPL-3.0-or-later #include "TableGenBackends.h" #include #include #include #include #include #include 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) { Output << " {GIMatchTableOpcode::" << Opcode << ", " << OperandIndex << ", " << Value << ", " << Auxiliary << ", " << Immediate << "},\n"; } void emitTypePredicate(std::ostream &Output, std::uint32_t OperandIndex, const NormalizedSelectionTypePredicate &Predicate) { emitInstruction(Output, "CheckOperandType", OperandIndex, Predicate.Bits, "static_cast(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.OperandTypes.size() + Rule.OperandBanks.size() + Rule.OperandClasses.size() + Rule.OperandDefConstants.size() + Rule.Temporaries.size() + Rule.EraseOperandDefinitions.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 NormalizedSelectionOperandDefConstantPredicate &Predicate : Rule.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 GeneratedGlobalISelConstantRanges = {{\n"; for (const NormalizedSelectionRule &Rule : Model.SelectionRules) { for (const NormalizedSelectionOperandDefConstantPredicate &Predicate : Rule.OperandDefConstants) { for (const NormalizedSelectionOperandDefConstantPredicate::Range &Range : Predicate.Ranges) Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n"; } } Output << "}};\n\n"; Output << "constexpr std::array 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); 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 NormalizedSelectionOperandDefConstantPredicate &Predicate : Rule.OperandDefConstants) { emitInstruction(Output, "CheckOperandDefConstantRanges", Predicate.OperandIndex, static_cast(FirstConstantRange), std::to_string(Predicate.Ranges.size())); FirstConstantRange += Predicate.Ranges.size(); } for (const NormalizedSelectionTemporary &Temporary : Rule.Temporaries) emitInstruction(Output, "CreateTemporary", Temporary.TypeFromOperand, Temporary.ID); 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::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::CapturedImmediate: emitInstruction(Output, "RenderCapturedImmediate", Renderer.Value, static_cast(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 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