// 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 instructionSide(NormalizedMacroFusionInstruction Instruction) noexcept { return Instruction == NormalizedMacroFusionInstruction::First ? "First" : "Second"; } void emitOpcodes(std::ostream &Output, const NormalizedMacroFusionRule &Rule, std::string_view Suffix, const std::vector &Opcodes) { Output << "constexpr std::array " << Rule.Symbol << Suffix << " = {{\n"; for (const std::uint32_t Opcode : Opcodes) Output << " Opcode::fromValue(" << Opcode << "),\n"; Output << "}};\n"; } } // namespace std::string emitMacroFusion(const NormalizedTargetModel &Model, std::string_view SourceName) { 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_MACRO_FUSION_RULES\n\n"; for (const NormalizedMacroFusionRule &Rule : Model.MacroFusionRules) { emitOpcodes(Output, Rule, "FirstOpcodes", Rule.FirstOpcodes); emitOpcodes(Output, Rule, "SecondOpcodes", Rule.SecondOpcodes); Output << "constexpr std::array " << Rule.Symbol << "OpcodePairs = {{\n"; for (const NormalizedMacroFusionOpcodePair &Pair : Rule.OpcodePairs) { Output << " {Opcode::fromValue(" << Pair.FirstOpcode << "), Opcode::fromValue(" << Pair.SecondOpcode << ")},\n"; } Output << "}};\n"; Output << "constexpr std::array " << Rule.Symbol << "ImmediatePredicates = {{\n"; for (const NormalizedMacroFusionImmediatePredicate &Predicate : Rule.ImmediatePredicates) { Output << " {MacroFusionInstruction::" << instructionSide(Predicate.Instruction) << ", " << Predicate.OperandIndex << ", " << Predicate.Minimum << ", " << Predicate.Maximum << "},\n"; } Output << "}};\n"; Output << "constexpr std::array " << Rule.Symbol << "RegisterInequalities = {{\n"; for (const NormalizedMacroFusionRegisterInequality &Predicate : Rule.RegisterInequalities) { Output << " {MacroFusionInstruction::" << instructionSide(Predicate.Instruction) << ", " << Predicate.LeftOperand << ", " << Predicate.RightOperand << "},\n"; } Output << "}};\n"; Output << "constexpr std::array " << Rule.Symbol << "ImmediateRelations = {{\n"; for (const NormalizedMacroFusionImmediateRelation &Relation : Rule.ImmediateRelations) Output << " {" << Relation.FirstOperand << ", " << Relation.SecondOperand << "},\n"; Output << "}};\n\n"; } Output << "constexpr std::array GeneratedMacroFusionRules = {{\n"; for (const NormalizedMacroFusionRule &Rule : Model.MacroFusionRules) { Output << " {"; appendQuoted(Output, Rule.Symbol); Output << ", "; appendQuoted(Output, Rule.Feature); Output << ", " << Rule.Symbol << "FirstOpcodes, " << Rule.Symbol << "SecondOpcodes, " << Rule.Symbol << "OpcodePairs, " << Rule.Symbol << "ImmediatePredicates, " << Rule.Symbol << "RegisterInequalities, " << Rule.Symbol << "ImmediateRelations, " << Rule.FirstDefinitionOperand << ", " << Rule.SecondUseOperand << ", " << Rule.SecondDefinitionOperand << ", "; if (Rule.CommutableSecondUseOperand) Output << *Rule.CommutableSecondUseOperand; else Output << "MacroFusionRule::NoOperand"; Output << ", " << (Rule.RequireSingleNonDebugUse ? "true" : "false") << ", " << (Rule.RequireSecondDestinationTie ? "true" : "false") << "},\n"; } Output << "}};\n\n"; Output << "[[nodiscard]] constexpr std::span " "generatedMacroFusionRules() noexcept {\n" " return GeneratedMacroFusionRules;\n" "}\n\n"; Output << "#endif // GET_MACRO_FUSION_RULES\n"; return Output.str(); } } // namespace rcc::targetgen