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 "SubtargetFeatureInfo.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Twine.h"
22 #include <functional>
23 #include <vector>
24 
25 namespace llvm {
26 class CodeGenTarget;
27 
28 namespace gi {
29 class RuleMatcher;
30 class LLTCodeGen;
31 class MatchTable;
32 } // namespace gi
33 
34 /// Abstract base class for TableGen backends that emit a
35 /// `GIMatchTableExecutor`-derived class.
36 class GlobalISelMatchTableExecutorEmitter {
37   /// Emits logic to check features required by \p Rules using the
38 
39   /// SubtargetFeatures map.
40   void emitSubtargetFeatureBitsetImpl(raw_ostream &OS,
41                                       ArrayRef<gi::RuleMatcher> Rules);
42 
43   /// Emits an enum + an array that stores references to
44   /// \p ComplexOperandMatchers.
45   void emitComplexPredicates(raw_ostream &OS,
46                              ArrayRef<Record *> ComplexOperandMatchers);
47 
48   /// Emits an enum + an array that stores references to
49   /// \p CustomOperandRenderers.
50   void emitCustomOperandRenderers(raw_ostream &OS,
51                                   ArrayRef<StringRef> CustomOperandRenderers);
52 
53   /// Emits an enum + an array to reference \p TypeObjects (LLTs) in the match
54   /// table.
55   void emitTypeObjects(raw_ostream &OS, ArrayRef<gi::LLTCodeGen> TypeObjects);
56 
57   /// Emits the getMatchTable function which contains all of the match table's
58   /// opcodes.
59   void emitMatchTable(raw_ostream &OS, const gi::MatchTable &Table);
60 
61   /// Helper function to emit `test` functions for the executor. This emits both
62   /// an enum to reference predicates in the MatchTable, and a function to
63   /// switch over the enum & execute the predicate's C++ code.
64   ///
65   /// \tparam PredicateObject An object representing a predicate to emit.
66   /// \param OS Output stream
67   /// \param TypeIdentifier Identifier used for the type of the predicate,
68   ///        e.g. `MI` for MachineInstrs.
69   /// \param ArgType Full type of the argument, e.g. `const MachineInstr &`
70   /// \param ArgName Name of the argument, e.g. `MI` for MachineInstrs.
71   /// \param AdditionalArgs Optional additional argument declarations.
72   /// \param AdditionalDeclarations Optional declarations to write at the start
73   ///        of the function, before switching over the predicates enum.
74   /// \param Predicates Predicates to emit.
75   /// \param GetPredEnumName Returns an enum name for a given predicate.
76   /// \param GetPredCode Returns the C++ code of a given predicate.
77   /// \param Comment Optional comment for the enum declaration.
78   template <typename PredicateObject>
79   void emitCxxPredicateFns(
80       raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
81       StringRef ArgName, StringRef AdditionalArgs,
82       StringRef AdditionalDeclarations, ArrayRef<PredicateObject> Predicates,
83       std::function<StringRef(PredicateObject)> GetPredEnumName,
84       std::function<StringRef(PredicateObject)> GetPredCode,
85       StringRef Comment) {
86     if (!Comment.empty())
87       OS << "// " << Comment << "\n";
88     if (!Predicates.empty()) {
89       OS << "enum {\n";
90       StringRef EnumeratorSeparator = " = GICXXPred_Invalid + 1,\n";
91       for (const auto &Pred : Predicates) {
92         OS << "  GICXXPred_" << TypeIdentifier << "_Predicate_"
93            << GetPredEnumName(Pred) << EnumeratorSeparator;
94         EnumeratorSeparator = ",\n";
95       }
96       OS << "};\n";
97     }
98 
99     OS << "bool " << getClassName() << "::test" << ArgName << "Predicate_"
100        << TypeIdentifier << "(unsigned PredicateID, " << ArgType << " "
101        << ArgName << AdditionalArgs << ") const {\n"
102        << AdditionalDeclarations;
103     if (!AdditionalDeclarations.empty())
104       OS << "\n";
105     if (!Predicates.empty()) {
106       OS << "  switch (PredicateID) {\n";
107       for (const auto &Pred : Predicates) {
108         const auto Code = GetPredCode(Pred);
109         OS << "  case GICXXPred_" << TypeIdentifier << "_Predicate_"
110            << GetPredEnumName(Pred) << ": {\n"
111            << "    " << Code << "\n";
112         if (!StringRef(Code).ltrim().startswith("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 Comment = "") {
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 Comment = "") {
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 emitTemporariesDecl.
186   virtual void emitAdditionalTemporariesDecl(raw_ostream &OS,
187                                              StringRef Indent) {}
188 
189   /// Emit additional content in emitTemporariesInit.
190   virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {}
191 
192   /// Emit the `testMIPredicate_MI` function.
193   /// Note: `emitMIPredicateFnsImpl` can be used to do most of the work.
194   virtual void emitMIPredicateFns(raw_ostream &OS) = 0;
195 
196   /// Emit the `testImmPredicate_I64` function.
197   /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
198   virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0;
199 
200   /// Emit the `testImmPredicate_APFloat` function.
201   /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
202   virtual void emitAPFloatImmPredicateFns(raw_ostream &OS) = 0;
203 
204   /// Emit the `testImmPredicate_APInt` function.
205   /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
206   virtual void emitAPIntImmPredicateFns(raw_ostream &OS) = 0;
207   virtual void emitTestSimplePredicate(raw_ostream &OS) = 0;
208   virtual void emitRunCustomAction(raw_ostream &OS) = 0;
209 
210   void emitExecutorImpl(raw_ostream &OS, const gi::MatchTable &Table,
211                         ArrayRef<gi::LLTCodeGen> TypeObjects,
212                         ArrayRef<gi::RuleMatcher> Rules,
213                         ArrayRef<Record *> ComplexOperandMatchers,
214                         ArrayRef<StringRef> CustomOperandRenderers,
215                         StringRef IfDefName);
216   void emitPredicateBitset(raw_ostream &OS, StringRef IfDefName);
217   void emitTemporariesDecl(raw_ostream &OS, StringRef IfDefName);
218   void emitTemporariesInit(raw_ostream &OS, unsigned MaxTemporaries,
219                            StringRef IfDefName);
220   void emitPredicatesDecl(raw_ostream &OS, StringRef IfDefName);
221   void emitPredicatesInit(raw_ostream &OS, StringRef IfDefName);
222 
223   // Map of predicates to their subtarget features.
224   SubtargetFeatureInfoMap SubtargetFeatures;
225 };
226 } // namespace llvm
227 
228 #endif
229