mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
312 lines
11 KiB
C++
312 lines
11 KiB
C++
//===- ExtendedInterfaceFile.cpp - Extended Interface File ------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief Implements the Extended Interface File
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ExtendedInterfaceFile.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
using namespace llvm;
|
|
|
|
TAPI_NAMESPACE_INTERNAL_BEGIN
|
|
|
|
static XPIKind convertSymbolKindToXPIKind(SymbolKind kind) {
|
|
switch (kind) {
|
|
case SymbolKind::GlobalSymbol:
|
|
return XPIKind::GlobalSymbol;
|
|
case SymbolKind::ObjectiveCClass:
|
|
return XPIKind::ObjectiveCClass;
|
|
case SymbolKind::ObjectiveCClassEHType:
|
|
return XPIKind::ObjectiveCClassEHType;
|
|
case SymbolKind::ObjectiveCInstanceVariable:
|
|
return XPIKind::ObjectiveCInstanceVariable;
|
|
}
|
|
llvm_unreachable("unexpected SymbolKind kind");
|
|
}
|
|
|
|
void ExtendedInterfaceFile::addSymbol(XPIKind kind, StringRef name,
|
|
ArchitectureSet archs, SymbolFlags flags,
|
|
XPIAccess access) {
|
|
switch (kind) {
|
|
default:
|
|
llvm_unreachable("invalid XPI kind");
|
|
case XPIKind::GlobalSymbol:
|
|
_symbols->addGlobalSymbol(name, archs, flags, access);
|
|
break;
|
|
case XPIKind::ObjectiveCClass:
|
|
_symbols->addObjCClass(name, archs, access);
|
|
break;
|
|
case XPIKind::ObjectiveCClassEHType:
|
|
_symbols->addObjCClassEHType(name, archs, access);
|
|
break;
|
|
case XPIKind::ObjectiveCInstanceVariable:
|
|
_symbols->addObjCInstanceVariable(name, archs, access);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ObjCClass *ExtendedInterfaceFile::addObjCClass(StringRef name,
|
|
ArchitectureSet archs,
|
|
XPIAccess access,
|
|
ObjCClass *superClass) {
|
|
return _symbols->addObjCClass(name, archs, access, superClass);
|
|
}
|
|
|
|
ObjCSelector *ExtendedInterfaceFile::addObjCSelector(
|
|
ObjCContainer *container, StringRef name, ArchitectureSet archs,
|
|
bool isInstanceMethod, bool isDynamic, XPIAccess access) {
|
|
return _symbols->addObjCSelector(container, name, archs, isInstanceMethod,
|
|
isDynamic, access);
|
|
}
|
|
|
|
ObjCCategory *ExtendedInterfaceFile::addObjCCategory(ObjCClass *baseClass,
|
|
StringRef name,
|
|
ArchitectureSet archs,
|
|
XPIAccess access) {
|
|
return _symbols->addObjCCategory(baseClass, name, archs, access);
|
|
}
|
|
|
|
ObjCProtocol *ExtendedInterfaceFile::addObjCProtocol(StringRef name,
|
|
ArchitectureSet archs,
|
|
XPIAccess access) {
|
|
return _symbols->addObjCProtocol(name, archs, access);
|
|
}
|
|
|
|
void ExtendedInterfaceFile::addUndefinedSymbol(XPIKind kind, StringRef name,
|
|
ArchitectureSet archs,
|
|
SymbolFlags flags) {
|
|
switch (kind) {
|
|
default:
|
|
llvm_unreachable("invalid XPI kind");
|
|
case XPIKind::GlobalSymbol:
|
|
_undefineds->addGlobalSymbol(name, archs, flags, XPIAccess::Exported);
|
|
break;
|
|
case XPIKind::ObjectiveCClass:
|
|
_undefineds->addObjCClass(name, archs, XPIAccess::Exported);
|
|
break;
|
|
case XPIKind::ObjectiveCClassEHType:
|
|
_undefineds->addObjCClassEHType(name, archs, XPIAccess::Exported);
|
|
break;
|
|
case XPIKind::ObjectiveCInstanceVariable:
|
|
_undefineds->addObjCInstanceVariable(name, archs, XPIAccess::Exported);
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool ExtendedInterfaceFile::contains(XPIKind kind, StringRef name,
|
|
XPI const **result) const {
|
|
if (auto *it = _symbols->findSymbol(kind, name)) {
|
|
if (result)
|
|
*result = it;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Expected<std::unique_ptr<ExtendedInterfaceFile>>
|
|
ExtendedInterfaceFile::merge(const ExtendedInterfaceFile *otherInterface,
|
|
bool allowArchitectureMerges) const {
|
|
// Verify files can be merged.
|
|
if (getFileType() != otherInterface->getFileType()) {
|
|
return make_error<StringError>("file types do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (!allowArchitectureMerges) {
|
|
if ((getArchitectures() & otherInterface->getArchitectures()) !=
|
|
Architecture::unknown) {
|
|
return make_error<StringError>("architectures overlap",
|
|
inconvertibleErrorCode());
|
|
}
|
|
}
|
|
|
|
if (getPlatform() != otherInterface->getPlatform()) {
|
|
return make_error<StringError>("platforms do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (getInstallName() != otherInterface->getInstallName()) {
|
|
return make_error<StringError>("install names do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (getCurrentVersion() != otherInterface->getCurrentVersion()) {
|
|
return make_error<StringError>("current versions do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (getCompatibilityVersion() != otherInterface->getCompatibilityVersion()) {
|
|
return make_error<StringError>("compatibility versions do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (getSwiftABIVersion() != otherInterface->getSwiftABIVersion()) {
|
|
return make_error<StringError>("swift ABI versions do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (isTwoLevelNamespace() != otherInterface->isTwoLevelNamespace()) {
|
|
return make_error<StringError>("two level namespace flags do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (isApplicationExtensionSafe() !=
|
|
otherInterface->isApplicationExtensionSafe()) {
|
|
return make_error<StringError>(
|
|
"application extension safe flags do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (isInstallAPI() != otherInterface->isInstallAPI()) {
|
|
return make_error<StringError>("installapi flags do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (getObjCConstraint() != otherInterface->getObjCConstraint()) {
|
|
return make_error<StringError>("installapi flags do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
if (getParentUmbrella() != otherInterface->getParentUmbrella()) {
|
|
return make_error<StringError>("parent umbrellas do not match",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
std::unique_ptr<ExtendedInterfaceFile> interface(new ExtendedInterfaceFile());
|
|
interface->setFileType(getFileType());
|
|
interface->setPath(getPath());
|
|
interface->setPlatform(getPlatform());
|
|
interface->setInstallName(getInstallName());
|
|
interface->setCurrentVersion(getCurrentVersion());
|
|
interface->setCompatibilityVersion(getCompatibilityVersion());
|
|
interface->setSwiftABIVersion(getSwiftABIVersion());
|
|
interface->setTwoLevelNamespace(isTwoLevelNamespace());
|
|
interface->setApplicationExtensionSafe(isApplicationExtensionSafe());
|
|
interface->setInstallAPI(isInstallAPI());
|
|
interface->setObjCConstraint(getObjCConstraint());
|
|
interface->setParentUmbrella(getParentUmbrella());
|
|
|
|
interface->setArchitectures(getArchitectures() |
|
|
otherInterface->getArchitectures());
|
|
|
|
for (const auto &lib : allowableClients())
|
|
interface->addAllowableClient(lib.getInstallName(), lib.getArchitectures());
|
|
|
|
for (const auto &lib : otherInterface->allowableClients())
|
|
interface->addAllowableClient(lib.getInstallName(), lib.getArchitectures());
|
|
|
|
for (const auto &lib : reexportedLibraries())
|
|
interface->addReexportedLibrary(lib.getInstallName(),
|
|
lib.getArchitectures());
|
|
|
|
for (const auto &lib : otherInterface->reexportedLibraries())
|
|
interface->addReexportedLibrary(lib.getInstallName(),
|
|
lib.getArchitectures());
|
|
|
|
for (const auto &uuid : uuids())
|
|
interface->addUUID(uuid.first, uuid.second);
|
|
|
|
for (const auto &uuid : otherInterface->uuids())
|
|
interface->addUUID(uuid.first, uuid.second);
|
|
|
|
for (const auto *symbol : symbols())
|
|
interface->addSymbol(symbol->getKind(), symbol->getName(),
|
|
symbol->getArchitectures(), symbol->getSymbolFlags(),
|
|
symbol->getAccess());
|
|
|
|
for (const auto *symbol : otherInterface->symbols())
|
|
interface->addSymbol(symbol->getKind(), symbol->getName(),
|
|
symbol->getArchitectures(), symbol->getSymbolFlags(),
|
|
symbol->getAccess());
|
|
|
|
for (const auto *symbol : undefineds())
|
|
interface->addUndefinedSymbol(symbol->getKind(), symbol->getName(),
|
|
symbol->getArchitectures(),
|
|
symbol->getSymbolFlags());
|
|
|
|
for (const auto *symbol : otherInterface->undefineds())
|
|
interface->addUndefinedSymbol(symbol->getKind(), symbol->getName(),
|
|
symbol->getArchitectures(),
|
|
symbol->getSymbolFlags());
|
|
|
|
return std::move(interface);
|
|
}
|
|
|
|
bool ExtendedInterfaceFile::removeSymbol(XPIKind kind, StringRef name) {
|
|
return _symbols->removeSymbol(kind, name);
|
|
}
|
|
|
|
bool ExtendedInterfaceFile::removeSymbol(SymbolKind kind, StringRef name) {
|
|
return removeSymbol(convertSymbolKindToXPIKind(kind), name);
|
|
}
|
|
|
|
void ExtendedInterfaceFile::printSymbolsForArch(Architecture arch) const {
|
|
std::vector<std::string> exports;
|
|
for (const auto *symbol : this->exports()) {
|
|
if (!symbol->getArchitectures().has(arch))
|
|
continue;
|
|
|
|
switch (symbol->getKind()) {
|
|
case XPIKind::GlobalSymbol:
|
|
exports.emplace_back(symbol->getName());
|
|
break;
|
|
case XPIKind::ObjectiveCClass:
|
|
if (getPlatform() == Platform::macOS && arch == Architecture::i386) {
|
|
exports.emplace_back(".objc_class_name_" + symbol->getName().str());
|
|
} else {
|
|
exports.emplace_back("_OBJC_CLASS_$_" + symbol->getName().str());
|
|
exports.emplace_back("_OBJC_METACLASS_$_" + symbol->getName().str());
|
|
}
|
|
break;
|
|
case XPIKind::ObjectiveCClassEHType:
|
|
exports.emplace_back("_OBJC_EHTYPE_$_" + symbol->getName().str());
|
|
break;
|
|
case XPIKind::ObjectiveCInstanceVariable:
|
|
exports.emplace_back("_OBJC_IVAR_$_" + symbol->getName().str());
|
|
break;
|
|
default:
|
|
llvm_unreachable("Unexpected symbol kind for exported symbols");
|
|
}
|
|
}
|
|
|
|
sort(exports);
|
|
for (auto &symbol : exports)
|
|
outs() << symbol << "\n";
|
|
}
|
|
|
|
void ExtendedInterfaceFile::printSymbols(ArchitectureSet archs) const {
|
|
if (archs.empty())
|
|
archs = getArchitectures();
|
|
|
|
if (getArchitectures().contains(archs)) {
|
|
bool firstItr = true;
|
|
for (auto arch : getArchitectures()) {
|
|
if (!archs.has(arch))
|
|
continue;
|
|
|
|
if (firstItr)
|
|
firstItr = false;
|
|
else
|
|
outs() << "\n";
|
|
if (archs.count() > 1)
|
|
outs() << getPath() << " (for architecture " << arch << "):\n";
|
|
printSymbolsForArch(arch);
|
|
}
|
|
} else {
|
|
outs() << "file: " << getPath()
|
|
<< " does not contain architecture: " << archs << "\n";
|
|
}
|
|
}
|
|
|
|
TAPI_NAMESPACE_INTERNAL_END
|