DiffConsumer.cpp revision 231057
1169691Skan//===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===//
2169691Skan//
3169691Skan//                     The LLVM Compiler Infrastructure
4169691Skan//
5169691Skan// This file is distributed under the University of Illinois Open Source
6169691Skan// License. See LICENSE.TXT for details.
7169691Skan//
8169691Skan//===----------------------------------------------------------------------===//
9169691Skan//
10169691Skan// This files implements the the LLVM difference Consumer
11169691Skan//
12169691Skan//===----------------------------------------------------------------------===//
13169691Skan
14169691Skan#include "DiffConsumer.h"
15169691Skan
16169691Skan#include "llvm/Module.h"
17169691Skan#include "llvm/Instructions.h"
18169691Skan#include "llvm/Support/ErrorHandling.h"
19169691Skan
20169691Skanusing namespace llvm;
21169691Skan
22169691Skanstatic void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){
23169691Skan  unsigned IN = 0;
24169691Skan
25169691Skan  // Arguments get the first numbers.
26169691Skan  for (Function::arg_iterator
27169691Skan         AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI)
28169691Skan    if (!AI->hasName())
29169691Skan      Numbering[&*AI] = IN++;
30169691Skan
31169691Skan  // Walk the basic blocks in order.
32169691Skan  for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) {
33169691Skan    if (!FI->hasName())
34169691Skan      Numbering[&*FI] = IN++;
35169691Skan
36169691Skan    // Walk the instructions in order.
37169691Skan    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
38169691Skan      // void instructions don't get numbers.
39169691Skan      if (!BI->hasName() && !BI->getType()->isVoidTy())
40169691Skan        Numbering[&*BI] = IN++;
41169691Skan  }
42169691Skan
43169691Skan  assert(!Numbering.empty() && "asked for numbering but numbering was no-op");
44169691Skan}
45169691Skan
46169691Skan
47169691Skanvoid DiffConsumer::printValue(Value *V, bool isL) {
48169691Skan  if (V->hasName()) {
49169691Skan    out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName();
50169691Skan    return;
51169691Skan  }
52169691Skan  if (V->getType()->isVoidTy()) {
53169691Skan    if (isa<StoreInst>(V)) {
54169691Skan      out << "store to ";
55169691Skan      printValue(cast<StoreInst>(V)->getPointerOperand(), isL);
56169691Skan    } else if (isa<CallInst>(V)) {
57169691Skan      out << "call to ";
58169691Skan      printValue(cast<CallInst>(V)->getCalledValue(), isL);
59169691Skan    } else if (isa<InvokeInst>(V)) {
60169691Skan      out << "invoke to ";
61169691Skan      printValue(cast<InvokeInst>(V)->getCalledValue(), isL);
62169691Skan    } else {
63169691Skan      out << *V;
64169691Skan    }
65169691Skan    return;
66169691Skan  }
67169691Skan
68169691Skan  unsigned N = contexts.size();
69169691Skan  while (N > 0) {
70169691Skan    --N;
71169691Skan    DiffContext &ctxt = contexts[N];
72169691Skan    if (!ctxt.IsFunction) continue;
73169691Skan    if (isL) {
74169691Skan      if (ctxt.LNumbering.empty())
75169691Skan        ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering);
76169691Skan      out << '%' << ctxt.LNumbering[V];
77169691Skan      return;
78169691Skan    } else {
79169691Skan      if (ctxt.RNumbering.empty())
80169691Skan        ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering);
81169691Skan      out << '%' << ctxt.RNumbering[V];
82169691Skan      return;
83169691Skan    }
84169691Skan  }
85169691Skan
86169691Skan  out << "<anonymous>";
87169691Skan}
88169691Skan
89169691Skanvoid DiffConsumer::header() {
90169691Skan  if (contexts.empty()) return;
91169691Skan  for (SmallVectorImpl<DiffContext>::iterator
92169691Skan         I = contexts.begin(), E = contexts.end(); I != E; ++I) {
93169691Skan    if (I->Differences) continue;
94169691Skan    if (isa<Function>(I->L)) {
95169691Skan      // Extra newline between functions.
96169691Skan      if (Differences) out << "\n";
97169691Skan
98169691Skan      Function *L = cast<Function>(I->L);
99169691Skan      Function *R = cast<Function>(I->R);
100169691Skan      if (L->getName() != R->getName())
101169691Skan        out << "in function " << L->getName()
102169691Skan            << " / " << R->getName() << ":\n";
103169691Skan      else
104169691Skan        out << "in function " << L->getName() << ":\n";
105169691Skan    } else if (isa<BasicBlock>(I->L)) {
106169691Skan      BasicBlock *L = cast<BasicBlock>(I->L);
107169691Skan      BasicBlock *R = cast<BasicBlock>(I->R);
108169691Skan      if (L->hasName() && R->hasName() && L->getName() == R->getName())
109169691Skan        out << "  in block %" << L->getName() << ":\n";
110169691Skan      else {
111169691Skan        out << "  in block ";
112169691Skan        printValue(L, true);
113169691Skan        out << " / ";
114169691Skan        printValue(R, false);
115169691Skan        out << ":\n";
116169691Skan      }
117169691Skan    } else if (isa<Instruction>(I->L)) {
118169691Skan      out << "    in instruction ";
119169691Skan      printValue(I->L, true);
120169691Skan      out << " / ";
121169691Skan      printValue(I->R, false);
122169691Skan      out << ":\n";
123169691Skan    }
124169691Skan
125169691Skan    I->Differences = true;
126169691Skan  }
127169691Skan}
128169691Skan
129169691Skanvoid DiffConsumer::indent() {
130169691Skan  unsigned N = Indent;
131169691Skan  while (N--) out << ' ';
132169691Skan}
133169691Skan
134169691Skanbool DiffConsumer::hadDifferences() const {
135169691Skan  return Differences;
136169691Skan}
137169691Skan
138169691Skanvoid DiffConsumer::enterContext(Value *L, Value *R) {
139169691Skan  contexts.push_back(DiffContext(L, R));
140169691Skan  Indent += 2;
141169691Skan}
142169691Skan
143169691Skanvoid DiffConsumer::exitContext() {
144169691Skan  Differences |= contexts.back().Differences;
145169691Skan  contexts.pop_back();
146169691Skan  Indent -= 2;
147169691Skan}
148169691Skan
149169691Skanvoid DiffConsumer::log(StringRef text) {
150169691Skan  header();
151169691Skan  indent();
152169691Skan  out << text << '\n';
153169691Skan}
154169691Skan
155169691Skanvoid DiffConsumer::logf(const LogBuilder &Log) {
156169691Skan  header();
157169691Skan  indent();
158169691Skan
159169691Skan  unsigned arg = 0;
160169691Skan
161169691Skan  StringRef format = Log.getFormat();
162169691Skan  while (true) {
163169691Skan    size_t percent = format.find('%');
164169691Skan    if (percent == StringRef::npos) {
165169691Skan      out << format;
166169691Skan      break;
167169691Skan    }
168169691Skan    assert(format[percent] == '%');
169169691Skan
170169691Skan    if (percent > 0) out << format.substr(0, percent);
171169691Skan
172169691Skan    switch (format[percent+1]) {
173169691Skan    case '%': out << '%'; break;
174169691Skan    case 'l': printValue(Log.getArgument(arg++), true); break;
175169691Skan    case 'r': printValue(Log.getArgument(arg++), false); break;
176169691Skan    default: llvm_unreachable("unknown format character");
177169691Skan    }
178169691Skan
179169691Skan    format = format.substr(percent+2);
180169691Skan  }
181169691Skan
182169691Skan  out << '\n';
183169691Skan}
184169691Skan
185169691Skanvoid DiffConsumer::logd(const DiffLogBuilder &Log) {
186169691Skan  header();
187169691Skan
188169691Skan  for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) {
189169691Skan    indent();
190169691Skan    switch (Log.getLineKind(I)) {
191169691Skan    case DC_match:
192169691Skan      out << "  ";
193169691Skan      Log.getLeft(I)->dump();
194169691Skan      //printValue(Log.getLeft(I), true);
195169691Skan      break;
196169691Skan    case DC_left:
197169691Skan      out << "< ";
198169691Skan      Log.getLeft(I)->dump();
199169691Skan      //printValue(Log.getLeft(I), true);
200169691Skan      break;
201169691Skan    case DC_right:
202169691Skan      out << "> ";
203169691Skan      Log.getRight(I)->dump();
204169691Skan      //printValue(Log.getRight(I), false);
205169691Skan      break;
206169691Skan    }
207169691Skan    //out << "\n";
208169691Skan  }
209169691Skan}
210169691Skan