xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/Attributes.cpp (revision be092bcde96bdcfde9013d60e442cca023bfbd1b)
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:
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  
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  
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  
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  
126  void Attributes::emit(raw_ostream &OS) {
127    emitTargetIndependentNames(OS);
128    emitFnAttrCompatCheck(OS, false);
129    emitAttributeProperties(OS);
130  }
131  
132  namespace llvm {
133  
134  void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
135    Attributes(RK).emit(OS);
136  }
137  
138  } // End llvm namespace.
139