xref: /llvm-project/mlir/lib/TableGen/Constraint.cpp (revision a3d41879ecf5690a73f9226951d3856c7faa34a4)
18f5fa566SLei Zhang //===- Constraint.cpp - Constraint class ----------------------------------===//
28f5fa566SLei Zhang //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68f5fa566SLei Zhang //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
88f5fa566SLei Zhang //
98f5fa566SLei Zhang // Constraint wrapper to simplify using TableGen Record for constraints.
108f5fa566SLei Zhang //
118f5fa566SLei Zhang //===----------------------------------------------------------------------===//
128f5fa566SLei Zhang 
138f5fa566SLei Zhang #include "mlir/TableGen/Constraint.h"
148f5fa566SLei Zhang #include "llvm/TableGen/Record.h"
158f5fa566SLei Zhang 
1695019de8SRiver Riddle using namespace mlir;
178f5fa566SLei Zhang using namespace mlir::tblgen;
188f5fa566SLei Zhang 
198f5fa566SLei Zhang Constraint::Constraint(const llvm::Record *record)
20b8186b31SMogball     : Constraint(record, CK_Uncategorized) {
217c59120fSJacques Pienaar   // Look through OpVariable's to their constraint.
227c59120fSJacques Pienaar   if (def->isSubClassOf("OpVariable"))
237c59120fSJacques Pienaar     def = def->getValueAsDef("constraint");
24b8186b31SMogball 
257c59120fSJacques Pienaar   if (def->isSubClassOf("TypeConstraint")) {
268f5fa566SLei Zhang     kind = CK_Type;
277c59120fSJacques Pienaar   } else if (def->isSubClassOf("AttrConstraint")) {
288f5fa566SLei Zhang     kind = CK_Attr;
297c59120fSJacques Pienaar   } else if (def->isSubClassOf("RegionConstraint")) {
303650df50SLei Zhang     kind = CK_Region;
317c59120fSJacques Pienaar   } else if (def->isSubClassOf("SuccessorConstraint")) {
32b1de971bSRiver Riddle     kind = CK_Successor;
33340d746aSMehdi Amini   } else if (!def->isSubClassOf("Constraint")) {
343e4ad66fSMehdi Amini     llvm::errs() << "Expected a constraint but got: \n" << *def << "\n";
35340d746aSMehdi Amini     llvm::report_fatal_error("Abort");
368f5fa566SLei Zhang   }
378f5fa566SLei Zhang }
388f5fa566SLei Zhang 
398f5fa566SLei Zhang Pred Constraint::getPredicate() const {
408f5fa566SLei Zhang   auto *val = def->getValue("predicate");
418f5fa566SLei Zhang 
428f5fa566SLei Zhang   // If no predicate is specified, then return the null predicate (which
438f5fa566SLei Zhang   // corresponds to true).
448f5fa566SLei Zhang   if (!val)
458f5fa566SLei Zhang     return Pred();
468f5fa566SLei Zhang 
478f5fa566SLei Zhang   const auto *pred = dyn_cast<llvm::DefInit>(val->getValue());
488f5fa566SLei Zhang   return Pred(pred);
498f5fa566SLei Zhang }
508f5fa566SLei Zhang 
518f5fa566SLei Zhang std::string Constraint::getConditionTemplate() const {
528f5fa566SLei Zhang   return getPredicate().getCondition();
538f5fa566SLei Zhang }
548f5fa566SLei Zhang 
55e0a93e4bSRiver Riddle StringRef Constraint::getSummary() const {
563cfe412eSFangrui Song   if (std::optional<StringRef> summary =
573cfe412eSFangrui Song           def->getValueAsOptionalString("summary"))
5895019de8SRiver Riddle     return *summary;
598f5fa566SLei Zhang   return def->getName();
608f5fa566SLei Zhang }
618f5fa566SLei Zhang 
62bf352e0bSRiver Riddle StringRef Constraint::getDescription() const {
6330c67587SKazu Hirata   return def->getValueAsOptionalString("description").value_or("");
64bf352e0bSRiver Riddle }
65bf352e0bSRiver Riddle 
6681f2f4dfSRiver Riddle StringRef Constraint::getDefName() const {
673cfe412eSFangrui Song   if (std::optional<StringRef> baseDefName = getBaseDefName())
68b3fc0fa8SRiver Riddle     return *baseDefName;
69b3fc0fa8SRiver Riddle   return def->getName();
70b3fc0fa8SRiver Riddle }
71b3fc0fa8SRiver Riddle 
72b3fc0fa8SRiver Riddle std::string Constraint::getUniqueDefName() const {
73b3fc0fa8SRiver Riddle   std::string defName = def->getName().str();
74b3fc0fa8SRiver Riddle 
75b3fc0fa8SRiver Riddle   // Non-anonymous classes already have a unique name from the def.
76b3fc0fa8SRiver Riddle   if (!def->isAnonymous())
77b3fc0fa8SRiver Riddle     return defName;
78b3fc0fa8SRiver Riddle 
79b3fc0fa8SRiver Riddle   // Otherwise, this is an anonymous class. In these cases we still use the def
80b3fc0fa8SRiver Riddle   // name, but we also try attach the name of the base def when present to make
81b3fc0fa8SRiver Riddle   // the name more obvious.
823cfe412eSFangrui Song   if (std::optional<StringRef> baseDefName = getBaseDefName())
83b3fc0fa8SRiver Riddle     return (*baseDefName + "(" + defName + ")").str();
84b3fc0fa8SRiver Riddle   return defName;
85b3fc0fa8SRiver Riddle }
86b3fc0fa8SRiver Riddle 
873cfe412eSFangrui Song std::optional<StringRef> Constraint::getBaseDefName() const {
8881f2f4dfSRiver Riddle   // Functor used to check a base def in the case where the current def is
8981f2f4dfSRiver Riddle   // anonymous.
903cfe412eSFangrui Song   auto checkBaseDefFn = [&](StringRef baseName) -> std::optional<StringRef> {
91b3fc0fa8SRiver Riddle     if (const auto *defValue = def->getValue(baseName)) {
92b3fc0fa8SRiver Riddle       if (const auto *defInit = dyn_cast<llvm::DefInit>(defValue->getValue()))
93b3fc0fa8SRiver Riddle         return Constraint(defInit->getDef(), kind).getDefName();
94b3fc0fa8SRiver Riddle     }
951a36588eSKazu Hirata     return std::nullopt;
9681f2f4dfSRiver Riddle   };
9781f2f4dfSRiver Riddle 
9881f2f4dfSRiver Riddle   switch (kind) {
9981f2f4dfSRiver Riddle   case CK_Attr:
10081f2f4dfSRiver Riddle     if (def->isAnonymous())
10181f2f4dfSRiver Riddle       return checkBaseDefFn("baseAttr");
1021a36588eSKazu Hirata     return std::nullopt;
10381f2f4dfSRiver Riddle   case CK_Type:
10481f2f4dfSRiver Riddle     if (def->isAnonymous())
10581f2f4dfSRiver Riddle       return checkBaseDefFn("baseType");
1061a36588eSKazu Hirata     return std::nullopt;
10781f2f4dfSRiver Riddle   default:
1081a36588eSKazu Hirata     return std::nullopt;
10981f2f4dfSRiver Riddle   }
110*a3d41879SMatthias Springer }
111*a3d41879SMatthias Springer 
112*a3d41879SMatthias Springer std::optional<StringRef> Constraint::getCppFunctionName() const {
113*a3d41879SMatthias Springer   std::optional<StringRef> name =
114*a3d41879SMatthias Springer       def->getValueAsOptionalString("cppFunctionName");
115*a3d41879SMatthias Springer   if (!name || *name == "")
116*a3d41879SMatthias Springer     return std::nullopt;
117*a3d41879SMatthias Springer   return name;
11881f2f4dfSRiver Riddle }
11981f2f4dfSRiver Riddle 
1207768ea9fSLei Zhang AppliedConstraint::AppliedConstraint(Constraint &&constraint,
1217768ea9fSLei Zhang                                      llvm::StringRef self,
122c72d849eSLei Zhang                                      std::vector<std::string> &&entities)
123adcd0268SBenjamin Kramer     : constraint(constraint), self(std::string(self)),
124adcd0268SBenjamin Kramer       entities(std::move(entities)) {}
1251bd1edafSRiver Riddle 
1261bd1edafSRiver Riddle Constraint DenseMapInfo<Constraint>::getEmptyKey() {
1271bd1edafSRiver Riddle   return Constraint(RecordDenseMapInfo::getEmptyKey(),
1281bd1edafSRiver Riddle                     Constraint::CK_Uncategorized);
1291bd1edafSRiver Riddle }
1301bd1edafSRiver Riddle 
1311bd1edafSRiver Riddle Constraint DenseMapInfo<Constraint>::getTombstoneKey() {
1321bd1edafSRiver Riddle   return Constraint(RecordDenseMapInfo::getTombstoneKey(),
1331bd1edafSRiver Riddle                     Constraint::CK_Uncategorized);
1341bd1edafSRiver Riddle }
1351bd1edafSRiver Riddle 
1361bd1edafSRiver Riddle unsigned DenseMapInfo<Constraint>::getHashValue(Constraint constraint) {
1371bd1edafSRiver Riddle   if (constraint == getEmptyKey())
1381bd1edafSRiver Riddle     return RecordDenseMapInfo::getHashValue(RecordDenseMapInfo::getEmptyKey());
1391bd1edafSRiver Riddle   if (constraint == getTombstoneKey()) {
1401bd1edafSRiver Riddle     return RecordDenseMapInfo::getHashValue(
1411bd1edafSRiver Riddle         RecordDenseMapInfo::getTombstoneKey());
1421bd1edafSRiver Riddle   }
1431bd1edafSRiver Riddle   return llvm::hash_combine(constraint.getPredicate(), constraint.getSummary());
1441bd1edafSRiver Riddle }
1451bd1edafSRiver Riddle 
1461bd1edafSRiver Riddle bool DenseMapInfo<Constraint>::isEqual(Constraint lhs, Constraint rhs) {
1471bd1edafSRiver Riddle   if (lhs == rhs)
1481bd1edafSRiver Riddle     return true;
1491bd1edafSRiver Riddle   if (lhs == getEmptyKey() || lhs == getTombstoneKey())
1501bd1edafSRiver Riddle     return false;
1511bd1edafSRiver Riddle   if (rhs == getEmptyKey() || rhs == getTombstoneKey())
1521bd1edafSRiver Riddle     return false;
1531bd1edafSRiver Riddle   return lhs.getPredicate() == rhs.getPredicate() &&
1541bd1edafSRiver Riddle          lhs.getSummary() == rhs.getSummary();
1551bd1edafSRiver Riddle }
156