diff options
Diffstat (limited to 'llvm/tools/llvm-tapi-diff/DiffEngine.cpp')
| -rw-r--r-- | llvm/tools/llvm-tapi-diff/DiffEngine.cpp | 553 |
1 files changed, 0 insertions, 553 deletions
diff --git a/llvm/tools/llvm-tapi-diff/DiffEngine.cpp b/llvm/tools/llvm-tapi-diff/DiffEngine.cpp deleted file mode 100644 index 3e07bb94f4df..000000000000 --- a/llvm/tools/llvm-tapi-diff/DiffEngine.cpp +++ /dev/null @@ -1,553 +0,0 @@ -//===-- DiffEngine.cpp - Structural file comparison -----------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file defines the implementation of the llvm-tapi difference -// engine, which structurally compares two tbd files. -// -//===----------------------------------------------------------------------===/ -#include "DiffEngine.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/TextAPI/InterfaceFile.h" -#include "llvm/TextAPI/Symbol.h" -#include "llvm/TextAPI/Target.h" -#include <iterator> - -using namespace llvm; -using namespace MachO; -using namespace object; - -StringRef setOrderIndicator(InterfaceInputOrder Order) { - return ((Order == lhs) ? "< " : "> "); -} - -// The following template specialization implementations -// need to be explicitly placed into the llvm namespace -// to work around a GCC 4.8 bug. -namespace llvm { - -template <typename T, DiffAttrKind U> -inline void DiffScalarVal<T, U>::print(raw_ostream &OS, std::string Indent) { - OS << Indent << "\t" << setOrderIndicator(Order) << Val << "\n"; -} - -template <> -inline void -DiffScalarVal<StringRef, AD_Diff_Scalar_Str>::print(raw_ostream &OS, - std::string Indent) { - OS << Indent << "\t\t" << setOrderIndicator(Order) << Val << "\n"; -} - -template <> -inline void -DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>::print(raw_ostream &OS, - std::string Indent) { - OS << Indent << "\t" << setOrderIndicator(Order) << std::to_string(Val) - << "\n"; -} - -template <> -inline void -DiffScalarVal<bool, AD_Diff_Scalar_Bool>::print(raw_ostream &OS, - std::string Indent) { - OS << Indent << "\t" << setOrderIndicator(Order) - << ((Val == true) ? "true" : "false") << "\n"; -} - -} // end namespace llvm - -StringLiteral SymScalar::getSymbolNamePrefix(MachO::SymbolKind Kind) { - switch (Kind) { - case MachO::SymbolKind::GlobalSymbol: - return StringLiteral(""); - case MachO::SymbolKind::ObjectiveCClass: - return ObjC2MetaClassNamePrefix; - case MachO::SymbolKind ::ObjectiveCClassEHType: - return ObjC2EHTypePrefix; - case MachO::SymbolKind ::ObjectiveCInstanceVariable: - return ObjC2IVarPrefix; - } - llvm_unreachable("Unknown llvm::MachO::SymbolKind enum"); -} - -std::string SymScalar::getFlagString(const MachO::Symbol *Sym) { - if (Sym->getFlags() == SymbolFlags::None) - return {}; - SmallString<64> Flags(" - "); - if (Sym->isThreadLocalValue()) - Flags.append("Thread-Local "); - if (Sym->isWeakDefined()) - Flags.append("Weak-Defined "); - if (Sym->isWeakReferenced()) - Flags.append("Weak-Referenced "); - if (Sym->isUndefined()) - Flags.append("Undefined "); - if (Sym->isReexported()) - Flags.append("Reexported "); - if (Sym->isData()) - Flags.append("Data "); - if (Sym->isText()) - Flags.append("Text "); - - return std::string(Flags); -} - -void SymScalar::print(raw_ostream &OS, std::string Indent, MachO::Target Targ) { - if (Val->getKind() == MachO::SymbolKind::ObjectiveCClass) { - if (Targ.Arch == MachO::AK_i386 && Targ.Platform == MachO::PLATFORM_MACOS) { - OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ") - << ObjC1ClassNamePrefix << Val->getName() << getFlagString(Val) - << "\n"; - return; - } - OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ") - << ObjC2ClassNamePrefix << Val->getName() << getFlagString(Val) << "\n"; - } - OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ") - << getSymbolNamePrefix(Val->getKind()) << Val->getName() - << getFlagString(Val) << "\n"; -} - -bool checkSymbolEquality(llvm::MachO::InterfaceFile::const_symbol_range LHS, - llvm::MachO::InterfaceFile::const_symbol_range RHS) { - if (std::distance(LHS.begin(), LHS.end()) != - std::distance(RHS.begin(), RHS.end())) - return false; - return std::equal(LHS.begin(), LHS.end(), RHS.begin(), - [&](auto LHS, auto RHS) { return *LHS == *RHS; }); -} - -template <typename TargetVecT, typename ValTypeT, typename V> -void addDiffForTargSlice(V Val, Target Targ, DiffOutput &Diff, - InterfaceInputOrder Order) { - auto TargetVector = llvm::find_if( - Diff.Values, [&](const std::unique_ptr<AttributeDiff> &RawTVec) { - if (TargetVecT *TVec = dyn_cast<TargetVecT>(RawTVec.get())) - return TVec->Targ == Targ; - return false; - }); - if (TargetVector != Diff.Values.end()) { - ValTypeT NewVal(Order, Val); - cast<TargetVecT>(TargetVector->get())->TargValues.push_back(NewVal); - } else { - auto NewTargetVec = std::make_unique<TargetVecT>(Targ); - ValTypeT NewVal(Order, Val); - NewTargetVec->TargValues.push_back(NewVal); - Diff.Values.push_back(std::move(NewTargetVec)); - } -} - -DiffOutput getSingleAttrDiff(const std::vector<InterfaceFileRef> &IRefVec, - std::string Name, InterfaceInputOrder Order) { - DiffOutput Diff(Name); - Diff.Kind = AD_Str_Vec; - for (const auto &IRef : IRefVec) - for (auto Targ : IRef.targets()) - addDiffForTargSlice<DiffStrVec, - DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>( - IRef.getInstallName(), Targ, Diff, Order); - return Diff; -} - -DiffOutput -getSingleAttrDiff(const std::vector<std::pair<Target, std::string>> &PairVec, - std::string Name, InterfaceInputOrder Order) { - DiffOutput Diff(Name); - Diff.Kind = AD_Str_Vec; - for (const auto &Pair : PairVec) - addDiffForTargSlice<DiffStrVec, - DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>( - StringRef(Pair.second), Pair.first, Diff, Order); - return Diff; -} - -DiffOutput getSingleAttrDiff(InterfaceFile::const_symbol_range SymRange, - std::string Name, InterfaceInputOrder Order) { - DiffOutput Diff(Name); - Diff.Kind = AD_Sym_Vec; - for (const auto *Sym : SymRange) - for (auto Targ : Sym->targets()) - addDiffForTargSlice<DiffSymVec, SymScalar>(Sym, Targ, Diff, Order); - return Diff; -} - -template <typename T> -DiffOutput getSingleAttrDiff(T SingleAttr, std::string Attribute) { - DiffOutput Diff(Attribute); - Diff.Kind = SingleAttr.getKind(); - Diff.Values.push_back(std::make_unique<T>(SingleAttr)); - return Diff; -} - -template <typename T, DiffAttrKind U> -void diffAttribute(std::string Name, std::vector<DiffOutput> &Output, - DiffScalarVal<T, U> Attr) { - Output.push_back(getSingleAttrDiff(Attr, Name)); -} - -template <typename T> -void diffAttribute(std::string Name, std::vector<DiffOutput> &Output, - const T &Val, InterfaceInputOrder Order) { - Output.push_back(getSingleAttrDiff(Val, Name, Order)); -} - -std::vector<DiffOutput> getSingleIF(InterfaceFile *Interface, - InterfaceInputOrder Order) { - std::vector<DiffOutput> Output; - diffAttribute("Install Name", Output, - DiffScalarVal<StringRef, AD_Diff_Scalar_Str>( - Order, Interface->getInstallName())); - diffAttribute("Current Version", Output, - DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>( - Order, Interface->getCurrentVersion())); - diffAttribute("Compatibility Version", Output, - DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>( - Order, Interface->getCompatibilityVersion())); - diffAttribute("Swift ABI Version", Output, - DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>( - Order, Interface->getSwiftABIVersion())); - diffAttribute("Two Level Namespace", Output, - DiffScalarVal<bool, AD_Diff_Scalar_Bool>( - Order, Interface->isTwoLevelNamespace())); - diffAttribute("Application Extension Safe", Output, - DiffScalarVal<bool, AD_Diff_Scalar_Bool>( - Order, Interface->isApplicationExtensionSafe())); - diffAttribute("Reexported Libraries", Output, - Interface->reexportedLibraries(), Order); - diffAttribute("Allowable Clients", Output, Interface->allowableClients(), - Order); - diffAttribute("Parent Umbrellas", Output, Interface->umbrellas(), Order); - diffAttribute("Symbols", Output, Interface->symbols(), Order); - for (auto Doc : Interface->documents()) { - DiffOutput Documents("Inlined Reexported Frameworks/Libraries"); - Documents.Kind = AD_Inline_Doc; - Documents.Values.push_back(std::make_unique<InlineDoc>( - InlineDoc(Doc->getInstallName(), getSingleIF(Doc.get(), Order)))); - Output.push_back(std::move(Documents)); - } - return Output; -} - -void findAndAddDiff(const std::vector<InterfaceFileRef> &CollectedIRefVec, - const std::vector<InterfaceFileRef> &LookupIRefVec, - DiffOutput &Result, InterfaceInputOrder Order) { - Result.Kind = AD_Str_Vec; - for (const auto &IRef : CollectedIRefVec) - for (auto Targ : IRef.targets()) { - auto FoundIRef = llvm::any_of(LookupIRefVec, [&](const auto LIRef) { - return llvm::is_contained(LIRef.targets(), Targ) && - IRef.getInstallName() == LIRef.getInstallName(); - }); - if (!FoundIRef) - addDiffForTargSlice<DiffStrVec, - DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>( - IRef.getInstallName(), Targ, Result, Order); - } -} - -void findAndAddDiff( - const std::vector<std::pair<Target, std::string>> &CollectedPairs, - const std::vector<std::pair<Target, std::string>> &LookupPairs, - DiffOutput &Result, InterfaceInputOrder Order) { - Result.Kind = AD_Str_Vec; - for (const auto &Pair : CollectedPairs) { - auto FoundPair = llvm::find(LookupPairs, Pair); - if (FoundPair == LookupPairs.end()) - addDiffForTargSlice<DiffStrVec, - DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>( - StringRef(Pair.second), Pair.first, Result, Order); - } -} - -void findAndAddDiff(InterfaceFile::const_symbol_range CollectedSyms, - InterfaceFile::const_symbol_range LookupSyms, - DiffOutput &Result, InterfaceInputOrder Order) { - Result.Kind = AD_Sym_Vec; - for (const auto *Sym : CollectedSyms) - for (const auto Targ : Sym->targets()) { - auto FoundSym = llvm::any_of(LookupSyms, [&](const auto LSym) { - return (Sym->getName() == LSym->getName() && - Sym->getKind() == LSym->getKind() && - Sym->getFlags() == LSym->getFlags() && - llvm::is_contained(LSym->targets(), Targ)); - }); - if (!FoundSym) - addDiffForTargSlice<DiffSymVec, SymScalar>(Sym, Targ, Result, Order); - } -} - -template <typename T> -DiffOutput recordDifferences(T LHS, T RHS, std::string Attr) { - DiffOutput Diff(Attr); - if (LHS.getKind() == RHS.getKind()) { - Diff.Kind = LHS.getKind(); - Diff.Values.push_back(std::make_unique<T>(LHS)); - Diff.Values.push_back(std::make_unique<T>(RHS)); - } - return Diff; -} - -template <typename T> -DiffOutput recordDifferences(const std::vector<T> &LHS, - const std::vector<T> &RHS, std::string Attr) { - DiffOutput Diff(Attr); - Diff.Kind = AD_Str_Vec; - findAndAddDiff(LHS, RHS, Diff, lhs); - findAndAddDiff(RHS, LHS, Diff, rhs); - return Diff; -} - -DiffOutput recordDifferences(llvm::MachO::InterfaceFile::const_symbol_range LHS, - llvm::MachO::InterfaceFile::const_symbol_range RHS, - std::string Attr) { - DiffOutput Diff(Attr); - Diff.Kind = AD_Sym_Vec; - findAndAddDiff(LHS, RHS, Diff, lhs); - findAndAddDiff(RHS, LHS, Diff, rhs); - return Diff; -} - -std::vector<DiffOutput> -DiffEngine::findDifferences(const InterfaceFile *IFLHS, - const InterfaceFile *IFRHS) { - std::vector<DiffOutput> Output; - if (IFLHS->getInstallName() != IFRHS->getInstallName()) - Output.push_back(recordDifferences( - DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(lhs, - IFLHS->getInstallName()), - DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(rhs, - IFRHS->getInstallName()), - "Install Name")); - - if (IFLHS->getCurrentVersion() != IFRHS->getCurrentVersion()) - Output.push_back(recordDifferences( - DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>( - lhs, IFLHS->getCurrentVersion()), - DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>( - rhs, IFRHS->getCurrentVersion()), - "Current Version")); - if (IFLHS->getCompatibilityVersion() != IFRHS->getCompatibilityVersion()) - Output.push_back(recordDifferences( - DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>( - lhs, IFLHS->getCompatibilityVersion()), - DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>( - rhs, IFRHS->getCompatibilityVersion()), - "Compatibility Version")); - if (IFLHS->getSwiftABIVersion() != IFRHS->getSwiftABIVersion()) - Output.push_back( - recordDifferences(DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>( - lhs, IFLHS->getSwiftABIVersion()), - DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>( - rhs, IFRHS->getSwiftABIVersion()), - "Swift ABI Version")); - - if (IFLHS->isTwoLevelNamespace() != IFRHS->isTwoLevelNamespace()) - Output.push_back(recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>( - lhs, IFLHS->isTwoLevelNamespace()), - DiffScalarVal<bool, AD_Diff_Scalar_Bool>( - rhs, IFRHS->isTwoLevelNamespace()), - "Two Level Namespace")); - - if (IFLHS->isApplicationExtensionSafe() != - IFRHS->isApplicationExtensionSafe()) - Output.push_back( - recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>( - lhs, IFLHS->isApplicationExtensionSafe()), - DiffScalarVal<bool, AD_Diff_Scalar_Bool>( - rhs, IFRHS->isApplicationExtensionSafe()), - "Application Extension Safe")); - - if (IFLHS->reexportedLibraries() != IFRHS->reexportedLibraries()) - Output.push_back(recordDifferences(IFLHS->reexportedLibraries(), - IFRHS->reexportedLibraries(), - "Reexported Libraries")); - - if (IFLHS->allowableClients() != IFRHS->allowableClients()) - Output.push_back(recordDifferences(IFLHS->allowableClients(), - IFRHS->allowableClients(), - "Allowable Clients")); - - if (IFLHS->umbrellas() != IFRHS->umbrellas()) - Output.push_back(recordDifferences(IFLHS->umbrellas(), IFRHS->umbrellas(), - "Parent Umbrellas")); - - if (!checkSymbolEquality(IFLHS->symbols(), IFRHS->symbols())) - Output.push_back( - recordDifferences(IFLHS->symbols(), IFRHS->symbols(), "Symbols")); - - if (IFLHS->documents() != IFRHS->documents()) { - DiffOutput Docs("Inlined Reexported Frameworks/Libraries"); - Docs.Kind = AD_Inline_Doc; - std::vector<StringRef> DocsInserted; - // Iterate through inline frameworks/libraries from interface file and find - // match based on install name. - for (auto DocLHS : IFLHS->documents()) { - auto Pair = llvm::find_if(IFRHS->documents(), [&](const auto &DocRHS) { - return (DocLHS->getInstallName() == DocRHS->getInstallName()); - }); - // If a match found, recursively get differences between the pair. - if (Pair != IFRHS->documents().end()) { - InlineDoc PairDiff = - InlineDoc(DocLHS->getInstallName(), - findDifferences(DocLHS.get(), Pair->get())); - if (!PairDiff.DocValues.empty()) - Docs.Values.push_back( - std::make_unique<InlineDoc>(std::move(PairDiff))); - } - // If a match is not found, get attributes from single item. - else - Docs.Values.push_back(std::make_unique<InlineDoc>(InlineDoc( - DocLHS->getInstallName(), getSingleIF(DocLHS.get(), lhs)))); - DocsInserted.push_back(DocLHS->getInstallName()); - } - for (auto DocRHS : IFRHS->documents()) { - auto WasGathered = - llvm::any_of(DocsInserted, [&](const auto &GatheredDoc) { - return (GatheredDoc == DocRHS->getInstallName()); - }); - if (!WasGathered) - Docs.Values.push_back(std::make_unique<InlineDoc>(InlineDoc( - DocRHS->getInstallName(), getSingleIF(DocRHS.get(), rhs)))); - } - if (!Docs.Values.empty()) - Output.push_back(std::move(Docs)); - } - return Output; -} - -template <typename T> -void printSingleVal(std::string Indent, const DiffOutput &Attr, - raw_ostream &OS) { - if (Attr.Values.empty()) - return; - OS << Indent << Attr.Name << "\n"; - for (auto &RawItem : Attr.Values) - if (T *Item = dyn_cast<T>(RawItem.get())) - Item->print(OS, Indent); -} - -template <typename T> -T *castValues(const std::unique_ptr<AttributeDiff> &RawAttr) { - T *CastAttr = cast<T>(RawAttr.get()); - return CastAttr; -} - -template <typename T> void sortTargetValues(std::vector<T> &TargValues) { - llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) { - return ValA.getOrder() < ValB.getOrder(); - }); - llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) { - return ValA.getOrder() == ValB.getOrder() && ValA.getVal() < ValB.getVal(); - }); -} - -template <typename T> -void printVecVal(std::string Indent, const DiffOutput &Attr, raw_ostream &OS) { - if (Attr.Values.empty()) - return; - - OS << Indent << Attr.Name << "\n"; - - std::vector<T *> SortedAttrs; - - llvm::transform(Attr.Values, std::back_inserter(SortedAttrs), castValues<T>); - - llvm::sort(SortedAttrs, [&](const auto &ValA, const auto &ValB) { - return ValA->Targ < ValB->Targ; - }); - - for (auto *Vec : SortedAttrs) { - sortTargetValues<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>( - Vec->TargValues); - OS << Indent << "\t" << getTargetTripleName(Vec->Targ) << "\n"; - for (auto &Item : Vec->TargValues) - Item.print(OS, Indent); - } -} - -template <> -void printVecVal<DiffSymVec>(std::string Indent, const DiffOutput &Attr, - raw_ostream &OS) { - if (Attr.Values.empty()) - return; - - OS << Indent << Attr.Name << "\n"; - - std::vector<DiffSymVec *> SortedAttrs; - - llvm::transform(Attr.Values, std::back_inserter(SortedAttrs), - castValues<DiffSymVec>); - - llvm::sort(SortedAttrs, [&](const auto &ValA, const auto &ValB) { - return ValA->Targ < ValB->Targ; - }); - for (auto *SymVec : SortedAttrs) { - sortTargetValues<SymScalar>(SymVec->TargValues); - OS << Indent << "\t" << getTargetTripleName(SymVec->Targ) << "\n"; - for (auto &Item : SymVec->TargValues) - Item.print(OS, Indent, SymVec->Targ); - } -} - -void DiffEngine::printDifferences(raw_ostream &OS, - const std::vector<DiffOutput> &Diffs, - int IndentCounter) { - std::string Indent = std::string(IndentCounter, '\t'); - for (auto &Attr : Diffs) { - switch (Attr.Kind) { - case AD_Diff_Scalar_Str: - if (IndentCounter == 0) - printSingleVal<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(Indent, - Attr, OS); - break; - case AD_Diff_Scalar_PackedVersion: - printSingleVal< - DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>>(Indent, - Attr, OS); - break; - case AD_Diff_Scalar_Unsigned: - printSingleVal<DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>>(Indent, - Attr, OS); - break; - case AD_Diff_Scalar_Bool: - printSingleVal<DiffScalarVal<bool, AD_Diff_Scalar_Bool>>(Indent, Attr, - OS); - break; - case AD_Str_Vec: - printVecVal<DiffStrVec>(Indent, Attr, OS); - break; - case AD_Sym_Vec: - printVecVal<DiffSymVec>(Indent, Attr, OS); - break; - case AD_Inline_Doc: - if (!Attr.Values.empty()) { - OS << Indent << Attr.Name << "\n"; - for (auto &Item : Attr.Values) - if (InlineDoc *Doc = dyn_cast<InlineDoc>(Item.get())) - if (!Doc->DocValues.empty()) { - OS << Indent << "\t" << Doc->InstallName << "\n"; - printDifferences(OS, std::move(Doc->DocValues), 2); - } - } - break; - } - } -} - -bool DiffEngine::compareFiles(raw_ostream &OS) { - const auto *IFLHS = &(FileLHS->getInterfaceFile()); - const auto *IFRHS = &(FileRHS->getInterfaceFile()); - if (*IFLHS == *IFRHS) - return false; - OS << "< " << std::string(IFLHS->getPath().data()) << "\n> " - << std::string(IFRHS->getPath().data()) << "\n\n"; - std::vector<DiffOutput> Diffs = findDifferences(IFLHS, IFRHS); - printDifferences(OS, Diffs, 0); - return true; -} |
