blob: ece934d1adb4559482fa400aa0be5c67d3bd5a54 [file] [log] [blame]
//===- 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