1dd58ef01SDimitry Andric //===- Attributes.cpp - Generate attributes -------------------------------===//
2dd58ef01SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dd58ef01SDimitry Andric //
7dd58ef01SDimitry Andric //===----------------------------------------------------------------------===//
8dd58ef01SDimitry Andric
9dd58ef01SDimitry Andric #include "llvm/TableGen/Record.h"
107fa27ce4SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
11dd58ef01SDimitry Andric #include <vector>
12dd58ef01SDimitry Andric using namespace llvm;
13dd58ef01SDimitry Andric
14dd58ef01SDimitry Andric #define DEBUG_TYPE "attr-enum"
15dd58ef01SDimitry Andric
16dd58ef01SDimitry Andric namespace {
17dd58ef01SDimitry Andric
18dd58ef01SDimitry Andric class Attributes {
19dd58ef01SDimitry Andric public:
Attributes(RecordKeeper & R)20dd58ef01SDimitry Andric Attributes(RecordKeeper &R) : Records(R) {}
217fa27ce4SDimitry Andric void run(raw_ostream &OS);
22dd58ef01SDimitry Andric
23dd58ef01SDimitry Andric private:
24cfca06d7SDimitry Andric void emitTargetIndependentNames(raw_ostream &OS);
25dd58ef01SDimitry Andric void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
26344a3780SDimitry Andric void emitAttributeProperties(raw_ostream &OF);
27dd58ef01SDimitry Andric
28dd58ef01SDimitry Andric RecordKeeper &Records;
29dd58ef01SDimitry Andric };
30dd58ef01SDimitry Andric
31dd58ef01SDimitry Andric } // End anonymous namespace.
32dd58ef01SDimitry Andric
emitTargetIndependentNames(raw_ostream & OS)33cfca06d7SDimitry Andric void Attributes::emitTargetIndependentNames(raw_ostream &OS) {
34cfca06d7SDimitry Andric OS << "#ifdef GET_ATTR_NAMES\n";
35cfca06d7SDimitry Andric OS << "#undef GET_ATTR_NAMES\n";
36dd58ef01SDimitry Andric
37cfca06d7SDimitry Andric OS << "#ifndef ATTRIBUTE_ALL\n";
38cfca06d7SDimitry Andric OS << "#define ATTRIBUTE_ALL(FIRST, SECOND)\n";
39cfca06d7SDimitry Andric OS << "#endif\n\n";
40dd58ef01SDimitry Andric
41cfca06d7SDimitry Andric auto Emit = [&](ArrayRef<StringRef> KindNames, StringRef MacroName) {
42cfca06d7SDimitry Andric OS << "#ifndef " << MacroName << "\n";
43cfca06d7SDimitry Andric OS << "#define " << MacroName
44cfca06d7SDimitry Andric << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, SECOND)\n";
45cfca06d7SDimitry Andric OS << "#endif\n\n";
46cfca06d7SDimitry Andric for (StringRef KindName : KindNames) {
47e3b55780SDimitry Andric for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
48cfca06d7SDimitry Andric OS << MacroName << "(" << A->getName() << ","
49cfca06d7SDimitry Andric << A->getValueAsString("AttrString") << ")\n";
50dd58ef01SDimitry Andric }
5101095a5dSDimitry Andric }
52cfca06d7SDimitry Andric OS << "#undef " << MacroName << "\n\n";
53cfca06d7SDimitry Andric };
5401095a5dSDimitry Andric
55cfca06d7SDimitry Andric // Emit attribute enums in the same order llvm::Attribute::operator< expects.
56ac9a064cSDimitry Andric Emit({"EnumAttr", "TypeAttr", "IntAttr", "ConstantRangeAttr",
57ac9a064cSDimitry Andric "ConstantRangeListAttr"},
58ac9a064cSDimitry Andric "ATTRIBUTE_ENUM");
59cfca06d7SDimitry Andric Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
607fa27ce4SDimitry Andric Emit({"ComplexStrAttr"}, "ATTRIBUTE_COMPLEXSTR");
6101095a5dSDimitry Andric
62cfca06d7SDimitry Andric OS << "#undef ATTRIBUTE_ALL\n";
63344a3780SDimitry Andric OS << "#endif\n\n";
64344a3780SDimitry Andric
65344a3780SDimitry Andric OS << "#ifdef GET_ATTR_ENUM\n";
66344a3780SDimitry Andric OS << "#undef GET_ATTR_ENUM\n";
67344a3780SDimitry Andric unsigned Value = 1; // Leave zero for AttrKind::None.
68ac9a064cSDimitry Andric for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr",
69ac9a064cSDimitry Andric "ConstantRangeAttr", "ConstantRangeListAttr"}) {
70344a3780SDimitry Andric OS << "First" << KindName << " = " << Value << ",\n";
71e3b55780SDimitry Andric for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
72344a3780SDimitry Andric OS << A->getName() << " = " << Value << ",\n";
73344a3780SDimitry Andric Value++;
74344a3780SDimitry Andric }
75344a3780SDimitry Andric OS << "Last" << KindName << " = " << (Value - 1) << ",\n";
76344a3780SDimitry Andric }
77344a3780SDimitry Andric OS << "#endif\n\n";
7801095a5dSDimitry Andric }
7901095a5dSDimitry Andric
emitFnAttrCompatCheck(raw_ostream & OS,bool IsStringAttr)80dd58ef01SDimitry Andric void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
81dd58ef01SDimitry Andric OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
82dd58ef01SDimitry Andric OS << "#undef GET_ATTR_COMPAT_FUNC\n";
83dd58ef01SDimitry Andric
84dd58ef01SDimitry Andric OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
85dd58ef01SDimitry Andric << " const Function &Callee) {\n";
86dd58ef01SDimitry Andric OS << " bool Ret = true;\n\n";
87dd58ef01SDimitry Andric
88dd58ef01SDimitry Andric std::vector<Record *> CompatRules =
89dd58ef01SDimitry Andric Records.getAllDerivedDefinitions("CompatRule");
90dd58ef01SDimitry Andric
91dd58ef01SDimitry Andric for (auto *Rule : CompatRules) {
92f382538dSDimitry Andric StringRef FuncName = Rule->getValueAsString("CompatFunc");
93ac9a064cSDimitry Andric OS << " Ret &= " << FuncName << "(Caller, Callee";
94ac9a064cSDimitry Andric StringRef AttrName = Rule->getValueAsString("AttrName");
95ac9a064cSDimitry Andric if (!AttrName.empty())
96ac9a064cSDimitry Andric OS << ", \"" << AttrName << "\"";
97ac9a064cSDimitry Andric OS << ");\n";
98dd58ef01SDimitry Andric }
99dd58ef01SDimitry Andric
100dd58ef01SDimitry Andric OS << "\n";
101dd58ef01SDimitry Andric OS << " return Ret;\n";
102dd58ef01SDimitry Andric OS << "}\n\n";
103dd58ef01SDimitry Andric
104dd58ef01SDimitry Andric std::vector<Record *> MergeRules =
105dd58ef01SDimitry Andric Records.getAllDerivedDefinitions("MergeRule");
106dd58ef01SDimitry Andric OS << "static inline void mergeFnAttrs(Function &Caller,\n"
107dd58ef01SDimitry Andric << " const Function &Callee) {\n";
108dd58ef01SDimitry Andric
109dd58ef01SDimitry Andric for (auto *Rule : MergeRules) {
110f382538dSDimitry Andric StringRef FuncName = Rule->getValueAsString("MergeFunc");
111dd58ef01SDimitry Andric OS << " " << FuncName << "(Caller, Callee);\n";
112dd58ef01SDimitry Andric }
113dd58ef01SDimitry Andric
114dd58ef01SDimitry Andric OS << "}\n\n";
115dd58ef01SDimitry Andric
116dd58ef01SDimitry Andric OS << "#endif\n";
117dd58ef01SDimitry Andric }
118dd58ef01SDimitry Andric
emitAttributeProperties(raw_ostream & OS)119344a3780SDimitry Andric void Attributes::emitAttributeProperties(raw_ostream &OS) {
120344a3780SDimitry Andric OS << "#ifdef GET_ATTR_PROP_TABLE\n";
121344a3780SDimitry Andric OS << "#undef GET_ATTR_PROP_TABLE\n";
122344a3780SDimitry Andric OS << "static const uint8_t AttrPropTable[] = {\n";
123ac9a064cSDimitry Andric for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr",
124ac9a064cSDimitry Andric "ConstantRangeAttr", "ConstantRangeListAttr"}) {
125e3b55780SDimitry Andric for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
126344a3780SDimitry Andric OS << "0";
127344a3780SDimitry Andric for (Init *P : *A->getValueAsListInit("Properties"))
128344a3780SDimitry Andric OS << " | AttributeProperty::" << cast<DefInit>(P)->getDef()->getName();
129344a3780SDimitry Andric OS << ",\n";
130344a3780SDimitry Andric }
131344a3780SDimitry Andric }
132344a3780SDimitry Andric OS << "};\n";
133344a3780SDimitry Andric OS << "#endif\n";
134344a3780SDimitry Andric }
135344a3780SDimitry Andric
run(raw_ostream & OS)1367fa27ce4SDimitry Andric void Attributes::run(raw_ostream &OS) {
137cfca06d7SDimitry Andric emitTargetIndependentNames(OS);
138dd58ef01SDimitry Andric emitFnAttrCompatCheck(OS, false);
139344a3780SDimitry Andric emitAttributeProperties(OS);
140dd58ef01SDimitry Andric }
141dd58ef01SDimitry Andric
1427fa27ce4SDimitry Andric static TableGen::Emitter::OptClass<Attributes> X("gen-attrs",
1437fa27ce4SDimitry Andric "Generate attributes");
144