forked from OSchip/llvm-project
[TableGen] Move generated *Attr class methods out of line
After this change, clang spends ~200ms parsing Attrs.inc instead of ~560ms. A large part of the cost was from the StringSwitch instantiations, but this is a good way to avoid similar problems in the future. Reviewed By: aaron.ballman, rjmccall Differential Revision: https://reviews.llvm.org/D76040
This commit is contained in:
parent
e79397f5e2
commit
7420f96924
|
@ -426,8 +426,8 @@ namespace {
|
|||
}
|
||||
|
||||
void writeCtorBody(raw_ostream &OS) const override {
|
||||
OS << " if (!" << getUpperName() << ".empty())\n";
|
||||
OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
|
||||
OS << " if (!" << getUpperName() << ".empty())\n";
|
||||
OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
|
||||
<< ".data(), " << getLowerName() << "Length);\n";
|
||||
}
|
||||
|
||||
|
@ -691,8 +691,8 @@ namespace {
|
|||
}
|
||||
|
||||
void writeCtorBody(raw_ostream &OS) const override {
|
||||
OS << " std::copy(" << getUpperName() << ", " << getUpperName()
|
||||
<< " + " << ArgSizeName << ", " << ArgName << ");\n";
|
||||
OS << " std::copy(" << getUpperName() << ", " << getUpperName() << " + "
|
||||
<< ArgSizeName << ", " << ArgName << ");\n";
|
||||
}
|
||||
|
||||
void writeCtorInitializers(raw_ostream &OS) const override {
|
||||
|
@ -894,37 +894,45 @@ namespace {
|
|||
OS << " }\n";
|
||||
}
|
||||
|
||||
void writeConversion(raw_ostream &OS) const {
|
||||
OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
|
||||
OS << type << " &Out) {\n";
|
||||
OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
|
||||
void writeConversion(raw_ostream &OS, bool Header) const {
|
||||
if (Header) {
|
||||
OS << " static bool ConvertStrTo" << type << "(StringRef Val, " << type
|
||||
<< " &Out);\n";
|
||||
OS << " static const char *Convert" << type << "ToStr(" << type
|
||||
<< " Val);\n";
|
||||
return;
|
||||
}
|
||||
|
||||
OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << type
|
||||
<< "(StringRef Val, " << type << " &Out) {\n";
|
||||
OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
|
||||
OS << type << ">>(Val)\n";
|
||||
for (size_t I = 0; I < enums.size(); ++I) {
|
||||
OS << " .Case(\"" << values[I] << "\", ";
|
||||
OS << " .Case(\"" << values[I] << "\", ";
|
||||
OS << getAttrName() << "Attr::" << enums[I] << ")\n";
|
||||
}
|
||||
OS << " .Default(Optional<" << type << ">());\n";
|
||||
OS << " if (R) {\n";
|
||||
OS << " Out = *R;\n return true;\n }\n";
|
||||
OS << " return false;\n";
|
||||
OS << " }\n\n";
|
||||
OS << " .Default(Optional<" << type << ">());\n";
|
||||
OS << " if (R) {\n";
|
||||
OS << " Out = *R;\n return true;\n }\n";
|
||||
OS << " return false;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
// Mapping from enumeration values back to enumeration strings isn't
|
||||
// trivial because some enumeration values have multiple named
|
||||
// enumerators, such as type_visibility(internal) and
|
||||
// type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden.
|
||||
OS << " static const char *Convert" << type << "ToStr("
|
||||
<< type << " Val) {\n"
|
||||
<< " switch(Val) {\n";
|
||||
OS << "const char *" << getAttrName() << "Attr::Convert" << type
|
||||
<< "ToStr(" << type << " Val) {\n"
|
||||
<< " switch(Val) {\n";
|
||||
SmallDenseSet<StringRef, 8> Uniques;
|
||||
for (size_t I = 0; I < enums.size(); ++I) {
|
||||
if (Uniques.insert(enums[I]).second)
|
||||
OS << " case " << getAttrName() << "Attr::" << enums[I]
|
||||
OS << " case " << getAttrName() << "Attr::" << enums[I]
|
||||
<< ": return \"" << values[I] << "\";\n";
|
||||
}
|
||||
OS << " }\n"
|
||||
<< " llvm_unreachable(\"No enumerator with that value\");\n"
|
||||
<< " }\n";
|
||||
OS << " }\n"
|
||||
<< " llvm_unreachable(\"No enumerator with that value\");\n"
|
||||
<< "}\n";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1006,33 +1014,42 @@ namespace {
|
|||
OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
|
||||
}
|
||||
|
||||
void writeConversion(raw_ostream &OS) const {
|
||||
OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
|
||||
void writeConversion(raw_ostream &OS, bool Header) const {
|
||||
if (Header) {
|
||||
OS << " static bool ConvertStrTo" << type << "(StringRef Val, " << type
|
||||
<< " &Out);\n";
|
||||
OS << " static const char *Convert" << type << "ToStr(" << type
|
||||
<< " Val);\n";
|
||||
return;
|
||||
}
|
||||
|
||||
OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << type
|
||||
<< "(StringRef Val, ";
|
||||
OS << type << " &Out) {\n";
|
||||
OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
|
||||
OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
|
||||
OS << type << ">>(Val)\n";
|
||||
for (size_t I = 0; I < enums.size(); ++I) {
|
||||
OS << " .Case(\"" << values[I] << "\", ";
|
||||
OS << " .Case(\"" << values[I] << "\", ";
|
||||
OS << getAttrName() << "Attr::" << enums[I] << ")\n";
|
||||
}
|
||||
OS << " .Default(Optional<" << type << ">());\n";
|
||||
OS << " if (R) {\n";
|
||||
OS << " Out = *R;\n return true;\n }\n";
|
||||
OS << " return false;\n";
|
||||
OS << " }\n\n";
|
||||
OS << " .Default(Optional<" << type << ">());\n";
|
||||
OS << " if (R) {\n";
|
||||
OS << " Out = *R;\n return true;\n }\n";
|
||||
OS << " return false;\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << " static const char *Convert" << type << "ToStr("
|
||||
<< type << " Val) {\n"
|
||||
<< " switch(Val) {\n";
|
||||
OS << "const char *" << getAttrName() << "Attr::Convert" << type
|
||||
<< "ToStr(" << type << " Val) {\n"
|
||||
<< " switch(Val) {\n";
|
||||
SmallDenseSet<StringRef, 8> Uniques;
|
||||
for (size_t I = 0; I < enums.size(); ++I) {
|
||||
if (Uniques.insert(enums[I]).second)
|
||||
OS << " case " << getAttrName() << "Attr::" << enums[I]
|
||||
<< ": return \"" << values[I] << "\";\n";
|
||||
OS << " case " << getAttrName() << "Attr::" << enums[I]
|
||||
<< ": return \"" << values[I] << "\";\n";
|
||||
}
|
||||
OS << " }\n"
|
||||
<< " llvm_unreachable(\"No enumerator with that value\");\n"
|
||||
<< " }\n";
|
||||
OS << " }\n"
|
||||
<< " llvm_unreachable(\"No enumerator with that value\");\n"
|
||||
<< "}\n";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1208,15 +1225,15 @@ namespace {
|
|||
{}
|
||||
|
||||
void writeCtorBody(raw_ostream &OS) const override {
|
||||
OS << " for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n"
|
||||
" ++I) {\n"
|
||||
" StringRef Ref = " << getUpperName() << "[I];\n"
|
||||
" if (!Ref.empty()) {\n"
|
||||
" char *Mem = new (Ctx, 1) char[Ref.size()];\n"
|
||||
" std::memcpy(Mem, Ref.data(), Ref.size());\n"
|
||||
" " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n"
|
||||
" }\n"
|
||||
" }\n";
|
||||
OS << " for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n"
|
||||
" ++I) {\n"
|
||||
" StringRef Ref = " << getUpperName() << "[I];\n"
|
||||
" if (!Ref.empty()) {\n"
|
||||
" char *Mem = new (Ctx, 1) char[Ref.size()];\n"
|
||||
" std::memcpy(Mem, Ref.data(), Ref.size());\n"
|
||||
" " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n"
|
||||
" }\n"
|
||||
" }\n";
|
||||
}
|
||||
|
||||
void writeValueImpl(raw_ostream &OS) const override {
|
||||
|
@ -1353,7 +1370,7 @@ static void writeDeprecatedAttrValue(raw_ostream &OS, std::string &Variety) {
|
|||
OS << " OS << \"";
|
||||
}
|
||||
|
||||
static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
|
||||
static void writeGetSpellingFunction(const Record &R, raw_ostream &OS) {
|
||||
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
|
||||
|
||||
OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
|
||||
|
@ -1377,7 +1394,7 @@ static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
|
|||
}
|
||||
|
||||
static void
|
||||
writePrettyPrintFunction(Record &R,
|
||||
writePrettyPrintFunction(const Record &R,
|
||||
const std::vector<std::unique_ptr<Argument>> &Args,
|
||||
raw_ostream &OS) {
|
||||
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
|
||||
|
@ -2231,13 +2248,8 @@ static void emitClangAttrThisIsaIdentifierArgList(RecordKeeper &Records,
|
|||
OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
|
||||
}
|
||||
|
||||
// Emits the class definitions for attributes.
|
||||
void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Attribute classes' definitions", OS);
|
||||
|
||||
OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
|
||||
OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
|
||||
|
||||
static void emitAttributes(RecordKeeper &Records, raw_ostream &OS,
|
||||
bool Header) {
|
||||
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
|
||||
ParsedAttrMap AttrMap = getParsedAttrList(Records);
|
||||
|
||||
|
@ -2271,7 +2283,10 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
Inheritable = true;
|
||||
}
|
||||
|
||||
OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
|
||||
if (Header)
|
||||
OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
|
||||
else
|
||||
OS << "\n// " << R.getName() << "Attr implementation\n\n";
|
||||
|
||||
std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
|
||||
std::vector<std::unique_ptr<Argument>> Args;
|
||||
|
@ -2281,8 +2296,10 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
bool HasFakeArg = false;
|
||||
for (const auto *ArgRecord : ArgRecords) {
|
||||
Args.emplace_back(createArgument(*ArgRecord, R.getName()));
|
||||
Args.back()->writeDeclarations(OS);
|
||||
OS << "\n\n";
|
||||
if (Header) {
|
||||
Args.back()->writeDeclarations(OS);
|
||||
OS << "\n\n";
|
||||
}
|
||||
|
||||
// For these purposes, fake takes priority over optional.
|
||||
if (Args.back()->isFake()) {
|
||||
|
@ -2292,7 +2309,8 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
}
|
||||
}
|
||||
|
||||
OS << "public:\n";
|
||||
if (Header)
|
||||
OS << "public:\n";
|
||||
|
||||
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
|
||||
|
||||
|
@ -2305,8 +2323,11 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
// This maps spelling index values to semantic Spelling enumerants.
|
||||
SemanticSpellingMap SemanticToSyntacticMap;
|
||||
|
||||
std::string SpellingEnum;
|
||||
if (!ElideSpelling)
|
||||
OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
|
||||
SpellingEnum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
|
||||
if (Header)
|
||||
OS << SpellingEnum;
|
||||
|
||||
const auto &ParsedAttrSpellingItr = llvm::find_if(
|
||||
AttrMap, [R](const std::pair<std::string, const Record *> &P) {
|
||||
|
@ -2315,9 +2336,14 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
|
||||
// Emit CreateImplicit factory methods.
|
||||
auto emitCreate = [&](bool Implicit, bool emitFake) {
|
||||
OS << " static " << R.getName() << "Attr *Create";
|
||||
if (Implicit)
|
||||
OS << "Implicit";
|
||||
if (Header)
|
||||
OS << " static ";
|
||||
OS << R.getName() << "Attr *";
|
||||
if (!Header)
|
||||
OS << R.getName() << "Attr::";
|
||||
OS << "Create";
|
||||
if (Implicit)
|
||||
OS << "Implicit";
|
||||
OS << "(";
|
||||
OS << "ASTContext &Ctx";
|
||||
for (auto const &ai : Args) {
|
||||
|
@ -2325,8 +2351,17 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
OS << ", ";
|
||||
ai->writeCtorParameters(OS);
|
||||
}
|
||||
OS << ", const AttributeCommonInfo &CommonInfo = {SourceRange{}}) {\n";
|
||||
OS << " auto *A = new (Ctx) " << R.getName();
|
||||
OS << ", const AttributeCommonInfo &CommonInfo";
|
||||
if (Header)
|
||||
OS << " = {SourceRange{}}";
|
||||
OS << ")";
|
||||
if (Header) {
|
||||
OS << ";\n";
|
||||
return;
|
||||
}
|
||||
|
||||
OS << " {\n";
|
||||
OS << " auto *A = new (Ctx) " << R.getName();
|
||||
OS << "Attr(Ctx, CommonInfo";
|
||||
for (auto const &ai : Args) {
|
||||
if (ai->isFake() && !emitFake) continue;
|
||||
|
@ -2335,18 +2370,23 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
}
|
||||
OS << ");\n";
|
||||
if (Implicit) {
|
||||
OS << " A->setImplicit(true);\n";
|
||||
OS << " A->setImplicit(true);\n";
|
||||
}
|
||||
if (Implicit || ElideSpelling) {
|
||||
OS << " if (!A->isAttributeSpellingListCalculated() && "
|
||||
OS << " if (!A->isAttributeSpellingListCalculated() && "
|
||||
"!A->getAttrName())\n";
|
||||
OS << " A->setAttributeSpellingListIndex(0);\n";
|
||||
OS << " A->setAttributeSpellingListIndex(0);\n";
|
||||
}
|
||||
OS << " return A;\n }\n\n";
|
||||
OS << " return A;\n}\n\n";
|
||||
};
|
||||
|
||||
auto emitCreateNoCI = [&](bool Implicit, bool emitFake) {
|
||||
OS <<" static " << R.getName() << "Attr *Create";
|
||||
if (Header)
|
||||
OS << " static ";
|
||||
OS << R.getName() << "Attr *";
|
||||
if (!Header)
|
||||
OS << R.getName() << "Attr::";
|
||||
OS << "Create";
|
||||
if (Implicit)
|
||||
OS << "Implicit";
|
||||
OS << "(";
|
||||
|
@ -2357,12 +2397,19 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
ai->writeCtorParameters(OS);
|
||||
}
|
||||
OS << ", SourceRange Range, AttributeCommonInfo::Syntax Syntax";
|
||||
if (!ElideSpelling)
|
||||
OS << ", " << R.getName()
|
||||
<< "Attr::Spelling S = "
|
||||
"static_cast<Spelling>(SpellingNotCalculated)";
|
||||
OS << ") {\n";
|
||||
OS << " AttributeCommonInfo I(Range, ";
|
||||
if (!ElideSpelling) {
|
||||
OS << ", " << R.getName() << "Attr::Spelling S";
|
||||
if (Header)
|
||||
OS << " = static_cast<Spelling>(SpellingNotCalculated)";
|
||||
}
|
||||
OS << ")";
|
||||
if (Header) {
|
||||
OS << ";\n";
|
||||
return;
|
||||
}
|
||||
|
||||
OS << " {\n";
|
||||
OS << " AttributeCommonInfo I(Range, ";
|
||||
|
||||
if (ParsedAttrSpellingItr != std::end(AttrMap))
|
||||
OS << "AT_" << ParsedAttrSpellingItr->first;
|
||||
|
@ -2373,7 +2420,7 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
if (!ElideSpelling)
|
||||
OS << ", S";
|
||||
OS << ");\n";
|
||||
OS << " return Create";
|
||||
OS << " return Create";
|
||||
if (Implicit)
|
||||
OS << "Implicit";
|
||||
OS << "(Ctx";
|
||||
|
@ -2383,7 +2430,7 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
ai->writeImplicitCtorArgs(OS);
|
||||
}
|
||||
OS << ", I);\n";
|
||||
OS << " }\n";
|
||||
OS << "}\n\n";
|
||||
};
|
||||
|
||||
auto emitCreates = [&](bool emitFake) {
|
||||
|
@ -2393,6 +2440,9 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
emitCreateNoCI(false, emitFake);
|
||||
};
|
||||
|
||||
if (Header)
|
||||
OS << " // Factory methods\n";
|
||||
|
||||
// Emit a CreateImplicit that takes all the arguments.
|
||||
emitCreates(true);
|
||||
|
||||
|
@ -2407,7 +2457,11 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
if (arg->isOptional()) return emitOpt;
|
||||
return true;
|
||||
};
|
||||
OS << " " << R.getName()
|
||||
if (Header)
|
||||
OS << " ";
|
||||
else
|
||||
OS << R.getName() << "Attr::";
|
||||
OS << R.getName()
|
||||
<< "Attr(ASTContext &Ctx, const AttributeCommonInfo &CommonInfo";
|
||||
OS << '\n';
|
||||
for (auto const &ai : Args) {
|
||||
|
@ -2417,8 +2471,12 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
OS << "\n";
|
||||
}
|
||||
|
||||
OS << " )\n";
|
||||
OS << " : " << SuperName << "(Ctx, CommonInfo, ";
|
||||
OS << " )";
|
||||
if (Header) {
|
||||
OS << ";\n";
|
||||
return;
|
||||
}
|
||||
OS << "\n : " << SuperName << "(Ctx, CommonInfo, ";
|
||||
OS << "attr::" << R.getName() << ", "
|
||||
<< (R.getValueAsBit("LateParsed") ? "true" : "false");
|
||||
if (Inheritable) {
|
||||
|
@ -2444,9 +2502,12 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
if (!shouldEmitArg(ai)) continue;
|
||||
ai->writeCtorBody(OS);
|
||||
}
|
||||
OS << " }\n\n";
|
||||
OS << "}\n\n";
|
||||
};
|
||||
|
||||
if (Header)
|
||||
OS << "\n // Constructors\n";
|
||||
|
||||
// Emit a constructor that includes all the arguments.
|
||||
// This is necessary for cloning.
|
||||
emitCtor(true, true);
|
||||
|
@ -2459,43 +2520,84 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
if (HasOptArg)
|
||||
emitCtor(false, false);
|
||||
|
||||
OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
|
||||
OS << " void printPretty(raw_ostream &OS,\n"
|
||||
<< " const PrintingPolicy &Policy) const;\n";
|
||||
OS << " const char *getSpelling() const;\n";
|
||||
if (Header) {
|
||||
OS << '\n';
|
||||
OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
|
||||
OS << " void printPretty(raw_ostream &OS,\n"
|
||||
<< " const PrintingPolicy &Policy) const;\n";
|
||||
OS << " const char *getSpelling() const;\n";
|
||||
}
|
||||
|
||||
if (!ElideSpelling) {
|
||||
assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
|
||||
OS << " Spelling getSemanticSpelling() const {\n";
|
||||
WriteSemanticSpellingSwitch("getAttributeSpellingListIndex()",
|
||||
SemanticToSyntacticMap, OS);
|
||||
OS << " }\n";
|
||||
if (Header)
|
||||
OS << " Spelling getSemanticSpelling() const;\n";
|
||||
else {
|
||||
OS << R.getName() << "Attr::Spelling " << R.getName()
|
||||
<< "Attr::getSemanticSpelling() const {\n";
|
||||
WriteSemanticSpellingSwitch("getAttributeSpellingListIndex()",
|
||||
SemanticToSyntacticMap, OS);
|
||||
OS << "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
writeAttrAccessorDefinition(R, OS);
|
||||
if (Header)
|
||||
writeAttrAccessorDefinition(R, OS);
|
||||
|
||||
for (auto const &ai : Args) {
|
||||
ai->writeAccessors(OS);
|
||||
if (Header) {
|
||||
ai->writeAccessors(OS);
|
||||
} else {
|
||||
ai->writeAccessorDefinitions(OS);
|
||||
}
|
||||
OS << "\n\n";
|
||||
|
||||
// Don't write conversion routines for fake arguments.
|
||||
if (ai->isFake()) continue;
|
||||
|
||||
if (ai->isEnumArg())
|
||||
static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);
|
||||
static_cast<const EnumArgument *>(ai.get())->writeConversion(OS,
|
||||
Header);
|
||||
else if (ai->isVariadicEnumArg())
|
||||
static_cast<const VariadicEnumArgument *>(ai.get())
|
||||
->writeConversion(OS);
|
||||
static_cast<const VariadicEnumArgument *>(ai.get())->writeConversion(
|
||||
OS, Header);
|
||||
}
|
||||
|
||||
OS << R.getValueAsString("AdditionalMembers");
|
||||
OS << "\n\n";
|
||||
if (Header) {
|
||||
OS << R.getValueAsString("AdditionalMembers");
|
||||
OS << "\n\n";
|
||||
|
||||
OS << " static bool classof(const Attr *A) { return A->getKind() == "
|
||||
<< "attr::" << R.getName() << "; }\n";
|
||||
OS << " static bool classof(const Attr *A) { return A->getKind() == "
|
||||
<< "attr::" << R.getName() << "; }\n";
|
||||
|
||||
OS << "};\n\n";
|
||||
OS << "};\n\n";
|
||||
} else {
|
||||
OS << R.getName() << "Attr *" << R.getName()
|
||||
<< "Attr::clone(ASTContext &C) const {\n";
|
||||
OS << " auto *A = new (C) " << R.getName() << "Attr(C, *this";
|
||||
for (auto const &ai : Args) {
|
||||
OS << ", ";
|
||||
ai->writeCloneArgs(OS);
|
||||
}
|
||||
OS << ");\n";
|
||||
OS << " A->Inherited = Inherited;\n";
|
||||
OS << " A->IsPackExpansion = IsPackExpansion;\n";
|
||||
OS << " A->setImplicit(Implicit);\n";
|
||||
OS << " return A;\n}\n\n";
|
||||
|
||||
writePrettyPrintFunction(R, Args, OS);
|
||||
writeGetSpellingFunction(R, OS);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Emits the class definitions for attributes.
|
||||
void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Attribute classes' definitions", OS);
|
||||
|
||||
OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
|
||||
OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
|
||||
|
||||
emitAttributes(Records, OS, true);
|
||||
|
||||
OS << "#endif // LLVM_CLANG_ATTR_CLASSES_INC\n";
|
||||
}
|
||||
|
@ -2504,38 +2606,9 @@ void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
|
|||
void clang::EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Attribute classes' member function definitions", OS);
|
||||
|
||||
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
|
||||
emitAttributes(Records, OS, false);
|
||||
|
||||
for (auto *Attr : Attrs) {
|
||||
Record &R = *Attr;
|
||||
|
||||
if (!R.getValueAsBit("ASTNode"))
|
||||
continue;
|
||||
|
||||
std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
|
||||
std::vector<std::unique_ptr<Argument>> Args;
|
||||
for (const auto *Arg : ArgRecords)
|
||||
Args.emplace_back(createArgument(*Arg, R.getName()));
|
||||
|
||||
for (auto const &ai : Args)
|
||||
ai->writeAccessorDefinitions(OS);
|
||||
|
||||
OS << R.getName() << "Attr *" << R.getName()
|
||||
<< "Attr::clone(ASTContext &C) const {\n";
|
||||
OS << " auto *A = new (C) " << R.getName() << "Attr(C, *this";
|
||||
for (auto const &ai : Args) {
|
||||
OS << ", ";
|
||||
ai->writeCloneArgs(OS);
|
||||
}
|
||||
OS << ");\n";
|
||||
OS << " A->Inherited = Inherited;\n";
|
||||
OS << " A->IsPackExpansion = IsPackExpansion;\n";
|
||||
OS << " A->setImplicit(Implicit);\n";
|
||||
OS << " return A;\n}\n\n";
|
||||
|
||||
writePrettyPrintFunction(R, Args, OS);
|
||||
writeGetSpellingFunction(R, OS);
|
||||
}
|
||||
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
|
||||
|
||||
// Instead of relying on virtual dispatch we just create a huge dispatch
|
||||
// switch. This is both smaller and faster than virtual functions.
|
||||
|
|
Loading…
Reference in New Issue