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