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 if (!def->isSubClassOf("Constraint")) { 34 llvm::errs() << "Expected a constraint but got: \n" << *def << "\n"; 35 llvm::report_fatal_error("Abort"); 36 } 37 } 38 39 Pred Constraint::getPredicate() const { 40 auto *val = def->getValue("predicate"); 41 42 // If no predicate is specified, then return the null predicate (which 43 // corresponds to true). 44 if (!val) 45 return Pred(); 46 47 const auto *pred = dyn_cast<llvm::DefInit>(val->getValue()); 48 return Pred(pred); 49 } 50 51 std::string Constraint::getConditionTemplate() const { 52 return getPredicate().getCondition(); 53 } 54 55 StringRef Constraint::getSummary() const { 56 if (std::optional<StringRef> summary = 57 def->getValueAsOptionalString("summary")) 58 return *summary; 59 return def->getName(); 60 } 61 62 StringRef Constraint::getDescription() const { 63 return def->getValueAsOptionalString("description").value_or(""); 64 } 65 66 StringRef Constraint::getDefName() const { 67 if (std::optional<StringRef> baseDefName = getBaseDefName()) 68 return *baseDefName; 69 return def->getName(); 70 } 71 72 std::string Constraint::getUniqueDefName() const { 73 std::string defName = def->getName().str(); 74 75 // Non-anonymous classes already have a unique name from the def. 76 if (!def->isAnonymous()) 77 return defName; 78 79 // Otherwise, this is an anonymous class. In these cases we still use the def 80 // name, but we also try attach the name of the base def when present to make 81 // the name more obvious. 82 if (std::optional<StringRef> baseDefName = getBaseDefName()) 83 return (*baseDefName + "(" + defName + ")").str(); 84 return defName; 85 } 86 87 std::optional<StringRef> Constraint::getBaseDefName() const { 88 // Functor used to check a base def in the case where the current def is 89 // anonymous. 90 auto checkBaseDefFn = [&](StringRef baseName) -> std::optional<StringRef> { 91 if (const auto *defValue = def->getValue(baseName)) { 92 if (const auto *defInit = dyn_cast<llvm::DefInit>(defValue->getValue())) 93 return Constraint(defInit->getDef(), kind).getDefName(); 94 } 95 return std::nullopt; 96 }; 97 98 switch (kind) { 99 case CK_Attr: 100 if (def->isAnonymous()) 101 return checkBaseDefFn("baseAttr"); 102 return std::nullopt; 103 case CK_Type: 104 if (def->isAnonymous()) 105 return checkBaseDefFn("baseType"); 106 return std::nullopt; 107 default: 108 return std::nullopt; 109 } 110 } 111 112 std::optional<StringRef> Constraint::getCppFunctionName() const { 113 std::optional<StringRef> name = 114 def->getValueAsOptionalString("cppFunctionName"); 115 if (!name || *name == "") 116 return std::nullopt; 117 return name; 118 } 119 120 AppliedConstraint::AppliedConstraint(Constraint &&constraint, 121 llvm::StringRef self, 122 std::vector<std::string> &&entities) 123 : constraint(constraint), self(std::string(self)), 124 entities(std::move(entities)) {} 125 126 Constraint DenseMapInfo<Constraint>::getEmptyKey() { 127 return Constraint(RecordDenseMapInfo::getEmptyKey(), 128 Constraint::CK_Uncategorized); 129 } 130 131 Constraint DenseMapInfo<Constraint>::getTombstoneKey() { 132 return Constraint(RecordDenseMapInfo::getTombstoneKey(), 133 Constraint::CK_Uncategorized); 134 } 135 136 unsigned DenseMapInfo<Constraint>::getHashValue(Constraint constraint) { 137 if (constraint == getEmptyKey()) 138 return RecordDenseMapInfo::getHashValue(RecordDenseMapInfo::getEmptyKey()); 139 if (constraint == getTombstoneKey()) { 140 return RecordDenseMapInfo::getHashValue( 141 RecordDenseMapInfo::getTombstoneKey()); 142 } 143 return llvm::hash_combine(constraint.getPredicate(), constraint.getSummary()); 144 } 145 146 bool DenseMapInfo<Constraint>::isEqual(Constraint lhs, Constraint rhs) { 147 if (lhs == rhs) 148 return true; 149 if (lhs == getEmptyKey() || lhs == getTombstoneKey()) 150 return false; 151 if (rhs == getEmptyKey() || rhs == getTombstoneKey()) 152 return false; 153 return lhs.getPredicate() == rhs.getPredicate() && 154 lhs.getSummary() == rhs.getSummary(); 155 } 156