251 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// This file contains common code related to emitting11/// GIMatchTableExecutor-derived classes.12///13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_GLOBALISELMATCHTABLEEXECUTOREMITTER_H16#define LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_GLOBALISELMATCHTABLEEXECUTOREMITTER_H17 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 24namespace llvm {25class CodeGenTarget;26 27namespace gi {28class RuleMatcher;29class LLTCodeGen;30class MatchTable;31} // namespace gi32 33/// Abstract base class for TableGen backends that emit a34/// `GIMatchTableExecutor`-derived class.35class GlobalISelMatchTableExecutorEmitter {36 /// Emits logic to check features required by \p Rules using the37 38 /// SubtargetFeatures map.39 void emitSubtargetFeatureBitsetImpl(raw_ostream &OS,40 ArrayRef<gi::RuleMatcher> Rules);41 42 /// Emits an enum + an array that stores references to43 /// \p ComplexOperandMatchers.44 void emitComplexPredicates(raw_ostream &OS,45 ArrayRef<const Record *> ComplexOperandMatchers);46 47 /// Emits an enum + an array that stores references to48 /// \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 match53 /// table.54 void emitTypeObjects(raw_ostream &OS, ArrayRef<gi::LLTCodeGen> TypeObjects);55 56 /// Emits the getMatchTable function which contains all of the match table's57 /// opcodes.58 void emitMatchTable(raw_ostream &OS, const gi::MatchTable &Table);59 60 /// Helper function to emit `test` functions for the executor. This emits both61 /// an enum to reference predicates in the MatchTable, and a function to62 /// 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 stream66 /// \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 start72 /// 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 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 stream129 /// \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 Comment = "") {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 Comment = "") {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 stream173 /// \param TypeIdentifier Identifier used for the type of the predicate174 /// \param ArgType Full type of the argument175 /// \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 Comment = "") {186 return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm", "", "",187 Predicates, GetPredEnumName, GetPredCode,188 Comment);189 }190 191 GlobalISelMatchTableExecutorEmitter() = default;192 193public: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 emitExecutorImpl203 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` function213 /// 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 llvm249 250#endif // LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_GLOBALISELMATCHTABLEEXECUTOREMITTER_H251