xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Attributes.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- Attributes.cpp - Generate attributes -------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
1006c3fb27SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
110b57cec5SDimitry Andric #include <vector>
120b57cec5SDimitry Andric using namespace llvm;
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #define DEBUG_TYPE "attr-enum"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace {
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric class Attributes {
190b57cec5SDimitry Andric public:
200b57cec5SDimitry Andric   Attributes(RecordKeeper &R) : Records(R) {}
2106c3fb27SDimitry Andric   void run(raw_ostream &OS);
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric private:
245ffd83dbSDimitry Andric   void emitTargetIndependentNames(raw_ostream &OS);
250b57cec5SDimitry Andric   void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
26fe6060f1SDimitry Andric   void emitAttributeProperties(raw_ostream &OF);
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric   RecordKeeper &Records;
290b57cec5SDimitry Andric };
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric } // End anonymous namespace.
320b57cec5SDimitry Andric 
335ffd83dbSDimitry Andric void Attributes::emitTargetIndependentNames(raw_ostream &OS) {
345ffd83dbSDimitry Andric   OS << "#ifdef GET_ATTR_NAMES\n";
355ffd83dbSDimitry Andric   OS << "#undef GET_ATTR_NAMES\n";
360b57cec5SDimitry Andric 
375ffd83dbSDimitry Andric   OS << "#ifndef ATTRIBUTE_ALL\n";
385ffd83dbSDimitry Andric   OS << "#define ATTRIBUTE_ALL(FIRST, SECOND)\n";
395ffd83dbSDimitry Andric   OS << "#endif\n\n";
400b57cec5SDimitry Andric 
415ffd83dbSDimitry Andric   auto Emit = [&](ArrayRef<StringRef> KindNames, StringRef MacroName) {
425ffd83dbSDimitry Andric     OS << "#ifndef " << MacroName << "\n";
435ffd83dbSDimitry Andric     OS << "#define " << MacroName
445ffd83dbSDimitry Andric        << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, SECOND)\n";
455ffd83dbSDimitry Andric     OS << "#endif\n\n";
465ffd83dbSDimitry Andric     for (StringRef KindName : KindNames) {
47bdd1243dSDimitry Andric       for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
485ffd83dbSDimitry Andric         OS << MacroName << "(" << A->getName() << ","
495ffd83dbSDimitry Andric            << A->getValueAsString("AttrString") << ")\n";
500b57cec5SDimitry Andric       }
510b57cec5SDimitry Andric     }
525ffd83dbSDimitry Andric     OS << "#undef " << MacroName << "\n\n";
535ffd83dbSDimitry Andric   };
540b57cec5SDimitry Andric 
555ffd83dbSDimitry Andric   // Emit attribute enums in the same order llvm::Attribute::operator< expects.
56*0fca6ea1SDimitry Andric   Emit({"EnumAttr", "TypeAttr", "IntAttr", "ConstantRangeAttr",
57*0fca6ea1SDimitry Andric         "ConstantRangeListAttr"},
58*0fca6ea1SDimitry Andric        "ATTRIBUTE_ENUM");
595ffd83dbSDimitry Andric   Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
6006c3fb27SDimitry Andric   Emit({"ComplexStrAttr"}, "ATTRIBUTE_COMPLEXSTR");
610b57cec5SDimitry Andric 
625ffd83dbSDimitry Andric   OS << "#undef ATTRIBUTE_ALL\n";
63fe6060f1SDimitry Andric   OS << "#endif\n\n";
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric   OS << "#ifdef GET_ATTR_ENUM\n";
66fe6060f1SDimitry Andric   OS << "#undef GET_ATTR_ENUM\n";
67fe6060f1SDimitry Andric   unsigned Value = 1; // Leave zero for AttrKind::None.
68*0fca6ea1SDimitry Andric   for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr",
69*0fca6ea1SDimitry Andric                              "ConstantRangeAttr", "ConstantRangeListAttr"}) {
70fe6060f1SDimitry Andric     OS << "First" << KindName << " = " << Value << ",\n";
71bdd1243dSDimitry Andric     for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
72fe6060f1SDimitry Andric       OS << A->getName() << " = " << Value << ",\n";
73fe6060f1SDimitry Andric       Value++;
74fe6060f1SDimitry Andric     }
75fe6060f1SDimitry Andric     OS << "Last" << KindName << " = " << (Value - 1) << ",\n";
76fe6060f1SDimitry Andric   }
77fe6060f1SDimitry Andric   OS << "#endif\n\n";
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
810b57cec5SDimitry Andric   OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
820b57cec5SDimitry Andric   OS << "#undef GET_ATTR_COMPAT_FUNC\n";
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
850b57cec5SDimitry Andric      << "                                        const Function &Callee) {\n";
860b57cec5SDimitry Andric   OS << "  bool Ret = true;\n\n";
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   std::vector<Record *> CompatRules =
890b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("CompatRule");
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   for (auto *Rule : CompatRules) {
920b57cec5SDimitry Andric     StringRef FuncName = Rule->getValueAsString("CompatFunc");
934c2d3b02SDimitry Andric     OS << "  Ret &= " << FuncName << "(Caller, Callee";
944c2d3b02SDimitry Andric     StringRef AttrName = Rule->getValueAsString("AttrName");
954c2d3b02SDimitry Andric     if (!AttrName.empty())
964c2d3b02SDimitry Andric       OS << ", \"" << AttrName << "\"";
974c2d3b02SDimitry Andric     OS << ");\n";
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   OS << "\n";
1010b57cec5SDimitry Andric   OS << "  return Ret;\n";
1020b57cec5SDimitry Andric   OS << "}\n\n";
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   std::vector<Record *> MergeRules =
1050b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("MergeRule");
1060b57cec5SDimitry Andric   OS << "static inline void mergeFnAttrs(Function &Caller,\n"
1070b57cec5SDimitry Andric      << "                                const Function &Callee) {\n";
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   for (auto *Rule : MergeRules) {
1100b57cec5SDimitry Andric     StringRef FuncName = Rule->getValueAsString("MergeFunc");
1110b57cec5SDimitry Andric     OS << "  " << FuncName << "(Caller, Callee);\n";
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   OS << "}\n\n";
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   OS << "#endif\n";
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
119fe6060f1SDimitry Andric void Attributes::emitAttributeProperties(raw_ostream &OS) {
120fe6060f1SDimitry Andric   OS << "#ifdef GET_ATTR_PROP_TABLE\n";
121fe6060f1SDimitry Andric   OS << "#undef GET_ATTR_PROP_TABLE\n";
122fe6060f1SDimitry Andric   OS << "static const uint8_t AttrPropTable[] = {\n";
123*0fca6ea1SDimitry Andric   for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr",
124*0fca6ea1SDimitry Andric                              "ConstantRangeAttr", "ConstantRangeListAttr"}) {
125bdd1243dSDimitry Andric     for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
126fe6060f1SDimitry Andric       OS << "0";
127fe6060f1SDimitry Andric       for (Init *P : *A->getValueAsListInit("Properties"))
128fe6060f1SDimitry Andric         OS << " | AttributeProperty::" << cast<DefInit>(P)->getDef()->getName();
129fe6060f1SDimitry Andric       OS << ",\n";
130fe6060f1SDimitry Andric     }
131fe6060f1SDimitry Andric   }
132fe6060f1SDimitry Andric   OS << "};\n";
133fe6060f1SDimitry Andric   OS << "#endif\n";
134fe6060f1SDimitry Andric }
135fe6060f1SDimitry Andric 
13606c3fb27SDimitry Andric void Attributes::run(raw_ostream &OS) {
1375ffd83dbSDimitry Andric   emitTargetIndependentNames(OS);
1380b57cec5SDimitry Andric   emitFnAttrCompatCheck(OS, false);
139fe6060f1SDimitry Andric   emitAttributeProperties(OS);
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
14206c3fb27SDimitry Andric static TableGen::Emitter::OptClass<Attributes> X("gen-attrs",
14306c3fb27SDimitry Andric                                                  "Generate attributes");
144