xref: /llvm-project/llvm/utils/TableGen/Basic/Attributes.cpp (revision 27f30029741ecf023baece7b3dde1ff9011ffefc)
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