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