1 //===- Constraint.cpp - Constraint class ----------------------------------===// 2 // 3 // Part of the LLVM Project, 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 // 9 // Constraint wrapper to simplify using TableGen Record for constraints. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "mlir/TableGen/Constraint.h" 14 #include "llvm/TableGen/Record.h" 15 16 using namespace mlir; 17 using namespace mlir::tblgen; 18 19 Constraint::Constraint(const llvm::Record *record) 20 : Constraint(record, CK_Uncategorized) { 21 // Look through OpVariable's to their constraint. 22 if (def->isSubClassOf("OpVariable")) 23 def = def->getValueAsDef("constraint"); 24 25 if (def->isSubClassOf("TypeConstraint")) { 26 kind = CK_Type; 27 } else if (def->isSubClassOf("AttrConstraint")) { 28 kind = CK_Attr; 29 } else if (def->isSubClassOf("RegionConstraint")) { 30 kind = CK_Region; 31 } else if (def->isSubClassOf("SuccessorConstraint")) { 32 kind = CK_Successor; 33 } else { 34 assert(def->isSubClassOf("Constraint")); 35 } 36 } 37 38 Pred Constraint::getPredicate() const { 39 auto *val = def->getValue("predicate"); 40 41 // If no predicate is specified, then return the null predicate (which 42 // corresponds to true). 43 if (!val) 44 return Pred(); 45 46 const auto *pred = dyn_cast<llvm::DefInit>(val->getValue()); 47 return Pred(pred); 48 } 49 50 std::string Constraint::getConditionTemplate() const { 51 return getPredicate().getCondition(); 52 } 53 54 StringRef Constraint::getSummary() const { 55 if (Optional<StringRef> summary = def->getValueAsOptionalString("summary")) 56 return *summary; 57 return def->getName(); 58 } 59 60 StringRef Constraint::getDefName() const { 61 if (Optional<StringRef> baseDefName = getBaseDefName()) 62 return *baseDefName; 63 return def->getName(); 64 } 65 66 std::string Constraint::getUniqueDefName() const { 67 std::string defName = def->getName().str(); 68 69 // Non-anonymous classes already have a unique name from the def. 70 if (!def->isAnonymous()) 71 return defName; 72 73 // Otherwise, this is an anonymous class. In these cases we still use the def 74 // name, but we also try attach the name of the base def when present to make 75 // the name more obvious. 76 if (Optional<StringRef> baseDefName = getBaseDefName()) 77 return (*baseDefName + "(" + defName + ")").str(); 78 return defName; 79 } 80 81 Optional<StringRef> Constraint::getBaseDefName() const { 82 // Functor used to check a base def in the case where the current def is 83 // anonymous. 84 auto checkBaseDefFn = [&](StringRef baseName) -> Optional<StringRef> { 85 if (const auto *defValue = def->getValue(baseName)) { 86 if (const auto *defInit = dyn_cast<llvm::DefInit>(defValue->getValue())) 87 return Constraint(defInit->getDef(), kind).getDefName(); 88 } 89 return llvm::None; 90 }; 91 92 switch (kind) { 93 case CK_Attr: 94 if (def->isAnonymous()) 95 return checkBaseDefFn("baseAttr"); 96 return llvm::None; 97 case CK_Type: 98 if (def->isAnonymous()) 99 return checkBaseDefFn("baseType"); 100 return llvm::None; 101 default: 102 return llvm::None; 103 } 104 } 105 106 AppliedConstraint::AppliedConstraint(Constraint &&constraint, 107 llvm::StringRef self, 108 std::vector<std::string> &&entities) 109 : constraint(constraint), self(std::string(self)), 110 entities(std::move(entities)) {} 111 112 Constraint DenseMapInfo<Constraint>::getEmptyKey() { 113 return Constraint(RecordDenseMapInfo::getEmptyKey(), 114 Constraint::CK_Uncategorized); 115 } 116 117 Constraint DenseMapInfo<Constraint>::getTombstoneKey() { 118 return Constraint(RecordDenseMapInfo::getTombstoneKey(), 119 Constraint::CK_Uncategorized); 120 } 121 122 unsigned DenseMapInfo<Constraint>::getHashValue(Constraint constraint) { 123 if (constraint == getEmptyKey()) 124 return RecordDenseMapInfo::getHashValue(RecordDenseMapInfo::getEmptyKey()); 125 if (constraint == getTombstoneKey()) { 126 return RecordDenseMapInfo::getHashValue( 127 RecordDenseMapInfo::getTombstoneKey()); 128 } 129 return llvm::hash_combine(constraint.getPredicate(), constraint.getSummary()); 130 } 131 132 bool DenseMapInfo<Constraint>::isEqual(Constraint lhs, Constraint rhs) { 133 if (lhs == rhs) 134 return true; 135 if (lhs == getEmptyKey() || lhs == getTombstoneKey()) 136 return false; 137 if (rhs == getEmptyKey() || rhs == getTombstoneKey()) 138 return false; 139 return lhs.getPredicate() == rhs.getPredicate() && 140 lhs.getSummary() == rhs.getSummary(); 141 } 142