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