1*349cc55cSDimitry Andric //===-- DiffConsumer.h - Difference Consumer --------------------*- C++ -*-===//
2*349cc55cSDimitry Andric //
3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*349cc55cSDimitry Andric //
7*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8*349cc55cSDimitry Andric //
9*349cc55cSDimitry Andric // This header defines the interface to the LLVM difference Consumer
10*349cc55cSDimitry Andric //
11*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
12*349cc55cSDimitry Andric 
13*349cc55cSDimitry Andric #ifndef LLVM_TOOLS_LLVM_DIFF_DIFFCONSUMER_H
14*349cc55cSDimitry Andric #define LLVM_TOOLS_LLVM_DIFF_DIFFCONSUMER_H
15*349cc55cSDimitry Andric 
16*349cc55cSDimitry Andric #include "DiffLog.h"
17*349cc55cSDimitry Andric #include "llvm/ADT/DenseMap.h"
18*349cc55cSDimitry Andric #include "llvm/ADT/SmallVector.h"
19*349cc55cSDimitry Andric #include "llvm/IR/Value.h"
20*349cc55cSDimitry Andric #include "llvm/Support/Casting.h"
21*349cc55cSDimitry Andric #include "llvm/Support/raw_ostream.h"
22*349cc55cSDimitry Andric 
23*349cc55cSDimitry Andric namespace llvm {
24*349cc55cSDimitry Andric class StringRef;
25*349cc55cSDimitry Andric   class Module;
26*349cc55cSDimitry Andric   class Value;
27*349cc55cSDimitry Andric   class Function;
28*349cc55cSDimitry Andric 
29*349cc55cSDimitry Andric   /// The interface for consumers of difference data.
30*349cc55cSDimitry Andric   class Consumer {
31*349cc55cSDimitry Andric     virtual void anchor();
32*349cc55cSDimitry Andric   public:
33*349cc55cSDimitry Andric     /// Record that a local context has been entered.  Left and
34*349cc55cSDimitry Andric     /// Right are IR "containers" of some sort which are being
35*349cc55cSDimitry Andric     /// considered for structural equivalence: global variables,
36*349cc55cSDimitry Andric     /// functions, blocks, instructions, etc.
37*349cc55cSDimitry Andric     virtual void enterContext(const Value *Left, const Value *Right) = 0;
38*349cc55cSDimitry Andric 
39*349cc55cSDimitry Andric     /// Record that a local context has been exited.
40*349cc55cSDimitry Andric     virtual void exitContext() = 0;
41*349cc55cSDimitry Andric 
42*349cc55cSDimitry Andric     /// Record a difference within the current context.
43*349cc55cSDimitry Andric     virtual void log(StringRef Text) = 0;
44*349cc55cSDimitry Andric 
45*349cc55cSDimitry Andric     /// Record a formatted difference within the current context.
46*349cc55cSDimitry Andric     virtual void logf(const LogBuilder &Log) = 0;
47*349cc55cSDimitry Andric 
48*349cc55cSDimitry Andric     /// Record a line-by-line instruction diff.
49*349cc55cSDimitry Andric     virtual void logd(const DiffLogBuilder &Log) = 0;
50*349cc55cSDimitry Andric 
51*349cc55cSDimitry Andric   protected:
~Consumer()52*349cc55cSDimitry Andric     virtual ~Consumer() {}
53*349cc55cSDimitry Andric   };
54*349cc55cSDimitry Andric 
55*349cc55cSDimitry Andric   class DiffConsumer : public Consumer {
56*349cc55cSDimitry Andric   private:
57*349cc55cSDimitry Andric     struct DiffContext {
DiffContextDiffContext58*349cc55cSDimitry Andric       DiffContext(const Value *L, const Value *R)
59*349cc55cSDimitry Andric           : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {}
60*349cc55cSDimitry Andric       const Value *L;
61*349cc55cSDimitry Andric       const Value *R;
62*349cc55cSDimitry Andric       bool Differences;
63*349cc55cSDimitry Andric       bool IsFunction;
64*349cc55cSDimitry Andric       DenseMap<const Value *, unsigned> LNumbering;
65*349cc55cSDimitry Andric       DenseMap<const Value *, unsigned> RNumbering;
66*349cc55cSDimitry Andric     };
67*349cc55cSDimitry Andric 
68*349cc55cSDimitry Andric     raw_ostream &out;
69*349cc55cSDimitry Andric     SmallVector<DiffContext, 5> contexts;
70*349cc55cSDimitry Andric     bool Differences;
71*349cc55cSDimitry Andric     unsigned Indent;
72*349cc55cSDimitry Andric 
73*349cc55cSDimitry Andric     void printValue(const Value *V, bool isL);
74*349cc55cSDimitry Andric     void header();
75*349cc55cSDimitry Andric     void indent();
76*349cc55cSDimitry Andric 
77*349cc55cSDimitry Andric   public:
DiffConsumer()78*349cc55cSDimitry Andric     DiffConsumer()
79*349cc55cSDimitry Andric       : out(errs()), Differences(false), Indent(0) {}
80*349cc55cSDimitry Andric 
81*349cc55cSDimitry Andric     void reset();
82*349cc55cSDimitry Andric     bool hadDifferences() const;
83*349cc55cSDimitry Andric     void enterContext(const Value *L, const Value *R) override;
84*349cc55cSDimitry Andric     void exitContext() override;
85*349cc55cSDimitry Andric     void log(StringRef text) override;
86*349cc55cSDimitry Andric     void logf(const LogBuilder &Log) override;
87*349cc55cSDimitry Andric     void logd(const DiffLogBuilder &Log) override;
88*349cc55cSDimitry Andric   };
89*349cc55cSDimitry Andric }
90*349cc55cSDimitry Andric 
91*349cc55cSDimitry Andric #endif
92