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
24namespace llvm {
25class CodeGenTarget;
26
27namespace gi {
28class RuleMatcher;
29class LLTCodeGen;
30class MatchTable;
31} // namespace gi
32
33/// Abstract base class for TableGen backends that emit a
34/// `GIMatchTableExecutor`-derived class.
35class 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 Comment) {
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("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
125protected:
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
173public:
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  std::map<std::string, unsigned> HwModes;
227};
228} // namespace llvm
229
230#endif
231