1 //===- Attributes.cpp - Generate attributes -------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/MemoryBuffer.h" 10 #include "llvm/TableGen/Record.h" 11 #include <algorithm> 12 #include <string> 13 #include <vector> 14 using namespace llvm; 15 16 #define DEBUG_TYPE "attr-enum" 17 18 namespace { 19 20 class Attributes { 21 public: 22 Attributes(RecordKeeper &R) : Records(R) {} 23 void emit(raw_ostream &OS); 24 25 private: 26 void emitTargetIndependentNames(raw_ostream &OS); 27 void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr); 28 void emitAttributeProperties(raw_ostream &OF); 29 30 RecordKeeper &Records; 31 }; 32 33 } // End anonymous namespace. 34 35 void Attributes::emitTargetIndependentNames(raw_ostream &OS) { 36 OS << "#ifdef GET_ATTR_NAMES\n"; 37 OS << "#undef GET_ATTR_NAMES\n"; 38 39 OS << "#ifndef ATTRIBUTE_ALL\n"; 40 OS << "#define ATTRIBUTE_ALL(FIRST, SECOND)\n"; 41 OS << "#endif\n\n"; 42 43 auto Emit = [&](ArrayRef<StringRef> KindNames, StringRef MacroName) { 44 OS << "#ifndef " << MacroName << "\n"; 45 OS << "#define " << MacroName 46 << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, SECOND)\n"; 47 OS << "#endif\n\n"; 48 for (StringRef KindName : KindNames) { 49 for (auto A : Records.getAllDerivedDefinitions(KindName)) { 50 OS << MacroName << "(" << A->getName() << "," 51 << A->getValueAsString("AttrString") << ")\n"; 52 } 53 } 54 OS << "#undef " << MacroName << "\n\n"; 55 }; 56 57 // Emit attribute enums in the same order llvm::Attribute::operator< expects. 58 Emit({"EnumAttr", "TypeAttr", "IntAttr"}, "ATTRIBUTE_ENUM"); 59 Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL"); 60 61 OS << "#undef ATTRIBUTE_ALL\n"; 62 OS << "#endif\n\n"; 63 64 OS << "#ifdef GET_ATTR_ENUM\n"; 65 OS << "#undef GET_ATTR_ENUM\n"; 66 unsigned Value = 1; // Leave zero for AttrKind::None. 67 for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) { 68 OS << "First" << KindName << " = " << Value << ",\n"; 69 for (auto A : Records.getAllDerivedDefinitions(KindName)) { 70 OS << A->getName() << " = " << Value << ",\n"; 71 Value++; 72 } 73 OS << "Last" << KindName << " = " << (Value - 1) << ",\n"; 74 } 75 OS << "#endif\n\n"; 76 } 77 78 void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) { 79 OS << "#ifdef GET_ATTR_COMPAT_FUNC\n"; 80 OS << "#undef GET_ATTR_COMPAT_FUNC\n"; 81 82 OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n" 83 << " const Function &Callee) {\n"; 84 OS << " bool Ret = true;\n\n"; 85 86 std::vector<Record *> CompatRules = 87 Records.getAllDerivedDefinitions("CompatRule"); 88 89 for (auto *Rule : CompatRules) { 90 StringRef FuncName = Rule->getValueAsString("CompatFunc"); 91 OS << " Ret &= " << FuncName << "(Caller, Callee);\n"; 92 } 93 94 OS << "\n"; 95 OS << " return Ret;\n"; 96 OS << "}\n\n"; 97 98 std::vector<Record *> MergeRules = 99 Records.getAllDerivedDefinitions("MergeRule"); 100 OS << "static inline void mergeFnAttrs(Function &Caller,\n" 101 << " const Function &Callee) {\n"; 102 103 for (auto *Rule : MergeRules) { 104 StringRef FuncName = Rule->getValueAsString("MergeFunc"); 105 OS << " " << FuncName << "(Caller, Callee);\n"; 106 } 107 108 OS << "}\n\n"; 109 110 OS << "#endif\n"; 111 } 112 113 void Attributes::emitAttributeProperties(raw_ostream &OS) { 114 OS << "#ifdef GET_ATTR_PROP_TABLE\n"; 115 OS << "#undef GET_ATTR_PROP_TABLE\n"; 116 OS << "static const uint8_t AttrPropTable[] = {\n"; 117 for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) { 118 for (auto A : Records.getAllDerivedDefinitions(KindName)) { 119 OS << "0"; 120 for (Init *P : *A->getValueAsListInit("Properties")) 121 OS << " | AttributeProperty::" << cast<DefInit>(P)->getDef()->getName(); 122 OS << ",\n"; 123 } 124 } 125 OS << "};\n"; 126 OS << "#endif\n"; 127 } 128 129 void Attributes::emit(raw_ostream &OS) { 130 emitTargetIndependentNames(OS); 131 emitFnAttrCompatCheck(OS, false); 132 emitAttributeProperties(OS); 133 } 134 135 namespace llvm { 136 137 void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) { 138 Attributes(RK).emit(OS); 139 } 140 141 } // End llvm namespace. 142