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