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