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
|