diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2011-05-02 19:34:44 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2011-05-02 19:34:44 +0000 | 
| commit | 6b943ff3a3f8617113ecbf611cf0f8957e4e19d2 (patch) | |
| tree | fc5f365fb9035b2d0c622bbf06c9bbe8627d7279 /tools/llvm-diff | |
| parent | d0e4e96dc17a6c1c6de3340842c80f0e187ba349 (diff) | |
Notes
Diffstat (limited to 'tools/llvm-diff')
| -rw-r--r-- | tools/llvm-diff/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | tools/llvm-diff/DiffConsumer.cpp | 209 | ||||
| -rw-r--r-- | tools/llvm-diff/DiffConsumer.h | 92 | ||||
| -rw-r--r-- | tools/llvm-diff/DiffLog.cpp | 53 | ||||
| -rw-r--r-- | tools/llvm-diff/DiffLog.h | 80 | ||||
| -rw-r--r-- | tools/llvm-diff/DifferenceEngine.cpp | 27 | ||||
| -rw-r--r-- | tools/llvm-diff/DifferenceEngine.h | 96 | ||||
| -rw-r--r-- | tools/llvm-diff/llvm-diff.cpp | 218 | 
8 files changed, 455 insertions, 322 deletions
diff --git a/tools/llvm-diff/CMakeLists.txt b/tools/llvm-diff/CMakeLists.txt index f6d65c947a58c..c59d69ea0d455 100644 --- a/tools/llvm-diff/CMakeLists.txt +++ b/tools/llvm-diff/CMakeLists.txt @@ -2,5 +2,7 @@ set(LLVM_LINK_COMPONENTS support asmparser bitreader)  add_llvm_tool(llvm-diff    llvm-diff.cpp +  DiffConsumer.cpp +  DiffLog.cpp    DifferenceEngine.cpp    ) diff --git a/tools/llvm-diff/DiffConsumer.cpp b/tools/llvm-diff/DiffConsumer.cpp new file mode 100644 index 0000000000000..c23e8fb91a1b7 --- /dev/null +++ b/tools/llvm-diff/DiffConsumer.cpp @@ -0,0 +1,209 @@ +//===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files implements the the LLVM difference Consumer +// +//===----------------------------------------------------------------------===// + +#include "DiffConsumer.h" + +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ +  unsigned IN = 0; + +  // Arguments get the first numbers. +  for (Function::arg_iterator +         AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) +    if (!AI->hasName()) +      Numbering[&*AI] = IN++; + +  // Walk the basic blocks in order. +  for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { +    if (!FI->hasName()) +      Numbering[&*FI] = IN++; + +    // Walk the instructions in order. +    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) +      // void instructions don't get numbers. +      if (!BI->hasName() && !BI->getType()->isVoidTy()) +        Numbering[&*BI] = IN++; +  } + +  assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); +} + + +void DiffConsumer::printValue(Value *V, bool isL) { +  if (V->hasName()) { +    out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); +    return; +  } +  if (V->getType()->isVoidTy()) { +    if (isa<StoreInst>(V)) { +      out << "store to "; +      printValue(cast<StoreInst>(V)->getPointerOperand(), isL); +    } else if (isa<CallInst>(V)) { +      out << "call to "; +      printValue(cast<CallInst>(V)->getCalledValue(), isL); +    } else if (isa<InvokeInst>(V)) { +      out << "invoke to "; +      printValue(cast<InvokeInst>(V)->getCalledValue(), isL); +    } else { +      out << *V; +    } +    return; +  } + +  unsigned N = contexts.size(); +  while (N > 0) { +    --N; +    DiffContext &ctxt = contexts[N]; +    if (!ctxt.IsFunction) continue; +    if (isL) { +      if (ctxt.LNumbering.empty()) +        ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering); +      out << '%' << ctxt.LNumbering[V]; +      return; +    } else { +      if (ctxt.RNumbering.empty()) +        ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering); +      out << '%' << ctxt.RNumbering[V]; +      return; +    } +  } + +  out << "<anonymous>"; +} + +void DiffConsumer::header() { +  if (contexts.empty()) return; +  for (SmallVectorImpl<DiffContext>::iterator +         I = contexts.begin(), E = contexts.end(); I != E; ++I) { +    if (I->Differences) continue; +    if (isa<Function>(I->L)) { +      // Extra newline between functions. +      if (Differences) out << "\n"; + +      Function *L = cast<Function>(I->L); +      Function *R = cast<Function>(I->R); +      if (L->getName() != R->getName()) +        out << "in function " << L->getName() +            << " / " << R->getName() << ":\n"; +      else +        out << "in function " << L->getName() << ":\n"; +    } else if (isa<BasicBlock>(I->L)) { +      BasicBlock *L = cast<BasicBlock>(I->L); +      BasicBlock *R = cast<BasicBlock>(I->R); +      if (L->hasName() && R->hasName() && L->getName() == R->getName()) +        out << "  in block %" << L->getName() << ":\n"; +      else { +        out << "  in block "; +        printValue(L, true); +        out << " / "; +        printValue(R, false); +        out << ":\n"; +      } +    } else if (isa<Instruction>(I->L)) { +      out << "    in instruction "; +      printValue(I->L, true); +      out << " / "; +      printValue(I->R, false); +      out << ":\n"; +    } + +    I->Differences = true; +  } +} + +void DiffConsumer::indent() { +  unsigned N = Indent; +  while (N--) out << ' '; +} + +bool DiffConsumer::hadDifferences() const { +  return Differences; +} + +void DiffConsumer::enterContext(Value *L, Value *R) { +  contexts.push_back(DiffContext(L, R)); +  Indent += 2; +} + +void DiffConsumer::exitContext() { +  Differences |= contexts.back().Differences; +  contexts.pop_back(); +  Indent -= 2; +} + +void DiffConsumer::log(StringRef text) { +  header(); +  indent(); +  out << text << '\n'; +} + +void DiffConsumer::logf(const LogBuilder &Log) { +  header(); +  indent(); + +  unsigned arg = 0; + +  StringRef format = Log.getFormat(); +  while (true) { +    size_t percent = format.find('%'); +    if (percent == StringRef::npos) { +      out << format; +      break; +    } +    assert(format[percent] == '%'); + +    if (percent > 0) out << format.substr(0, percent); + +    switch (format[percent+1]) { +    case '%': out << '%'; break; +    case 'l': printValue(Log.getArgument(arg++), true); break; +    case 'r': printValue(Log.getArgument(arg++), false); break; +    default: llvm_unreachable("unknown format character"); +    } + +    format = format.substr(percent+2); +  } + +  out << '\n'; +} + +void DiffConsumer::logd(const DiffLogBuilder &Log) { +  header(); + +  for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { +    indent(); +    switch (Log.getLineKind(I)) { +    case DC_match: +      out << "  "; +      Log.getLeft(I)->dump(); +      //printValue(Log.getLeft(I), true); +      break; +    case DC_left: +      out << "< "; +      Log.getLeft(I)->dump(); +      //printValue(Log.getLeft(I), true); +      break; +    case DC_right: +      out << "> "; +      Log.getRight(I)->dump(); +      //printValue(Log.getRight(I), false); +      break; +    } +    //out << "\n"; +  } +} diff --git a/tools/llvm-diff/DiffConsumer.h b/tools/llvm-diff/DiffConsumer.h new file mode 100644 index 0000000000000..b95d42713a643 --- /dev/null +++ b/tools/llvm-diff/DiffConsumer.h @@ -0,0 +1,92 @@ +//===-- DiffConsumer.h - Difference Consumer --------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference Consumer +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_DIFFCONSUMER_H_ +#define _LLVM_DIFFCONSUMER_H_ + +#include "DiffLog.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Casting.h" + +namespace llvm { +  class Module; +  class Value; +  class Function; + +  /// The interface for consumers of difference data. +  class Consumer { +  public: +    /// Record that a local context has been entered.  Left and +    /// Right are IR "containers" of some sort which are being +    /// considered for structural equivalence: global variables, +    /// functions, blocks, instructions, etc. +    virtual void enterContext(Value *Left, Value *Right) = 0; + +    /// Record that a local context has been exited. +    virtual void exitContext() = 0; + +    /// Record a difference within the current context. +    virtual void log(StringRef Text) = 0; + +    /// Record a formatted difference within the current context. +    virtual void logf(const LogBuilder &Log) = 0; + +    /// Record a line-by-line instruction diff. +    virtual void logd(const DiffLogBuilder &Log) = 0; + +  protected: +    virtual ~Consumer() {} +  }; + +  class DiffConsumer : public Consumer { +  private: +    struct DiffContext { +      DiffContext(Value *L, Value *R) +        : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {} +      Value *L; +      Value *R; +      bool Differences; +      bool IsFunction; +      DenseMap<Value*,unsigned> LNumbering; +      DenseMap<Value*,unsigned> RNumbering; +    }; + +    raw_ostream &out; +    Module *LModule; +    Module *RModule; +    SmallVector<DiffContext, 5> contexts; +    bool Differences; +    unsigned Indent; + +    void printValue(Value *V, bool isL); +    void header(); +    void indent(); + +  public: +    DiffConsumer(Module *L, Module *R) +      : out(errs()), LModule(L), RModule(R), Differences(false), Indent(0) {} + +    bool hadDifferences() const; +    void enterContext(Value *L, Value *R); +    void exitContext(); +    void log(StringRef text); +    void logf(const LogBuilder &Log); +    void logd(const DiffLogBuilder &Log); +  }; +} + +#endif diff --git a/tools/llvm-diff/DiffLog.cpp b/tools/llvm-diff/DiffLog.cpp new file mode 100644 index 0000000000000..9cc0c889fd1f8 --- /dev/null +++ b/tools/llvm-diff/DiffLog.cpp @@ -0,0 +1,53 @@ +//===-- DiffLog.h - Difference Log Builder and accessories ------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference log builder. +// +//===----------------------------------------------------------------------===// + +#include "DiffLog.h" +#include "DiffConsumer.h" + +#include "llvm/Instructions.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +using namespace llvm; + +LogBuilder::~LogBuilder() { +  consumer.logf(*this); +} + +StringRef LogBuilder::getFormat() const { return Format; } + +unsigned LogBuilder::getNumArguments() const { return Arguments.size(); } +Value *LogBuilder::getArgument(unsigned I) const { return Arguments[I]; } + +DiffLogBuilder::~DiffLogBuilder() { consumer.logd(*this); } + +void DiffLogBuilder::addMatch(Instruction *L, Instruction *R) { +  Diff.push_back(DiffRecord(L, R)); +} +void DiffLogBuilder::addLeft(Instruction *L) { +  // HACK: VS 2010 has a bug in the stdlib that requires this. +  Diff.push_back(DiffRecord(L, DiffRecord::second_type(0))); +} +void DiffLogBuilder::addRight(Instruction *R) { +  // HACK: VS 2010 has a bug in the stdlib that requires this. +  Diff.push_back(DiffRecord(DiffRecord::first_type(0), R)); +} + +unsigned DiffLogBuilder::getNumLines() const { return Diff.size(); } + +DiffChange DiffLogBuilder::getLineKind(unsigned I) const { +  return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left) +                        : DC_right); +} +Instruction *DiffLogBuilder::getLeft(unsigned I) const { return Diff[I].first; } +Instruction *DiffLogBuilder::getRight(unsigned I) const { return Diff[I].second; } diff --git a/tools/llvm-diff/DiffLog.h b/tools/llvm-diff/DiffLog.h new file mode 100644 index 0000000000000..43e318ac4e9fe --- /dev/null +++ b/tools/llvm-diff/DiffLog.h @@ -0,0 +1,80 @@ +//===-- DiffLog.h - Difference Log Builder and accessories ------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference log builder. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_DIFFLOG_H_ +#define _LLVM_DIFFLOG_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { +  class Instruction; +  class Value; +  class Consumer; + +  /// Trichotomy assumption +  enum DiffChange { DC_match, DC_left, DC_right }; + +  /// A temporary-object class for building up log messages. +  class LogBuilder { +    Consumer &consumer; + +    /// The use of a stored StringRef here is okay because +    /// LogBuilder should be used only as a temporary, and as a +    /// temporary it will be destructed before whatever temporary +    /// might be initializing this format. +    StringRef Format; + +    SmallVector<Value*, 4> Arguments; + +  public: +    LogBuilder(Consumer &c, StringRef Format) +      : consumer(c), Format(Format) {} + +    LogBuilder &operator<<(Value *V) { +      Arguments.push_back(V); +      return *this; +    } + +    ~LogBuilder(); + +    StringRef getFormat() const; +    unsigned getNumArguments() const; +    Value *getArgument(unsigned I) const; +  }; + +  /// A temporary-object class for building up diff messages. +  class DiffLogBuilder { +    typedef std::pair<Instruction*,Instruction*> DiffRecord; +    SmallVector<DiffRecord, 20> Diff; + +    Consumer &consumer; + +  public: +    DiffLogBuilder(Consumer &c) : consumer(c) {} +    ~DiffLogBuilder(); + +    void addMatch(Instruction *L, Instruction *R); +    // HACK: VS 2010 has a bug in the stdlib that requires this. +    void addLeft(Instruction *L); +    void addRight(Instruction *R); + +    unsigned getNumLines() const; +    DiffChange getLineKind(unsigned I) const; +    Instruction *getLeft(unsigned I) const; +    Instruction *getRight(unsigned I) const; +  }; + +} + +#endif diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp index b0a24d0737eca..ba2cec2992554 100644 --- a/tools/llvm-diff/DifferenceEngine.cpp +++ b/tools/llvm-diff/DifferenceEngine.cpp @@ -14,6 +14,7 @@  #include "DifferenceEngine.h" +#include "llvm/Constants.h"  #include "llvm/Function.h"  #include "llvm/Instructions.h"  #include "llvm/Module.h" @@ -266,7 +267,7 @@ class FunctionDifferenceEngine {      } else if (isa<PHINode>(L)) {        // FIXME: implement. -      // This is really wierd;  type uniquing is broken? +      // This is really weird;  type uniquing is broken?        if (L->getType() != R->getType()) {          if (!L->getType()->isPointerTy() || !R->getType()->isPointerTy()) {            if (Complain) Engine.log("different phi types"); @@ -506,30 +507,30 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,    for (unsigned I = 0; I != NL+1; ++I) {      Cur[I].Cost = I * LeftCost;      for (unsigned J = 0; J != I; ++J) -      Cur[I].Path.push_back(DifferenceEngine::DC_left); +      Cur[I].Path.push_back(DC_left);    }    for (BasicBlock::iterator RI = RStart; RI != RE; ++RI) {      // Initialize the first row.      Next[0] = Cur[0];      Next[0].Cost += RightCost; -    Next[0].Path.push_back(DifferenceEngine::DC_right); +    Next[0].Path.push_back(DC_right);      unsigned Index = 1;      for (BasicBlock::iterator LI = LStart; LI != LE; ++LI, ++Index) {        if (matchForBlockDiff(&*LI, &*RI)) {          Next[Index] = Cur[Index-1];          Next[Index].Cost += MatchCost; -        Next[Index].Path.push_back(DifferenceEngine::DC_match); +        Next[Index].Path.push_back(DC_match);          TentativeValues.insert(std::make_pair(&*LI, &*RI));        } else if (Next[Index-1].Cost <= Cur[Index].Cost) {          Next[Index] = Next[Index-1];          Next[Index].Cost += LeftCost; -        Next[Index].Path.push_back(DifferenceEngine::DC_left); +        Next[Index].Path.push_back(DC_left);        } else {          Next[Index] = Cur[Index];          Next[Index].Cost += RightCost; -        Next[Index].Path.push_back(DifferenceEngine::DC_right); +        Next[Index].Path.push_back(DC_right);        }      } @@ -543,23 +544,23 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,    SmallVectorImpl<char> &Path = Cur[NL].Path;    BasicBlock::iterator LI = LStart, RI = RStart; -  DifferenceEngine::DiffLogBuilder Diff(Engine); +  DiffLogBuilder Diff(Engine.getConsumer());    // Drop trailing matches. -  while (Path.back() == DifferenceEngine::DC_match) +  while (Path.back() == DC_match)      Path.pop_back();    // Skip leading matches.    SmallVectorImpl<char>::iterator      PI = Path.begin(), PE = Path.end(); -  while (PI != PE && *PI == DifferenceEngine::DC_match) { +  while (PI != PE && *PI == DC_match) {      unify(&*LI, &*RI);      ++PI, ++LI, ++RI;    }    for (; PI != PE; ++PI) { -    switch (static_cast<DifferenceEngine::DiffChange>(*PI)) { -    case DifferenceEngine::DC_match: +    switch (static_cast<DiffChange>(*PI)) { +    case DC_match:        assert(LI != LE && RI != RE);        {          Instruction *L = &*LI, *R = &*RI; @@ -569,13 +570,13 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,        ++LI; ++RI;        break; -    case DifferenceEngine::DC_left: +    case DC_left:        assert(LI != LE);        Diff.addLeft(&*LI);        ++LI;        break; -    case DifferenceEngine::DC_right: +    case DC_right:        assert(RI != RE);        Diff.addRight(&*RI);        ++RI; diff --git a/tools/llvm-diff/DifferenceEngine.h b/tools/llvm-diff/DifferenceEngine.h index 6eefb06118fa6..5b4f80b99e557 100644 --- a/tools/llvm-diff/DifferenceEngine.h +++ b/tools/llvm-diff/DifferenceEngine.h @@ -17,6 +17,8 @@  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/StringRef.h" +#include "DiffLog.h" +#include "DiffConsumer.h"  #include <utility> @@ -32,95 +34,6 @@ namespace llvm {    /// A class for performing structural comparisons of LLVM assembly.    class DifferenceEngine {    public: -    /// A temporary-object class for building up log messages. -    class LogBuilder { -      DifferenceEngine &Engine; - -      /// The use of a stored StringRef here is okay because -      /// LogBuilder should be used only as a temporary, and as a -      /// temporary it will be destructed before whatever temporary -      /// might be initializing this format. -      StringRef Format; - -      SmallVector<Value*, 4> Arguments; - -    public: -      LogBuilder(DifferenceEngine &Engine, StringRef Format) -        : Engine(Engine), Format(Format) {} - -      LogBuilder &operator<<(Value *V) { -        Arguments.push_back(V); -        return *this; -      } - -      ~LogBuilder() { -        Engine.consumer.logf(*this); -      } - -      StringRef getFormat() const { return Format; } - -      unsigned getNumArguments() const { return Arguments.size(); } -      Value *getArgument(unsigned I) const { return Arguments[I]; } -    }; - -    enum DiffChange { DC_match, DC_left, DC_right }; - -    /// A temporary-object class for building up diff messages. -    class DiffLogBuilder { -      typedef std::pair<Instruction*,Instruction*> DiffRecord; -      SmallVector<DiffRecord, 20> Diff; - -      DifferenceEngine &Engine; - -    public: -      DiffLogBuilder(DifferenceEngine &Engine) : Engine(Engine) {} -      ~DiffLogBuilder() { Engine.consumer.logd(*this); } - -      void addMatch(Instruction *L, Instruction *R) { -        Diff.push_back(DiffRecord(L, R)); -      } -      void addLeft(Instruction *L) { -        // HACK: VS 2010 has a bug in the stdlib that requires this. -        Diff.push_back(DiffRecord(L, DiffRecord::second_type(0))); -      } -      void addRight(Instruction *R) { -        // HACK: VS 2010 has a bug in the stdlib that requires this. -        Diff.push_back(DiffRecord(DiffRecord::first_type(0), R)); -      } - -      unsigned getNumLines() const { return Diff.size(); } -      DiffChange getLineKind(unsigned I) const { -        return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left) -                              : DC_right); -      } -      Instruction *getLeft(unsigned I) const { return Diff[I].first; } -      Instruction *getRight(unsigned I) const { return Diff[I].second; } -    }; - -    /// The interface for consumers of difference data. -    struct Consumer { -      /// Record that a local context has been entered.  Left and -      /// Right are IR "containers" of some sort which are being -      /// considered for structural equivalence: global variables, -      /// functions, blocks, instructions, etc. -      virtual void enterContext(Value *Left, Value *Right) = 0; - -      /// Record that a local context has been exited. -      virtual void exitContext() = 0; - -      /// Record a difference within the current context. -      virtual void log(StringRef Text) = 0; - -      /// Record a formatted difference within the current context. -      virtual void logf(const LogBuilder &Log) = 0; - -      /// Record a line-by-line instruction diff. -      virtual void logd(const DiffLogBuilder &Log) = 0; - -    protected: -      virtual ~Consumer() {} -    }; -      /// A RAII object for recording the current context.      struct Context {        Context(DifferenceEngine &Engine, Value *L, Value *R) : Engine(Engine) { @@ -149,14 +62,13 @@ namespace llvm {      void diff(Module *L, Module *R);      void diff(Function *L, Function *R); -      void log(StringRef text) {        consumer.log(text);      } -      LogBuilder logf(StringRef text) { -      return LogBuilder(*this, text); +      return LogBuilder(consumer, text);      } +    Consumer& getConsumer() const { return consumer; }      /// Installs an oracle to decide whether two global values are      /// equivalent as operands.  Without an oracle, global values are diff --git a/tools/llvm-diff/llvm-diff.cpp b/tools/llvm-diff/llvm-diff.cpp index b932ccc7437c3..76853f1e43306 100644 --- a/tools/llvm-diff/llvm-diff.cpp +++ b/tools/llvm-diff/llvm-diff.cpp @@ -11,9 +11,9 @@  //  //===----------------------------------------------------------------------===// +#include "DiffLog.h"  #include "DifferenceEngine.h" -#include "llvm/Instructions.h"  #include "llvm/LLVMContext.h"  #include "llvm/Module.h"  #include "llvm/Type.h" @@ -21,7 +21,6 @@  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/StringRef.h"  #include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/IRReader.h"  #include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/raw_ostream.h" @@ -43,221 +42,6 @@ static Module *ReadModule(LLVMContext &Context, StringRef Name) {    return M;  } -namespace { -  struct DiffContext { -    DiffContext(Value *L, Value *R) -      : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {} -    Value *L; -    Value *R; -    bool Differences; -    bool IsFunction; -    DenseMap<Value*,unsigned> LNumbering; -    DenseMap<Value*,unsigned> RNumbering; -  }; -} - -static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ -  unsigned IN = 0; - -  // Arguments get the first numbers. -  for (Function::arg_iterator -         AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) -    if (!AI->hasName()) -      Numbering[&*AI] = IN++; - -  // Walk the basic blocks in order. -  for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { -    if (!FI->hasName()) -      Numbering[&*FI] = IN++; - -    // Walk the instructions in order. -    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) -      // void instructions don't get numbers. -      if (!BI->hasName() && !BI->getType()->isVoidTy()) -        Numbering[&*BI] = IN++; -  } - -  assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); -} - -namespace { -class DiffConsumer : public DifferenceEngine::Consumer { -private: -  raw_ostream &out; -  Module *LModule; -  Module *RModule; -  SmallVector<DiffContext, 5> contexts; -  bool Differences; -  unsigned Indent; - -  void printValue(Value *V, bool isL) { -    if (V->hasName()) { -      out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); -      return; -    } -    if (V->getType()->isVoidTy()) { -      if (isa<StoreInst>(V)) { -        out << "store to "; -        printValue(cast<StoreInst>(V)->getPointerOperand(), isL); -      } else if (isa<CallInst>(V)) { -        out << "call to "; -        printValue(cast<CallInst>(V)->getCalledValue(), isL); -      } else if (isa<InvokeInst>(V)) { -        out << "invoke to "; -        printValue(cast<InvokeInst>(V)->getCalledValue(), isL); -      } else { -        out << *V; -      } -      return; -    } - -    unsigned N = contexts.size(); -    while (N > 0) { -      --N; -      DiffContext &ctxt = contexts[N]; -      if (!ctxt.IsFunction) continue; -      if (isL) { -        if (ctxt.LNumbering.empty()) -          ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering); -        out << '%' << ctxt.LNumbering[V]; -        return; -      } else { -        if (ctxt.RNumbering.empty()) -          ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering); -        out << '%' << ctxt.RNumbering[V]; -        return; -      } -    } - -    out << "<anonymous>"; -  } - -  void header() { -    if (contexts.empty()) return; -    for (SmallVectorImpl<DiffContext>::iterator -           I = contexts.begin(), E = contexts.end(); I != E; ++I) { -      if (I->Differences) continue; -      if (isa<Function>(I->L)) { -        // Extra newline between functions. -        if (Differences) out << "\n"; - -        Function *L = cast<Function>(I->L); -        Function *R = cast<Function>(I->R); -        if (L->getName() != R->getName()) -          out << "in function " << L->getName() -              << " / " << R->getName() << ":\n"; -        else -          out << "in function " << L->getName() << ":\n"; -      } else if (isa<BasicBlock>(I->L)) { -        BasicBlock *L = cast<BasicBlock>(I->L); -        BasicBlock *R = cast<BasicBlock>(I->R); -        if (L->hasName() && R->hasName() && L->getName() == R->getName()) -          out << "  in block %" << L->getName() << ":\n"; -        else { -          out << "  in block "; -          printValue(L, true); -          out << " / "; -          printValue(R, false); -          out << ":\n"; -        } -      } else if (isa<Instruction>(I->L)) { -        out << "    in instruction "; -        printValue(I->L, true); -        out << " / "; -        printValue(I->R, false); -        out << ":\n"; -      } - -      I->Differences = true; -    } -  } - -  void indent() { -    unsigned N = Indent; -    while (N--) out << ' '; -  } - -public: -  DiffConsumer(Module *L, Module *R) -    : out(errs()), LModule(L), RModule(R), Differences(false), Indent(0) {} - -  bool hadDifferences() const { return Differences; } - -  void enterContext(Value *L, Value *R) { -    contexts.push_back(DiffContext(L, R)); -    Indent += 2; -  } -  void exitContext() { -    Differences |= contexts.back().Differences; -    contexts.pop_back(); -    Indent -= 2; -  } - -  void log(StringRef text) { -    header(); -    indent(); -    out << text << '\n'; -  } - -  void logf(const DifferenceEngine::LogBuilder &Log) { -    header(); -    indent(); - -    unsigned arg = 0; - -    StringRef format = Log.getFormat(); -    while (true) { -      size_t percent = format.find('%'); -      if (percent == StringRef::npos) { -        out << format; -        break; -      } -      assert(format[percent] == '%'); - -      if (percent > 0) out << format.substr(0, percent); - -      switch (format[percent+1]) { -      case '%': out << '%'; break; -      case 'l': printValue(Log.getArgument(arg++), true); break; -      case 'r': printValue(Log.getArgument(arg++), false); break; -      default: llvm_unreachable("unknown format character"); -      } - -      format = format.substr(percent+2); -    } - -    out << '\n'; -  } - -  void logd(const DifferenceEngine::DiffLogBuilder &Log) { -    header(); - -    for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { -      indent(); -      switch (Log.getLineKind(I)) { -      case DifferenceEngine::DC_match: -        out << "  "; -        Log.getLeft(I)->dump(); -        //printValue(Log.getLeft(I), true); -        break; -      case DifferenceEngine::DC_left: -        out << "< "; -        Log.getLeft(I)->dump(); -        //printValue(Log.getLeft(I), true); -        break; -      case DifferenceEngine::DC_right: -        out << "> "; -        Log.getRight(I)->dump(); -        //printValue(Log.getRight(I), false); -        break; -      } -      //out << "\n"; -    } -  } -   -}; -} // end anonymous namespace -  static void diffGlobal(DifferenceEngine &Engine, Module *L, Module *R,                         StringRef Name) {    // Drop leading sigils from the global name.  | 
