1 //===-- DiffEngine.h - File comparator --------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This header defines the interface to the llvm-tapi difference engine, 10 // which structurally compares two tbd files. 11 // 12 //===----------------------------------------------------------------------===/ 13 #ifndef LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H 14 #define LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H 15 16 #include "llvm/Object/TapiUniversal.h" 17 #include "llvm/Support/raw_ostream.h" 18 #include "llvm/TextAPI/Symbol.h" 19 #include "llvm/TextAPI/Target.h" 20 21 namespace llvm { 22 23 /// InterfaceInputOrder determines from which file the diff attribute belongs 24 /// to. 25 enum InterfaceInputOrder { lhs, rhs }; 26 27 /// DiffAttrKind is the enum that holds the concrete bases for RTTI. 28 enum DiffAttrKind { 29 AD_Diff_Scalar_PackedVersion, 30 AD_Diff_Scalar_Unsigned, 31 AD_Diff_Scalar_Bool, 32 AD_Diff_Scalar_Str, 33 AD_Str_Vec, 34 AD_Sym_Vec, 35 AD_Inline_Doc, 36 }; 37 38 /// AttributeDiff is the abstract class for RTTI. 39 class AttributeDiff { 40 public: AttributeDiff(DiffAttrKind Kind)41 AttributeDiff(DiffAttrKind Kind) : Kind(Kind){}; ~AttributeDiff()42 virtual ~AttributeDiff(){}; getKind()43 DiffAttrKind getKind() const { return Kind; } 44 45 private: 46 DiffAttrKind Kind; 47 }; 48 49 /// DiffOutput is the representation of a diff for a single attribute. 50 struct DiffOutput { 51 /// The name of the attribute. 52 std::string Name; 53 /// The kind for RTTI 54 DiffAttrKind Kind; 55 /// Different values for the attribute 56 /// from each file where a diff is present. 57 std::vector<std::unique_ptr<AttributeDiff>> Values; DiffOutputDiffOutput58 DiffOutput(std::string Name) : Name(Name){}; 59 }; 60 61 /// DiffScalarVal is a template class for the different types of scalar values. 62 template <class T, DiffAttrKind U> class DiffScalarVal : public AttributeDiff { 63 public: DiffScalarVal(InterfaceInputOrder Order,T Val)64 DiffScalarVal(InterfaceInputOrder Order, T Val) 65 : AttributeDiff(U), Order(Order), Val(Val){}; 66 classof(const AttributeDiff * A)67 static bool classof(const AttributeDiff *A) { return A->getKind() == U; } 68 69 void print(raw_ostream &, std::string); 70 getVal()71 T getVal() const { return Val; } getOrder()72 InterfaceInputOrder getOrder() const { return Order; } 73 74 private: 75 /// The order is the file from which the diff is found. 76 InterfaceInputOrder Order; 77 T Val; 78 }; 79 80 /// SymScalar is the diff symbol and the order. 81 class SymScalar { 82 public: SymScalar(InterfaceInputOrder Order,const MachO::Symbol * Sym)83 SymScalar(InterfaceInputOrder Order, const MachO::Symbol *Sym) 84 : Order(Order), Val(Sym){}; 85 getFlagString(MachO::SymbolFlags Flags)86 std::string getFlagString(MachO::SymbolFlags Flags) { 87 return Flags != MachO::SymbolFlags::None 88 ? " - " + stringifySymbolFlag(Flags) 89 : stringifySymbolFlag(Flags); 90 } 91 92 void print(raw_ostream &OS, std::string Indent, MachO::Target Targ); 93 getVal()94 const MachO::Symbol *getVal() const { return Val; } getOrder()95 InterfaceInputOrder getOrder() const { return Order; } 96 97 private: 98 /// The order is the file from which the diff is found. 99 InterfaceInputOrder Order; 100 const MachO::Symbol *Val; 101 StringLiteral getSymbolNamePrefix(MachO::SymbolKind Kind); 102 std::string stringifySymbolFlag(MachO::SymbolFlags Flag); 103 }; 104 105 class DiffStrVec : public AttributeDiff { 106 public: 107 MachO::Target Targ; 108 /// Values is a vector of StringRef values associated with the target. 109 std::vector<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>> TargValues; DiffStrVec(MachO::Target Targ)110 DiffStrVec(MachO::Target Targ) : AttributeDiff(AD_Str_Vec), Targ(Targ){}; 111 classof(const AttributeDiff * A)112 static bool classof(const AttributeDiff *A) { 113 return A->getKind() == AD_Str_Vec; 114 } 115 }; 116 117 class DiffSymVec : public AttributeDiff { 118 public: 119 MachO::Target Targ; 120 /// Values is a vector of symbol values associated with the target. 121 std::vector<SymScalar> TargValues; DiffSymVec(MachO::Target Targ)122 DiffSymVec(MachO::Target Targ) : AttributeDiff(AD_Sym_Vec), Targ(Targ){}; 123 classof(const AttributeDiff * A)124 static bool classof(const AttributeDiff *A) { 125 return A->getKind() == AD_Sym_Vec; 126 } 127 }; 128 129 /// InlineDoc represents an inlined framework/library in a TBD File. 130 class InlineDoc : public AttributeDiff { 131 public: 132 /// Install name of the framework/library. 133 std::string InstallName; 134 /// Differences found from each file. 135 std::vector<DiffOutput> DocValues; InlineDoc(StringRef InstName,std::vector<DiffOutput> Diff)136 InlineDoc(StringRef InstName, std::vector<DiffOutput> Diff) 137 : AttributeDiff(AD_Inline_Doc), InstallName(InstName), 138 DocValues(std::move(Diff)){}; 139 classof(const AttributeDiff * A)140 static bool classof(const AttributeDiff *A) { 141 return A->getKind() == AD_Inline_Doc; 142 } 143 }; 144 145 /// DiffEngine contains the methods to compare the input files and print the 146 /// output of the differences found in the files. 147 class DiffEngine { 148 public: DiffEngine(object::TapiUniversal * InputFileNameLHS,object::TapiUniversal * InputFileNameRHS)149 DiffEngine(object::TapiUniversal *InputFileNameLHS, 150 object::TapiUniversal *InputFileNameRHS) 151 : FileLHS(InputFileNameLHS), FileRHS(InputFileNameRHS){}; 152 bool compareFiles(raw_ostream &); 153 154 private: 155 object::TapiUniversal *FileLHS; 156 object::TapiUniversal *FileRHS; 157 158 /// Function that prints the differences found in the files. 159 void printDifferences(raw_ostream &, const std::vector<DiffOutput> &, int); 160 /// Function that does the comparison of the TBD files and returns the 161 /// differences. 162 std::vector<DiffOutput> findDifferences(const MachO::InterfaceFile *, 163 const MachO::InterfaceFile *); 164 }; 165 166 } // namespace llvm 167 168 #endif 169