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::getDescription() const { 61 return def->getValueAsOptionalString("description").value_or(""); 62 } 63 64 StringRef Constraint::getDefName() const { 65 if (Optional<StringRef> baseDefName = getBaseDefName()) 66 return *baseDefName; 67 return def->getName(); 68 } 69 70 std::string Constraint::getUniqueDefName() const { 71 std::string defName = def->getName().str(); 72 73 // Non-anonymous classes already have a unique name from the def. 74 if (!def->isAnonymous()) 75 return defName; 76 77 // Otherwise, this is an anonymous class. In these cases we still use the def 78 // name, but we also try attach the name of the base def when present to make 79 // the name more obvious. 80 if (Optional<StringRef> baseDefName = getBaseDefName()) 81 return (*baseDefName + "(" + defName + ")").str(); 82 return defName; 83 } 84 85 Optional<StringRef> Constraint::getBaseDefName() const { 86 // Functor used to check a base def in the case where the current def is 87 // anonymous. 88 auto checkBaseDefFn = [&](StringRef baseName) -> Optional<StringRef> { 89 if (const auto *defValue = def->getValue(baseName)) { 90 if (const auto *defInit = dyn_cast<llvm::DefInit>(defValue->getValue())) 91 return Constraint(defInit->getDef(), kind).getDefName(); 92 } 93 return llvm::None; 94 }; 95 96 switch (kind) { 97 case CK_Attr: 98 if (def->isAnonymous()) 99 return checkBaseDefFn("baseAttr"); 100 return llvm::None; 101 case CK_Type: 102 if (def->isAnonymous()) 103 return checkBaseDefFn("baseType"); 104 return llvm::None; 105 default: 106 return llvm::None; 107 } 108 } 109 110 AppliedConstraint::AppliedConstraint(Constraint &&constraint, 111 llvm::StringRef self, 112 std::vector<std::string> &&entities) 113 : constraint(constraint), self(std::string(self)), 114 entities(std::move(entities)) {} 115 116 Constraint DenseMapInfo<Constraint>::getEmptyKey() { 117 return Constraint(RecordDenseMapInfo::getEmptyKey(), 118 Constraint::CK_Uncategorized); 119 } 120 121 Constraint DenseMapInfo<Constraint>::getTombstoneKey() { 122 return Constraint(RecordDenseMapInfo::getTombstoneKey(), 123 Constraint::CK_Uncategorized); 124 } 125 126 unsigned DenseMapInfo<Constraint>::getHashValue(Constraint constraint) { 127 if (constraint == getEmptyKey()) 128 return RecordDenseMapInfo::getHashValue(RecordDenseMapInfo::getEmptyKey()); 129 if (constraint == getTombstoneKey()) { 130 return RecordDenseMapInfo::getHashValue( 131 RecordDenseMapInfo::getTombstoneKey()); 132 } 133 return llvm::hash_combine(constraint.getPredicate(), constraint.getSummary()); 134 } 135 136 bool DenseMapInfo<Constraint>::isEqual(Constraint lhs, Constraint rhs) { 137 if (lhs == rhs) 138 return true; 139 if (lhs == getEmptyKey() || lhs == getTombstoneKey()) 140 return false; 141 if (rhs == getEmptyKey() || rhs == getTombstoneKey()) 142 return false; 143 return lhs.getPredicate() == rhs.getPredicate() && 144 lhs.getSummary() == rhs.getSummary(); 145 } 146