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:
Attributes(RecordKeeper & R)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
emitTargetIndependentNames(raw_ostream & OS)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
emitFnAttrCompatCheck(raw_ostream & OS,bool IsStringAttr)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
emitAttributeProperties(raw_ostream & OS)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
emit(raw_ostream & OS)126 void Attributes::emit(raw_ostream &OS) {
127 emitTargetIndependentNames(OS);
128 emitFnAttrCompatCheck(OS, false);
129 emitAttributeProperties(OS);
130 }
131
132 namespace llvm {
133
EmitAttributes(RecordKeeper & RK,raw_ostream & OS)134 void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
135 Attributes(RK).emit(OS);
136 }
137
138 } // End llvm namespace.
139