1d932679cSAkira Hatanaka //===- Attributes.cpp - Generate attributes -------------------------------===//
2d932679cSAkira Hatanaka //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d932679cSAkira Hatanaka //
7d932679cSAkira Hatanaka //===----------------------------------------------------------------------===//
8d932679cSAkira Hatanaka 
9d932679cSAkira Hatanaka #include "llvm/TableGen/Record.h"
10d932679cSAkira Hatanaka #include <vector>
11d932679cSAkira Hatanaka using namespace llvm;
12d932679cSAkira Hatanaka 
13d932679cSAkira Hatanaka #define DEBUG_TYPE "attr-enum"
14d932679cSAkira Hatanaka 
15d932679cSAkira Hatanaka namespace {
16d932679cSAkira Hatanaka 
17d932679cSAkira Hatanaka class Attributes {
18d932679cSAkira Hatanaka public:
Attributes(RecordKeeper & R)19d932679cSAkira Hatanaka   Attributes(RecordKeeper &R) : Records(R) {}
20d932679cSAkira Hatanaka   void emit(raw_ostream &OS);
21d932679cSAkira Hatanaka 
22d932679cSAkira Hatanaka private:
23cfe87a4aSTyker   void emitTargetIndependentNames(raw_ostream &OS);
241cb242ebSAkira Hatanaka   void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
25*7ed3e878SNikita Popov   void emitAttributeProperties(raw_ostream &OF);
261cb242ebSAkira Hatanaka 
27d932679cSAkira Hatanaka   RecordKeeper &Records;
28d932679cSAkira Hatanaka };
29d932679cSAkira Hatanaka 
30d932679cSAkira Hatanaka } // End anonymous namespace.
31d932679cSAkira Hatanaka 
emitTargetIndependentNames(raw_ostream & OS)32cfe87a4aSTyker void Attributes::emitTargetIndependentNames(raw_ostream &OS) {
33cfe87a4aSTyker   OS << "#ifdef GET_ATTR_NAMES\n";
34cfe87a4aSTyker   OS << "#undef GET_ATTR_NAMES\n";
35d932679cSAkira Hatanaka 
36cfe87a4aSTyker   OS << "#ifndef ATTRIBUTE_ALL\n";
37cfe87a4aSTyker   OS << "#define ATTRIBUTE_ALL(FIRST, SECOND)\n";
38cfe87a4aSTyker   OS << "#endif\n\n";
39d932679cSAkira Hatanaka 
40ed766f1bSBenjamin Kramer   auto Emit = [&](ArrayRef<StringRef> KindNames, StringRef MacroName) {
41cfe87a4aSTyker     OS << "#ifndef " << MacroName << "\n";
42ed766f1bSBenjamin Kramer     OS << "#define " << MacroName
43ed766f1bSBenjamin Kramer        << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, SECOND)\n";
44cfe87a4aSTyker     OS << "#endif\n\n";
45ed766f1bSBenjamin Kramer     for (StringRef KindName : KindNames) {
46ed766f1bSBenjamin Kramer       for (auto A : Records.getAllDerivedDefinitions(KindName)) {
47ed766f1bSBenjamin Kramer         OS << MacroName << "(" << A->getName() << ","
48cfe87a4aSTyker            << A->getValueAsString("AttrString") << ")\n";
4960b31453SAmaury Sechet       }
50ed766f1bSBenjamin Kramer     }
51cfe87a4aSTyker     OS << "#undef " << MacroName << "\n\n";
52cfe87a4aSTyker   };
5360b31453SAmaury Sechet 
54ed766f1bSBenjamin Kramer   // Emit attribute enums in the same order llvm::Attribute::operator< expects.
55ed766f1bSBenjamin Kramer   Emit({"EnumAttr", "TypeAttr", "IntAttr"}, "ATTRIBUTE_ENUM");
56ed766f1bSBenjamin Kramer   Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
5760b31453SAmaury Sechet 
58cfe87a4aSTyker   OS << "#undef ATTRIBUTE_ALL\n";
595d1464cbSNikita Popov   OS << "#endif\n\n";
605d1464cbSNikita Popov 
615d1464cbSNikita Popov   OS << "#ifdef GET_ATTR_ENUM\n";
625d1464cbSNikita Popov   OS << "#undef GET_ATTR_ENUM\n";
635d1464cbSNikita Popov   unsigned Value = 1; // Leave zero for AttrKind::None.
645d1464cbSNikita Popov   for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) {
655d1464cbSNikita Popov     OS << "First" << KindName << " = " << Value << ",\n";
665d1464cbSNikita Popov     for (auto A : Records.getAllDerivedDefinitions(KindName)) {
675d1464cbSNikita Popov       OS << A->getName() << " = " << Value << ",\n";
685d1464cbSNikita Popov       Value++;
695d1464cbSNikita Popov     }
705d1464cbSNikita Popov     OS << "Last" << KindName << " = " << (Value - 1) << ",\n";
715d1464cbSNikita Popov   }
725d1464cbSNikita Popov   OS << "#endif\n\n";
7360b31453SAmaury Sechet }
7460b31453SAmaury Sechet 
emitFnAttrCompatCheck(raw_ostream & OS,bool IsStringAttr)751cb242ebSAkira Hatanaka void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
761cb242ebSAkira Hatanaka   OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
771cb242ebSAkira Hatanaka   OS << "#undef GET_ATTR_COMPAT_FUNC\n";
781cb242ebSAkira Hatanaka 
791cb242ebSAkira Hatanaka   OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
801cb242ebSAkira Hatanaka      << "                                        const Function &Callee) {\n";
811cb242ebSAkira Hatanaka   OS << "  bool Ret = true;\n\n";
821cb242ebSAkira Hatanaka 
831cb242ebSAkira Hatanaka   std::vector<Record *> CompatRules =
841cb242ebSAkira Hatanaka       Records.getAllDerivedDefinitions("CompatRule");
851cb242ebSAkira Hatanaka 
861cb242ebSAkira Hatanaka   for (auto *Rule : CompatRules) {
87bcd3c37fSCraig Topper     StringRef FuncName = Rule->getValueAsString("CompatFunc");
881cb242ebSAkira Hatanaka     OS << "  Ret &= " << FuncName << "(Caller, Callee);\n";
891cb242ebSAkira Hatanaka   }
901cb242ebSAkira Hatanaka 
911cb242ebSAkira Hatanaka   OS << "\n";
921cb242ebSAkira Hatanaka   OS << "  return Ret;\n";
931cb242ebSAkira Hatanaka   OS << "}\n\n";
941cb242ebSAkira Hatanaka 
951cb242ebSAkira Hatanaka   std::vector<Record *> MergeRules =
961cb242ebSAkira Hatanaka       Records.getAllDerivedDefinitions("MergeRule");
971cb242ebSAkira Hatanaka   OS << "static inline void mergeFnAttrs(Function &Caller,\n"
981cb242ebSAkira Hatanaka      << "                                const Function &Callee) {\n";
991cb242ebSAkira Hatanaka 
1001cb242ebSAkira Hatanaka   for (auto *Rule : MergeRules) {
101bcd3c37fSCraig Topper     StringRef FuncName = Rule->getValueAsString("MergeFunc");
1021cb242ebSAkira Hatanaka     OS << "  " << FuncName << "(Caller, Callee);\n";
1031cb242ebSAkira Hatanaka   }
1041cb242ebSAkira Hatanaka 
1051cb242ebSAkira Hatanaka   OS << "}\n\n";
1061cb242ebSAkira Hatanaka 
1071cb242ebSAkira Hatanaka   OS << "#endif\n";
1081cb242ebSAkira Hatanaka }
1091cb242ebSAkira Hatanaka 
emitAttributeProperties(raw_ostream & OS)110*7ed3e878SNikita Popov void Attributes::emitAttributeProperties(raw_ostream &OS) {
111*7ed3e878SNikita Popov   OS << "#ifdef GET_ATTR_PROP_TABLE\n";
112*7ed3e878SNikita Popov   OS << "#undef GET_ATTR_PROP_TABLE\n";
113*7ed3e878SNikita Popov   OS << "static const uint8_t AttrPropTable[] = {\n";
114*7ed3e878SNikita Popov   for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) {
115*7ed3e878SNikita Popov     for (auto A : Records.getAllDerivedDefinitions(KindName)) {
116*7ed3e878SNikita Popov       OS << "0";
117*7ed3e878SNikita Popov       for (Init *P : *A->getValueAsListInit("Properties"))
118*7ed3e878SNikita Popov         OS << " | AttributeProperty::" << cast<DefInit>(P)->getDef()->getName();
119*7ed3e878SNikita Popov       OS << ",\n";
120*7ed3e878SNikita Popov     }
121*7ed3e878SNikita Popov   }
122*7ed3e878SNikita Popov   OS << "};\n";
123*7ed3e878SNikita Popov   OS << "#endif\n";
124*7ed3e878SNikita Popov }
125*7ed3e878SNikita Popov 
emit(raw_ostream & OS)126d932679cSAkira Hatanaka void Attributes::emit(raw_ostream &OS) {
127cfe87a4aSTyker   emitTargetIndependentNames(OS);
1281cb242ebSAkira Hatanaka   emitFnAttrCompatCheck(OS, false);
129*7ed3e878SNikita Popov   emitAttributeProperties(OS);
130d932679cSAkira Hatanaka }
131d932679cSAkira Hatanaka 
132d932679cSAkira Hatanaka namespace llvm {
133d932679cSAkira Hatanaka 
EmitAttributes(RecordKeeper & RK,raw_ostream & OS)134d932679cSAkira Hatanaka void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
135d932679cSAkira Hatanaka   Attributes(RK).emit(OS);
136d932679cSAkira Hatanaka }
137d932679cSAkira Hatanaka 
138d932679cSAkira Hatanaka } // End llvm namespace.
139