| //===- RecordVisitor.cpp --------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// | |
| /// Implements the TAPI Record Visitor. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/TextAPI/RecordVisitor.h" | |
| using namespace llvm; | |
| using namespace llvm::MachO; | |
| RecordVisitor::~RecordVisitor() = default; | |
| void RecordVisitor::visitObjCInterface(const ObjCInterfaceRecord &) {} | |
| void RecordVisitor::visitObjCCategory(const ObjCCategoryRecord &) {} | |
| static bool shouldSkipRecord(const Record &R, const bool RecordUndefs) { | |
| if (R.isExported()) | |
| return false; | |
| // Skip non exported symbols unless for flat namespace libraries. | |
| return !(RecordUndefs && R.isUndefined()); | |
| } | |
| void SymbolConverter::visitGlobal(const GlobalRecord &GR) { | |
| 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, | |
| StringRef ContainerName) { | |
| for (auto *IV : IVars) { | |
| if (shouldSkipRecord(*IV, RecordUndefs)) | |
| continue; | |
| std::string Name = | |
| ObjCIVarRecord::createScopedName(ContainerName, IV->getName()); | |
| Symbols->addGlobal(EncodeKind::ObjectiveCInstanceVariable, Name, | |
| IV->getFlags(), Targ); | |
| } | |
| } | |
| void SymbolConverter::visitObjCInterface(const ObjCInterfaceRecord &ObjCR) { | |
| if (!shouldSkipRecord(ObjCR, RecordUndefs)) { | |
| 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()); | |
| for (const auto *Cat : ObjCR.getObjCCategories()) | |
| addIVars(Cat->getObjCIVars(), ObjCR.getName()); | |
| } | |
| void SymbolConverter::visitObjCCategory(const ObjCCategoryRecord &Cat) { | |
| addIVars(Cat.getObjCIVars(), Cat.getSuperClassName()); | |
| } |