Provide a way to specify inliner's attribute compatibility and merging.
[oota-llvm.git] / utils / TableGen / Attributes.cpp
index 385a244d74d416f2a7e1dd6bc4af7886f2e4a021..7b001bf14de588a4ee6831d2da740e70b26c9cfa 100644 (file)
@@ -27,6 +27,12 @@ public:
 
 private:
   void emitTargetIndependentEnums(raw_ostream &OS);
+  void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
+
+  void printEnumAttrClasses(raw_ostream &OS,
+                            const std::vector<Record *> &Records);
+  void printStrBoolAttrClasses(raw_ostream &OS,
+                               const std::vector<Record *> &Records);
 
   RecordKeeper &Records;
 };
@@ -37,7 +43,7 @@ void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
   OS << "#ifdef GET_ATTR_ENUM\n";
   OS << "#undef GET_ATTR_ENUM\n";
 
-  const std::vector<Record*> &Attrs =
+  std::vector<Record*> Attrs =
       Records.getAllDerivedDefinitions("EnumAttr");
 
   for (auto A : Attrs)
@@ -46,8 +52,99 @@ void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
   OS << "#endif\n";
 }
 
+void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
+  OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
+  OS << "#undef GET_ATTR_COMPAT_FUNC\n";
+
+  OS << "struct EnumAttr {\n";
+  OS << "  static bool isSet(const Function &Fn,\n";
+  OS << "                    Attribute::AttrKind Kind) {\n";
+  OS << "    return Fn.hasFnAttribute(Kind);\n";
+  OS << "  }\n\n";
+  OS << "  static void set(Function &Fn,\n";
+  OS << "                  Attribute::AttrKind Kind, bool Val) {\n";
+  OS << "    if (Val)\n";
+  OS << "      Fn.addFnAttr(Kind);\n";
+  OS << "    else\n";
+  OS << "      Fn.removeFnAttr(Kind);\n";
+  OS << "  }\n";
+  OS << "};\n\n";
+
+  OS << "struct StrBoolAttr {\n";
+  OS << "  static bool isSet(const Function &Fn,\n";
+  OS << "                    StringRef Kind) {\n";
+  OS << "    auto A = Fn.getFnAttribute(Kind);\n";
+  OS << "    return A.getValueAsString().equals(\"true\");\n";
+  OS << "  }\n\n";
+  OS << "  static void set(Function &Fn,\n";
+  OS << "                  StringRef Kind, bool Val) {\n";
+  OS << "    Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
+  OS << "  }\n";
+  OS << "};\n\n";
+
+  printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
+  printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
+
+  OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
+     << "                                        const Function &Callee) {\n";
+  OS << "  bool Ret = true;\n\n";
+
+  std::vector<Record *> CompatRules =
+      Records.getAllDerivedDefinitions("CompatRule");
+
+  for (auto *Rule : CompatRules) {
+    std::string FuncName = Rule->getValueAsString("CompatFunc");
+    OS << "  Ret &= " << FuncName << "(Caller, Callee);\n";
+  }
+
+  OS << "\n";
+  OS << "  return Ret;\n";
+  OS << "}\n\n";
+
+  std::vector<Record *> MergeRules =
+      Records.getAllDerivedDefinitions("MergeRule");
+  OS << "static inline void mergeFnAttrs(Function &Caller,\n"
+     << "                                const Function &Callee) {\n";
+
+  for (auto *Rule : MergeRules) {
+    std::string FuncName = Rule->getValueAsString("MergeFunc");
+    OS << "  " << FuncName << "(Caller, Callee);\n";
+  }
+
+  OS << "}\n\n";
+
+  OS << "#endif\n";
+}
+
+void Attributes::printEnumAttrClasses(raw_ostream &OS,
+                                      const std::vector<Record *> &Records) {
+  OS << "// EnumAttr classes\n";
+  for (const auto *R : Records) {
+    OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
+    OS << "  static enum Attribute::AttrKind getKind() {\n";
+    OS << "    return llvm::Attribute::" << R->getName() << ";\n";
+    OS << "  }\n";
+    OS << "};\n";
+  }
+  OS << "\n";
+}
+
+void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
+                                         const std::vector<Record *> &Records) {
+  OS << "// StrBoolAttr classes\n";
+  for (const auto *R : Records) {
+    OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
+    OS << "  static const char *getKind() {\n";
+    OS << "    return \"" << R->getValueAsString("AttrString") << "\";\n";
+    OS << "  }\n";
+    OS << "};\n";
+  }
+  OS << "\n";
+}
+
 void Attributes::emit(raw_ostream &OS) {
   emitTargetIndependentEnums(OS);
+  emitFnAttrCompatCheck(OS, false);
 }
 
 namespace llvm {