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