diff options
Diffstat (limited to 'backend/utils/TableGen/MacroFusionEmitter.cpp')
| -rw-r--r-- | backend/utils/TableGen/MacroFusionEmitter.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/backend/utils/TableGen/MacroFusionEmitter.cpp b/backend/utils/TableGen/MacroFusionEmitter.cpp new file mode 100644 index 0000000..2018a43 --- /dev/null +++ b/backend/utils/TableGen/MacroFusionEmitter.cpp @@ -0,0 +1,100 @@ +// 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 +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<std::uint32_t> &Opcodes) { + Output << "constexpr std::array<Opcode, " << Opcodes.size() << "> " << 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<MacroFusionOpcodePair, " << Rule.OpcodePairs.size() << "> " + << 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<MacroFusionImmediatePredicate, " + << Rule.ImmediatePredicates.size() << "> " << 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<MacroFusionRegisterInequality, " + << Rule.RegisterInequalities.size() << "> " << 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<MacroFusionImmediateRelation, " + << Rule.ImmediateRelations.size() << "> " << Rule.Symbol << "ImmediateRelations = {{\n"; + for (const NormalizedMacroFusionImmediateRelation &Relation : Rule.ImmediateRelations) + Output << " {" << Relation.FirstOperand << ", " << Relation.SecondOperand << "},\n"; + Output << "}};\n\n"; + } + + Output << "constexpr std::array<MacroFusionRule, " << Model.MacroFusionRules.size() + << "> 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<const MacroFusionRule> " + "generatedMacroFusionRules() noexcept {\n" + " return GeneratedMacroFusionRules;\n" + "}\n\n"; + Output << "#endif // GET_MACRO_FUSION_RULES\n"; + return Output.str(); +} + +} // namespace rcc::targetgen |
