17d523365SDimitry Andric //===- Attributes.cpp - Generate attributes -------------------------------===//
27d523365SDimitry Andric //
37d523365SDimitry Andric // The LLVM Compiler Infrastructure
47d523365SDimitry Andric //
57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source
67d523365SDimitry Andric // License. See LICENSE.TXT for details.
77d523365SDimitry Andric //
87d523365SDimitry Andric //===----------------------------------------------------------------------===//
97d523365SDimitry Andric
107d523365SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
117d523365SDimitry Andric #include "llvm/TableGen/Record.h"
127d523365SDimitry Andric #include <algorithm>
137d523365SDimitry Andric #include <string>
147d523365SDimitry Andric #include <vector>
157d523365SDimitry Andric using namespace llvm;
167d523365SDimitry Andric
177d523365SDimitry Andric #define DEBUG_TYPE "attr-enum"
187d523365SDimitry Andric
197d523365SDimitry Andric namespace {
207d523365SDimitry Andric
217d523365SDimitry Andric class Attributes {
227d523365SDimitry Andric public:
Attributes(RecordKeeper & R)237d523365SDimitry Andric Attributes(RecordKeeper &R) : Records(R) {}
247d523365SDimitry Andric void emit(raw_ostream &OS);
257d523365SDimitry Andric
267d523365SDimitry Andric private:
277d523365SDimitry Andric void emitTargetIndependentEnums(raw_ostream &OS);
283ca95b02SDimitry Andric void emitConversionFn(raw_ostream &OS);
297d523365SDimitry Andric void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
307d523365SDimitry Andric
317d523365SDimitry Andric void printEnumAttrClasses(raw_ostream &OS,
327d523365SDimitry Andric const std::vector<Record *> &Records);
337d523365SDimitry Andric void printStrBoolAttrClasses(raw_ostream &OS,
347d523365SDimitry Andric const std::vector<Record *> &Records);
357d523365SDimitry Andric
367d523365SDimitry Andric RecordKeeper &Records;
377d523365SDimitry Andric };
387d523365SDimitry Andric
397d523365SDimitry Andric } // End anonymous namespace.
407d523365SDimitry Andric
emitTargetIndependentEnums(raw_ostream & OS)417d523365SDimitry Andric void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
427d523365SDimitry Andric OS << "#ifdef GET_ATTR_ENUM\n";
437d523365SDimitry Andric OS << "#undef GET_ATTR_ENUM\n";
447d523365SDimitry Andric
457d523365SDimitry Andric std::vector<Record*> Attrs =
467d523365SDimitry Andric Records.getAllDerivedDefinitions("EnumAttr");
477d523365SDimitry Andric
487d523365SDimitry Andric for (auto A : Attrs)
497d523365SDimitry Andric OS << A->getName() << ",\n";
507d523365SDimitry Andric
517d523365SDimitry Andric OS << "#endif\n";
527d523365SDimitry Andric }
537d523365SDimitry Andric
emitConversionFn(raw_ostream & OS)543ca95b02SDimitry Andric void Attributes::emitConversionFn(raw_ostream &OS) {
553ca95b02SDimitry Andric OS << "#ifdef GET_ATTR_KIND_FROM_NAME\n";
563ca95b02SDimitry Andric OS << "#undef GET_ATTR_KIND_FROM_NAME\n";
573ca95b02SDimitry Andric
583ca95b02SDimitry Andric std::vector<Record*> Attrs =
593ca95b02SDimitry Andric Records.getAllDerivedDefinitions("EnumAttr");
603ca95b02SDimitry Andric
613ca95b02SDimitry Andric OS << "static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {\n";
623ca95b02SDimitry Andric OS << " return StringSwitch<Attribute::AttrKind>(AttrName)\n";
633ca95b02SDimitry Andric
643ca95b02SDimitry Andric for (auto A : Attrs) {
653ca95b02SDimitry Andric OS << " .Case(\"" << A->getValueAsString("AttrString");
663ca95b02SDimitry Andric OS << "\", Attribute::" << A->getName() << ")\n";
673ca95b02SDimitry Andric }
683ca95b02SDimitry Andric
693ca95b02SDimitry Andric OS << " .Default(Attribute::None);\n";
703ca95b02SDimitry Andric OS << "}\n\n";
713ca95b02SDimitry Andric
723ca95b02SDimitry Andric OS << "#endif\n";
733ca95b02SDimitry Andric }
743ca95b02SDimitry Andric
emitFnAttrCompatCheck(raw_ostream & OS,bool IsStringAttr)757d523365SDimitry Andric void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
767d523365SDimitry Andric OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
777d523365SDimitry Andric OS << "#undef GET_ATTR_COMPAT_FUNC\n";
787d523365SDimitry Andric
797d523365SDimitry Andric OS << "struct EnumAttr {\n";
807d523365SDimitry Andric OS << " static bool isSet(const Function &Fn,\n";
817d523365SDimitry Andric OS << " Attribute::AttrKind Kind) {\n";
827d523365SDimitry Andric OS << " return Fn.hasFnAttribute(Kind);\n";
837d523365SDimitry Andric OS << " }\n\n";
847d523365SDimitry Andric OS << " static void set(Function &Fn,\n";
857d523365SDimitry Andric OS << " Attribute::AttrKind Kind, bool Val) {\n";
867d523365SDimitry Andric OS << " if (Val)\n";
877d523365SDimitry Andric OS << " Fn.addFnAttr(Kind);\n";
887d523365SDimitry Andric OS << " else\n";
897d523365SDimitry Andric OS << " Fn.removeFnAttr(Kind);\n";
907d523365SDimitry Andric OS << " }\n";
917d523365SDimitry Andric OS << "};\n\n";
927d523365SDimitry Andric
937d523365SDimitry Andric OS << "struct StrBoolAttr {\n";
947d523365SDimitry Andric OS << " static bool isSet(const Function &Fn,\n";
957d523365SDimitry Andric OS << " StringRef Kind) {\n";
967d523365SDimitry Andric OS << " auto A = Fn.getFnAttribute(Kind);\n";
977d523365SDimitry Andric OS << " return A.getValueAsString().equals(\"true\");\n";
987d523365SDimitry Andric OS << " }\n\n";
997d523365SDimitry Andric OS << " static void set(Function &Fn,\n";
1007d523365SDimitry Andric OS << " StringRef Kind, bool Val) {\n";
1017d523365SDimitry Andric OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
1027d523365SDimitry Andric OS << " }\n";
1037d523365SDimitry Andric OS << "};\n\n";
1047d523365SDimitry Andric
1057d523365SDimitry Andric printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
1067d523365SDimitry Andric printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
1077d523365SDimitry Andric
1087d523365SDimitry Andric OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
1097d523365SDimitry Andric << " const Function &Callee) {\n";
1107d523365SDimitry Andric OS << " bool Ret = true;\n\n";
1117d523365SDimitry Andric
1127d523365SDimitry Andric std::vector<Record *> CompatRules =
1137d523365SDimitry Andric Records.getAllDerivedDefinitions("CompatRule");
1147d523365SDimitry Andric
1157d523365SDimitry Andric for (auto *Rule : CompatRules) {
116*f9448bf3SDimitry Andric StringRef FuncName = Rule->getValueAsString("CompatFunc");
1177d523365SDimitry Andric OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
1187d523365SDimitry Andric }
1197d523365SDimitry Andric
1207d523365SDimitry Andric OS << "\n";
1217d523365SDimitry Andric OS << " return Ret;\n";
1227d523365SDimitry Andric OS << "}\n\n";
1237d523365SDimitry Andric
1247d523365SDimitry Andric std::vector<Record *> MergeRules =
1257d523365SDimitry Andric Records.getAllDerivedDefinitions("MergeRule");
1267d523365SDimitry Andric OS << "static inline void mergeFnAttrs(Function &Caller,\n"
1277d523365SDimitry Andric << " const Function &Callee) {\n";
1287d523365SDimitry Andric
1297d523365SDimitry Andric for (auto *Rule : MergeRules) {
130*f9448bf3SDimitry Andric StringRef FuncName = Rule->getValueAsString("MergeFunc");
1317d523365SDimitry Andric OS << " " << FuncName << "(Caller, Callee);\n";
1327d523365SDimitry Andric }
1337d523365SDimitry Andric
1347d523365SDimitry Andric OS << "}\n\n";
1357d523365SDimitry Andric
1367d523365SDimitry Andric OS << "#endif\n";
1377d523365SDimitry Andric }
1387d523365SDimitry Andric
printEnumAttrClasses(raw_ostream & OS,const std::vector<Record * > & Records)1397d523365SDimitry Andric void Attributes::printEnumAttrClasses(raw_ostream &OS,
1407d523365SDimitry Andric const std::vector<Record *> &Records) {
1417d523365SDimitry Andric OS << "// EnumAttr classes\n";
1427d523365SDimitry Andric for (const auto *R : Records) {
1437d523365SDimitry Andric OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
1447d523365SDimitry Andric OS << " static enum Attribute::AttrKind getKind() {\n";
1457d523365SDimitry Andric OS << " return llvm::Attribute::" << R->getName() << ";\n";
1467d523365SDimitry Andric OS << " }\n";
1477d523365SDimitry Andric OS << "};\n";
1487d523365SDimitry Andric }
1497d523365SDimitry Andric OS << "\n";
1507d523365SDimitry Andric }
1517d523365SDimitry Andric
printStrBoolAttrClasses(raw_ostream & OS,const std::vector<Record * > & Records)1527d523365SDimitry Andric void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
1537d523365SDimitry Andric const std::vector<Record *> &Records) {
1547d523365SDimitry Andric OS << "// StrBoolAttr classes\n";
1557d523365SDimitry Andric for (const auto *R : Records) {
1567d523365SDimitry Andric OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
157d88c1a5aSDimitry Andric OS << " static StringRef getKind() {\n";
1587d523365SDimitry Andric OS << " return \"" << R->getValueAsString("AttrString") << "\";\n";
1597d523365SDimitry Andric OS << " }\n";
1607d523365SDimitry Andric OS << "};\n";
1617d523365SDimitry Andric }
1627d523365SDimitry Andric OS << "\n";
1637d523365SDimitry Andric }
1647d523365SDimitry Andric
emit(raw_ostream & OS)1657d523365SDimitry Andric void Attributes::emit(raw_ostream &OS) {
1667d523365SDimitry Andric emitTargetIndependentEnums(OS);
1673ca95b02SDimitry Andric emitConversionFn(OS);
1687d523365SDimitry Andric emitFnAttrCompatCheck(OS, false);
1697d523365SDimitry Andric }
1707d523365SDimitry Andric
1717d523365SDimitry Andric namespace llvm {
1727d523365SDimitry Andric
EmitAttributes(RecordKeeper & RK,raw_ostream & OS)1737d523365SDimitry Andric void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
1747d523365SDimitry Andric Attributes(RK).emit(OS);
1757d523365SDimitry Andric }
1767d523365SDimitry Andric
1777d523365SDimitry Andric } // End llvm namespace.
178