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