#ifndef LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
#define LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
#include "llvm/ADT/Optional.h"
#include "llvm/Object/TapiUniversal.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/Symbol.h"
#include "llvm/TextAPI/Target.h"
namespace llvm {
enum InterfaceInputOrder { lhs, rhs };
enum DiffAttrKind {
AD_Diff_Scalar_PackedVersion,
AD_Diff_Scalar_Unsigned,
AD_Diff_Scalar_Bool,
AD_Diff_Scalar_Str,
AD_Str_Vec,
AD_Sym_Vec,
AD_Inline_Doc,
};
class AttributeDiff {
public:
AttributeDiff(DiffAttrKind Kind) : Kind(Kind){};
virtual ~AttributeDiff(){};
DiffAttrKind getKind() const { return Kind; }
private:
DiffAttrKind Kind;
};
struct DiffOutput {
std::string Name;
DiffAttrKind Kind;
std::vector<std::unique_ptr<AttributeDiff>> Values;
DiffOutput(std::string Name) : Name(Name){};
};
template <class T, DiffAttrKind U> class DiffScalarVal : public AttributeDiff {
public:
DiffScalarVal(InterfaceInputOrder Order, T Val)
: AttributeDiff(U), Order(Order), Val(Val){};
static bool classof(const AttributeDiff *A) { return A->getKind() == U; }
void print(raw_ostream &, std::string);
T getVal() const { return Val; }
InterfaceInputOrder getOrder() const { return Order; }
private:
InterfaceInputOrder Order;
T Val;
};
class SymScalar {
public:
SymScalar(InterfaceInputOrder Order, const MachO::Symbol *Sym)
: Order(Order), Val(Sym){};
std::string getFlagString(MachO::SymbolFlags Flags) {
return Flags != MachO::SymbolFlags::None
? " - " + stringifySymbolFlag(Flags)
: stringifySymbolFlag(Flags);
}
void print(raw_ostream &OS, std::string Indent, MachO::Target Targ);
const MachO::Symbol *getVal() const { return Val; }
InterfaceInputOrder getOrder() const { return Order; }
private:
InterfaceInputOrder Order;
const MachO::Symbol *Val;
StringLiteral getSymbolNamePrefix(MachO::SymbolKind Kind);
std::string stringifySymbolFlag(MachO::SymbolFlags Flag);
};
class DiffStrVec : public AttributeDiff {
public:
MachO::Target Targ;
std::vector<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>> TargValues;
DiffStrVec(MachO::Target Targ) : AttributeDiff(AD_Str_Vec), Targ(Targ){};
static bool classof(const AttributeDiff *A) {
return A->getKind() == AD_Str_Vec;
}
};
class DiffSymVec : public AttributeDiff {
public:
MachO::Target Targ;
std::vector<SymScalar> TargValues;
DiffSymVec(MachO::Target Targ) : AttributeDiff(AD_Sym_Vec), Targ(Targ){};
static bool classof(const AttributeDiff *A) {
return A->getKind() == AD_Sym_Vec;
}
};
class InlineDoc : public AttributeDiff {
public:
std::string InstallName;
std::vector<DiffOutput> DocValues;
InlineDoc(StringRef InstName, std::vector<DiffOutput> Diff)
: AttributeDiff(AD_Inline_Doc), InstallName(InstName),
DocValues(std::move(Diff)){};
static bool classof(const AttributeDiff *A) {
return A->getKind() == AD_Inline_Doc;
}
};
class DiffEngine {
public:
DiffEngine(object::TapiUniversal *InputFileNameLHS,
object::TapiUniversal *InputFileNameRHS)
: FileLHS(InputFileNameLHS), FileRHS(InputFileNameRHS){};
bool compareFiles(raw_ostream &);
private:
object::TapiUniversal *FileLHS;
object::TapiUniversal *FileRHS;
void printDifferences(raw_ostream &, const std::vector<DiffOutput> &, int);
std::vector<DiffOutput> findDifferences(const MachO::InterfaceFile *,
const MachO::InterfaceFile *);
};
}
#endif