Home | History | Annotate | Download | only in TableGen
      1 //===- Attributes.cpp - Generate attributes -------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/Support/MemoryBuffer.h"
     11 #include "llvm/TableGen/Record.h"
     12 #include <algorithm>
     13 #include <string>
     14 #include <vector>
     15 using namespace llvm;
     16 
     17 #define DEBUG_TYPE "attr-enum"
     18 
     19 namespace {
     20 
     21 class Attributes {
     22 public:
     23   Attributes(RecordKeeper &R) : Records(R) {}
     24   void emit(raw_ostream &OS);
     25 
     26 private:
     27   void emitTargetIndependentEnums(raw_ostream &OS);
     28   void emitConversionFn(raw_ostream &OS);
     29   void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
     30 
     31   void printEnumAttrClasses(raw_ostream &OS,
     32                             const std::vector<Record *> &Records);
     33   void printStrBoolAttrClasses(raw_ostream &OS,
     34                                const std::vector<Record *> &Records);
     35 
     36   RecordKeeper &Records;
     37 };
     38 
     39 } // End anonymous namespace.
     40 
     41 void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
     42   OS << "#ifdef GET_ATTR_ENUM\n";
     43   OS << "#undef GET_ATTR_ENUM\n";
     44 
     45   std::vector<Record*> Attrs =
     46       Records.getAllDerivedDefinitions("EnumAttr");
     47 
     48   for (auto A : Attrs)
     49     OS << A->getName() << ",\n";
     50 
     51   OS << "#endif\n";
     52 }
     53 
     54 void Attributes::emitConversionFn(raw_ostream &OS) {
     55   OS << "#ifdef GET_ATTR_KIND_FROM_NAME\n";
     56   OS << "#undef GET_ATTR_KIND_FROM_NAME\n";
     57 
     58   std::vector<Record*> Attrs =
     59       Records.getAllDerivedDefinitions("EnumAttr");
     60 
     61   OS << "static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {\n";
     62   OS << "  return StringSwitch<Attribute::AttrKind>(AttrName)\n";
     63 
     64   for (auto A : Attrs) {
     65     OS << "    .Case(\"" << A->getValueAsString("AttrString");
     66     OS << "\", Attribute::" << A->getName() << ")\n";
     67   }
     68 
     69   OS << "    .Default(Attribute::None);\n";
     70   OS << "}\n\n";
     71 
     72   OS << "#endif\n";
     73 }
     74 
     75 void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
     76   OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
     77   OS << "#undef GET_ATTR_COMPAT_FUNC\n";
     78 
     79   OS << "struct EnumAttr {\n";
     80   OS << "  static bool isSet(const Function &Fn,\n";
     81   OS << "                    Attribute::AttrKind Kind) {\n";
     82   OS << "    return Fn.hasFnAttribute(Kind);\n";
     83   OS << "  }\n\n";
     84   OS << "  static void set(Function &Fn,\n";
     85   OS << "                  Attribute::AttrKind Kind, bool Val) {\n";
     86   OS << "    if (Val)\n";
     87   OS << "      Fn.addFnAttr(Kind);\n";
     88   OS << "    else\n";
     89   OS << "      Fn.removeFnAttr(Kind);\n";
     90   OS << "  }\n";
     91   OS << "};\n\n";
     92 
     93   OS << "struct StrBoolAttr {\n";
     94   OS << "  static bool isSet(const Function &Fn,\n";
     95   OS << "                    StringRef Kind) {\n";
     96   OS << "    auto A = Fn.getFnAttribute(Kind);\n";
     97   OS << "    return A.getValueAsString().equals(\"true\");\n";
     98   OS << "  }\n\n";
     99   OS << "  static void set(Function &Fn,\n";
    100   OS << "                  StringRef Kind, bool Val) {\n";
    101   OS << "    Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
    102   OS << "  }\n";
    103   OS << "};\n\n";
    104 
    105   printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
    106   printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
    107 
    108   OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
    109      << "                                        const Function &Callee) {\n";
    110   OS << "  bool Ret = true;\n\n";
    111 
    112   std::vector<Record *> CompatRules =
    113       Records.getAllDerivedDefinitions("CompatRule");
    114 
    115   for (auto *Rule : CompatRules) {
    116     StringRef FuncName = Rule->getValueAsString("CompatFunc");
    117     OS << "  Ret &= " << FuncName << "(Caller, Callee);\n";
    118   }
    119 
    120   OS << "\n";
    121   OS << "  return Ret;\n";
    122   OS << "}\n\n";
    123 
    124   std::vector<Record *> MergeRules =
    125       Records.getAllDerivedDefinitions("MergeRule");
    126   OS << "static inline void mergeFnAttrs(Function &Caller,\n"
    127      << "                                const Function &Callee) {\n";
    128 
    129   for (auto *Rule : MergeRules) {
    130     StringRef FuncName = Rule->getValueAsString("MergeFunc");
    131     OS << "  " << FuncName << "(Caller, Callee);\n";
    132   }
    133 
    134   OS << "}\n\n";
    135 
    136   OS << "#endif\n";
    137 }
    138 
    139 void Attributes::printEnumAttrClasses(raw_ostream &OS,
    140                                       const std::vector<Record *> &Records) {
    141   OS << "// EnumAttr classes\n";
    142   for (const auto *R : Records) {
    143     OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
    144     OS << "  static enum Attribute::AttrKind getKind() {\n";
    145     OS << "    return llvm::Attribute::" << R->getName() << ";\n";
    146     OS << "  }\n";
    147     OS << "};\n";
    148   }
    149   OS << "\n";
    150 }
    151 
    152 void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
    153                                          const std::vector<Record *> &Records) {
    154   OS << "// StrBoolAttr classes\n";
    155   for (const auto *R : Records) {
    156     OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
    157     OS << "  static StringRef getKind() {\n";
    158     OS << "    return \"" << R->getValueAsString("AttrString") << "\";\n";
    159     OS << "  }\n";
    160     OS << "};\n";
    161   }
    162   OS << "\n";
    163 }
    164 
    165 void Attributes::emit(raw_ostream &OS) {
    166   emitTargetIndependentEnums(OS);
    167   emitConversionFn(OS);
    168   emitFnAttrCompatCheck(OS, false);
    169 }
    170 
    171 namespace llvm {
    172 
    173 void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
    174   Attributes(RK).emit(OS);
    175 }
    176 
    177 } // End llvm namespace.
    178