162 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Dialect/IRDL/IR/IRDL.h"10#include "mlir/Dialect/IRDL/IRDLSymbols.h"11#include "mlir/IR/ValueRange.h"12#include <optional>13 14using namespace mlir;15using namespace mlir::irdl;16 17/// Maps given `args` to the index in the `valueToConstr`18static SmallVector<unsigned>19getConstraintIndicesForArgs(mlir::OperandRange args,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 33std::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>> const37 &attrs) {38 return std::make_unique<IsConstraint>(getExpectedAttr());39}40 41std::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>> const45 &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 or73 // 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 96std::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>> const100 &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 125std::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>> const129 &attrs) {130 return std::make_unique<AnyOfConstraint>(131 getConstraintIndicesForArgs(getArgs(), valueToConstr));132}133 134std::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>> const138 &attrs) {139 return std::make_unique<AllOfConstraint>(140 getConstraintIndicesForArgs(getArgs(), valueToConstr));141}142 143std::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>> const147 &attrs) {148 return std::make_unique<AnyAttributeConstraint>();149}150 151std::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>> const155 &attrs) {156 return std::make_unique<RegionConstraint>(157 getConstrainedArguments() ? std::optional{getConstraintIndicesForArgs(158 getEntryBlockArgs(), valueToConstr)}159 : std::nullopt,160 getNumberOfBlocks());161}162