aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/TextAPI
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/TextAPI')
-rw-r--r--llvm/lib/TextAPI/RecordVisitor.cpp37
-rw-r--r--llvm/lib/TextAPI/RecordsSlice.cpp63
-rw-r--r--llvm/lib/TextAPI/Symbol.cpp23
-rw-r--r--llvm/lib/TextAPI/SymbolSet.cpp19
4 files changed, 106 insertions, 36 deletions
diff --git a/llvm/lib/TextAPI/RecordVisitor.cpp b/llvm/lib/TextAPI/RecordVisitor.cpp
index b049c9e..3ff6bbd 100644
--- a/llvm/lib/TextAPI/RecordVisitor.cpp
+++ b/llvm/lib/TextAPI/RecordVisitor.cpp
@@ -28,10 +28,20 @@ static bool shouldSkipRecord(const Record &R, const bool RecordUndefs) {
}
void SymbolConverter::visitGlobal(const GlobalRecord &GR) {
- auto [SymName, SymKind] = parseSymbol(GR.getName(), GR.getFlags());
+ auto [SymName, SymKind, InterfaceType] = parseSymbol(GR.getName());
if (shouldSkipRecord(GR, RecordUndefs))
return;
Symbols->addGlobal(SymKind, SymName, GR.getFlags(), Targ);
+
+ if (InterfaceType == ObjCIFSymbolKind::None) {
+ Symbols->addGlobal(SymKind, SymName, GR.getFlags(), Targ);
+ return;
+ }
+
+ // It is impossible to hold a complete ObjCInterface with a single
+ // GlobalRecord, so continue to treat this symbol a generic global.
+ Symbols->addGlobal(EncodeKind::GlobalSymbol, GR.getName(), GR.getFlags(),
+ Targ);
}
void SymbolConverter::addIVars(const ArrayRef<ObjCIVarRecord *> IVars,
@@ -48,11 +58,28 @@ void SymbolConverter::addIVars(const ArrayRef<ObjCIVarRecord *> IVars,
void SymbolConverter::visitObjCInterface(const ObjCInterfaceRecord &ObjCR) {
if (!shouldSkipRecord(ObjCR, RecordUndefs)) {
- Symbols->addGlobal(EncodeKind::ObjectiveCClass, ObjCR.getName(),
- ObjCR.getFlags(), Targ);
- if (ObjCR.hasExceptionAttribute())
- Symbols->addGlobal(EncodeKind::ObjectiveCClassEHType, ObjCR.getName(),
+ if (ObjCR.isCompleteInterface()) {
+ Symbols->addGlobal(EncodeKind::ObjectiveCClass, ObjCR.getName(),
ObjCR.getFlags(), Targ);
+ if (ObjCR.hasExceptionAttribute())
+ Symbols->addGlobal(EncodeKind::ObjectiveCClassEHType, ObjCR.getName(),
+ ObjCR.getFlags(), Targ);
+ } else {
+ // Because there is not a complete interface, visit individual symbols
+ // instead.
+ if (ObjCR.isExportedSymbol(ObjCIFSymbolKind::EHType))
+ Symbols->addGlobal(EncodeKind::GlobalSymbol,
+ (ObjC2EHTypePrefix + ObjCR.getName()).str(),
+ ObjCR.getFlags(), Targ);
+ if (ObjCR.isExportedSymbol(ObjCIFSymbolKind::Class))
+ Symbols->addGlobal(EncodeKind::GlobalSymbol,
+ (ObjC2ClassNamePrefix + ObjCR.getName()).str(),
+ ObjCR.getFlags(), Targ);
+ if (ObjCR.isExportedSymbol(ObjCIFSymbolKind::MetaClass))
+ Symbols->addGlobal(EncodeKind::GlobalSymbol,
+ (ObjC2MetaClassNamePrefix + ObjCR.getName()).str(),
+ ObjCR.getFlags(), Targ);
+ }
}
addIVars(ObjCR.getObjCIVars(), ObjCR.getName());
diff --git a/llvm/lib/TextAPI/RecordsSlice.cpp b/llvm/lib/TextAPI/RecordsSlice.cpp
index 7f6fad17..f07853e 100644
--- a/llvm/lib/TextAPI/RecordsSlice.cpp
+++ b/llvm/lib/TextAPI/RecordsSlice.cpp
@@ -22,15 +22,21 @@ using namespace llvm::MachO;
Record *RecordsSlice::addRecord(StringRef Name, SymbolFlags Flags,
GlobalRecord::Kind GV, RecordLinkage Linkage) {
// Find a specific Record type to capture.
- auto [APIName, SymKind] = parseSymbol(Name, Flags);
+ auto [APIName, SymKind, InterfaceType] = parseSymbol(Name);
Name = APIName;
switch (SymKind) {
case EncodeKind::GlobalSymbol:
return addGlobal(Name, Linkage, GV, Flags);
case EncodeKind::ObjectiveCClass:
- return addObjCInterface(Name, Linkage);
- case EncodeKind::ObjectiveCClassEHType:
- return addObjCInterface(Name, Linkage, /*HasEHType=*/true);
+ return addObjCInterface(Name, Linkage, InterfaceType);
+ case EncodeKind::ObjectiveCClassEHType: {
+ ObjCInterfaceRecord *Rec = addObjCInterface(Name, Linkage, InterfaceType);
+ // When classes without ehtype are used in try/catch blocks
+ // a weak-defined symbol is exported.
+ if ((Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined)
+ updateFlags(Rec, SymbolFlags::WeakDefined);
+ return Rec;
+ }
case EncodeKind::ObjectiveCInstanceVariable: {
auto [Super, IVar] = Name.split('.');
// Attempt to find super class.
@@ -88,6 +94,39 @@ GlobalRecord *RecordsSlice::findGlobal(StringRef Name,
return Record;
}
+RecordLinkage
+ObjCInterfaceRecord::getLinkageForSymbol(ObjCIFSymbolKind CurrType) const {
+ assert(CurrType <= ObjCIFSymbolKind::EHType &&
+ "expected single ObjCIFSymbolKind enum value");
+ if (CurrType == ObjCIFSymbolKind::Class)
+ return Linkages.Class;
+
+ if (CurrType == ObjCIFSymbolKind::MetaClass)
+ return Linkages.MetaClass;
+
+ if (CurrType == ObjCIFSymbolKind::EHType)
+ return Linkages.EHType;
+
+ llvm_unreachable("unexpected ObjCIFSymbolKind");
+}
+
+void ObjCInterfaceRecord::updateLinkageForSymbols(ObjCIFSymbolKind SymType,
+ RecordLinkage Link) {
+ if ((SymType & ObjCIFSymbolKind::Class) == ObjCIFSymbolKind::Class)
+ Linkages.Class = std::max(Link, Linkages.Class);
+ if ((SymType & ObjCIFSymbolKind::MetaClass) == ObjCIFSymbolKind::MetaClass)
+ Linkages.MetaClass = std::max(Link, Linkages.MetaClass);
+ if ((SymType & ObjCIFSymbolKind::EHType) == ObjCIFSymbolKind::EHType)
+ Linkages.EHType = std::max(Link, Linkages.EHType);
+
+ // Obj-C Classes represent multiple symbols that could have competing
+ // linkages, in this case assign the largest one, when querying the linkage of
+ // the record itself. This allows visitors pick whether they want to account
+ // for complete symbol information.
+ Linkage =
+ std::max(Linkages.Class, std::max(Linkages.MetaClass, Linkages.EHType));
+}
+
ObjCInterfaceRecord *RecordsSlice::findObjCInterface(StringRef Name) const {
return findRecord<ObjCInterfaceRecord>(Name, Classes);
}
@@ -152,21 +191,17 @@ GlobalRecord *RecordsSlice::addGlobal(StringRef Name, RecordLinkage Linkage,
ObjCInterfaceRecord *RecordsSlice::addObjCInterface(StringRef Name,
RecordLinkage Linkage,
- bool HasEHType) {
+ ObjCIFSymbolKind SymType) {
Name = copyString(Name);
auto Result = Classes.insert({Name, nullptr});
- if (Result.second) {
+ if (Result.second)
Result.first->second =
- std::make_unique<ObjCInterfaceRecord>(Name, Linkage, HasEHType);
- } else {
- // ObjC classes represent multiple symbols that could have competing
- // linkages, in those cases assign the largest one.
- if (Linkage >= RecordLinkage::Rexported)
- updateLinkage(Result.first->second.get(), Linkage);
- }
-
+ std::make_unique<ObjCInterfaceRecord>(Name, Linkage, SymType);
+ else
+ Result.first->second->updateLinkageForSymbols(SymType, Linkage);
return Result.first->second.get();
}
+
SymbolFlags Record::mergeFlags(SymbolFlags Flags, RecordLinkage Linkage) {
// Add Linkage properties into Flags.
switch (Linkage) {
diff --git a/llvm/lib/TextAPI/Symbol.cpp b/llvm/lib/TextAPI/Symbol.cpp
index e67627e..c899821 100644
--- a/llvm/lib/TextAPI/Symbol.cpp
+++ b/llvm/lib/TextAPI/Symbol.cpp
@@ -72,30 +72,23 @@ bool Symbol::operator==(const Symbol &O) const {
std::tie(O.Name, O.Kind, O.Targets, RHSFlags);
}
-SimpleSymbol parseSymbol(StringRef SymName, const SymbolFlags Flags) {
+SimpleSymbol parseSymbol(StringRef SymName) {
if (SymName.starts_with(ObjC1ClassNamePrefix))
return {SymName.drop_front(ObjC1ClassNamePrefix.size()),
- EncodeKind::ObjectiveCClass};
+ EncodeKind::ObjectiveCClass, ObjCIFSymbolKind::Class};
if (SymName.starts_with(ObjC2ClassNamePrefix))
return {SymName.drop_front(ObjC2ClassNamePrefix.size()),
- EncodeKind::ObjectiveCClass};
+ EncodeKind::ObjectiveCClass, ObjCIFSymbolKind::Class};
if (SymName.starts_with(ObjC2MetaClassNamePrefix))
return {SymName.drop_front(ObjC2MetaClassNamePrefix.size()),
- EncodeKind::ObjectiveCClass};
- if (SymName.starts_with(ObjC2EHTypePrefix)) {
- // When classes without ehtype are used in try/catch blocks
- // a weak-defined symbol is exported. In those cases, treat these as a
- // global instead.
- if ((Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined)
- return {SymName, EncodeKind::GlobalSymbol};
+ EncodeKind::ObjectiveCClass, ObjCIFSymbolKind::MetaClass};
+ if (SymName.starts_with(ObjC2EHTypePrefix))
return {SymName.drop_front(ObjC2EHTypePrefix.size()),
- EncodeKind::ObjectiveCClassEHType};
- }
-
+ EncodeKind::ObjectiveCClassEHType, ObjCIFSymbolKind::EHType};
if (SymName.starts_with(ObjC2IVarPrefix))
return {SymName.drop_front(ObjC2IVarPrefix.size()),
- EncodeKind::ObjectiveCInstanceVariable};
- return {SymName, EncodeKind::GlobalSymbol};
+ EncodeKind::ObjectiveCInstanceVariable, ObjCIFSymbolKind::None};
+ return {SymName, EncodeKind::GlobalSymbol, ObjCIFSymbolKind::None};
}
} // end namespace MachO.
diff --git a/llvm/lib/TextAPI/SymbolSet.cpp b/llvm/lib/TextAPI/SymbolSet.cpp
index 0cbfa2f..2e0b416 100644
--- a/llvm/lib/TextAPI/SymbolSet.cpp
+++ b/llvm/lib/TextAPI/SymbolSet.cpp
@@ -28,6 +28,21 @@ Symbol *SymbolSet::addGlobal(EncodeKind Kind, StringRef Name, SymbolFlags Flags,
return Sym;
}
-const Symbol *SymbolSet::findSymbol(EncodeKind Kind, StringRef Name) const {
- return Symbols.lookup({Kind, Name});
+const Symbol *SymbolSet::findSymbol(EncodeKind Kind, StringRef Name,
+ ObjCIFSymbolKind ObjCIF) const {
+ if (auto result = Symbols.lookup({Kind, Name}))
+ return result;
+ if ((ObjCIF == ObjCIFSymbolKind::None) || (ObjCIF > ObjCIFSymbolKind::EHType))
+ return nullptr;
+ assert(ObjCIF <= ObjCIFSymbolKind::EHType &&
+ "expected single ObjCIFSymbolKind enum value");
+ // Non-complete ObjC Interfaces are represented as global symbols.
+ if (ObjCIF == ObjCIFSymbolKind::Class)
+ return Symbols.lookup(
+ {EncodeKind::GlobalSymbol, (ObjC2ClassNamePrefix + Name).str()});
+ if (ObjCIF == ObjCIFSymbolKind::MetaClass)
+ return Symbols.lookup(
+ {EncodeKind::GlobalSymbol, (ObjC2MetaClassNamePrefix + Name).str()});
+ return Symbols.lookup(
+ {EncodeKind::GlobalSymbol, (ObjC2EHTypePrefix + Name).str()});
}