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