MLIR  19.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 
10 #include "mlir/IR/ValueRange.h"
11 #include <optional>
12 
13 using namespace mlir;
14 using namespace mlir::irdl;
15 
16 /// Maps given `args` to the index in the `valueToConstr`
19  ArrayRef<Value> valueToConstr) {
20  SmallVector<unsigned> constraints;
21  for (Value arg : args) {
22  for (auto [i, value] : enumerate(valueToConstr)) {
23  if (value == arg) {
24  constraints.push_back(i);
25  break;
26  }
27  }
28  }
29  return constraints;
30 }
31 
32 std::unique_ptr<Constraint> IsOp::getVerifier(
33  ArrayRef<Value> valueToConstr,
34  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
35  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
36  &attrs) {
37  return std::make_unique<IsConstraint>(getExpectedAttr());
38 }
39 
40 std::unique_ptr<Constraint> BaseOp::getVerifier(
41  ArrayRef<Value> valueToConstr,
42  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
43  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
44  &attrs) {
45  MLIRContext *ctx = getContext();
46 
47  // Case where the input is a symbol reference.
48  // This corresponds to the case where the base is an IRDL type or attribute.
49  if (auto baseRef = getBaseRef()) {
50  Operation *defOp =
51  SymbolTable::lookupNearestSymbolFrom(getOperation(), baseRef.value());
52 
53  // Type case.
54  if (auto typeOp = dyn_cast<TypeOp>(defOp)) {
55  DynamicTypeDefinition *typeDef = types.at(typeOp).get();
56  auto name = StringAttr::get(ctx, typeDef->getDialect()->getNamespace() +
57  "." + typeDef->getName().str());
58  return std::make_unique<BaseTypeConstraint>(typeDef->getTypeID(), name);
59  }
60 
61  // Attribute case.
62  auto attrOp = cast<AttributeOp>(defOp);
63  DynamicAttrDefinition *attrDef = attrs.at(attrOp).get();
64  auto name = StringAttr::get(ctx, attrDef->getDialect()->getNamespace() +
65  "." + attrDef->getName().str());
66  return std::make_unique<BaseAttrConstraint>(attrDef->getTypeID(), name);
67  }
68 
69  // Case where the input is string literal.
70  // This corresponds to the case where the base is a registered type or
71  // attribute.
72  StringRef baseName = getBaseName().value();
73 
74  // Type case.
75  if (baseName[0] == '!') {
76  auto abstractType = AbstractType::lookup(baseName.drop_front(1), ctx);
77  if (!abstractType) {
78  emitError() << "no registered type with name " << baseName;
79  return nullptr;
80  }
81  return std::make_unique<BaseTypeConstraint>(abstractType->get().getTypeID(),
82  abstractType->get().getName());
83  }
84 
85  auto abstractAttr = AbstractAttribute::lookup(baseName.drop_front(1), ctx);
86  if (!abstractAttr) {
87  emitError() << "no registered attribute with name " << baseName;
88  return nullptr;
89  }
90  return std::make_unique<BaseAttrConstraint>(abstractAttr->get().getTypeID(),
91  abstractAttr->get().getName());
92 }
93 
94 std::unique_ptr<Constraint> ParametricOp::getVerifier(
95  ArrayRef<Value> valueToConstr,
96  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
97  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
98  &attrs) {
99  SmallVector<unsigned> constraints =
100  getConstraintIndicesForArgs(getArgs(), valueToConstr);
101 
102  // Symbol reference case for the base
103  SymbolRefAttr symRef = getBaseType();
104  Operation *defOp =
105  SymbolTable::lookupNearestSymbolFrom(getOperation(), symRef);
106  if (!defOp) {
107  emitError() << symRef << " does not refer to any existing symbol";
108  return nullptr;
109  }
110 
111  if (auto typeOp = dyn_cast<TypeOp>(defOp))
112  return std::make_unique<DynParametricTypeConstraint>(types.at(typeOp).get(),
113  constraints);
114 
115  if (auto attrOp = dyn_cast<AttributeOp>(defOp))
116  return std::make_unique<DynParametricAttrConstraint>(attrs.at(attrOp).get(),
117  constraints);
118 
119  llvm_unreachable("verifier should ensure that the referenced operation is "
120  "either a type or an attribute definition");
121 }
122 
123 std::unique_ptr<Constraint> AnyOfOp::getVerifier(
124  ArrayRef<Value> valueToConstr,
125  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
126  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
127  &attrs) {
128  return std::make_unique<AnyOfConstraint>(
129  getConstraintIndicesForArgs(getArgs(), valueToConstr));
130 }
131 
132 std::unique_ptr<Constraint> AllOfOp::getVerifier(
133  ArrayRef<Value> valueToConstr,
134  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
135  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
136  &attrs) {
137  return std::make_unique<AllOfConstraint>(
138  getConstraintIndicesForArgs(getArgs(), valueToConstr));
139 }
140 
141 std::unique_ptr<Constraint> AnyOp::getVerifier(
142  ArrayRef<Value> valueToConstr,
143  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
144  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
145  &attrs) {
146  return std::make_unique<AnyAttributeConstraint>();
147 }
148 
149 std::unique_ptr<RegionConstraint> RegionOp::getVerifier(
150  ArrayRef<Value> valueToConstr,
151  DenseMap<TypeOp, std::unique_ptr<DynamicTypeDefinition>> const &types,
152  DenseMap<AttributeOp, std::unique_ptr<DynamicAttrDefinition>> const
153  &attrs) {
154  return std::make_unique<RegionConstraint>(
155  getConstrainedArguments() ? std::optional{getConstraintIndicesForArgs(
156  getEntryBlockArgs(), valueToConstr)}
157  : std::nullopt,
158  getNumberOfBlocks());
159 }
static SmallVector< unsigned > getConstraintIndicesForArgs(mlir::OperandRange args, ArrayRef< Value > valueToConstr)
Maps given args to the index in the valueToConstr
Definition: IRDLOps.cpp:18
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:57
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:324
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
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:285
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...