blob: d526e08a96e3105410da5d6ba10284ceac8f73c5 [file] [log] [blame]
//===- GlobalISelMatchTableExecutorEmitter.h ------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This file contains common code related to emitting
/// GIMatchTableExecutor-derived classes.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H
#define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H
#include "SubtargetFeatureInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include <functional>
#include <vector>
namespace llvm {
class CodeGenTarget;
namespace gi {
class RuleMatcher;
class LLTCodeGen;
class MatchTable;
} // namespace gi
/// Abstract base class for TableGen backends that emit a
/// `GIMatchTableExecutor`-derived class.
class GlobalISelMatchTableExecutorEmitter {
/// Emits logic to check features required by \p Rules using the
/// SubtargetFeatures map.
void emitSubtargetFeatureBitsetImpl(raw_ostream &OS,
ArrayRef<gi::RuleMatcher> Rules);
/// Emits an enum + an array that stores references to
/// \p ComplexOperandMatchers.
void emitComplexPredicates(raw_ostream &OS,
ArrayRef<Record *> ComplexOperandMatchers);
/// Emits an enum + an array that stores references to
/// \p CustomOperandRenderers.
void emitCustomOperandRenderers(raw_ostream &OS,
ArrayRef<StringRef> CustomOperandRenderers);
/// Emits an enum + an array to reference \p TypeObjects (LLTs) in the match
/// table.
void emitTypeObjects(raw_ostream &OS, ArrayRef<gi::LLTCodeGen> TypeObjects);
/// Emits the getMatchTable function which contains all of the match table's
/// opcodes.
void emitMatchTable(raw_ostream &OS, const gi::MatchTable &Table);
/// Helper function to emit `test` functions for the executor. This emits both
/// an enum to reference predicates in the MatchTable, and a function to
/// switch over the enum & execute the predicate's C++ code.
///
/// \tparam PredicateObject An object representing a predicate to emit.
/// \param OS Output stream
/// \param TypeIdentifier Identifier used for the type of the predicate,
/// e.g. `MI` for MachineInstrs.
/// \param ArgType Full type of the argument, e.g. `const MachineInstr &`
/// \param ArgName Name of the argument, e.g. `MI` for MachineInstrs.
/// \param AdditionalArgs Optional additional argument declarations.
/// \param AdditionalDeclarations Optional declarations to write at the start
/// of the function, before switching over the predicates enum.
/// \param Predicates Predicates to emit.
/// \param GetPredEnumName Returns an enum name for a given predicate.
/// \param GetPredCode Returns the C++ code of a given predicate.
/// \param Comment Optional comment for the enum declaration.
template <typename PredicateObject>
void emitCxxPredicateFns(
raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
StringRef ArgName, StringRef AdditionalArgs,
StringRef AdditionalDeclarations, ArrayRef<PredicateObject> Predicates,
std::function<StringRef(PredicateObject)> GetPredEnumName,
std::function<StringRef(PredicateObject)> GetPredCode,
StringRef Comment) {
if (!Comment.empty())
OS << "// " << Comment << "\n";
if (!Predicates.empty()) {
OS << "enum {\n";
StringRef EnumeratorSeparator = " = GICXXPred_Invalid + 1,\n";
for (const auto &Pred : Predicates) {
OS << " GICXXPred_" << TypeIdentifier << "_Predicate_"
<< GetPredEnumName(Pred) << EnumeratorSeparator;
EnumeratorSeparator = ",\n";
}
OS << "};\n";
}
OS << "bool " << getClassName() << "::test" << ArgName << "Predicate_"
<< TypeIdentifier << "(unsigned PredicateID, " << ArgType << " "
<< ArgName << AdditionalArgs << ") const {\n"
<< AdditionalDeclarations;
if (!AdditionalDeclarations.empty())
OS << "\n";
if (!Predicates.empty()) {
OS << " switch (PredicateID) {\n";
for (const auto &Pred : Predicates) {
const auto Code = GetPredCode(Pred);
OS << " case GICXXPred_" << TypeIdentifier << "_Predicate_"
<< GetPredEnumName(Pred) << ": {\n"
<< " " << Code << "\n";
if (!StringRef(Code).ltrim().startswith("return")) {
OS << " llvm_unreachable(\"" << GetPredEnumName(Pred)
<< " should have returned\");\n";
}
OS << " }\n";
}
OS << " }\n";
}
OS << " llvm_unreachable(\"Unknown predicate\");\n"
<< " return false;\n"
<< "}\n";
}
protected:
/// Emits `testMIPredicate_MI`.
/// \tparam PredicateObject An object representing a predicate to emit.
/// \param OS Output stream
/// \param AdditionalDecls Additional C++ variable declarations.
/// \param Predicates Predicates to emit.
/// \param GetPredEnumName Returns an enum name for a given predicate.
/// \param GetPredCode Returns the C++ code of a given predicate.
/// \param Comment Optional comment for the enum declaration.
template <typename PredicateObject>
void emitMIPredicateFnsImpl(
raw_ostream &OS, StringRef AdditionalDecls,
ArrayRef<PredicateObject> Predicates,
std::function<StringRef(PredicateObject)> GetPredEnumName,
std::function<StringRef(PredicateObject)> GetPredCode,
StringRef Comment = "") {
return emitCxxPredicateFns(
OS, "MI", "const MachineInstr &", "MI", ", const MatcherState &State",
AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment);
}
/// Helper function to emit the following executor functions:
/// * testImmPredicate_I64 (TypeIdentifier=I64)
/// * testImmPredicate_APInt (TypeIdentifier=APInt)
/// * testImmPredicate_APFloat (TypeIdentifier=APFloat)
///
/// \tparam PredicateObject An object representing a predicate to emit.
/// \param OS Output stream
/// \param TypeIdentifier Identifier used for the type of the predicate
/// \param ArgType Full type of the argument
/// \param Predicates Predicates to emit.
/// \param GetPredEnumName Returns an enum name for a given predicate.
/// \param GetPredCode Returns the C++ code of a given predicate.
/// \param Comment Optional comment for the enum declaration.
template <typename PredicateObject>
void emitImmPredicateFnsImpl(
raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
ArrayRef<PredicateObject> Predicates,
std::function<StringRef(PredicateObject)> GetPredEnumName,
std::function<StringRef(PredicateObject)> GetPredCode,
StringRef Comment = "") {
return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm", "", "",
Predicates, GetPredEnumName, GetPredCode,
Comment);
}
GlobalISelMatchTableExecutorEmitter() = default;
public:
virtual ~GlobalISelMatchTableExecutorEmitter() = default;
virtual const CodeGenTarget &getTarget() const = 0;
/// \returns the name of the class being emitted including any prefixes, e.g.
/// `AMDGPUInstructionSelector`.
virtual StringRef getClassName() const = 0;
/// Emit additional content in emitExecutorImpl
virtual void emitAdditionalImpl(raw_ostream &OS) {}
/// Emit additional content in emitTemporariesDecl.
virtual void emitAdditionalTemporariesDecl(raw_ostream &OS,
StringRef Indent) {}
/// Emit additional content in emitTemporariesInit.
virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {}
/// Emit the `testMIPredicate_MI` function.
/// Note: `emitMIPredicateFnsImpl` can be used to do most of the work.
virtual void emitMIPredicateFns(raw_ostream &OS) = 0;
/// Emit the `testImmPredicate_I64` function.
/// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0;
/// Emit the `testImmPredicate_APFloat` function.
/// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
virtual void emitAPFloatImmPredicateFns(raw_ostream &OS) = 0;
/// Emit the `testImmPredicate_APInt` function.
/// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
virtual void emitAPIntImmPredicateFns(raw_ostream &OS) = 0;
virtual void emitTestSimplePredicate(raw_ostream &OS) = 0;
virtual void emitRunCustomAction(raw_ostream &OS) = 0;
void emitExecutorImpl(raw_ostream &OS, const gi::MatchTable &Table,
ArrayRef<gi::LLTCodeGen> TypeObjects,
ArrayRef<gi::RuleMatcher> Rules,
ArrayRef<Record *> ComplexOperandMatchers,
ArrayRef<StringRef> CustomOperandRenderers,
StringRef IfDefName);
void emitPredicateBitset(raw_ostream &OS, StringRef IfDefName);
void emitTemporariesDecl(raw_ostream &OS, StringRef IfDefName);
void emitTemporariesInit(raw_ostream &OS, unsigned MaxTemporaries,
StringRef IfDefName);
void emitPredicatesDecl(raw_ostream &OS, StringRef IfDefName);
void emitPredicatesInit(raw_ostream &OS, StringRef IfDefName);
// Map of predicates to their subtarget features.
SubtargetFeatureInfoMap SubtargetFeatures;
};
} // namespace llvm
#endif