// 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.OperandTypes.size() + Rule.OperandBanks.size() + Rule.OperandClasses.size() + Rule.AppendedImmediates.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); 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); emitInstruction(Output, "MutateOpcode", 0, Rule.ResultOpcode); for (const std::int64_t Immediate : Rule.AppendedImmediates) emitInstruction(Output, "AppendImmediate", 0, 0, "0", Immediate); 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