1 | //===- GlobalISelMatchTableExecutorEmitter.h ------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | /// \file |
10 | /// This file contains common code related to emitting |
11 | /// GIMatchTableExecutor-derived classes. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H |
16 | #define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H |
17 | |
18 | #include "Common/SubtargetFeatureInfo.h" |
19 | #include "llvm/ADT/ArrayRef.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include "llvm/ADT/Twine.h" |
22 | #include <functional> |
23 | |
24 | namespace llvm { |
25 | class CodeGenTarget; |
26 | |
27 | namespace gi { |
28 | class RuleMatcher; |
29 | class LLTCodeGen; |
30 | class MatchTable; |
31 | } // namespace gi |
32 | |
33 | /// Abstract base class for TableGen backends that emit a |
34 | /// `GIMatchTableExecutor`-derived class. |
35 | class GlobalISelMatchTableExecutorEmitter { |
36 | /// Emits logic to check features required by \p Rules using the |
37 | |
38 | /// SubtargetFeatures map. |
39 | void emitSubtargetFeatureBitsetImpl(raw_ostream &OS, |
40 | ArrayRef<gi::RuleMatcher> Rules); |
41 | |
42 | /// Emits an enum + an array that stores references to |
43 | /// \p ComplexOperandMatchers. |
44 | void emitComplexPredicates(raw_ostream &OS, |
45 | ArrayRef<Record *> ComplexOperandMatchers); |
46 | |
47 | /// Emits an enum + an array that stores references to |
48 | /// \p CustomOperandRenderers. |
49 | void emitCustomOperandRenderers(raw_ostream &OS, |
50 | ArrayRef<StringRef> CustomOperandRenderers); |
51 | |
52 | /// Emits an enum + an array to reference \p TypeObjects (LLTs) in the match |
53 | /// table. |
54 | void emitTypeObjects(raw_ostream &OS, ArrayRef<gi::LLTCodeGen> TypeObjects); |
55 | |
56 | /// Emits the getMatchTable function which contains all of the match table's |
57 | /// opcodes. |
58 | void emitMatchTable(raw_ostream &OS, const gi::MatchTable &Table); |
59 | |
60 | /// Helper function to emit `test` functions for the executor. This emits both |
61 | /// an enum to reference predicates in the MatchTable, and a function to |
62 | /// switch over the enum & execute the predicate's C++ code. |
63 | /// |
64 | /// \tparam PredicateObject An object representing a predicate to emit. |
65 | /// \param OS Output stream |
66 | /// \param TypeIdentifier Identifier used for the type of the predicate, |
67 | /// e.g. `MI` for MachineInstrs. |
68 | /// \param ArgType Full type of the argument, e.g. `const MachineInstr &` |
69 | /// \param ArgName Name of the argument, e.g. `MI` for MachineInstrs. |
70 | /// \param AdditionalArgs Optional additional argument declarations. |
71 | /// \param AdditionalDeclarations Optional declarations to write at the start |
72 | /// of the function, before switching over the predicates enum. |
73 | /// \param Predicates Predicates to emit. |
74 | /// \param GetPredEnumName Returns an enum name for a given predicate. |
75 | /// \param GetPredCode Returns the C++ code of a given predicate. |
76 | /// \param Comment Optional comment for the enum declaration. |
77 | template <typename PredicateObject> |
78 | void emitCxxPredicateFns( |
79 | raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType, |
80 | StringRef ArgName, StringRef AdditionalArgs, |
81 | StringRef AdditionalDeclarations, ArrayRef<PredicateObject> Predicates, |
82 | std::function<StringRef(PredicateObject)> GetPredEnumName, |
83 | std::function<StringRef(PredicateObject)> GetPredCode, |
84 | StringRef ) { |
85 | if (!Comment.empty()) |
86 | OS << "// " << Comment << "\n" ; |
87 | if (!Predicates.empty()) { |
88 | OS << "enum {\n" ; |
89 | StringRef EnumeratorSeparator = " = GICXXPred_Invalid + 1,\n" ; |
90 | for (const auto &Pred : Predicates) { |
91 | OS << " GICXXPred_" << TypeIdentifier << "_Predicate_" |
92 | << GetPredEnumName(Pred) << EnumeratorSeparator; |
93 | EnumeratorSeparator = ",\n" ; |
94 | } |
95 | OS << "};\n" ; |
96 | } |
97 | |
98 | OS << "bool " << getClassName() << "::test" << ArgName << "Predicate_" |
99 | << TypeIdentifier << "(unsigned PredicateID, " << ArgType << " " |
100 | << ArgName << AdditionalArgs << ") const {\n" |
101 | << AdditionalDeclarations; |
102 | if (!AdditionalDeclarations.empty()) |
103 | OS << "\n" ; |
104 | if (!Predicates.empty()) { |
105 | OS << " switch (PredicateID) {\n" ; |
106 | for (const auto &Pred : Predicates) { |
107 | // Ensure all code is indented. |
108 | const auto Code = join(split(GetPredCode(Pred).str(), "\n" ), "\n " ); |
109 | OS << " case GICXXPred_" << TypeIdentifier << "_Predicate_" |
110 | << GetPredEnumName(Pred) << ": {\n" |
111 | << " " << Code << "\n" ; |
112 | if (!StringRef(Code).ltrim().starts_with(Prefix: "return" )) { |
113 | OS << " llvm_unreachable(\"" << GetPredEnumName(Pred) |
114 | << " should have returned\");\n" ; |
115 | } |
116 | OS << " }\n" ; |
117 | } |
118 | OS << " }\n" ; |
119 | } |
120 | OS << " llvm_unreachable(\"Unknown predicate\");\n" |
121 | << " return false;\n" |
122 | << "}\n" ; |
123 | } |
124 | |
125 | protected: |
126 | /// Emits `testMIPredicate_MI`. |
127 | /// \tparam PredicateObject An object representing a predicate to emit. |
128 | /// \param OS Output stream |
129 | /// \param AdditionalDecls Additional C++ variable declarations. |
130 | /// \param Predicates Predicates to emit. |
131 | /// \param GetPredEnumName Returns an enum name for a given predicate. |
132 | /// \param GetPredCode Returns the C++ code of a given predicate. |
133 | /// \param Comment Optional comment for the enum declaration. |
134 | template <typename PredicateObject> |
135 | void emitMIPredicateFnsImpl( |
136 | raw_ostream &OS, StringRef AdditionalDecls, |
137 | ArrayRef<PredicateObject> Predicates, |
138 | std::function<StringRef(PredicateObject)> GetPredEnumName, |
139 | std::function<StringRef(PredicateObject)> GetPredCode, |
140 | StringRef = "" ) { |
141 | return emitCxxPredicateFns( |
142 | OS, "MI" , "const MachineInstr &" , "MI" , ", const MatcherState &State" , |
143 | AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment); |
144 | } |
145 | |
146 | /// Helper function to emit the following executor functions: |
147 | /// * testImmPredicate_I64 (TypeIdentifier=I64) |
148 | /// * testImmPredicate_APInt (TypeIdentifier=APInt) |
149 | /// * testImmPredicate_APFloat (TypeIdentifier=APFloat) |
150 | /// |
151 | /// \tparam PredicateObject An object representing a predicate to emit. |
152 | /// \param OS Output stream |
153 | /// \param TypeIdentifier Identifier used for the type of the predicate |
154 | /// \param ArgType Full type of the argument |
155 | /// \param Predicates Predicates to emit. |
156 | /// \param GetPredEnumName Returns an enum name for a given predicate. |
157 | /// \param GetPredCode Returns the C++ code of a given predicate. |
158 | /// \param Comment Optional comment for the enum declaration. |
159 | template <typename PredicateObject> |
160 | void emitImmPredicateFnsImpl( |
161 | raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType, |
162 | ArrayRef<PredicateObject> Predicates, |
163 | std::function<StringRef(PredicateObject)> GetPredEnumName, |
164 | std::function<StringRef(PredicateObject)> GetPredCode, |
165 | StringRef = "" ) { |
166 | return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm" , "" , "" , |
167 | Predicates, GetPredEnumName, GetPredCode, |
168 | Comment); |
169 | } |
170 | |
171 | GlobalISelMatchTableExecutorEmitter() = default; |
172 | |
173 | public: |
174 | virtual ~GlobalISelMatchTableExecutorEmitter() = default; |
175 | |
176 | virtual const CodeGenTarget &getTarget() const = 0; |
177 | |
178 | /// \returns the name of the class being emitted including any prefixes, e.g. |
179 | /// `AMDGPUInstructionSelector`. |
180 | virtual StringRef getClassName() const = 0; |
181 | |
182 | /// Emit additional content in emitExecutorImpl |
183 | virtual void emitAdditionalImpl(raw_ostream &OS) {} |
184 | |
185 | /// Emit additional content in emitTemporariesInit. |
186 | virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {} |
187 | |
188 | /// Emit the `testMIPredicate_MI` function. |
189 | /// Note: `emitMIPredicateFnsImpl` can be used to do most of the work. |
190 | virtual void emitMIPredicateFns(raw_ostream &OS) = 0; |
191 | |
192 | /// Emit the `testImmPredicate_I64` function. |
193 | /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work. |
194 | virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0; |
195 | |
196 | /// Emit the `testImmPredicate_APFloat` function. |
197 | /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work. |
198 | virtual void emitAPFloatImmPredicateFns(raw_ostream &OS) = 0; |
199 | |
200 | /// Emit the `testImmPredicate_APInt` function. |
201 | /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work. |
202 | virtual void emitAPIntImmPredicateFns(raw_ostream &OS) = 0; |
203 | virtual void emitTestSimplePredicate(raw_ostream &OS) = 0; |
204 | virtual void emitRunCustomAction(raw_ostream &OS) = 0; |
205 | |
206 | void emitExecutorImpl(raw_ostream &OS, const gi::MatchTable &Table, |
207 | ArrayRef<gi::LLTCodeGen> TypeObjects, |
208 | ArrayRef<gi::RuleMatcher> Rules, |
209 | ArrayRef<Record *> ComplexOperandMatchers, |
210 | ArrayRef<StringRef> CustomOperandRenderers, |
211 | StringRef IfDefName); |
212 | void emitPredicateBitset(raw_ostream &OS, StringRef IfDefName); |
213 | void emitTemporariesDecl(raw_ostream &OS, StringRef IfDefName); |
214 | void emitTemporariesInit(raw_ostream &OS, unsigned MaxTemporaries, |
215 | StringRef IfDefName); |
216 | void emitPredicatesDecl(raw_ostream &OS, StringRef IfDefName); |
217 | void emitPredicatesInit(raw_ostream &OS, StringRef IfDefName); |
218 | |
219 | // Map of predicates to their subtarget features. |
220 | SubtargetFeatureInfoMap SubtargetFeatures; |
221 | |
222 | std::map<std::string, unsigned> HwModes; |
223 | }; |
224 | } // namespace llvm |
225 | |
226 | #endif |
227 | |