// 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 { return 3U + (Rule.ResultType ? 1U : 0U) + (Rule.IntegerPredicate ? 1U : 0U) + Rule.OperandTypes.size() + Rule.OperandBanks.size() + Rule.OperandClasses.size() + Rule.OperandDefConstants.size() + (Rule.OperandRenderers ? Rule.OperandRenderers->size() : 0U) + Rule.AppendedImmediates.size() + Rule.EraseOperandDefinitions.size(); } } // namespace std::string emitGlobalISel(const NormalizedTargetModel &Model, std::string_view SourceName) { std::size_t InstructionCount = 0; for (const NormalizedSelectionRule &Rule : Model.SelectionRules) InstructionCount += instructionCount(Rule); 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 GeneratedGlobalISelInstructions = {{\n"; 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, "CheckOperandDefConstant", Predicate.OperandIndex, 0, "0", Predicate.Value); emitInstruction(Output, "MutateOpcode", 0, Rule.ResultOpcode); if (Rule.OperandRenderers) { for (const NormalizedSelectionOperandRenderer &Renderer : *Rule.OperandRenderers) { if (Renderer.SourceKind == NormalizedSelectionOperandRenderer::Kind::Operand) emitInstruction(Output, "RenderOperand", Renderer.Value); else emitInstruction(Output, "RenderPhysicalRegister", 0, Renderer.Value, std::to_string(Renderer.Flags)); } } for (const std::int64_t Immediate : Rule.AppendedImmediates) emitInstruction(Output, "AppendImmediate", 0, 0, "0", Immediate); 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" "}\n\n"; Output << "#endif // GET_GLOBALISEL_MATCH_TABLE\n"; return Output.str(); } } // namespace rcc::targetgen