xref: /openbsd-src/gnu/llvm/llvm/utils/TableGen/Attributes.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- Attributes.cpp - Generate attributes -------------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/TableGen/Record.h"
1009467b48Spatrick #include <vector>
1109467b48Spatrick using namespace llvm;
1209467b48Spatrick 
1309467b48Spatrick #define DEBUG_TYPE "attr-enum"
1409467b48Spatrick 
1509467b48Spatrick namespace {
1609467b48Spatrick 
1709467b48Spatrick class Attributes {
1809467b48Spatrick public:
Attributes(RecordKeeper & R)1909467b48Spatrick   Attributes(RecordKeeper &R) : Records(R) {}
2009467b48Spatrick   void emit(raw_ostream &OS);
2109467b48Spatrick 
2209467b48Spatrick private:
23097a140dSpatrick   void emitTargetIndependentNames(raw_ostream &OS);
2409467b48Spatrick   void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
2573471bf0Spatrick   void emitAttributeProperties(raw_ostream &OF);
2609467b48Spatrick 
2709467b48Spatrick   RecordKeeper &Records;
2809467b48Spatrick };
2909467b48Spatrick 
3009467b48Spatrick } // End anonymous namespace.
3109467b48Spatrick 
emitTargetIndependentNames(raw_ostream & OS)32097a140dSpatrick void Attributes::emitTargetIndependentNames(raw_ostream &OS) {
33097a140dSpatrick   OS << "#ifdef GET_ATTR_NAMES\n";
34097a140dSpatrick   OS << "#undef GET_ATTR_NAMES\n";
3509467b48Spatrick 
36097a140dSpatrick   OS << "#ifndef ATTRIBUTE_ALL\n";
37097a140dSpatrick   OS << "#define ATTRIBUTE_ALL(FIRST, SECOND)\n";
38097a140dSpatrick   OS << "#endif\n\n";
3909467b48Spatrick 
40097a140dSpatrick   auto Emit = [&](ArrayRef<StringRef> KindNames, StringRef MacroName) {
41097a140dSpatrick     OS << "#ifndef " << MacroName << "\n";
42097a140dSpatrick     OS << "#define " << MacroName
43097a140dSpatrick        << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, SECOND)\n";
44097a140dSpatrick     OS << "#endif\n\n";
45097a140dSpatrick     for (StringRef KindName : KindNames) {
46*d415bd75Srobert       for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
47097a140dSpatrick         OS << MacroName << "(" << A->getName() << ","
48097a140dSpatrick            << A->getValueAsString("AttrString") << ")\n";
4909467b48Spatrick       }
5009467b48Spatrick     }
51097a140dSpatrick     OS << "#undef " << MacroName << "\n\n";
52097a140dSpatrick   };
5309467b48Spatrick 
54097a140dSpatrick   // Emit attribute enums in the same order llvm::Attribute::operator< expects.
55097a140dSpatrick   Emit({"EnumAttr", "TypeAttr", "IntAttr"}, "ATTRIBUTE_ENUM");
56097a140dSpatrick   Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
5709467b48Spatrick 
58097a140dSpatrick   OS << "#undef ATTRIBUTE_ALL\n";
5973471bf0Spatrick   OS << "#endif\n\n";
6073471bf0Spatrick 
6173471bf0Spatrick   OS << "#ifdef GET_ATTR_ENUM\n";
6273471bf0Spatrick   OS << "#undef GET_ATTR_ENUM\n";
6373471bf0Spatrick   unsigned Value = 1; // Leave zero for AttrKind::None.
6473471bf0Spatrick   for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) {
6573471bf0Spatrick     OS << "First" << KindName << " = " << Value << ",\n";
66*d415bd75Srobert     for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
6773471bf0Spatrick       OS << A->getName() << " = " << Value << ",\n";
6873471bf0Spatrick       Value++;
6973471bf0Spatrick     }
7073471bf0Spatrick     OS << "Last" << KindName << " = " << (Value - 1) << ",\n";
7173471bf0Spatrick   }
7273471bf0Spatrick   OS << "#endif\n\n";
7309467b48Spatrick }
7409467b48Spatrick 
emitFnAttrCompatCheck(raw_ostream & OS,bool IsStringAttr)7509467b48Spatrick void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
7609467b48Spatrick   OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
7709467b48Spatrick   OS << "#undef GET_ATTR_COMPAT_FUNC\n";
7809467b48Spatrick 
7909467b48Spatrick   OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
8009467b48Spatrick      << "                                        const Function &Callee) {\n";
8109467b48Spatrick   OS << "  bool Ret = true;\n\n";
8209467b48Spatrick 
8309467b48Spatrick   std::vector<Record *> CompatRules =
8409467b48Spatrick       Records.getAllDerivedDefinitions("CompatRule");
8509467b48Spatrick 
8609467b48Spatrick   for (auto *Rule : CompatRules) {
8709467b48Spatrick     StringRef FuncName = Rule->getValueAsString("CompatFunc");
8809467b48Spatrick     OS << "  Ret &= " << FuncName << "(Caller, Callee);\n";
8909467b48Spatrick   }
9009467b48Spatrick 
9109467b48Spatrick   OS << "\n";
9209467b48Spatrick   OS << "  return Ret;\n";
9309467b48Spatrick   OS << "}\n\n";
9409467b48Spatrick 
9509467b48Spatrick   std::vector<Record *> MergeRules =
9609467b48Spatrick       Records.getAllDerivedDefinitions("MergeRule");
9709467b48Spatrick   OS << "static inline void mergeFnAttrs(Function &Caller,\n"
9809467b48Spatrick      << "                                const Function &Callee) {\n";
9909467b48Spatrick 
10009467b48Spatrick   for (auto *Rule : MergeRules) {
10109467b48Spatrick     StringRef FuncName = Rule->getValueAsString("MergeFunc");
10209467b48Spatrick     OS << "  " << FuncName << "(Caller, Callee);\n";
10309467b48Spatrick   }
10409467b48Spatrick 
10509467b48Spatrick   OS << "}\n\n";
10609467b48Spatrick 
10709467b48Spatrick   OS << "#endif\n";
10809467b48Spatrick }
10909467b48Spatrick 
emitAttributeProperties(raw_ostream & OS)11073471bf0Spatrick void Attributes::emitAttributeProperties(raw_ostream &OS) {
11173471bf0Spatrick   OS << "#ifdef GET_ATTR_PROP_TABLE\n";
11273471bf0Spatrick   OS << "#undef GET_ATTR_PROP_TABLE\n";
11373471bf0Spatrick   OS << "static const uint8_t AttrPropTable[] = {\n";
11473471bf0Spatrick   for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) {
115*d415bd75Srobert     for (auto *A : Records.getAllDerivedDefinitions(KindName)) {
11673471bf0Spatrick       OS << "0";
11773471bf0Spatrick       for (Init *P : *A->getValueAsListInit("Properties"))
11873471bf0Spatrick         OS << " | AttributeProperty::" << cast<DefInit>(P)->getDef()->getName();
11973471bf0Spatrick       OS << ",\n";
12073471bf0Spatrick     }
12173471bf0Spatrick   }
12273471bf0Spatrick   OS << "};\n";
12373471bf0Spatrick   OS << "#endif\n";
12473471bf0Spatrick }
12573471bf0Spatrick 
emit(raw_ostream & OS)12609467b48Spatrick void Attributes::emit(raw_ostream &OS) {
127097a140dSpatrick   emitTargetIndependentNames(OS);
12809467b48Spatrick   emitFnAttrCompatCheck(OS, false);
12973471bf0Spatrick   emitAttributeProperties(OS);
13009467b48Spatrick }
13109467b48Spatrick 
13209467b48Spatrick namespace llvm {
13309467b48Spatrick 
EmitAttributes(RecordKeeper & RK,raw_ostream & OS)13409467b48Spatrick void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
13509467b48Spatrick   Attributes(RK).emit(OS);
13609467b48Spatrick }
13709467b48Spatrick 
13809467b48Spatrick } // End llvm namespace.
139