aboutsummaryrefslogtreecommitdiff
path: root/backend/utils/TableGen/MacroFusionEmitter.cpp
blob: 2018a436933ff966d5c7b95f4a25e8b67d345fa6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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