MLIR  21.0.0git
IRDLOps.cpp
Go to the documentation of this file.
1 //===- IRDLOps.cpp - IRDL dialect -------------------------------*- C++ -*-===//
2 //
3 // This file is licensed 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 
11 #include "mlir/IR/ValueRange.h"
12 #include <optional>
13 
14 using namespace mlir;
15 using namespace mlir::irdl;
16 
17 /// Maps given `args` to the index in the `valueToConstr`
20  ArrayRef<Value> valueToConstr) {
21  SmallVector<unsigned> constraints;
22  for (Value arg : args) {
23  for (auto [i, value] : enumerate(valueToConstr)) {
24  if (value == arg) {
25  constraints.push_back(i);
26  break;
27  }
28  }
29  }
30  return constraints;
31 }
32 
33 std::unique_ptr<Constraint> IsOp::getVerifier(
34  ArrayRef<Value> valueToConstr,
35  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
36  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
37  &attrs) {
38  return std::make_unique<IsConstraint>(getExpectedAttr());
39 }
40 
41 std::unique_ptr<Constraint> BaseOp::getVerifier(
42  ArrayRef<Value> valueToConstr,
43  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
44  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
45  &attrs) {
46  MLIRContext *ctx = getContext();
47 
48  // Case where the input is a symbol reference.
49  // This corresponds to the case where the base is an IRDL type or attribute.
50  if (auto baseRef = getBaseRef()) {
51  // The verifier for BaseOp guarantees it is within a dialect.
52  Operation *defOp =
53  irdl::lookupSymbolNearDialect(getOperation(), baseRef.value());
54 
55  // Type case.
56  if (auto typeOp = dyn_cast<TypeOp>(defOp)) {
57  DynamicTypeDefinition *typeDef = types.at(typeOp).get();
58  auto name = StringAttr::get(ctx, typeDef->getDialect()->getNamespace() +
59  "." + typeDef->getName().str());
60  return std::make_unique<BaseTypeConstraint>(typeDef->getTypeID(), name);
61  }
62 
63  // Attribute case.
64  auto attrOp = cast<AttributeOp>(defOp);
65  DynamicAttrDefinition *attrDef = attrs.at(attrOp).get();
66  auto name = StringAttr::get(ctx, attrDef->getDialect()->getNamespace() +
67  "." + attrDef->getName().str());
68  return std::make_unique<BaseAttrConstraint>(attrDef->getTypeID(), name);
69  }
70 
71  // Case where the input is string literal.
72  // This corresponds to the case where the base is a registered type or
73  // attribute.
74  StringRef baseName = getBaseName().value();
75 
76  // Type case.
77  if (baseName[0] == '!') {
78  auto abstractType = AbstractType::lookup(baseName.drop_front(1), ctx);
79  if (!abstractType) {
80  emitError() << "no registered type with name " << baseName;
81  return nullptr;
82  }
83  return std::make_unique<BaseTypeConstraint>(abstractType->get().getTypeID(),
84  abstractType->get().getName());
85  }
86 
87  auto abstractAttr = AbstractAttribute::lookup(baseName.drop_front(1), ctx);
88  if (!abstractAttr) {
89  emitError() << "no registered attribute with name " << baseName;
90  return nullptr;
91  }
92  return std::make_unique<BaseAttrConstraint>(abstractAttr->get().getTypeID(),
93  abstractAttr->get().getName());
94 }
95 
96 std::unique_ptr<Constraint> ParametricOp::getVerifier(
97  ArrayRef<Value> valueToConstr,
98  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
99  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
100  &attrs) {
101  SmallVector<unsigned> constraints =
102  getConstraintIndicesForArgs(getArgs(), valueToConstr);
103 
104  // Symbol reference case for the base.
105  // The verifier for ParametricOp guarantees it is within a dialect.
106  SymbolRefAttr symRef = getBaseType();
107  Operation *defOp = irdl::lookupSymbolNearDialect(getOperation(), symRef);
108  if (!defOp) {
109  emitError() << symRef << " does not refer to any existing symbol";
110  return nullptr;
111  }
112 
113  if (auto typeOp = dyn_cast<TypeOp>(defOp))
114  return std::make_unique<DynParametricTypeConstraint>(types.at(typeOp).get(),
115  constraints);
116 
117  if (auto attrOp = dyn_cast<AttributeOp>(defOp))
118  return std::make_unique<DynParametricAttrConstraint>(attrs.at(attrOp).get(),
119  constraints);
120 
121  llvm_unreachable("verifier should ensure that the referenced operation is "
122  "either a type or an attribute definition");
123 }
124 
125 std::unique_ptr<Constraint> AnyOfOp::getVerifier(
126  ArrayRef<Value> valueToConstr,
127  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
128  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
129  &attrs) {
130  return std::make_unique<AnyOfConstraint>(
131  getConstraintIndicesForArgs(getArgs(), valueToConstr));
132 }
133 
134 std::unique_ptr<Constraint> AllOfOp::getVerifier(
135  ArrayRef<Value> valueToConstr,
136  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
137  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
138  &attrs) {
139  return std::make_unique<AllOfConstraint>(
140  getConstraintIndicesForArgs(getArgs(), valueToConstr));
141 }
142 
143 std::unique_ptr<Constraint> AnyOp::getVerifier(
144  ArrayRef<Value> valueToConstr,
145  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
146  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
147  &attrs) {
148  return std::make_unique<AnyAttributeConstraint>();
149 }
150 
151 std::unique_ptr<RegionConstraint> RegionOp::getVerifier(
152  ArrayRef<Value> valueToConstr,
153  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
154  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
155  &attrs) {
156  return std::make_unique<RegionConstraint>(
157  getConstrainedArguments() ? std::optional{getConstraintIndicesForArgs(
158  getEntryBlockArgs(), valueToConstr)}
159  : std::nullopt,
160  getNumberOfBlocks());
161 }
static SmallVector< unsigned > getConstraintIndicesForArgs(mlir::OperandRange args, ArrayRef< Value > valueToConstr)
Maps given args to the index in the valueToConstr
Definition: IRDLOps.cpp:19
static MLIRContext * getContext(OpFoldResult val)
static const AbstractAttribute & lookup(TypeID typeID, MLIRContext *context)
Look up the specified abstract attribute in the MLIRContext and return a reference to it.
static const AbstractType & lookup(TypeID typeID, MLIRContext *context)
Look up the specified abstract type in the MLIRContext and return a reference to it.
StringRef getNamespace() const
Definition: Dialect.h:54
The definition of a dynamic attribute.
ExtensibleDialect * getDialect() const
Return the dialect defining the attribute.
static std::unique_ptr< DynamicAttrDefinition > get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier)
Create a new attribute definition at runtime.
StringRef getName() const
Return the name of the attribute, in the format 'attrname' and not 'dialectname.attrname'.
The definition of a dynamic type.
StringRef getName() const
Return the name of the type, in the format 'typename' and not 'dialectname.typename'.
ExtensibleDialect * getDialect() const
Return the dialect defining the type.
static std::unique_ptr< DynamicTypeDefinition > get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier)
Create a new dynamic type definition.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:42
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
TypeID getTypeID() const
Return the TypeID owned by this object.
Definition: TypeID.h:381
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:344
Operation * lookupSymbolNearDialect(SymbolTableCollection &symbolTable, Operation *source, SymbolRefAttr symbol)
Looks up a symbol from the symbol table containing the source operation's dialect definition operatio...
Definition: IRDLSymbols.cpp:28
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...