Files
clang-p2996/mlir/include/mlir/TableGen/Operator.h
Matteo Franciolini cf0e8dca84 Add support for versioning properties in MLIR bytecode
[mlir] Add support for custom readProperties/writeProperties methods.

Currently, operations that opt-in to adopt properties will see auto-generated readProperties/writeProperties methods to emit and parse bytecode. If a dialects opts in to use `usePropertiesForAttributes`, those definitions will be generated for the current definition of the op without the possibility to handle attribute versioning.

The patch adds the capability for an operation to define its own read/write methods for the encoding of properties so that versioned operations can handle upgrading properties encodings.

In addition to this, the patch adds an example showing versioning on NamedProperties through the dialect version API exposed by the reader.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D155340
2023-07-28 19:44:33 -07:00

428 lines
15 KiB
C++

//===- Operator.h - Operator class ------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Operator wrapper to simplify using TableGen Record defining a MLIR Op.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_TABLEGEN_OPERATOR_H_
#define MLIR_TABLEGEN_OPERATOR_H_
#include "mlir/Support/LLVM.h"
#include "mlir/TableGen/Argument.h"
#include "mlir/TableGen/Attribute.h"
#include "mlir/TableGen/Builder.h"
#include "mlir/TableGen/Dialect.h"
#include "mlir/TableGen/Property.h"
#include "mlir/TableGen/Region.h"
#include "mlir/TableGen/Successor.h"
#include "mlir/TableGen/Trait.h"
#include "mlir/TableGen/Type.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SMLoc.h"
namespace llvm {
class DefInit;
class Record;
class StringInit;
} // namespace llvm
namespace mlir {
namespace tblgen {
/// This class represents an inferred result type. The result type can be
/// inferred from an argument or result type. If it is inferred from another
/// result type, that type must be buildable or inferred from yet another type.
class InferredResultType {
public:
InferredResultType(int index, std::string transformer)
: index(index), transformer(std::move(transformer)) {}
/// Returns true if result type is inferred from an argument type.
bool isArg() const { return isArgIndex(index); }
/// Return the mapped argument or result index.
int getIndex() const { return index; }
/// If the type is inferred from a result, return the result index.
int getResultIndex() const { return unmapResultIndex(index); }
// Mapping from result index to combined argument and result index.
// Arguments are indexed to match getArg index, while the result indexes are
// mapped to avoid overlap.
static int mapResultIndex(int i) { return -1 - i; }
static int unmapResultIndex(int i) { return -i - 1; }
static bool isResultIndex(int i) { return i < 0; }
static bool isArgIndex(int i) { return i >= 0; }
StringRef getTransformer() const { return transformer; }
private:
/// The index of the source argument or result.
int index;
/// The transfer to apply to the type to obtain the inferred type.
std::string transformer;
};
/// Wrapper class that contains a MLIR op's information (e.g., operands,
/// attributes) defined in TableGen and provides helper methods for
/// accessing them.
class Operator {
public:
explicit Operator(const llvm::Record &def);
explicit Operator(const llvm::Record *def) : Operator(*def) {}
/// Returns this op's dialect name.
StringRef getDialectName() const;
/// Returns the operation name. The name will follow the "<dialect>.<op-name>"
/// format if its dialect name is not empty.
std::string getOperationName() const;
/// Returns this op's C++ class name.
StringRef getCppClassName() const;
/// Returns this op's C++ class name prefixed with namespaces.
std::string getQualCppClassName() const;
/// Returns this op's C++ namespace.
StringRef getCppNamespace() const;
/// Returns the name of op's adaptor C++ class.
std::string getAdaptorName() const;
/// Returns the name of op's generic adaptor C++ class.
std::string getGenericAdaptorName() const;
/// Check invariants (like no duplicated or conflicted names) and abort the
/// process if any invariant is broken.
void assertInvariants() const;
/// A class used to represent the decorators of an operator variable, i.e.
/// argument or result.
struct VariableDecorator {
public:
explicit VariableDecorator(const llvm::Record *def) : def(def) {}
const llvm::Record &getDef() const { return *def; }
protected:
/// The TableGen definition of this decorator.
const llvm::Record *def;
};
/// A utility iterator over a list of variable decorators.
struct VariableDecoratorIterator
: public llvm::mapped_iterator<llvm::Init *const *,
VariableDecorator (*)(llvm::Init *)> {
/// Initializes the iterator to the specified iterator.
VariableDecoratorIterator(llvm::Init *const *it)
: llvm::mapped_iterator<llvm::Init *const *,
VariableDecorator (*)(llvm::Init *)>(it,
&unwrap) {}
static VariableDecorator unwrap(llvm::Init *init);
};
using var_decorator_iterator = VariableDecoratorIterator;
using var_decorator_range = llvm::iterator_range<VariableDecoratorIterator>;
using value_iterator = NamedTypeConstraint *;
using const_value_iterator = const NamedTypeConstraint *;
using value_range = llvm::iterator_range<value_iterator>;
using const_value_range = llvm::iterator_range<const_value_iterator>;
/// Returns true if this op has variable length operands or results.
bool isVariadic() const;
/// Returns true if default builders should not be generated.
bool skipDefaultBuilders() const;
/// Op result iterators.
const_value_iterator result_begin() const;
const_value_iterator result_end() const;
const_value_range getResults() const;
/// Returns the number of results this op produces.
int getNumResults() const;
/// Returns the op result at the given `index`.
NamedTypeConstraint &getResult(int index) { return results[index]; }
const NamedTypeConstraint &getResult(int index) const {
return results[index];
}
/// Returns the `index`-th result's type constraint.
TypeConstraint getResultTypeConstraint(int index) const;
/// Returns the `index`-th result's name.
StringRef getResultName(int index) const;
/// Returns the `index`-th result's decorators.
var_decorator_range getResultDecorators(int index) const;
/// Returns the number of variable length results in this operation.
unsigned getNumVariableLengthResults() const;
/// Op attribute iterators.
using const_attribute_iterator = const NamedAttribute *;
const_attribute_iterator attribute_begin() const;
const_attribute_iterator attribute_end() const;
llvm::iterator_range<const_attribute_iterator> getAttributes() const;
using attribute_iterator = NamedAttribute *;
attribute_iterator attribute_begin();
attribute_iterator attribute_end();
llvm::iterator_range<attribute_iterator> getAttributes();
int getNumAttributes() const { return attributes.size(); }
int getNumNativeAttributes() const { return numNativeAttributes; }
/// Op attribute accessors.
NamedAttribute &getAttribute(int index) { return attributes[index]; }
const NamedAttribute &getAttribute(int index) const {
return attributes[index];
}
/// Op operand iterators.
const_value_iterator operand_begin() const;
const_value_iterator operand_end() const;
const_value_range getOperands() const;
// Op properties iterators.
using const_property_iterator = const NamedProperty *;
const_property_iterator properties_begin() const {
return properties.begin();
}
const_property_iterator properties_end() const { return properties.end(); }
llvm::iterator_range<const_property_iterator> getProperties() const {
return properties;
}
using property_iterator = NamedProperty *;
property_iterator properties_begin() { return properties.begin(); }
property_iterator properties_end() { return properties.end(); }
llvm::iterator_range<property_iterator> getProperties() { return properties; }
int getNumCoreAttributes() const { return properties.size(); }
// Op properties accessors.
NamedProperty &getProperty(int index) { return properties[index]; }
const NamedProperty &getProperty(int index) const {
return properties[index];
}
int getNumOperands() const { return operands.size(); }
NamedTypeConstraint &getOperand(int index) { return operands[index]; }
const NamedTypeConstraint &getOperand(int index) const {
return operands[index];
}
/// Returns the number of variadic operands in this operation.
unsigned getNumVariableLengthOperands() const;
/// Returns the total number of arguments.
int getNumArgs() const { return arguments.size(); }
/// Returns true of the operation has a single variadic arg.
bool hasSingleVariadicArg() const;
/// Returns true if the operation has a single variadic result.
bool hasSingleVariadicResult() const {
return getNumResults() == 1 && getResult(0).isVariadic();
}
/// Returns true of the operation has no variadic regions.
bool hasNoVariadicRegions() const { return getNumVariadicRegions() == 0; }
using arg_iterator = const Argument *;
using arg_range = llvm::iterator_range<arg_iterator>;
/// Op argument (attribute or operand) iterators.
arg_iterator arg_begin() const;
arg_iterator arg_end() const;
arg_range getArgs() const;
/// Op argument (attribute or operand) accessors.
Argument getArg(int index) const;
StringRef getArgName(int index) const;
var_decorator_range getArgDecorators(int index) const;
/// Returns the trait wrapper for the given MLIR C++ `trait`.
const Trait *getTrait(llvm::StringRef trait) const;
/// Regions.
using const_region_iterator = const NamedRegion *;
const_region_iterator region_begin() const;
const_region_iterator region_end() const;
llvm::iterator_range<const_region_iterator> getRegions() const;
/// Returns the number of regions.
unsigned getNumRegions() const;
/// Returns the `index`-th region.
const NamedRegion &getRegion(unsigned index) const;
/// Returns the number of variadic regions in this operation.
unsigned getNumVariadicRegions() const;
/// Successors.
using const_successor_iterator = const NamedSuccessor *;
const_successor_iterator successor_begin() const;
const_successor_iterator successor_end() const;
llvm::iterator_range<const_successor_iterator> getSuccessors() const;
/// Returns the number of successors.
unsigned getNumSuccessors() const;
/// Returns the `index`-th successor.
const NamedSuccessor &getSuccessor(unsigned index) const;
/// Returns the number of variadic successors in this operation.
unsigned getNumVariadicSuccessors() const;
/// Trait.
using const_trait_iterator = const Trait *;
const_trait_iterator trait_begin() const;
const_trait_iterator trait_end() const;
llvm::iterator_range<const_trait_iterator> getTraits() const;
ArrayRef<SMLoc> getLoc() const;
/// Query functions for the documentation of the operator.
bool hasDescription() const;
StringRef getDescription() const;
bool hasSummary() const;
StringRef getSummary() const;
/// Query functions for the assembly format of the operator.
bool hasAssemblyFormat() const;
StringRef getAssemblyFormat() const;
/// Returns this op's extra class declaration code.
StringRef getExtraClassDeclaration() const;
/// Returns this op's extra class definition code.
StringRef getExtraClassDefinition() const;
/// Returns the Tablegen definition this operator was constructed from.
/// TODO: do not expose the TableGen record, this is a temporary solution to
/// OpEmitter requiring a Record because Operator does not provide enough
/// methods.
const llvm::Record &getDef() const;
/// Returns the dialect of the op.
const Dialect &getDialect() const { return dialect; }
/// Prints the contents in this operator to the given `os`. This is used for
/// debugging purposes.
void print(llvm::raw_ostream &os) const;
/// Return whether all the result types are known.
bool allResultTypesKnown() const { return allResultsHaveKnownTypes; };
/// Return all arguments or type constraints with same type as result[index].
/// Requires: all result types are known.
const InferredResultType &getInferredResultType(int index) const;
/// Pair consisting kind of argument and index into operands or attributes.
struct OperandOrAttribute {
enum class Kind { Operand, Attribute };
OperandOrAttribute(Kind kind, int index) {
packed = (index << 1) | (kind == Kind::Attribute);
}
int operandOrAttributeIndex() const { return (packed >> 1); }
Kind kind() { return (packed & 0x1) ? Kind::Attribute : Kind::Operand; }
private:
int packed;
};
/// Returns the OperandOrAttribute corresponding to the index.
OperandOrAttribute getArgToOperandOrAttribute(int index) const;
/// Returns the builders of this operation.
ArrayRef<Builder> getBuilders() const { return builders; }
/// Returns the getter name for the accessor of `name`.
std::string getGetterName(StringRef name) const;
/// Returns the setter name for the accessor of `name`.
std::string getSetterName(StringRef name) const;
/// Returns the remove name for the accessor of `name`.
std::string getRemoverName(StringRef name) const;
bool hasFolder() const;
/// Whether to generate the `readProperty`/`writeProperty` methods for
/// bytecode emission.
bool useCustomPropertiesEncoding() const;
private:
/// Populates the vectors containing operands, attributes, results and traits.
void populateOpStructure();
/// Populates type inference info (mostly equality) with input a mapping from
/// names to indices for arguments and results.
void populateTypeInferenceInfo(
const llvm::StringMap<int> &argumentsAndResultsIndex);
/// The dialect of this op.
Dialect dialect;
/// The unqualified C++ class name of the op.
StringRef cppClassName;
/// The C++ namespace for this op.
StringRef cppNamespace;
/// The operands of the op.
SmallVector<NamedTypeConstraint, 4> operands;
/// The attributes of the op. Contains native attributes (corresponding to
/// the actual stored attributed of the operation) followed by derived
/// attributes (corresponding to dynamic properties of the operation that are
/// computed upon request).
SmallVector<NamedAttribute, 4> attributes;
/// The properties of the op.
SmallVector<NamedProperty> properties;
/// The arguments of the op (operands and native attributes).
SmallVector<Argument, 4> arguments;
/// The results of the op.
SmallVector<NamedTypeConstraint, 4> results;
/// The successors of this op.
SmallVector<NamedSuccessor, 0> successors;
/// The traits of the op.
SmallVector<Trait, 4> traits;
/// The regions of this op.
SmallVector<NamedRegion, 1> regions;
/// The argument with the same type as the result.
SmallVector<InferredResultType> resultTypeMapping;
/// Map from argument to attribute or operand number.
SmallVector<OperandOrAttribute, 4> attrOrOperandMapping;
/// The builders of this operator.
SmallVector<Builder> builders;
/// The number of native attributes stored in the leading positions of
/// `attributes`.
int numNativeAttributes;
/// The TableGen definition of this op.
const llvm::Record &def;
/// Whether the type of all results are known.
bool allResultsHaveKnownTypes;
};
} // namespace tblgen
} // namespace mlir
#endif // MLIR_TABLEGEN_OPERATOR_H_