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