| 1 | //===- RecordVisitor.cpp --------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// Implements the TAPI Record Visitor. |
| 10 | /// |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "llvm/TextAPI/RecordVisitor.h" |
| 14 | |
| 15 | using namespace llvm; |
| 16 | using namespace llvm::MachO; |
| 17 | |
| 18 | RecordVisitor::~RecordVisitor() {} |
| 19 | void RecordVisitor::visitObjCInterface(const ObjCInterfaceRecord &) {} |
| 20 | void RecordVisitor::visitObjCCategory(const ObjCCategoryRecord &) {} |
| 21 | |
| 22 | static bool shouldSkipRecord(const Record &R, const bool RecordUndefs) { |
| 23 | if (R.isExported()) |
| 24 | return false; |
| 25 | |
| 26 | // Skip non exported symbols unless for flat namespace libraries. |
| 27 | return !(RecordUndefs && R.isUndefined()); |
| 28 | } |
| 29 | |
| 30 | void SymbolConverter::visitGlobal(const GlobalRecord &GR) { |
| 31 | auto [SymName, SymKind, InterfaceType] = parseSymbol(SymName: GR.getName()); |
| 32 | if (shouldSkipRecord(R: GR, RecordUndefs)) |
| 33 | return; |
| 34 | Symbols->addGlobal(Kind: SymKind, Name: SymName, Flags: GR.getFlags(), Targ); |
| 35 | |
| 36 | if (InterfaceType == ObjCIFSymbolKind::None) { |
| 37 | Symbols->addGlobal(Kind: SymKind, Name: SymName, Flags: GR.getFlags(), Targ); |
| 38 | return; |
| 39 | } |
| 40 | |
| 41 | // It is impossible to hold a complete ObjCInterface with a single |
| 42 | // GlobalRecord, so continue to treat this symbol a generic global. |
| 43 | Symbols->addGlobal(Kind: EncodeKind::GlobalSymbol, Name: GR.getName(), Flags: GR.getFlags(), |
| 44 | Targ); |
| 45 | } |
| 46 | |
| 47 | void SymbolConverter::addIVars(const ArrayRef<ObjCIVarRecord *> IVars, |
| 48 | StringRef ContainerName) { |
| 49 | for (auto *IV : IVars) { |
| 50 | if (shouldSkipRecord(R: *IV, RecordUndefs)) |
| 51 | continue; |
| 52 | std::string Name = |
| 53 | ObjCIVarRecord::createScopedName(SuperClass: ContainerName, IVar: IV->getName()); |
| 54 | Symbols->addGlobal(Kind: EncodeKind::ObjectiveCInstanceVariable, Name, |
| 55 | Flags: IV->getFlags(), Targ); |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | void SymbolConverter::visitObjCInterface(const ObjCInterfaceRecord &ObjCR) { |
| 60 | if (!shouldSkipRecord(R: ObjCR, RecordUndefs)) { |
| 61 | if (ObjCR.isCompleteInterface()) { |
| 62 | Symbols->addGlobal(Kind: EncodeKind::ObjectiveCClass, Name: ObjCR.getName(), |
| 63 | Flags: ObjCR.getFlags(), Targ); |
| 64 | if (ObjCR.hasExceptionAttribute()) |
| 65 | Symbols->addGlobal(Kind: EncodeKind::ObjectiveCClassEHType, Name: ObjCR.getName(), |
| 66 | Flags: ObjCR.getFlags(), Targ); |
| 67 | } else { |
| 68 | // Because there is not a complete interface, visit individual symbols |
| 69 | // instead. |
| 70 | if (ObjCR.isExportedSymbol(CurrType: ObjCIFSymbolKind::EHType)) |
| 71 | Symbols->addGlobal(Kind: EncodeKind::GlobalSymbol, |
| 72 | Name: (ObjC2EHTypePrefix + ObjCR.getName()).str(), |
| 73 | Flags: ObjCR.getFlags(), Targ); |
| 74 | if (ObjCR.isExportedSymbol(CurrType: ObjCIFSymbolKind::Class)) |
| 75 | Symbols->addGlobal(Kind: EncodeKind::GlobalSymbol, |
| 76 | Name: (ObjC2ClassNamePrefix + ObjCR.getName()).str(), |
| 77 | Flags: ObjCR.getFlags(), Targ); |
| 78 | if (ObjCR.isExportedSymbol(CurrType: ObjCIFSymbolKind::MetaClass)) |
| 79 | Symbols->addGlobal(Kind: EncodeKind::GlobalSymbol, |
| 80 | Name: (ObjC2MetaClassNamePrefix + ObjCR.getName()).str(), |
| 81 | Flags: ObjCR.getFlags(), Targ); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | addIVars(IVars: ObjCR.getObjCIVars(), ContainerName: ObjCR.getName()); |
| 86 | for (const auto *Cat : ObjCR.getObjCCategories()) |
| 87 | addIVars(IVars: Cat->getObjCIVars(), ContainerName: ObjCR.getName()); |
| 88 | } |
| 89 | |
| 90 | void SymbolConverter::visitObjCCategory(const ObjCCategoryRecord &Cat) { |
| 91 | addIVars(IVars: Cat.getObjCIVars(), ContainerName: Cat.getSuperClassName()); |
| 92 | } |
| 93 | |