Fix the printing of constants. Patch by Stepan Dyatkovskiy!
[oota-llvm.git] / tools / llvm-diff / DiffConsumer.cpp
1 //===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This files implements the the LLVM difference Consumer
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "DiffConsumer.h"
15
16 #include "llvm/Module.h"
17 #include "llvm/Instructions.h"
18 #include "llvm/Support/ErrorHandling.h"
19
20 using namespace llvm;
21
22 static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){
23   unsigned IN = 0;
24
25   // Arguments get the first numbers.
26   for (Function::arg_iterator
27          AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI)
28     if (!AI->hasName())
29       Numbering[&*AI] = IN++;
30
31   // Walk the basic blocks in order.
32   for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) {
33     if (!FI->hasName())
34       Numbering[&*FI] = IN++;
35
36     // Walk the instructions in order.
37     for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
38       // void instructions don't get numbers.
39       if (!BI->hasName() && !BI->getType()->isVoidTy())
40         Numbering[&*BI] = IN++;
41   }
42
43   assert(!Numbering.empty() && "asked for numbering but numbering was no-op");
44 }
45
46
47 void DiffConsumer::printValue(Value *V, bool isL) {
48   if (V->hasName()) {
49     out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName();
50     return;
51   }
52   if (V->getType()->isVoidTy()) {
53     if (isa<StoreInst>(V)) {
54       out << "store to ";
55       printValue(cast<StoreInst>(V)->getPointerOperand(), isL);
56     } else if (isa<CallInst>(V)) {
57       out << "call to ";
58       printValue(cast<CallInst>(V)->getCalledValue(), isL);
59     } else if (isa<InvokeInst>(V)) {
60       out << "invoke to ";
61       printValue(cast<InvokeInst>(V)->getCalledValue(), isL);
62     } else {
63       out << *V;
64     }
65     return;
66   }
67   if (dyn_cast<Constant>(V)) {
68     out << *V;
69     return;
70   }
71
72   unsigned N = contexts.size();
73   while (N > 0) {
74     --N;
75     DiffContext &ctxt = contexts[N];
76     if (!ctxt.IsFunction) continue;
77     if (isL) {
78       if (ctxt.LNumbering.empty())
79         ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering);
80       out << '%' << ctxt.LNumbering[V];
81       return;
82     } else {
83       if (ctxt.RNumbering.empty())
84         ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering);
85       out << '%' << ctxt.RNumbering[V];
86       return;
87     }
88   }
89
90   out << "<anonymous>";
91 }
92
93 void DiffConsumer::header() {
94   if (contexts.empty()) return;
95   for (SmallVectorImpl<DiffContext>::iterator
96          I = contexts.begin(), E = contexts.end(); I != E; ++I) {
97     if (I->Differences) continue;
98     if (isa<Function>(I->L)) {
99       // Extra newline between functions.
100       if (Differences) out << "\n";
101
102       Function *L = cast<Function>(I->L);
103       Function *R = cast<Function>(I->R);
104       if (L->getName() != R->getName())
105         out << "in function " << L->getName()
106             << " / " << R->getName() << ":\n";
107       else
108         out << "in function " << L->getName() << ":\n";
109     } else if (isa<BasicBlock>(I->L)) {
110       BasicBlock *L = cast<BasicBlock>(I->L);
111       BasicBlock *R = cast<BasicBlock>(I->R);
112       if (L->hasName() && R->hasName() && L->getName() == R->getName())
113         out << "  in block %" << L->getName() << ":\n";
114       else {
115         out << "  in block ";
116         printValue(L, true);
117         out << " / ";
118         printValue(R, false);
119         out << ":\n";
120       }
121     } else if (isa<Instruction>(I->L)) {
122       out << "    in instruction ";
123       printValue(I->L, true);
124       out << " / ";
125       printValue(I->R, false);
126       out << ":\n";
127     }
128
129     I->Differences = true;
130   }
131 }
132
133 void DiffConsumer::indent() {
134   unsigned N = Indent;
135   while (N--) out << ' ';
136 }
137
138 bool DiffConsumer::hadDifferences() const {
139   return Differences;
140 }
141
142 void DiffConsumer::enterContext(Value *L, Value *R) {
143   contexts.push_back(DiffContext(L, R));
144   Indent += 2;
145 }
146
147 void DiffConsumer::exitContext() {
148   Differences |= contexts.back().Differences;
149   contexts.pop_back();
150   Indent -= 2;
151 }
152
153 void DiffConsumer::log(StringRef text) {
154   header();
155   indent();
156   out << text << '\n';
157 }
158
159 void DiffConsumer::logf(const LogBuilder &Log) {
160   header();
161   indent();
162
163   unsigned arg = 0;
164
165   StringRef format = Log.getFormat();
166   while (true) {
167     size_t percent = format.find('%');
168     if (percent == StringRef::npos) {
169       out << format;
170       break;
171     }
172     assert(format[percent] == '%');
173
174     if (percent > 0) out << format.substr(0, percent);
175
176     switch (format[percent+1]) {
177     case '%': out << '%'; break;
178     case 'l': printValue(Log.getArgument(arg++), true); break;
179     case 'r': printValue(Log.getArgument(arg++), false); break;
180     default: llvm_unreachable("unknown format character");
181     }
182
183     format = format.substr(percent+2);
184   }
185
186   out << '\n';
187 }
188
189 void DiffConsumer::logd(const DiffLogBuilder &Log) {
190   header();
191
192   for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) {
193     indent();
194     switch (Log.getLineKind(I)) {
195     case DC_match:
196       out << "  ";
197       Log.getLeft(I)->dump();
198       //printValue(Log.getLeft(I), true);
199       break;
200     case DC_left:
201       out << "< ";
202       Log.getLeft(I)->dump();
203       //printValue(Log.getLeft(I), true);
204       break;
205     case DC_right:
206       out << "> ";
207       Log.getRight(I)->dump();
208       //printValue(Log.getRight(I), false);
209       break;
210     }
211     //out << "\n";
212   }
213 }