xref: /llvm-project/llvm/tools/llvm-diff/lib/DifferenceEngine.h (revision 4d293f215dfb6ab6af966175717e86468f708b1c)
1*4d293f21SBill Wendling //===-- DifferenceEngine.h - Module comparator ------------------*- C++ -*-===//
2*4d293f21SBill Wendling //
3*4d293f21SBill Wendling // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4d293f21SBill Wendling // See https://llvm.org/LICENSE.txt for license information.
5*4d293f21SBill Wendling // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4d293f21SBill Wendling //
7*4d293f21SBill Wendling //===----------------------------------------------------------------------===//
8*4d293f21SBill Wendling //
9*4d293f21SBill Wendling // This header defines the interface to the LLVM difference engine,
10*4d293f21SBill Wendling // which structurally compares functions within a module.
11*4d293f21SBill Wendling //
12*4d293f21SBill Wendling //===----------------------------------------------------------------------===//
13*4d293f21SBill Wendling 
14*4d293f21SBill Wendling #ifndef LLVM_TOOLS_LLVM_DIFF_DIFFERENCEENGINE_H
15*4d293f21SBill Wendling #define LLVM_TOOLS_LLVM_DIFF_DIFFERENCEENGINE_H
16*4d293f21SBill Wendling 
17*4d293f21SBill Wendling #include "DiffConsumer.h"
18*4d293f21SBill Wendling #include "DiffLog.h"
19*4d293f21SBill Wendling #include "llvm/ADT/StringRef.h"
20*4d293f21SBill Wendling #include <utility>
21*4d293f21SBill Wendling 
22*4d293f21SBill Wendling namespace llvm {
23*4d293f21SBill Wendling   class Function;
24*4d293f21SBill Wendling   class GlobalValue;
25*4d293f21SBill Wendling   class Instruction;
26*4d293f21SBill Wendling   class LLVMContext;
27*4d293f21SBill Wendling   class Module;
28*4d293f21SBill Wendling   class Twine;
29*4d293f21SBill Wendling   class Value;
30*4d293f21SBill Wendling 
31*4d293f21SBill Wendling   /// A class for performing structural comparisons of LLVM assembly.
32*4d293f21SBill Wendling   class DifferenceEngine {
33*4d293f21SBill Wendling   public:
34*4d293f21SBill Wendling     /// A RAII object for recording the current context.
35*4d293f21SBill Wendling     struct Context {
ContextContext36*4d293f21SBill Wendling       Context(DifferenceEngine &Engine, const Value *L, const Value *R)
37*4d293f21SBill Wendling           : Engine(Engine) {
38*4d293f21SBill Wendling         Engine.consumer.enterContext(L, R);
39*4d293f21SBill Wendling       }
40*4d293f21SBill Wendling 
~ContextContext41*4d293f21SBill Wendling       ~Context() {
42*4d293f21SBill Wendling         Engine.consumer.exitContext();
43*4d293f21SBill Wendling       }
44*4d293f21SBill Wendling 
45*4d293f21SBill Wendling     private:
46*4d293f21SBill Wendling       DifferenceEngine &Engine;
47*4d293f21SBill Wendling     };
48*4d293f21SBill Wendling 
49*4d293f21SBill Wendling     /// An oracle for answering whether two values are equivalent as
50*4d293f21SBill Wendling     /// operands.
51*4d293f21SBill Wendling     class Oracle {
52*4d293f21SBill Wendling       virtual void anchor();
53*4d293f21SBill Wendling     public:
54*4d293f21SBill Wendling       virtual bool operator()(const Value *L, const Value *R) = 0;
55*4d293f21SBill Wendling 
56*4d293f21SBill Wendling     protected:
~Oracle()57*4d293f21SBill Wendling       virtual ~Oracle() {}
58*4d293f21SBill Wendling     };
59*4d293f21SBill Wendling 
DifferenceEngine(Consumer & consumer)60*4d293f21SBill Wendling     DifferenceEngine(Consumer &consumer)
61*4d293f21SBill Wendling       : consumer(consumer), globalValueOracle(nullptr) {}
62*4d293f21SBill Wendling 
63*4d293f21SBill Wendling     void diff(const Module *L, const Module *R);
64*4d293f21SBill Wendling     void diff(const Function *L, const Function *R);
log(StringRef text)65*4d293f21SBill Wendling     void log(StringRef text) {
66*4d293f21SBill Wendling       consumer.log(text);
67*4d293f21SBill Wendling     }
logf(StringRef text)68*4d293f21SBill Wendling     LogBuilder logf(StringRef text) {
69*4d293f21SBill Wendling       return LogBuilder(consumer, text);
70*4d293f21SBill Wendling     }
getConsumer()71*4d293f21SBill Wendling     Consumer& getConsumer() const { return consumer; }
72*4d293f21SBill Wendling 
73*4d293f21SBill Wendling     /// Installs an oracle to decide whether two global values are
74*4d293f21SBill Wendling     /// equivalent as operands.  Without an oracle, global values are
75*4d293f21SBill Wendling     /// considered equivalent as operands precisely when they have the
76*4d293f21SBill Wendling     /// same name.
setGlobalValueOracle(Oracle * oracle)77*4d293f21SBill Wendling     void setGlobalValueOracle(Oracle *oracle) {
78*4d293f21SBill Wendling       globalValueOracle = oracle;
79*4d293f21SBill Wendling     }
80*4d293f21SBill Wendling 
81*4d293f21SBill Wendling     /// Determines whether two global values are equivalent.
82*4d293f21SBill Wendling     bool equivalentAsOperands(const GlobalValue *L, const GlobalValue *R);
83*4d293f21SBill Wendling 
84*4d293f21SBill Wendling   private:
85*4d293f21SBill Wendling     Consumer &consumer;
86*4d293f21SBill Wendling     Oracle *globalValueOracle;
87*4d293f21SBill Wendling   };
88*4d293f21SBill Wendling }
89*4d293f21SBill Wendling 
90*4d293f21SBill Wendling #endif
91