aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/TextAPI
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/TextAPI')
-rw-r--r--llvm/lib/TextAPI/BinaryReader/DylibReader.cpp10
-rw-r--r--llvm/lib/TextAPI/CMakeLists.txt1
-rw-r--r--llvm/lib/TextAPI/RecordVisitor.cpp65
-rw-r--r--llvm/lib/TextAPI/RecordsSlice.cpp120
4 files changed, 194 insertions, 2 deletions
diff --git a/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp
index b01130c..40b57b5 100644
--- a/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp
+++ b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp
@@ -417,3 +417,13 @@ Expected<Records> DylibReader::readFile(MemoryBufferRef Buffer,
return make_error<TextAPIError>(TextAPIErrorCode::EmptyResults);
return Results;
}
+
+Expected<std::unique_ptr<InterfaceFile>>
+DylibReader::get(MemoryBufferRef Buffer) {
+ ParseOption Options;
+ auto SlicesOrErr = readFile(Buffer, Options);
+ if (!SlicesOrErr)
+ return SlicesOrErr.takeError();
+
+ return convertToInterfaceFile(*SlicesOrErr);
+}
diff --git a/llvm/lib/TextAPI/CMakeLists.txt b/llvm/lib/TextAPI/CMakeLists.txt
index 75fc92f..2017a1ad 100644
--- a/llvm/lib/TextAPI/CMakeLists.txt
+++ b/llvm/lib/TextAPI/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMTextAPI
PackedVersion.cpp
Platform.cpp
RecordsSlice.cpp
+ RecordVisitor.cpp
Symbol.cpp
SymbolSet.cpp
Target.cpp
diff --git a/llvm/lib/TextAPI/RecordVisitor.cpp b/llvm/lib/TextAPI/RecordVisitor.cpp
new file mode 100644
index 0000000..cee04e6
--- /dev/null
+++ b/llvm/lib/TextAPI/RecordVisitor.cpp
@@ -0,0 +1,65 @@
+//===- 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() {}
+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] = parseSymbol(GR.getName(), GR.getFlags());
+ if (shouldSkipRecord(GR, RecordUndefs))
+ return;
+ Symbols->addGlobal(SymKind, SymName, 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(SymbolKind::ObjectiveCInstanceVariable, Name,
+ IV->getFlags(), Targ);
+ }
+}
+
+void SymbolConverter::visitObjCInterface(const ObjCInterfaceRecord &ObjCR) {
+ if (!shouldSkipRecord(ObjCR, RecordUndefs)) {
+ Symbols->addGlobal(SymbolKind::ObjectiveCClass, ObjCR.getName(),
+ ObjCR.getFlags(), Targ);
+ if (ObjCR.hasExceptionAttribute())
+ Symbols->addGlobal(SymbolKind::ObjectiveCClassEHType, ObjCR.getName(),
+ 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.getName());
+}
diff --git a/llvm/lib/TextAPI/RecordsSlice.cpp b/llvm/lib/TextAPI/RecordsSlice.cpp
index a220b25..7ceffc7 100644
--- a/llvm/lib/TextAPI/RecordsSlice.cpp
+++ b/llvm/lib/TextAPI/RecordsSlice.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/TextAPI/RecordsSlice.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/TextAPI/Record.h"
#include "llvm/TextAPI/Symbol.h"
#include <utility>
@@ -142,8 +143,10 @@ GlobalRecord *RecordsSlice::addGlobal(StringRef Name, RecordLinkage Linkage,
if (Result.second)
Result.first->second =
std::make_unique<GlobalRecord>(Name, Linkage, Flags, GV);
- else
+ else {
updateLinkage(Result.first->second.get(), Linkage);
+ updateFlags(Result.first->second.get(), Flags);
+ }
return Result.first->second.get();
}
@@ -164,6 +167,19 @@ ObjCInterfaceRecord *RecordsSlice::addObjCInterface(StringRef Name,
return Result.first->second.get();
}
+SymbolFlags Record::mergeFlags(SymbolFlags Flags, RecordLinkage Linkage) {
+ // Add Linkage properties into Flags.
+ switch (Linkage) {
+ case RecordLinkage::Rexported:
+ Flags |= SymbolFlags::Rexported;
+ return Flags;
+ case RecordLinkage::Undefined:
+ Flags |= SymbolFlags::Undefined;
+ return Flags;
+ default:
+ return Flags;
+ }
+}
bool ObjCInterfaceRecord::addObjCCategory(ObjCCategoryRecord *Record) {
auto Result = Categories.insert({Name, Record});
@@ -188,11 +204,26 @@ ObjCCategoryRecord *RecordsSlice::addObjCCategory(StringRef ClassToExtend,
return Result.first->second.get();
}
+std::vector<ObjCIVarRecord *> ObjCContainerRecord::getObjCIVars() const {
+ std::vector<ObjCIVarRecord *> Records;
+ llvm::for_each(IVars,
+ [&](auto &Record) { Records.push_back(Record.second.get()); });
+ return Records;
+}
+
+std::vector<ObjCCategoryRecord *>
+ObjCInterfaceRecord::getObjCCategories() const {
+ std::vector<ObjCCategoryRecord *> Records;
+ llvm::for_each(Categories,
+ [&](auto &Record) { Records.push_back(Record.second); });
+ return Records;
+}
+
ObjCIVarRecord *ObjCContainerRecord::addObjCIVar(StringRef IVar,
RecordLinkage Linkage) {
auto Result = IVars.insert({IVar, nullptr});
if (Result.second)
- Result.first->second = std::make_unique<ObjCIVarRecord>(Name, Linkage);
+ Result.first->second = std::make_unique<ObjCIVarRecord>(IVar, Linkage);
return Result.first->second.get();
}
@@ -222,3 +253,88 @@ RecordsSlice::BinaryAttrs &RecordsSlice::getBinaryAttrs() {
BA = std::make_unique<BinaryAttrs>();
return *BA;
}
+
+void RecordsSlice::visit(RecordVisitor &V) const {
+ for (auto &G : Globals)
+ V.visitGlobal(*G.second);
+ for (auto &C : Classes)
+ V.visitObjCInterface(*C.second);
+ for (auto &Cat : Categories)
+ V.visitObjCCategory(*Cat.second);
+}
+
+static std::unique_ptr<InterfaceFile>
+createInterfaceFile(const Records &Slices, StringRef InstallName) {
+ // Pickup symbols first.
+ auto Symbols = std::make_unique<SymbolSet>();
+ for (auto &S : Slices) {
+ if (S->empty())
+ continue;
+ auto &BA = S->getBinaryAttrs();
+ if (BA.InstallName != InstallName)
+ continue;
+
+ SymbolConverter Converter(Symbols.get(), S->getTarget(),
+ !BA.TwoLevelNamespace);
+ S->visit(Converter);
+ }
+
+ auto File = std::make_unique<InterfaceFile>(std::move(Symbols));
+ File->setInstallName(InstallName);
+ // Assign other attributes.
+ for (auto &S : Slices) {
+ if (S->empty())
+ continue;
+ auto &BA = S->getBinaryAttrs();
+ if (BA.InstallName != InstallName)
+ continue;
+ const Target &Targ = S->getTarget();
+ File->addTarget(Targ);
+ if (File->getFileType() == FileType::Invalid)
+ File->setFileType(BA.File);
+ if (BA.AppExtensionSafe && !File->isApplicationExtensionSafe())
+ File->setApplicationExtensionSafe();
+ if (BA.TwoLevelNamespace && !File->isTwoLevelNamespace())
+ File->setTwoLevelNamespace();
+ if (BA.OSLibNotForSharedCache && !File->isOSLibNotForSharedCache())
+ File->setOSLibNotForSharedCache();
+ if (File->getCurrentVersion().empty())
+ File->setCurrentVersion(BA.CurrentVersion);
+ if (File->getCompatibilityVersion().empty())
+ File->setCompatibilityVersion(BA.CompatVersion);
+ if (File->getSwiftABIVersion() == 0)
+ File->setSwiftABIVersion(BA.SwiftABI);
+ if (File->getPath().empty())
+ File->setPath(BA.Path);
+ if (!BA.ParentUmbrella.empty())
+ File->addParentUmbrella(Targ, BA.ParentUmbrella);
+ for (const auto &Client : BA.AllowableClients)
+ File->addAllowableClient(Client, Targ);
+ for (const auto &Lib : BA.RexportedLibraries)
+ File->addReexportedLibrary(Lib, Targ);
+ }
+
+ return File;
+}
+
+std::unique_ptr<InterfaceFile>
+llvm::MachO::convertToInterfaceFile(const Records &Slices) {
+ std::unique_ptr<InterfaceFile> File;
+ if (Slices.empty())
+ return File;
+
+ SetVector<StringRef> InstallNames;
+ for (auto &S : Slices) {
+ auto Name = S->getBinaryAttrs().InstallName;
+ if (Name.empty())
+ continue;
+ InstallNames.insert(Name);
+ }
+
+ File = createInterfaceFile(Slices, *InstallNames.begin());
+ for (auto it = std::next(InstallNames.begin()); it != InstallNames.end();
+ ++it)
+ File->addDocument(createInterfaceFile(Slices, *it));
+
+ return File;
+}