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_COMMON_GLOBALISEL_GLOBALISELMATCHTABLEEXECUTOREMITTER_H |
16 | #define LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_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<const 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 | llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, |
83 | llvm::function_ref<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 | llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, |
139 | llvm::function_ref<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 | /// Emits `testMOPredicate_MO`. |
147 | /// \tparam PredicateObject An object representing a predicate to emit. |
148 | /// \param OS Output stream. |
149 | /// \param AdditionalDecls Additional C++ variable declarations. |
150 | /// \param Predicates Predicates to emit. |
151 | /// \param GetPredEnumName Returns an enum name for a given predicate. |
152 | /// \param GetPredCode Returns the C++ code of a given predicate. |
153 | /// \param Comment Optional comment for the enum declaration. |
154 | template <typename PredicateObject> |
155 | void emitLeafPredicateFnsImpl( |
156 | raw_ostream &OS, StringRef AdditionalDecls, |
157 | ArrayRef<PredicateObject> Predicates, |
158 | llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, |
159 | llvm::function_ref<StringRef(PredicateObject)> GetPredCode, |
160 | StringRef = "" ) { |
161 | return emitCxxPredicateFns( |
162 | OS, "MO" , "const MachineOperand &" , "MO" , ", const MatcherState &State" , |
163 | AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment); |
164 | } |
165 | |
166 | /// Helper function to emit the following executor functions: |
167 | /// * testImmPredicate_I64 (TypeIdentifier=I64) |
168 | /// * testImmPredicate_APInt (TypeIdentifier=APInt) |
169 | /// * testImmPredicate_APFloat (TypeIdentifier=APFloat) |
170 | /// |
171 | /// \tparam PredicateObject An object representing a predicate to emit. |
172 | /// \param OS Output stream |
173 | /// \param TypeIdentifier Identifier used for the type of the predicate |
174 | /// \param ArgType Full type of the argument |
175 | /// \param Predicates Predicates to emit. |
176 | /// \param GetPredEnumName Returns an enum name for a given predicate. |
177 | /// \param GetPredCode Returns the C++ code of a given predicate. |
178 | /// \param Comment Optional comment for the enum declaration. |
179 | template <typename PredicateObject> |
180 | void emitImmPredicateFnsImpl( |
181 | raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType, |
182 | ArrayRef<PredicateObject> Predicates, |
183 | llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName, |
184 | llvm::function_ref<StringRef(PredicateObject)> GetPredCode, |
185 | StringRef = "" ) { |
186 | return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm" , "" , "" , |
187 | Predicates, GetPredEnumName, GetPredCode, |
188 | Comment); |
189 | } |
190 | |
191 | GlobalISelMatchTableExecutorEmitter() = default; |
192 | |
193 | public: |
194 | virtual ~GlobalISelMatchTableExecutorEmitter() = default; |
195 | |
196 | virtual const CodeGenTarget &getTarget() const = 0; |
197 | |
198 | /// \returns the name of the class being emitted including any prefixes, e.g. |
199 | /// `AMDGPUInstructionSelector`. |
200 | virtual StringRef getClassName() const = 0; |
201 | |
202 | /// Emit additional content in emitExecutorImpl |
203 | virtual void emitAdditionalImpl(raw_ostream &OS) {} |
204 | |
205 | /// Emit additional content in emitTemporariesInit. |
206 | virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {} |
207 | |
208 | /// Emit the `testMIPredicate_MI` function. |
209 | /// Note: `emitMIPredicateFnsImpl` can be used to do most of the work. |
210 | virtual void emitMIPredicateFns(raw_ostream &OS) = 0; |
211 | |
212 | /// Emit the `testLeafPredicate` function |
213 | /// Note `emitLeafPredicateFnsImpl` can be used to do most of the work. |
214 | virtual void emitLeafPredicateFns(raw_ostream &OS) = 0; |
215 | |
216 | /// Emit the `testImmPredicate_I64` function. |
217 | /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work. |
218 | virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0; |
219 | |
220 | /// Emit the `testImmPredicate_APFloat` function. |
221 | /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work. |
222 | virtual void emitAPFloatImmPredicateFns(raw_ostream &OS) = 0; |
223 | |
224 | /// Emit the `testImmPredicate_APInt` function. |
225 | /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work. |
226 | virtual void emitAPIntImmPredicateFns(raw_ostream &OS) = 0; |
227 | virtual void emitTestSimplePredicate(raw_ostream &OS) = 0; |
228 | virtual void emitRunCustomAction(raw_ostream &OS) = 0; |
229 | |
230 | void emitExecutorImpl(raw_ostream &OS, const gi::MatchTable &Table, |
231 | ArrayRef<gi::LLTCodeGen> TypeObjects, |
232 | ArrayRef<gi::RuleMatcher> Rules, |
233 | ArrayRef<const Record *> ComplexOperandMatchers, |
234 | ArrayRef<StringRef> CustomOperandRenderers, |
235 | StringRef IfDefName); |
236 | void emitPredicateBitset(raw_ostream &OS, StringRef IfDefName); |
237 | void emitTemporariesDecl(raw_ostream &OS, StringRef IfDefName); |
238 | void emitTemporariesInit(raw_ostream &OS, unsigned MaxTemporaries, |
239 | StringRef IfDefName); |
240 | void emitPredicatesDecl(raw_ostream &OS, StringRef IfDefName); |
241 | void emitPredicatesInit(raw_ostream &OS, StringRef IfDefName); |
242 | |
243 | // Map of predicates to their subtarget features. |
244 | SubtargetFeatureInfoMap SubtargetFeatures; |
245 | |
246 | std::map<std::string, unsigned> HwModes; |
247 | }; |
248 | } // namespace llvm |
249 | |
250 | #endif // LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_GLOBALISELMATCHTABLEEXECUTOREMITTER_H |
251 | |