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