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