[TableGen] Only store direct superclasses in Record (#123072)

In Record only store the direct superclasses instead of all
superclasses. getSuperClasses recurses to find all superclasses when
necessary.

This gives a small reduction in memory usage. On lib/Target/X86/X86.td I
measured about 2.0% reduction in total bytes allocated (measured by
valgrind) and 1.3% reduction in peak memory usage (measured by
/usr/bin/time -v).

---------

Co-authored-by: Min-Yih Hsu <min@myhsu.dev>
This commit is contained in:
Jay Foad 2025-04-24 18:57:51 +01:00 committed by GitHub
parent 6e3b16bec3
commit 2bc6f9d4b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 121 additions and 145 deletions

View File

@ -1526,7 +1526,8 @@ createArgument(const Record &Arg, StringRef Attr,
if (!Ptr) { if (!Ptr) {
// Search in reverse order so that the most-derived type is handled first. // Search in reverse order so that the most-derived type is handled first.
for (const auto &[Base, _] : reverse(Search->getSuperClasses())) { std::vector<const Record *> SCs = Search->getSuperClasses();
for (const Record *Base : reverse(SCs)) {
if ((Ptr = createArgument(Arg, Attr, Base))) if ((Ptr = createArgument(Arg, Attr, Base)))
break; break;
} }
@ -1856,17 +1857,16 @@ static LateAttrParseKind getLateAttrParseKind(const Record *Attr) {
auto *LAPK = Attr->getValueAsDef(LateParsedStr); auto *LAPK = Attr->getValueAsDef(LateParsedStr);
// Typecheck the `LateParsed` field. // Typecheck the `LateParsed` field.
SmallVector<const Record *, 1> SuperClasses; if (LAPK->getDirectSuperClasses().size() != 1)
LAPK->getDirectSuperClasses(SuperClasses);
if (SuperClasses.size() != 1)
PrintFatalError(Attr, "Field `" + Twine(LateParsedStr) + PrintFatalError(Attr, "Field `" + Twine(LateParsedStr) +
"`should only have one super class"); "`should only have one super class");
if (SuperClasses[0]->getName() != LateAttrParseKindStr) const Record *SuperClass = LAPK->getDirectSuperClasses()[0].first;
if (SuperClass->getName() != LateAttrParseKindStr)
PrintFatalError( PrintFatalError(
Attr, "Field `" + Twine(LateParsedStr) + "`should only have type `" + Attr, "Field `" + Twine(LateParsedStr) + "`should only have type `" +
Twine(LateAttrParseKindStr) + "` but found type `" + Twine(LateAttrParseKindStr) + "` but found type `" +
SuperClasses[0]->getName() + "`"); SuperClass->getName() + "`");
// Get Kind and verify the enum name matches the name in `Attr.td`. // Get Kind and verify the enum name matches the name in `Attr.td`.
unsigned Kind = LAPK->getValueAsInt(KindFieldStr); unsigned Kind = LAPK->getValueAsInt(KindFieldStr);
@ -2465,8 +2465,8 @@ static void emitStringSwitchCases(std::map<StringRef, FSIVecTy> &Map,
} }
static bool isTypeArgument(const Record *Arg) { static bool isTypeArgument(const Record *Arg) {
return !Arg->getSuperClasses().empty() && return !Arg->getDirectSuperClasses().empty() &&
Arg->getSuperClasses().back().first->getName() == "TypeArgument"; Arg->getDirectSuperClasses().back().first->getName() == "TypeArgument";
} }
/// Emits the first-argument-is-type property for attributes. /// Emits the first-argument-is-type property for attributes.
@ -2507,8 +2507,9 @@ static void emitClangAttrArgContextList(const RecordKeeper &Records,
} }
static bool isIdentifierArgument(const Record *Arg) { static bool isIdentifierArgument(const Record *Arg) {
return !Arg->getSuperClasses().empty() && return !Arg->getDirectSuperClasses().empty() &&
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) StringSwitch<bool>(
Arg->getDirectSuperClasses().back().first->getName())
.Case("IdentifierArgument", true) .Case("IdentifierArgument", true)
.Case("EnumArgument", true) .Case("EnumArgument", true)
.Case("VariadicEnumArgument", true) .Case("VariadicEnumArgument", true)
@ -2516,33 +2517,35 @@ static bool isIdentifierArgument(const Record *Arg) {
} }
static bool isVariadicIdentifierArgument(const Record *Arg) { static bool isVariadicIdentifierArgument(const Record *Arg) {
return !Arg->getSuperClasses().empty() && return !Arg->getDirectSuperClasses().empty() &&
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) StringSwitch<bool>(
Arg->getDirectSuperClasses().back().first->getName())
.Case("VariadicIdentifierArgument", true) .Case("VariadicIdentifierArgument", true)
.Case("VariadicParamOrParamIdxArgument", true) .Case("VariadicParamOrParamIdxArgument", true)
.Default(false); .Default(false);
} }
static bool isVariadicExprArgument(const Record *Arg) { static bool isVariadicExprArgument(const Record *Arg) {
return !Arg->getSuperClasses().empty() && return !Arg->getDirectSuperClasses().empty() &&
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) StringSwitch<bool>(
Arg->getDirectSuperClasses().back().first->getName())
.Case("VariadicExprArgument", true) .Case("VariadicExprArgument", true)
.Default(false); .Default(false);
} }
static bool isStringLiteralArgument(const Record *Arg) { static bool isStringLiteralArgument(const Record *Arg) {
if (Arg->getSuperClasses().empty()) if (Arg->getDirectSuperClasses().empty())
return false; return false;
StringRef ArgKind = Arg->getSuperClasses().back().first->getName(); StringRef ArgKind = Arg->getDirectSuperClasses().back().first->getName();
if (ArgKind == "EnumArgument") if (ArgKind == "EnumArgument")
return Arg->getValueAsBit("IsString"); return Arg->getValueAsBit("IsString");
return ArgKind == "StringArgument"; return ArgKind == "StringArgument";
} }
static bool isVariadicStringLiteralArgument(const Record *Arg) { static bool isVariadicStringLiteralArgument(const Record *Arg) {
if (Arg->getSuperClasses().empty()) if (Arg->getDirectSuperClasses().empty())
return false; return false;
StringRef ArgKind = Arg->getSuperClasses().back().first->getName(); StringRef ArgKind = Arg->getDirectSuperClasses().back().first->getName();
if (ArgKind == "VariadicEnumArgument") if (ArgKind == "VariadicEnumArgument")
return Arg->getValueAsBit("IsString"); return Arg->getValueAsBit("IsString");
return ArgKind == "VariadicStringArgument"; return ArgKind == "VariadicStringArgument";
@ -2631,8 +2634,9 @@ static void emitClangAttrStrictIdentifierArgList(const RecordKeeper &Records,
} }
static bool keywordThisIsaIdentifierInArgument(const Record *Arg) { static bool keywordThisIsaIdentifierInArgument(const Record *Arg) {
return !Arg->getSuperClasses().empty() && return !Arg->getDirectSuperClasses().empty() &&
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) StringSwitch<bool>(
Arg->getDirectSuperClasses().back().first->getName())
.Case("VariadicParamOrParamIdxArgument", true) .Case("VariadicParamOrParamIdxArgument", true)
.Default(false); .Default(false);
} }
@ -2718,11 +2722,11 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS,
if (!R.getValueAsBit("ASTNode")) if (!R.getValueAsBit("ASTNode"))
continue; continue;
ArrayRef<std::pair<const Record *, SMRange>> Supers = R.getSuperClasses(); std::vector<const Record *> Supers = R.getSuperClasses();
assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
std::string SuperName; std::string SuperName;
bool Inheritable = false; bool Inheritable = false;
for (const auto &[R, _] : reverse(Supers)) { for (const Record *R : reverse(Supers)) {
if (R->getName() != "TargetSpecificAttr" && if (R->getName() != "TargetSpecificAttr" &&
R->getName() != "DeclOrTypeAttr" && SuperName.empty()) R->getName() != "DeclOrTypeAttr" && SuperName.empty())
SuperName = R->getName().str(); SuperName = R->getName().str();
@ -3419,10 +3423,10 @@ namespace {
AttrClass *findSuperClass(const Record *R) const { AttrClass *findSuperClass(const Record *R) const {
// TableGen flattens the superclass list, so we just need to walk it // TableGen flattens the superclass list, so we just need to walk it
// in reverse. // in reverse.
auto SuperClasses = R->getSuperClasses(); std::vector<const Record *> SuperClasses = R->getSuperClasses();
for (signed i = 0, e = SuperClasses.size(); i != e; ++i) { for (const Record *R : reverse(SuperClasses)) {
auto SuperClass = findClassByRecord(SuperClasses[e - i - 1].first); if (AttrClass *SuperClass = findClassByRecord(R))
if (SuperClass) return SuperClass; return SuperClass;
} }
return nullptr; return nullptr;
} }
@ -4661,8 +4665,9 @@ static void GenerateHandleDeclAttribute(const Record &Attr, raw_ostream &OS) {
} }
static bool isParamExpr(const Record *Arg) { static bool isParamExpr(const Record *Arg) {
return !Arg->getSuperClasses().empty() && return !Arg->getDirectSuperClasses().empty() &&
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) StringSwitch<bool>(
Arg->getDirectSuperClasses().back().first->getName())
.Case("ExprArgument", true) .Case("ExprArgument", true)
.Case("VariadicExprArgument", true) .Case("VariadicExprArgument", true)
.Default(false); .Default(false);
@ -4785,7 +4790,7 @@ void EmitClangAttrParsedAttrImpl(const RecordKeeper &Records, raw_ostream &OS) {
if (Arg->getValueAsBitOrUnset("Fake", UnusedUnset)) if (Arg->getValueAsBitOrUnset("Fake", UnusedUnset))
continue; continue;
ArgNames.push_back(Arg->getValueAsString("Name").str()); ArgNames.push_back(Arg->getValueAsString("Name").str());
for (const auto &[Class, _] : Arg->getSuperClasses()) { for (const Record *Class : Arg->getSuperClasses()) {
if (Class->getName().starts_with("Variadic")) { if (Class->getName().starts_with("Variadic")) {
ArgNames.back().append("..."); ArgNames.back().append("...");
break; break;

View File

@ -2029,8 +2029,8 @@ void NeonEmitter::createIntrinsic(const Record *R,
std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types); std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types);
ClassKind CK = ClassNone; ClassKind CK = ClassNone;
if (R->getSuperClasses().size() >= 2) if (!R->getDirectSuperClasses().empty())
CK = ClassMap[R->getSuperClasses()[1].first]; CK = ClassMap[R->getDirectSuperClasses()[0].first];
std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs; std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs;
if (!CartesianProductWith.empty()) { if (!CartesianProductWith.empty()) {

View File

@ -610,29 +610,28 @@ functions returns null.
Getting Record Superclasses Getting Record Superclasses
=========================== ===========================
The ``Record`` class provides a function to obtain the superclasses of a The ``Record`` class provides a function to obtain the direct superclasses
record. It is named ``getSuperClasses`` and returns an ``ArrayRef`` of an of a record. It is named ``getDirectSuperClasses`` and returns an
array of ``std::pair`` pairs. The superclasses are in post-order: the order ``ArrayRef`` of an array of ``std::pair`` pairs. Each pair consists of a
in which the superclasses were visited while copying their fields into the pointer to the ``Record`` instance for a superclass record and an instance
record. Each pair consists of a pointer to the ``Record`` instance for a of the ``SMRange`` class. The range indicates the source file locations of
superclass record and an instance of the ``SMRange`` class. The range the beginning and end of the class definition.
indicates the source file locations of the beginning and end of the class
definition.
This example obtains the superclasses of the ``Prototype`` record and then This example obtains the direct superclasses of the ``Prototype`` record and
iterates over the pairs in the returned array. then iterates over the pairs in the returned array.
.. code-block:: text .. code-block:: text
ArrayRef<std::pair<const Record *, SMRange>> ArrayRef<std::pair<const Record *, SMRange>>
Superclasses = Prototype->getSuperClasses(); Superclasses = Prototype->getDirectSuperClasses();
for (const auto &SuperPair : Superclasses) { for (const auto &[Super, Range] : Superclasses) {
... ...
} }
The ``Record`` class also provides a function, ``getDirectSuperClasses``, to The ``Record`` class also provides a function, ``getSuperClasses``, to
append the *direct* superclasses of a record to a given vector of type return a vector of *all* superclasses of a record. The superclasses are in
``SmallVectorImpl<Record *>``. post-order: the order in which the superclasses were visited while copying
their fields into the record.
Emitting Text to the Output Stream Emitting Text to the Output Stream
================================== ==================================

View File

@ -1667,9 +1667,9 @@ private:
SmallVector<AssertionInfo, 0> Assertions; SmallVector<AssertionInfo, 0> Assertions;
SmallVector<DumpInfo, 0> Dumps; SmallVector<DumpInfo, 0> Dumps;
// All superclasses in the inheritance forest in post-order (yes, it // Direct superclasses, which are roots of the inheritance forest (yes, it
// must be a forest; diamond-shaped inheritance is not allowed). // must be a forest; diamond-shaped inheritance is not allowed).
SmallVector<std::pair<const Record *, SMRange>, 0> SuperClasses; SmallVector<std::pair<const Record *, SMRange>, 0> DirectSuperClasses;
// Tracks Record instances. Not owned by Record. // Tracks Record instances. Not owned by Record.
RecordKeeper &TrackedRecords; RecordKeeper &TrackedRecords;
@ -1703,8 +1703,9 @@ public:
Record(const Record &O) Record(const Record &O)
: Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), : Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
Values(O.Values), Assertions(O.Assertions), Values(O.Values), Assertions(O.Assertions),
SuperClasses(O.SuperClasses), TrackedRecords(O.TrackedRecords), DirectSuperClasses(O.DirectSuperClasses),
ID(getNewUID(O.getRecords())), Kind(O.Kind) {} TrackedRecords(O.TrackedRecords), ID(getNewUID(O.getRecords())),
Kind(O.Kind) {}
static unsigned getNewUID(RecordKeeper &RK); static unsigned getNewUID(RecordKeeper &RK);
@ -1755,15 +1756,30 @@ public:
ArrayRef<AssertionInfo> getAssertions() const { return Assertions; } ArrayRef<AssertionInfo> getAssertions() const { return Assertions; }
ArrayRef<DumpInfo> getDumps() const { return Dumps; } ArrayRef<DumpInfo> getDumps() const { return Dumps; }
ArrayRef<std::pair<const Record *, SMRange>> getSuperClasses() const { /// Append all superclasses in post-order to \p Classes.
return SuperClasses; void getSuperClasses(std::vector<const Record *> &Classes) const {
for (const Record *SC : make_first_range(DirectSuperClasses)) {
SC->getSuperClasses(Classes);
Classes.push_back(SC);
}
}
/// Return all superclasses in post-order.
std::vector<const Record *> getSuperClasses() const {
std::vector<const Record *> Classes;
getSuperClasses(Classes);
return Classes;
} }
/// Determine whether this record has the specified direct superclass. /// Determine whether this record has the specified direct superclass.
bool hasDirectSuperClass(const Record *SuperClass) const; bool hasDirectSuperClass(const Record *SuperClass) const {
return is_contained(make_first_range(DirectSuperClasses), SuperClass);
}
/// Append the direct superclasses of this record to Classes. /// Return the direct superclasses of this record.
void getDirectSuperClasses(SmallVectorImpl<const Record *> &Classes) const; ArrayRef<std::pair<const Record *, SMRange>> getDirectSuperClasses() const {
return DirectSuperClasses;
}
bool isTemplateArg(const Init *Name) const { bool isTemplateArg(const Init *Name) const {
return llvm::is_contained(TemplateArgs, Name); return llvm::is_contained(TemplateArgs, Name);
@ -1831,29 +1847,32 @@ public:
void checkUnusedTemplateArgs(); void checkUnusedTemplateArgs();
bool isSubClassOf(const Record *R) const { bool isSubClassOf(const Record *R) const {
for (const auto &[SC, _] : SuperClasses) for (const Record *SC : make_first_range(DirectSuperClasses)) {
if (SC == R) if (SC == R || SC->isSubClassOf(R))
return true; return true;
}
return false; return false;
} }
bool isSubClassOf(StringRef Name) const { bool isSubClassOf(StringRef Name) const {
for (const auto &[SC, _] : SuperClasses) { for (const Record *SC : make_first_range(DirectSuperClasses)) {
if (const auto *SI = dyn_cast<StringInit>(SC->getNameInit())) { if (const auto *SI = dyn_cast<StringInit>(SC->getNameInit())) {
if (SI->getValue() == Name) if (SI->getValue() == Name)
return true; return true;
} else if (SC->getNameInitAsString() == Name) { } else if (SC->getNameInitAsString() == Name) {
return true; return true;
} }
if (SC->isSubClassOf(Name))
return true;
} }
return false; return false;
} }
void addSuperClass(const Record *R, SMRange Range) { void addDirectSuperClass(const Record *R, SMRange Range) {
assert(!CorrespondingDefInit && assert(!CorrespondingDefInit &&
"changing type of record after it has been referenced"); "changing type of record after it has been referenced");
assert(!isSubClassOf(R) && "Already subclassing record!"); assert(!isSubClassOf(R) && "Already subclassing record!");
SuperClasses.emplace_back(R, Range); DirectSuperClasses.emplace_back(R, Range);
} }
/// If there are any field references that refer to fields that have been /// If there are any field references that refer to fields that have been

View File

@ -152,15 +152,14 @@ void DetailedRecordsEmitter::printTemplateArgs(const Record &Rec,
// are enclosed in parentheses. // are enclosed in parentheses.
void DetailedRecordsEmitter::printSuperclasses(const Record &Rec, void DetailedRecordsEmitter::printSuperclasses(const Record &Rec,
raw_ostream &OS) { raw_ostream &OS) {
ArrayRef<std::pair<const Record *, SMRange>> Superclasses = std::vector<const Record *> Superclasses = Rec.getSuperClasses();
Rec.getSuperClasses();
if (Superclasses.empty()) { if (Superclasses.empty()) {
OS << " Superclasses: (none)\n"; OS << " Superclasses: (none)\n";
return; return;
} }
OS << " Superclasses:"; OS << " Superclasses:";
for (const auto &[ClassRec, Loc] : Superclasses) { for (const Record *ClassRec : Superclasses) {
if (Rec.hasDirectSuperClass(ClassRec)) if (Rec.hasDirectSuperClass(ClassRec))
OS << formatv(" {0}", ClassRec->getNameInitAsString()); OS << formatv(" {0}", ClassRec->getNameInitAsString());
else else

View File

@ -151,7 +151,7 @@ void JSONEmitter::run(raw_ostream &OS) {
json::Array SuperClasses; json::Array SuperClasses;
// Add this def to the instance list for each of its superclasses. // Add this def to the instance list for each of its superclasses.
for (const auto &[SuperClass, Loc] : Def->getSuperClasses()) { for (const Record *SuperClass : Def->getSuperClasses()) {
std::string SuperName = SuperClass->getNameInitAsString(); std::string SuperName = SuperClass->getNameInitAsString();
SuperClasses.push_back(SuperName); SuperClasses.push_back(SuperName);
InstanceLists[SuperName].push_back(Name); InstanceLists[SuperName].push_back(Name);

View File

@ -336,7 +336,7 @@ static const RecordRecTy *resolveRecordTypes(const RecordRecTy *T1,
if (T2->isSubClassOf(R)) { if (T2->isSubClassOf(R)) {
CommonSuperClasses.push_back(R); CommonSuperClasses.push_back(R);
} else { } else {
R->getDirectSuperClasses(Stack); append_range(Stack, make_first_range(R->getDirectSuperClasses()));
} }
} }
@ -2482,11 +2482,8 @@ const DefInit *VarDefInit::instantiate() {
NewRec->resolveReferences(R); NewRec->resolveReferences(R);
// Add superclasses. // Add superclass.
for (const auto &[SC, Loc] : Class->getSuperClasses()) NewRec->addDirectSuperClass(
NewRec->addSuperClass(SC, Loc);
NewRec->addSuperClass(
Class, SMRange(Class->getLoc().back(), Class->getLoc().back())); Class, SMRange(Class->getLoc().back(), Class->getLoc().back()));
// Resolve internal references and store in record keeper // Resolve internal references and store in record keeper
@ -2962,7 +2959,7 @@ void Record::checkName() {
const RecordRecTy *Record::getType() const { const RecordRecTy *Record::getType() const {
SmallVector<const Record *, 4> DirectSCs; SmallVector<const Record *, 4> DirectSCs;
getDirectSuperClasses(DirectSCs); append_range(DirectSCs, make_first_range(getDirectSuperClasses()));
return RecordRecTy::get(TrackedRecords, DirectSCs); return RecordRecTy::get(TrackedRecords, DirectSCs);
} }
@ -2994,35 +2991,6 @@ void Record::setName(const Init *NewName) {
// this. See TGParser::ParseDef and TGParser::ParseDefm. // this. See TGParser::ParseDef and TGParser::ParseDefm.
} }
// NOTE for the next two functions:
// Superclasses are in post-order, so the final one is a direct
// superclass. All of its transitive superclases immediately precede it,
// so we can step through the direct superclasses in reverse order.
bool Record::hasDirectSuperClass(const Record *Superclass) const {
ArrayRef<std::pair<const Record *, SMRange>> SCs = getSuperClasses();
for (int I = SCs.size() - 1; I >= 0; --I) {
const Record *SC = SCs[I].first;
if (SC == Superclass)
return true;
I -= SC->getSuperClasses().size();
}
return false;
}
void Record::getDirectSuperClasses(
SmallVectorImpl<const Record *> &Classes) const {
ArrayRef<std::pair<const Record *, SMRange>> SCs = getSuperClasses();
while (!SCs.empty()) {
const Record *SC = SCs.back().first;
SCs = SCs.drop_back(1 + SC->getSuperClasses().size());
Classes.push_back(SC);
}
}
void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) {
const Init *OldName = getNameInit(); const Init *OldName = getNameInit();
const Init *NewName = Name->resolveReferences(R); const Init *NewName = Name->resolveReferences(R);
@ -3096,10 +3064,10 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {
} }
OS << " {"; OS << " {";
ArrayRef<std::pair<const Record *, SMRange>> SC = R.getSuperClasses(); std::vector<const Record *> SCs = R.getSuperClasses();
if (!SC.empty()) { if (!SCs.empty()) {
OS << "\t//"; OS << "\t//";
for (const auto &[SC, _] : SC) for (const Record *SC : SCs)
OS << " " << SC->getNameInitAsString(); OS << " " << SC->getNameInitAsString();
} }
OS << "\n"; OS << "\n";

View File

@ -312,7 +312,7 @@ const RecVec *SetTheory::expand(const Record *Set) {
return &I->second; return &I->second;
// This is the first time we see Set. Find a suitable expander. // This is the first time we see Set. Find a suitable expander.
for (const auto &[SuperClass, Loc] : Set->getSuperClasses()) { for (const Record *SuperClass : Set->getSuperClasses()) {
// Skip unnamed superclasses. // Skip unnamed superclasses.
if (!isa<StringInit>(SuperClass->getNameInit())) if (!isa<StringInit>(SuperClass->getNameInit()))
continue; continue;

View File

@ -332,17 +332,10 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
// Since everything went well, we can now set the "superclass" list for the // Since everything went well, we can now set the "superclass" list for the
// current record. // current record.
for (const auto &[SC, Loc] : SC->getSuperClasses()) {
if (CurRec->isSubClassOf(SC))
return Error(SubClass.RefRange.Start,
"Already subclass of '" + SC->getName() + "'!\n");
CurRec->addSuperClass(SC, Loc);
}
if (CurRec->isSubClassOf(SC)) if (CurRec->isSubClassOf(SC))
return Error(SubClass.RefRange.Start, return Error(SubClass.RefRange.Start,
"Already subclass of '" + SC->getName() + "'!\n"); "Already subclass of '" + SC->getName() + "'!\n");
CurRec->addSuperClass(SC, SubClass.RefRange); CurRec->addDirectSuperClass(SC, SubClass.RefRange);
return false; return false;
} }
@ -4056,7 +4049,7 @@ bool TGParser::ParseClass() {
if (CurRec) { if (CurRec) {
// If the body was previously defined, this is an error. // If the body was previously defined, this is an error.
if (!CurRec->getValues().empty() || if (!CurRec->getValues().empty() ||
!CurRec->getSuperClasses().empty() || !CurRec->getDirectSuperClasses().empty() ||
!CurRec->getTemplateArgs().empty()) !CurRec->getTemplateArgs().empty())
return TokError("Class '" + CurRec->getNameInitAsString() + return TokError("Class '" + CurRec->getNameInitAsString() +
"' already defined"); "' already defined");

View File

@ -110,11 +110,10 @@ void CallingConvEmitter::emitCallingConv(const Record *CC, raw_ostream &O) {
for (unsigned I = 0, E = CCActions->size(); I != E; ++I) { for (unsigned I = 0, E = CCActions->size(); I != E; ++I) {
const Record *Action = CCActions->getElementAsRecord(I); const Record *Action = CCActions->getElementAsRecord(I);
SwiftAction = SwiftAction =
llvm::any_of(Action->getSuperClasses(), llvm::any_of(Action->getSuperClasses(), [](const Record *Class) {
[](const std::pair<const Record *, SMRange> &Class) { std::string Name = Class->getNameInitAsString();
std::string Name = Class.first->getNameInitAsString(); return StringRef(Name).starts_with("CCIfSwift");
return StringRef(Name).starts_with("CCIfSwift"); });
});
O << "\n"; O << "\n";
emitAction(Action, indent(2), O); emitAction(Action, indent(2), O);

View File

@ -704,8 +704,8 @@ struct TupleExpander : SetTheory::Expander {
"Register tuple redefines register '" + Name + "'."); "Register tuple redefines register '" + Name + "'.");
// Copy Proto super-classes. // Copy Proto super-classes.
for (const auto &[Super, Loc] : Proto->getSuperClasses()) for (const auto &[Super, Loc] : Proto->getDirectSuperClasses())
NewReg->addSuperClass(Super, Loc); NewReg->addDirectSuperClass(Super, Loc);
// Copy Proto fields. // Copy Proto fields.
for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) { for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) {

View File

@ -834,7 +834,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
const Record *SearchableTable = Records.getClass("SearchableTable"); const Record *SearchableTable = Records.getClass("SearchableTable");
for (auto &NameRec : Records.getClasses()) { for (auto &NameRec : Records.getClasses()) {
const Record *Class = NameRec.second.get(); const Record *Class = NameRec.second.get();
if (Class->getSuperClasses().size() != 1 || if (Class->getDirectSuperClasses().size() != 1 ||
!Class->isSubClassOf(SearchableTable)) !Class->isSubClassOf(SearchableTable))
continue; continue;

View File

@ -113,7 +113,7 @@ getBaseValue(const Record *record, const RecordVal *value) {
// On success, `record` is updated to the new parent record. // On success, `record` is updated to the new parent record.
StringRef valueName = value->getName(); StringRef valueName = value->getName();
auto findValueInSupers = [&](const Record *&record) -> const RecordVal * { auto findValueInSupers = [&](const Record *&record) -> const RecordVal * {
for (auto [parentRecord, loc] : record->getSuperClasses()) { for (const Record *parentRecord : record->getSuperClasses()) {
if (auto *newBase = parentRecord->getValue(valueName)) { if (auto *newBase = parentRecord->getValue(valueName)) {
record = parentRecord; record = parentRecord;
return newBase; return newBase;

View File

@ -72,11 +72,10 @@ static StringRef extractOmpClauseName(const Record *clause) {
assert(ompClause && "base OpenMP records expected to be defined"); assert(ompClause && "base OpenMP records expected to be defined");
StringRef clauseClassName; StringRef clauseClassName;
SmallVector<const Record *, 1> clauseSuperClasses;
clause->getDirectSuperClasses(clauseSuperClasses);
// Check if OpenMP_Clause is a direct superclass. // Check if OpenMP_Clause is a direct superclass.
for (const Record *superClass : clauseSuperClasses) { for (const Record *superClass :
llvm::make_first_range(clause->getDirectSuperClasses())) {
if (superClass == ompClause) { if (superClass == ompClause) {
clauseClassName = clause->getName(); clauseClassName = clause->getName();
break; break;
@ -85,7 +84,7 @@ static StringRef extractOmpClauseName(const Record *clause) {
// Support indirectly-inherited OpenMP_Clauses. // Support indirectly-inherited OpenMP_Clauses.
if (clauseClassName.empty()) { if (clauseClassName.empty()) {
for (auto [superClass, _] : clause->getSuperClasses()) { for (const Record *superClass : clause->getSuperClasses()) {
if (superClass->isSubClassOf(ompClause)) { if (superClass->isSubClassOf(ompClause)) {
clauseClassName = superClass->getName(); clauseClassName = superClass->getName();
break; break;
@ -214,7 +213,7 @@ static StringRef translateArgumentType(ArrayRef<SMLoc> loc,
const Record *def = cast<DefInit>(init)->getDef(); const Record *def = cast<DefInit>(init)->getDef();
llvm::StringSet<> superClasses; llvm::StringSet<> superClasses;
for (auto [sc, _] : def->getSuperClasses()) for (const Record *sc : def->getSuperClasses())
superClasses.insert(sc->getNameInitAsString()); superClasses.insert(sc->getNameInitAsString());
// Handle wrapper-style superclasses. // Handle wrapper-style superclasses.

View File

@ -115,13 +115,12 @@ Availability::Availability(const Record *def) : def(def) {
} }
StringRef Availability::getClass() const { StringRef Availability::getClass() const {
SmallVector<const Record *, 1> parentClass; if (def->getDirectSuperClasses().size() != 1) {
def->getDirectSuperClasses(parentClass);
if (parentClass.size() != 1) {
PrintFatalError(def->getLoc(), PrintFatalError(def->getLoc(),
"expected to only have one direct superclass"); "expected to only have one direct superclass");
} }
return parentClass.front()->getName(); const Record *parentClass = def->getDirectSuperClasses().front().first;
return parentClass->getName();
} }
StringRef Availability::getInterfaceClassNamespace() const { StringRef Availability::getInterfaceClassNamespace() const {
@ -205,18 +204,17 @@ static bool emitInterfaceDefs(const RecordKeeper &records, raw_ostream &os) {
auto defs = records.getAllDerivedDefinitions("Availability"); auto defs = records.getAllDerivedDefinitions("Availability");
SmallVector<const Record *, 1> handledClasses; SmallVector<const Record *, 1> handledClasses;
for (const Record *def : defs) { for (const Record *def : defs) {
SmallVector<const Record *, 1> parent; if (def->getDirectSuperClasses().size() != 1) {
def->getDirectSuperClasses(parent);
if (parent.size() != 1) {
PrintFatalError(def->getLoc(), PrintFatalError(def->getLoc(),
"expected to only have one direct superclass"); "expected to only have one direct superclass");
} }
if (llvm::is_contained(handledClasses, parent.front())) const Record *parent = def->getDirectSuperClasses().front().first;
if (llvm::is_contained(handledClasses, parent))
continue; continue;
Availability availability(def); Availability availability(def);
emitInterfaceDef(availability, os); emitInterfaceDef(availability, os);
handledClasses.push_back(parent.front()); handledClasses.push_back(parent);
} }
return false; return false;
} }
@ -294,18 +292,17 @@ static bool emitInterfaceDecls(const RecordKeeper &records, raw_ostream &os) {
auto defs = records.getAllDerivedDefinitions("Availability"); auto defs = records.getAllDerivedDefinitions("Availability");
SmallVector<const Record *, 4> handledClasses; SmallVector<const Record *, 4> handledClasses;
for (const Record *def : defs) { for (const Record *def : defs) {
SmallVector<const Record *, 1> parent; if (def->getDirectSuperClasses().size() != 1) {
def->getDirectSuperClasses(parent);
if (parent.size() != 1) {
PrintFatalError(def->getLoc(), PrintFatalError(def->getLoc(),
"expected to only have one direct superclass"); "expected to only have one direct superclass");
} }
if (llvm::is_contained(handledClasses, parent.front())) const Record *parent = def->getDirectSuperClasses().front().first;
if (llvm::is_contained(handledClasses, parent))
continue; continue;
Availability avail(def); Availability avail(def);
emitInterfaceDecl(avail, os); emitInterfaceDecl(avail, os);
handledClasses.push_back(parent.front()); handledClasses.push_back(parent);
} }
return false; return false;
} }

View File

@ -100,13 +100,11 @@ Availability::Availability(const llvm::Record *def) : def(def) {
} }
StringRef Availability::getClass() const { StringRef Availability::getClass() const {
SmallVector<const Record *, 1> parentClass; if (def->getDirectSuperClasses().size() != 1) {
def->getDirectSuperClasses(parentClass);
if (parentClass.size() != 1) {
PrintFatalError(def->getLoc(), PrintFatalError(def->getLoc(),
"expected to only have one direct superclass"); "expected to only have one direct superclass");
} }
return parentClass.front()->getName(); return def->getDirectSuperClasses().front().first->getName();
} }
StringRef Availability::getQueryFnRetType() const { StringRef Availability::getQueryFnRetType() const {