diff options
Diffstat (limited to 'llvm/lib/TextAPI')
-rw-r--r-- | llvm/lib/TextAPI/RecordVisitor.cpp | 37 | ||||
-rw-r--r-- | llvm/lib/TextAPI/RecordsSlice.cpp | 63 | ||||
-rw-r--r-- | llvm/lib/TextAPI/Symbol.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/TextAPI/SymbolSet.cpp | 19 |
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()}); } |