mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
70d02c15c5
This prevents invalid implicit conversation which caused buildbot failure.
557 lines
21 KiB
C++
557 lines
21 KiB
C++
//===-- 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/Support/Casting.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/TextAPI/InterfaceFile.h"
|
|
#include "llvm/TextAPI/Symbol.h"
|
|
#include "llvm/TextAPI/Target.h"
|
|
|
|
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::stringifySymbolFlag(MachO::SymbolFlags Flag) {
|
|
switch (Flag) {
|
|
case MachO::SymbolFlags::None:
|
|
return "";
|
|
case MachO::SymbolFlags::ThreadLocalValue:
|
|
return "Thread-Local";
|
|
case MachO::SymbolFlags::WeakDefined:
|
|
return "Weak-Defined";
|
|
case MachO::SymbolFlags::WeakReferenced:
|
|
return "Weak-Referenced";
|
|
case MachO::SymbolFlags::Undefined:
|
|
return "Undefined";
|
|
case MachO::SymbolFlags::Rexported:
|
|
return "Reexported";
|
|
}
|
|
llvm_unreachable("Unknown llvm::MachO::SymbolFlags enum");
|
|
}
|
|
|
|
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::PlatformKind::macOS) {
|
|
OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
|
|
<< ObjC1ClassNamePrefix << Val->getName()
|
|
<< getFlagString(Val->getFlags()) << "\n";
|
|
return;
|
|
}
|
|
OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
|
|
<< ObjC2ClassNamePrefix << Val->getName()
|
|
<< getFlagString(Val->getFlags()) << "\n";
|
|
}
|
|
OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
|
|
<< getSymbolNamePrefix(Val->getKind()) << Val->getName()
|
|
<< getFlagString(Val->getFlags()) << "\n";
|
|
}
|
|
|
|
bool checkSymbolEquality(llvm::MachO::InterfaceFile::const_symbol_range LHS,
|
|
llvm::MachO::InterfaceFile::const_symbol_range RHS) {
|
|
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("InstallAPI", Output,
|
|
DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
|
|
Order, Interface->isInstallAPI()));
|
|
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::find_if(LookupIRefVec, [&](const auto LIRef) {
|
|
auto FoundTarg = llvm::find(LIRef.targets(), Targ);
|
|
return (FoundTarg != LIRef.targets().end() &&
|
|
IRef.getInstallName() == LIRef.getInstallName());
|
|
});
|
|
if (FoundIRef == LookupIRefVec.end())
|
|
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::find_if(LookupSyms, [&](const auto LSym) {
|
|
auto FoundTarg = llvm::find(LSym->targets(), Targ);
|
|
return (Sym->getName() == LSym->getName() &&
|
|
Sym->getKind() == LSym->getKind() &&
|
|
Sym->getFlags() == LSym->getFlags() &&
|
|
FoundTarg != LSym->targets().end());
|
|
});
|
|
if (FoundSym == LookupSyms.end())
|
|
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->isInstallAPI() != IFRHS->isInstallAPI())
|
|
Output.push_back(recordDifferences(
|
|
DiffScalarVal<bool, AD_Diff_Scalar_Bool>(lhs, IFLHS->isInstallAPI()),
|
|
DiffScalarVal<bool, AD_Diff_Scalar_Bool>(rhs, IFRHS->isInstallAPI()),
|
|
"InstallAPI"));
|
|
|
|
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::find_if(DocsInserted, [&](const auto &GatheredDoc) {
|
|
return (GatheredDoc == DocRHS->getInstallName());
|
|
});
|
|
if (WasGathered == DocsInserted.end())
|
|
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;
|
|
}
|