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