diff options
Diffstat (limited to 'llvm/utils/TableGen/Attributes.cpp')
| -rw-r--r-- | llvm/utils/TableGen/Attributes.cpp | 176 | 
1 files changed, 176 insertions, 0 deletions
| diff --git a/llvm/utils/TableGen/Attributes.cpp b/llvm/utils/TableGen/Attributes.cpp new file mode 100644 index 000000000000..6fbc595d7300 --- /dev/null +++ b/llvm/utils/TableGen/Attributes.cpp @@ -0,0 +1,176 @@ +//===- Attributes.cpp - Generate attributes -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TableGen/Record.h" +#include <algorithm> +#include <string> +#include <vector> +using namespace llvm; + +#define DEBUG_TYPE "attr-enum" + +namespace { + +class Attributes { +public: +  Attributes(RecordKeeper &R) : Records(R) {} +  void emit(raw_ostream &OS); + +private: +  void emitTargetIndependentEnums(raw_ostream &OS); +  void emitConversionFn(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; +}; + +} // End anonymous namespace. + +void Attributes::emitTargetIndependentEnums(raw_ostream &OS) { +  OS << "#ifdef GET_ATTR_ENUM\n"; +  OS << "#undef GET_ATTR_ENUM\n"; + +  std::vector<Record*> Attrs = +      Records.getAllDerivedDefinitions("EnumAttr"); + +  for (auto A : Attrs) +    OS << A->getName() << ",\n"; + +  OS << "#endif\n"; +} + +void Attributes::emitConversionFn(raw_ostream &OS) { +  OS << "#ifdef GET_ATTR_KIND_FROM_NAME\n"; +  OS << "#undef GET_ATTR_KIND_FROM_NAME\n"; + +  std::vector<Record*> Attrs = +      Records.getAllDerivedDefinitions("EnumAttr"); + +  OS << "static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {\n"; +  OS << "  return StringSwitch<Attribute::AttrKind>(AttrName)\n"; + +  for (auto A : Attrs) { +    OS << "    .Case(\"" << A->getValueAsString("AttrString"); +    OS << "\", Attribute::" << A->getName() << ")\n"; +  } + +  OS << "    .Default(Attribute::None);\n"; +  OS << "}\n\n"; + +  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) { +    StringRef 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) { +    StringRef 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 StringRef getKind() {\n"; +    OS << "    return \"" << R->getValueAsString("AttrString") << "\";\n"; +    OS << "  }\n"; +    OS << "};\n"; +  } +  OS << "\n"; +} + +void Attributes::emit(raw_ostream &OS) { +  emitTargetIndependentEnums(OS); +  emitConversionFn(OS); +  emitFnAttrCompatCheck(OS, false); +} + +namespace llvm { + +void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) { +  Attributes(RK).emit(OS); +} + +} // End llvm namespace. | 
